去年的时候做了个工地扬尘的项目,起步的时候是先做了识别一张图里的扬尘的工作,用的算法不麻烦,主要是分水岭的算法,两篇博文把分水岭讲的太好了,分享给大家
http://www.cnblogs.com/mikewolf2002/p/3304118.html
http://blog.sciencenet.cn/blog-733228-578509.html
今年找出来了,当时还是用C写的,太跟不上时代了,毕竟opencv已经不提倡那种方式了,改了改换成C++的封装,因为当时要给师弟们看,所以注释写的已经很详细了(我自认为)。给大家提供一种思路,共同进步学习~~~
#include "stdafx.h"
#include
using namespace cv;
int main()
{
Mat g_midimage,himg,simg,vimg,tmpimage,binary_image;
Mat g_srcimage=imread("6.jpg");//读图片
cvtColor(g_srcimage,g_midimage,COLOR_BGR2HSV);//RGB转HSV
vector hsv;
//split three channels
split(g_midimage,hsv);//分离HSV三通道,分成三张图片
himg=hsv[0];
simg=hsv[1];
vimg=hsv[2];
//二值化H,S,V图像
for (int i=0;i(i,j);
if ((hvalue>0&&hvalue<30)||(hvalue>170&&hvalue<180))//当H图像像素值在0~30和170~180范围内时,得到为白色否则为黑,下面相同。
himg.at(i,j)=255;
else
himg.at(i,j)=0;
}
}
for (int i=0;i(i,j);
if ((svalue>0&&svalue<20)||(svalue>50&&svalue<100))
simg.at(i,j)=255;
else
simg.at(i,j)=0;
}
}
for (int i=0;i(i,j);
if (vvalue>170&&vvalue<220)
vimg.at(i,j)=255;
else
vimg.at(i,j)=0;
}
}
//将三通道合并,最终得到二值化图像binary_image
bitwise_and(himg,simg,tmpimage);
bitwise_and(tmpimage,vimg,binary_image);
imshow("binary",binary_image);
//腐蚀操作得到前景图片,腐蚀6次
Mat fg;
erode(binary_image,fg,Mat(),Point(-1,-1),6);
//显示前景图片
imshow("foreground",fg);
//膨胀操作,膨胀6次
Mat bg;
dilate(binary_image,bg,Mat(),Point(-1,-1),6);
//将膨胀的图片阈值化操作,得到背景图片,
threshold(bg,bg,1,128,THRESH_BINARY_INV);
//显示背景图片
imshow("background",bg);
//将前景和背景图片相加,得到掩膜图片
Mat markers(binary_image.size(),CV_8U,Scalar(0));
markers=fg+bg;
imshow("markers",markers);
//分水岭函数的掩膜必须是32位的,故将八位图片转化成32位图片,进行分水岭操作,结果存在markers中
markers.convertTo(markers,CV_32S);
watershed(g_srcimage,markers);
//将得到的markers图片转化成八位图片
Mat tmp;
markers.convertTo(tmp,CV_8U);
//像素统计,逐行统计,计算白色区域的像素和
double pixekcount=0.,blackcount=0.;
for (int i=0;i(i,j);
if(gvalue==255)
blackcount++;
}
}
//计算白色区域的比例
double scale_img;
scale_img=blackcount/pixekcount;
//大于0.05则在图上打上有问题的标签
if(scale_img>0.05)
{
putText(tmp,"have question",Point(0,10),3,0.3,Scalar(255,0,0));//打印函数
imshow("segment",tmp);//显示有问题的图片,按计划这里应该是传图片或者存图片
printf( "1!!!");//发送有问题信号,我是打印出来方便观察的
}
else
printf( "0");//没有问题信号
imshow("segment",tmp);//显示最终的图片
waitKey(0);
return 0;
}
下图是识别的结果,还比较理想,我们试了很多个图,多数情况能比较好的搞定问题。