opencv之分水嶺實現影象分割
阿新 • • 發佈:2019-01-30
本文需要了解的庫函式有:
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; }