您的位置:首页 > 运维架构

Opencv图像识别从零到精通(15)-----阈值分割、固定阈值Threshold、自适应阈值分割adaptiveThreshold、OSTU大津法

2016-07-24 18:24 585 查看
[b] 当我们用图像技术来找到图像特征的时候,其中很重要的一个步骤就是分割,不区分出来我们想要的就没有办法得到其中的参数,而这里首先介绍阈值分割,也是最基础的分割方式,一共有下面三个部分组成。本来想介绍一个函数与定义然后再跟着例子,但是感觉有点乱,然后就按现在这样来说了,当后面看到不懂的在前面的函数与定义都会提及到,希望对大家有用。

[/b]

(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关于他是什么回事,想看理论的可以到我以前的写一篇文章中,很清晰明了/article/7603901.html
<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,欢迎图像识别与图像算法,共同学习与交流
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: