以下是要处理的图片:
首先第一步运用中值滤波及膨胀腐蚀处理得到图片如下:
仔细看看已经有一些黑点木有啦,那个大黑点应该已经不影响后面进行了
下面进行去背景光的操作,第一幅图为差分法,第二幅为除法
这里我们已经看到胶棒白色部分也被去除了,没办法,白色反射所有色光嘛。所以分割前可以先将白色部分通过系列操作改成别的颜色好些,这里就不做啦。
下面进行阀值化操作得到下图:
下面要开始对阀值化操作后的图片进行连通域操作了,得到下图:
还是袋子上白色的部分在去光的时候一并去除了,导致连通域多了好多内部的。还是建议去光之前将白色转色好些,最后就是画出轮廓啦。
下面给出代码:
include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
Mat calculateLightPattern(Mat img);
Mat quguang(Mat img,Mat pattern);
Mat quguangchufa(Mat img,Mat pattern);
void ConnectedComponentsStats(Mat img);
static Scalar randomColor( RNG& rng )
{
int icolor = (unsigned) rng;
return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}
int main(int agrc,char**agrv)
{
Mat srcImage=imread("1.jpg");
medianBlur(srcImage,srcImage,3);
Mat element=getStructuringElement(MORPH_ELLIPSE,Size(7,7));
dilate(srcImage,srcImage,element);
erode(srcImage,srcImage,element);
Mat pattern;
Mat result1,result2;
Mat img_thr;
pattern=calculateLightPattern(srcImage);
result1=quguang(srcImage,pattern);
result2=quguangchufa(srcImage,pattern);
//imshow("result",result2);
//imshow("result1",result1);
//imshow("srcImage",srcImage);
threshold(result1,img_thr,40,255,THRESH_BINARY); //阀值来处理
cvtColor(img_thr,img_thr,CV_RGB2GRAY);//因为
ConnectedComponentsStats(img_thr);
//Mat img1;
//img_thr.convertTo(img1,CV_8SC1);
//imshow("img_",img_thr);
//ConnectedComponents(img1);
waitKey(0);
}
Mat calculateLightPattern(Mat img)
{
Mat pattern;
blur(img,pattern,Size(img.cols/2,img.rows/2));//将原图大核模糊可近似作为光图近似值
return pattern;
}
Mat quguang(Mat img,Mat pattern)
{
Mat result;
result=pattern-img;
return result;
}
Mat quguangchufa(Mat img,Mat pattern)
{
Mat img32,pattern32;
img.convertTo(img32,CV_32F);
pattern.convertTo(pattern32,CV_32F);
Mat result;
result=1-(img32/pattern32);
result=result*255;
result.convertTo(result,CV_8UC1);
return result;
}
void ConnectedComponentsStats(Mat img)
{
//连通区域统计信息的三个量
Mat labels,stats,centroids;
int num_objects=connectedComponentsWithStats(img,labels,stats,centroids);
//检查检测到连通域的数目
if(num_objects<2)//1的时候应该是只有背景(个人理解)
{
cout<<"No object detected"<<endl;
return;
}
else
{
cout<<"Number of objects detected:"<<num_objects-1<<endl;
}
Mat output=Mat::zeros(img.rows,img.cols,CV_8UC3);
RNG rng(0xFFFFFFFF);//RNG为随机数生成器类
for(int i=1;i<num_objects;i++)
{
cout<<"Object"<<i<<"with pos:"<<centroids.at<Point2d>(i)<<"with area"<<stats.at<int>(i,CC_STAT_AREA)<<endl;//A
Mat mask=(labels==i);
output.setTo(randomColor(rng),mask);
//使用区域绘制文本
stringstream ss;//添加统计区域信息
ss<<"area:"<<stats.at<int>(i,CC_STAT_AREA);
putText(output,ss.str(),centroids.at<Point2d>(i),FONT_HERSHEY_SIMPLEX,0.4,Scalar(255,255,255));
//在output上描述信息(这里利用了putText函数)
}
imshow("result",output);
}