例子代码:
#include<opencv2/opencv.hpp>
#include<iostream>
usingnamespacestd;
usingnamespacecv;
MatsrcImg,maskImg,cannyOutImg;
PointprevPt(-1,-1);
//鼠标回调函数
staticvoidMouse(intevent,intx,inty,intflags,void*);
staticvoidShowHelpText();//提升用户操作函数
voidtest(){
srcImg=imread("home.jpg");
if(srcImg.empty())
{
cout<<"couldnotloadimage...\n"<<endl;
}
//namedWindow("Originalimage",CV_WINDOW_NORMAL);
imshow("WindowOne",srcImg);
MatsrcImg2,grayImg;
srcImg.copyTo(srcImg2);
cvtColor(srcImg,maskImg,COLOR_BGR2GRAY);
cvtColor(maskImg,grayImg,COLOR_GRAY2BGR);
maskImg=Scalar::all(0);
setMouseCallback("WindowOne",Mouse,0);//鼠标回调函数
//轮询按键,进行处理
while(true)
{
intc=waitKey(0);
//按键值为ESC,退出
if((char)c==27)
break;
//按键值为2,回复源图像
if((char)c=='2')
{
maskImg=Scalar::all(0);
srcImg2.copyTo(srcImg);
imshow("image",srcImg);
}
//按键值为1或者空格,则进行处理
if((char)c=='1'||(char)c=='')
{
//定义一些参数
inti,j,compCount=0;
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
//寻找轮廓
findContours(maskImg,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE);
//轮廓为空时的处理
if(contours.empty())
continue;
//复制掩膜
MatmaskImg2(maskImg.size(),CV_32S);
maskImg2=Scalar::all(0);
//循环绘制出轮廓
for(inti=0;i>=0;i=hierarchy[i][0],compCount )
drawContours(maskImg2,contours,i,Scalar::all(compCount 1),-1,8,hierarchy,INT_MAX);
//compCount为零时的处理
if(compCount==0)
continue;
//生成随机颜色
vector<Vec3b>colorTab;
for(intj=0;j<compCount;j )
{
intb=theRNG().uniform(0,255);
intg=theRNG().uniform(0,255);
intr=theRNG().uniform(0,255);
colorTab.push_back(Vec3b((uchar)b,(uchar)g,(uchar)r));
}
//计算处理的时间
doubledTime=(double)getTickCount();
watershed(srcImg2,maskImg2);
dTime=(double)getTickCount()-dTime;
cout<<"\t处理时间为:"<<dTime*1000./getTickFrequency();
//双层循坏,将分水岭图像遍历存入watershedImg中
MatwatershedImg(maskImg2.size(),CV_8UC3);
for(inti=0;i<maskImg2.rows;i )
for(intj=0;j<maskImg2.cols;j )
{
intindex=maskImg2.at<int>(i,j);
if(index==-1)
watershedImg.at<Vec3b>(i,j)=Vec3b(255,255,255);
elseif(index<=0||index>compCount)
watershedImg.at<Vec3b>(i,j)=Vec3b(0,0,0);
else
watershedImg.at<Vec3b>(i,j)=colorTab[index-1];
}
//混合灰度图像和分水岭效果图并显示最终的窗口
watershedImg=watershedImg*0.5 grayImg*0.5;
imshow("watershedtransform",watershedImg);
}
}
}
staticvoidMouse(intevent,intx,inty,intflags,void*){
//处理鼠标不在窗口中的情况
if(x<0||x>=srcImg.cols||y<0||y>=srcImg.rows)
return;
//处理鼠标左键相关消息
if(event==EVENT_LBUTTONUP||!(flags&EVENT_FLAG_LBUTTON))
prevPt=Point(-1,-1);
//处理鼠标左键按下并移动,绘制出白色线条
elseif(event==EVENT_MOUSEMOVE&&(flags&EVENT_FLAG_LBUTTON))
{
Pointpt(x,y);
if(prevPt.x<0)
prevPt=pt;
line(maskImg,prevPt,pt,Scalar::all(255),5,8,0);
line(srcImg,prevPt,pt,Scalar::all(255),5,8,0);
prevPt=pt;
imshow("WindowOne",srcImg);
}
}
staticvoidShowHelpText(){
cout<<"请先用鼠标在图片窗口中标记出大致的区域"<<endl;
cout<<"然后再按键【1】或者【SPACE】启动算法"<<endl;
cout<<"按键【1】或者【SPACE】启动算法"<<endl;
cout<<"按键【2】-恢复原始图像"<<endl;
cout<<"按键【ESC】-退出程序"<<endl;
}
intmain(){
ShowHelpText();
test();
waitKey(0);
return0;
}
效果图: