【转】Emgu 图像阈值
原文地址:http://www.cnblogs.com/CoverCat/p/5043833.html
转载,备查
Visual Studio Community 2015 工程和代码:http://pan.baidu.com/s/1o7lxYSM
内容
在这篇文章中将提到以下内容:
- 全局阈值
- 自适应阈值
- Otsu's二值化
在图像处理中,会希望忽略掉一些灰度细节,只保留主体的轮廓,对灰度图像进行阈值化处理能达到这个目的。
“其基本的思想是,给定一个数组和一个阈值,然后根据数组中的每个元素的值是低于还是高于阈值而进行一些处理”——《学习OpenCV(中文版)》,这里说的“数组”即为图像数据,
而“进行一些处理”说的是进行分类,只有两类,根据值不同分到不同的类中。
准备工作
- 创建工程——参考Emgu学习之(一)——Emgu介绍创建一个名为“Threshold”WinForm项目
- 在Form1.cs中引用命名空间:
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
- 界面:在Form1中添加1行2列的TableLayoutPanel容器,然后添加2个Emgu.CV.UI.ImageBox控件(参考Emgu学习之(二)——图像读取、显示、保存),添加后界面如下:
- 设置imageBox1和imageBox2的SizeMode属性为StretchImage
全局阈值
全局阈值指的是整个图像数据使用一个阈值进行筛选分类,OpenCV提供cvThreshold()方法进行阈值化操作,在Emgu中对应的方法名称为Threshold。
Threshold方法接受一个类型为ThresholdType的参数,ThresholdType是一个枚举类型,其枚举值为:
Binary = ,
BinaryInv = ,
Trunc = ,
ToZero = ,
ToZeroInv = ,
Mask = ,//这里不做介绍
Otsu = //后面会做介绍
- Binary(二进制阈值化)——二进制阈值化是指将大于阀值的像素点设置为最大值,而小于阀值的像素点设置为0,即:
value = value > threshold ? max_value : 0
- BinaryInv(反向二进制阈值化)——与二进制阈值化正好相反,反向二进制阈值化是在像素点的值大于阀值时像素点设置为0,反之则设置为最大值,即:
value = value > threshold ? 0 : max_value
- Trunc(截断阈值化)——截断阈值化是指当像素点的值大于阀值时,像素点的值设置为阀值,反之则保留像素值本身,即:
value = value > threshold ? threshold : value
- ToZero(超阈值归零化)——超阈值归零化是指当像素点的值大于阀值时,像素点保留原值,反之则设置为0,即:
value = value > threshold ? value : 0
- ToZeroINV(低于阈值归零化)——与超阈值归零化相反,低于阈值归零化是指当像素点的值大于阀值时,像素点值被设置为0,反之则保留像素点原值,即:
value = value > threshold ? 0 : value
从上边描述我们可以看出二进制阈值化/反二进制阈值化需要一个max_value(最大值)的参数,同时,二进制阈值化/反二进制阈值化处理后图像数据中只存在两种
可能的值:0和max_value,这种图像称为二值化图像。
“在数字图像处理中,二值图像占有非常重要的地位,首先,图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮
廓。其次,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,
否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。”——百度百科
下面的代码显示了如何使用二进制阈值化处理,如果你要使用不是二进制阈值化处理,那么max_value可以不用在意设什么值。
{
using (var image = new Image<Bgr, Byte>(Properties.Resources.chess3))
{
var grayImage = image.Convert<Gray, Byte>();//转为灰度图
var threshImage = grayImage.CopyBlank(); CvInvoke.Threshold(
grayImage,
threshImage,
, //阀值
, //最大值
ThresholdType.Binary);//二进制阈值化 imageBox1.Image = grayImage;
imageBox2.Image = threshImage;
}
}
效果如下: Binary -> BinaryInv -> Trunc -> ToZero -> ToZeroInv
自适应阈值
全局阈值是整幅图像使用一个阀值,这并不能适应所有的情况。自适应阈值是图像的不同的区域使用不同的阀值,而阀值是对这个区域计算得来的,OpenCV提供cvAdaptiveThreshold()
函数进行自适应阈值化处理,这个函数提供两种计算阀值的方法,分别为CV_ADAPTIVE_THRESH_MEAN_C和CV_ADAPTIVE_THRESH_GAUSSIAN_C。
“在这两种情况下,自适应阈值T(x,y)在每个像素点都不同。通过计算像素点周围的b x b区域的加权平均,然后减去一个常数来得到自适应阈值, b有参数block_size指定,常数有param1
指定。如果使用CV_ADAPTIVE_THRESH_MEAN_C方法,那么对区域的所有像素平均加权。如果使用了CV_ADAPTIVE_THRESH_GAUSSIAN_C放,那么区域中的(x,y)周围的像素
根据高斯函数按照它们离中心点的距离进行加权计算。”——《学习OpenCV(中文版)》
Emgu中CVInvoke类提供了AdaptiveThreshold静态方法进行自适应阈值处理,这个方法的原型为:
public static void AdaptiveThreshold(
IInputArray src, //原图像
IOutputArray dst, //结果图像
double maxValue, //二进制阈值化/反二进制阈值化处理使用到的最大值
CvEnum.AdaptiveThresholdType adaptiveType, // 自适应阈值计算方式:MeanC或GaussianC
CvEnum.ThresholdType thresholdType, //阈值化方式,必须为二进制阈值化和反二进制阈值化之一(Binary / BinaryInv)
int blockSize, //计算使用的区域矩阵大小:3,5,7,9...
double param1) //常数
同时,Image类也提供了一个封装了AdaptiveThreshold方法的ThresholdAdaptive方法,下面的代码中使用的几位Image类的ThresholdAdaptive方法:
private void Form1_Load(object sender, EventArgs e)
{
var grayImage = new Image<Gray, Byte>(Properties.Resources.chess3);
//CvInvoke.AdaptiveThreshold(grayImage, threshImage, 255, AdaptiveThresholdType.GaussianC, ThresholdType.BinaryInv, 12, 5);
var threshImage = grayImage.ThresholdAdaptive(
new Gray(),
AdaptiveThresholdType.MeanC,
ThresholdType.Binary,
,
new Gray()); imageBox1.Image = grayImage;
imageBox2.Image = threshImage;
}
执行效果为:MeanC -> GaussianC
Otsu二值化
在全局阈值的代码中,我们使用150作为二进制阈值化的阀值,但是这个阀值是我随意选择的,我并不确定这个阀值是否是合适的阈值。而如果使用Otsu二值化方法,它可以根据
图像的直方图计算出一个阀值。使用Otsu方法用到的是全局阈值提到过的Threshold方法,只是在传入的ThresholdType值为Otsu,代码如下:
var grayImage = new Image<Gray, Byte>(Properties.Resources.chess3);
var threshImage = grayImage.CopyBlank();
CvInvoke.Threshold(
grayImage,
threshImage,
,
,
ThresholdType.Otsu); imageBox1.Image = grayImage;
imageBox2.Image = threshImage;
运行效果:
【转】Emgu 图像阈值的更多相关文章
- opencv学习之路(13)、图像阈值化threshold
一.图像阈值化简介 二.固定阈值 三.自适应阈值 #include<opencv2/opencv.hpp> using namespace cv; void main(){ Mat src ...
- [python-opencv]图像二值化【图像阈值】
图像二值化[图像阈值]简介: 如果灰度图像的像素值大于阈值,则为其分配一个值(可以是白色255),否则为其分配另一个值(可以是黑色0) 图像二值化就是将灰度图像上的像素值设置为0或255,也就是将整个 ...
- Emgu学习之(四)——图像阈值
http://www.cnblogs.com/CoverCat/p/5043833.html Visual Studio Community 2015 工程和代码:http://pan.baidu.c ...
- opencv2函数学习之threshold:实现图像阈值化
在opencv2中,threshold函数可以进行阈值化操作. double threshold( const Mat& src, Mat& dst, double thresh,do ...
- 图像阈值化-threshold、adaptivethreshold
在图像处理中阈值化操作,从一副图像中利用阈值分割出我们需要的物体部分(当然这里的物体可以是一部分或者整体).这样的图像分割方法是基于图像中物体与背景之间的灰度差异,而且此分割属于像素级的分割.open ...
- opencv之图像阈值化处理
一.函数简介 1.threshold-图像简单阈值化处理 函数原型:threshold(src, thresh, maxval, type, dst=None) src:图像矩阵 thresh:阈值 ...
- opencv图像阈值操作
使用threshold方法和adaptivethreshold方法对图像进行阈值分割操作. 1.使用threshold方法,设置一个阈值,将大于阈值的值变换为最大值,小于阈值的值变换为0. #-*- ...
- OpenCV学习笔记(7)——图像阈值
简单阈值,自适应阈值,Otsu's二值化等 1.简单阈值 当像素值高于阈值时,我们给这个像素赋予一个新值,否则给他赋予另一个值.这个函数就是cv2.threshhold().这个函数的第一个参数就是原 ...
- 读《Adaptive Thresholding Using the Integral Image》自适应图像阈值
图像的二值化问题总是一个问题.虽然使用深度学习的方法取得了不小的进展,但是传统的方法还是值得借鉴. 刚好随机游走到这篇文章 挖个07年的坟 地址:http://people.scs.carleton ...
随机推荐
- 数据库内连接GROUP BY查询外键表数据行的总数
最近看了看SQL,刚好遇到这个问题. INNER JOIN [外键表] ON [主键表] 内链接,用 GROUP BY 分组外键数据,COUNT(*)计算该外键数据总行数,最后用 ORDER BY 排 ...
- NLog基础配置
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nl ...
- c# 对html字符串进行编码
/// <summary> /// 对html字符串进行编码 /// </summary> /// <param name="html">htm ...
- c#:HttpClient加标头
using (var client = new HttpClient()) { string requestUrl = string.Format("{0}{1}", ConstD ...
- 如何使tinymce编辑器的高度随内容自变化(转载)
如何使tinymce编辑器的高度随内容自变化 最简单的方法就是在配置时添加Autoresize插件: tinymce.init({ selector: "textarea", // ...
- HDFS的副本存放策略(全)
HDFS的副本存放策略 HDFS作为Hadoop中的一个分布式文件系统,而且是专门为它的MapReduce设计,所以HDFS除了必须满足自己作为分布式文件系统的高可靠性外,还必须为MapReduc ...
- VB.Net DataSet 填充資料庫內容
'導入命名空間Imports System.Data.OleDb '定義變量 Dim ds As DataSet = New DataSet() Dim i, cn As Integer Dim Sq ...
- (白话理解)CAS机制
(白话理解)CAS机制 通过一段对话我们来了解cas用意 示例程序:启动两个线程,每个线程中让静态变量count循环累加100次. 最终输出的count结果是什么呢?一定会是200吗? 加了同步锁之后 ...
- 2018-02-06 编程猫IDE体验:对Scratch的改进
前两天偶遇编程猫推介(为什么没有中文的编程?), 第一眼感觉像Scratch, 求证之下确实, 并且据说有改良. 今天非常粗浅地尝试一下, 限于水平没有做出很炫的效果, 不过颇有些发现. 首先上最终效 ...
- JavaScript异步和单线程
一,同步和异步的区别: 同步会阻塞代码执行,而异步不会.(比如alert是同步,setTimeout是异步) 二,前端使用异步的场景: 1,定时任务:setTimeout,setInterval 2, ...