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

opencv之分水岭实现图像分割

2013-04-30 22:40 337 查看
本文需要了解的库函数有:

void cvWatershed( const CvArr* image, CvArr* markers );//分水岭算法分割图像
void  cvAddWeighted( const CvArr* src1, double alpha,
const CvArr* src2, double beta,
double gamma, CvArr* dst );//计算两个数组的加权值的和


代码演示:

#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cvaux.lib")
#pragma comment(lib,"highgui.lib")
#pragma comment(lib,"cxcore.lib")
#include<cv.h>
#include<highgui.h>
#include<stdio.h>
#include<math.h>

IplImage	*image=NULL;
IplImage	*gray=NULL;//灰度图像
IplImage	*img0=NULL;
IplImage	*mask=NULL;
IplImage	*maskers=NULL;//标记轮廓线的图像
IplImage	*wated=NULL;//分水岭分割后的图像
CvPoint prev_pt;

void on_mouse( int event, int x, int y, int flags, void* param )
{
if( !image )
return;

if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
prev_pt = cvPoint(-1,-1);
else if( event == CV_EVENT_LBUTTONDOWN )
prev_pt = cvPoint(x,y);
else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )
{
CvPoint pt = cvPoint(x,y);
if( prev_pt.x < 0 )
prev_pt = pt;
cvLine( mask, prev_pt, pt, cvScalarAll(255), 5, 8, 0 );
cvLine( image, prev_pt, pt, cvScalarAll(255), 5, 8, 0 );
prev_pt = pt;
cvShowImage( "image", image );
}
}

int main()
{
CvRNG rng = cvRNG(-1);
image = cvLoadImage("fruits.jpg",1);	//加载图像

img0 = cvCloneImage(image);	//拷贝图像
mask = cvCreateImage(cvGetSize(image),8,1);//掩码图像
maskers = cvCreateImage(cvGetSize(image),IPL_DEPTH_32S,1);//标记轮廓线的图像
wated  = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,3);//分水岭分割后的图像
gray = cvCreateImage(cvGetSize(image),8,3);//彩色灰度图像
//生成灰度彩色图像
cvCvtColor(image,mask,CV_BGR2GRAY);
cvCvtColor(mask,gray,CV_GRAY2BGR);

cvZero(mask);//清空
cvNamedWindow("image",1);
cvShowImage( "image", image );
cvNamedWindow("分水岭分割",1);
cvSetMouseCallback( "image", on_mouse, 0 );
CvMemStorage* storage = cvCreateMemStorage(0);

for(;;)
{
char c =cvWaitKey(0);
if(c=='\r')
{
cvClearMemStorage(storage);//清空
//查找轮廓
CvSeq* seq =NULL;
cvFindContours( mask, storage, &seq, sizeof(CvContour),
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

cvZero(maskers);//清空
int count = 0;//计数器

for(;seq!=NULL;seq=seq->h_next,count++)
{
cvDrawContours(maskers,seq,cvScalarAll(count+1),cvScalarAll(count+1),-1,-1,8,cvPoint(0,0));//绘制到标记图像上
}

//产生随机颜色
CvMat* color_tab = cvCreateMat( 1, count, CV_8UC3 );
for(int j = 0; j < count; j++ )
{
uchar* ptr = color_tab->data.ptr + j*3;
ptr[0] = (uchar)(cvRandInt(&rng)%180 + 50);
ptr[1] = (uchar)(cvRandInt(&rng)%180 + 50);
ptr[2] = (uchar)(cvRandInt(&rng)%180 + 50);
}

//运动分水岭分割算法
cvWatershed(img0,maskers);
//显示算法后的分割图像
for(int  i = 0; i < maskers->height; i++ )
for(int  j = 0; j < maskers->width; j++ )
{
int idx = CV_IMAGE_ELEM( maskers, int, i, j );
uchar* dst = &CV_IMAGE_ELEM( wated, uchar, i, j*3 );
if( idx == -1 )
dst[0] = dst[1] = dst[2] = (uchar)255;
else if( idx <= 0 || idx > count )
dst[0] = dst[1] = dst[2] = (uchar)0; // should not get here
else
{
//	dst[0] = 255; dst[1] = 0; dst[2] =0; //填充颜色
uchar* ptr = color_tab->data.ptr + (idx-1)*3;
dst[0] = ptr[0]; dst[1] = ptr[1]; dst[2] = ptr[2];
}
}
cvAddWeighted(gray,0.5,wated,0.5,0,wated);
cvShowImage( "分水岭分割", wated );
cvReleaseMat( &color_tab );
}
}

cvDestroyWindow("image");
cvDestroyWindow("分水岭分割");
cvReleaseMemStorage(&storage);
cvReleaseImage(&image);
cvReleaseImage(&img0);
cvReleaseImage(&mask);
cvReleaseImage(&gray);
cvReleaseImage(&maskers);
cvReleaseImage(&wated);
return 0;
}




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: