当我们用图像技术来找到图像特征的时候,其中很重要的一个步骤就是分割,不区分出来我们想要的就没有办法得到其中的参数,而这里首先介绍阈值分割,也是最基础的分割方式,一共有下面三个部分组成。本来想介绍一个函数与定义然后再跟着例子,但是感觉有点乱,然后就按现在这样来说了,当后面看到不懂的在前面的函数与定义都会提及到,希望对大家有用。
(1)、函数与定义
(2)、代码应用
- Threshold()
- adaptiveThreshold()
- ostu
(3)、matlab辅助
一、函数与定义
阈值分割是一种区域分割技术,将灰度根据主观愿望分成两个或者多个灰度区间,利用图像中背景和目标物体的灰度上的差异,旋转一个合适的阈值进行分割。
一般的分割有全局分割和局部分割,这是不同的思路,在Opencv中给出了threshold(),adapativeThreshold(),这两个函数中的tpye会给出很多的方法
<span style="font-size:18px;">double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)</span>
参数信息:
- 第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。
- 第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。
- 第三个参数,double类型的thresh,阈值的具体值。
- 第四个参数,double类型的maxval,当第五个参数阈值类型type取 THRESH_BINARY 或THRESH_BINARY_INV阈值类型时的最大值.
- 第五个参数,int类型的type,阈值类型,。
第五个参数,第五参数有以下几种类型
- 0: THRESH_BINARY 当前点值大于阈值时,取Maxval,也就是第四个参数,下面再不说明,否则设置为0
- 1: THRESH_BINARY_INV 当前点值大于阈值时,设置为0,否则设置为Maxval
- 2: THRESH_TRUNC 当前点值大于阈值时,设置为阈值,否则不改变
- 3: THRESH_TOZERO 当前点值大于阈值时,不改变,否则设置为0
- 4: THRESH_TOZERO_INV 当前点值大于阈值时,设置为0,否则不改变
源代码中的定义
<span style="font-size:18px;">enum
{
CV_THRESH_BINARY =0, /* value = value > threshold ? max_value : 0 */
CV_THRESH_BINARY_INV =1, /* value = value > threshold ? 0 : max_value */
CV_THRESH_TRUNC =2, /* value = value > threshold ? threshold : value */
CV_THRESH_TOZERO =3, /* value = value > threshold ? value : 0 */
CV_THRESH_TOZERO_INV =4, /* value = value > threshold ? 0 : value */
CV_THRESH_MASK =7,
CV_THRESH_OTSU =8 /* use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values */
};</span>
<span style="font-size:18px;">void cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,
int threshold_type=CV_THRESH_BINARY,
int block_size=3, double param1=5 );</span>
-
src 输入图像.
dst 输出图像.
max_value使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
adaptive_method自适应阈值算法使用:CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C (见讨论).
threshold_type
- 取阈值类型:必须是下者之一
- CV_THRESH_BINARY,
- CV_THRESH_BINARY_INV
- 取阈值类型:必须是下者之一
- block_size用来计算阈值的象素邻域大小: 3, 5, 7, ... param1与方法有关的参数。对方法 CV_ADAPTIVE_THRESH_MEAN_C 和 CV_ADAPTIVE_THRESH_GAUSSIAN_C, 它是一个从均值或加权均值提取的常数(见讨论), 尽管它可以是负数。
二、代码应用
(1)
- Threshold()
<span style="font-size:18px;">#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Mat dst,gray,bluriamge;
int thresh,thresh1;
void on_thresh(int,void*)
{
threshold(bluriamge,dst,thresh,255,thresh1);
imshow("threshold二值化灰图",dst);
}
int main()
{
Mat src;
src=imread("lena.jpg");
cvtColor( src, gray, CV_BGR2GRAY );
blur( gray, bluriamge, Size(3,3) );
imshow("threshold二值化灰图",src);
namedWindow("threshold二值化灰图");
createTrackbar("阈值:","threshold二值化灰图",&thresh,255,on_thresh);
createTrackbar("type:","threshold二值化灰图",&thresh1,4,on_thresh);
on_thresh(0,0);
waitKey(0);
return 0;
}</span>
(2)adaptiveThreshold

<span style="font-size:18px;">#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
#include <iostream>
int main(int argc, char** argv)
{
cv::Mat image = cv::imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (image.empty())
{
std::cout<<"read image failure"<<std::endl;
return -1;
}
int th = 100;
cv::Mat global;
cv::threshold(image, global, th, 255, CV_THRESH_BINARY_INV);
int blockSize = 25;
int constValue = 10;
cv::Mat local;
cv::adaptiveThreshold(image, local, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, blockSize, constValue);
cv::imshow("globalThreshold", global);
cv::imshow("localThreshold", local);
cv::waitKey(0);
return 0;
}</span>
(3)OSTU关于他是什么回事,想看理论的可以到我以前的写一篇文章中,很清晰明了
http://blog.youkuaiyun.com/qq_20823641/article/details/51480651
<span style="font-size:18px;">#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
#include <iostream>
int piexlSum;
int thresh;
float w1,u1,w2,u2,g,gmax;
int main(int argc, uchar* argv[])
{
vector<int> hist(256);
Mat img=imread("lena.jpg",0);
Mat dst1;
for(auto it=img.begin<uchar>();it!=img.end<uchar>();++it)
hist[*it]++;
piexlSum=img.cols*img.rows;
for(int i=0;i!=hist.size();i++)
{
w1=w2=u1=u2=0;
for(int j=0;j!=hist.size();j++)
{
float k=(float)hist[j]/piexlSum;
if(j<=i)
{
w1+=k;
u1+=j*k ;
}
else
{
w2+=k;
u2+=j*k;
}
}
g=w1*w2*(u1-u2)*(u1-u2);
if(g>gmax)
{
gmax=g;
thresh=i;
}
}
threshold(img,dst1,thresh,255,CV_THRESH_OTSU);
imshow("otsu1",dst1);
waitKey(0);
return 0;
} </span>
三、Matlab辅助
I=imread('d:\lena.jpg');
I=rgb2gray(I);
figure
subplot(1,2,1)
imshow(I);
title('原图')
[width,height]=size(I);
level=graythresh(I);
BW=im2bw(I,level);
subplot(1,2,2)
imshow(BW);
title('otsu算法阈值分割效果图');
图像识别算法交流 QQ群:145076161,欢迎图像识别与图像算法,共同学习与交流