OpenCV使用分水嶺演算法實現影象分割
阿新 • • 發佈:2022-04-12
一、概述
案例:使用分水嶺演算法實現影象的分割實現
API:介紹參考上一遍
實現步驟:
1.輸入影象
2.灰度化
3.二值化
4.執行距離變換
5.歸一化
6.二值化
7.生成marker:通過findContours+drawContours來建立一個marker
8.將7生成的marker放入分水嶺函式:watershed
9.給marker著色
10.輸出著色後的影象
ps:此演算法關鍵點在於生成marker。生成marker之後其實已經完成了演算法,後面的著色只是為了讓輸出更加好看。
二、程式碼樣例
Mat src = imread(filePath);//輸入原圖 if(src.empty()){ // qDebug()<<"影象為空"; return; } //影象灰度化 Mat gray; cvtColor(src,gray,COLOR_BGR2GRAY); //影象二值化 Mat binary; threshold(gray,binary,0,255,THRESH_BINARY|cv::THRESH_OTSU); imshow("binary",binary); qDebug()<<"binary...."; //執行距離變換 Mat dist; distanceTransform(binary,dist,DistanceTypes::DIST_L2,3,CV_32F); qDebug()<<"distanceTransform...."; normalize(dist,dist,0.0,1.0,NORM_MINMAX);//歸一化0~1之間 qDebug()<<"normalize...."; //重新二值化預值 threshold(dist,dist,0.1,1.0,THRESH_BINARY); qDebug()<<"threshold...."; normalize(dist,dist,0,255,NORM_MINMAX); qDebug()<<"normalize...."; dist.convertTo(dist,CV_8UC1);// qDebug()<<"convertTo...."; //開始生成marker並繪製出來 vector<vector<Point>> contours; vector<Vec4i> heri; findContours(dist,contours,RETR_CCOMP,CHAIN_APPROX_SIMPLE); qDebug()<<"findContours...."; Mat marker = Mat::zeros(dist.size(),CV_32S); for(size_t i = 0;i<contours.size();i++){ drawContours(marker,contours,i,Scalar(i+1),-1, 8, heri, INT_MAX); } qDebug()<<"drawContours...."<<contours.size(); circle(marker, Point(5, 5), 3, Scalar(255), -1); watershed(src,marker); qDebug()<<"watershed...."; // marker.convertTo(marker,CV_8UC1);//ps:此處需要注意(到這裡實際上已經完成了演算法)。一旦不轉換就不能用imshow,一旦轉換了後面的marker著色就會出現異常 // imshow("marker",marker); qDebug()<<"imshow(marker,marker);...."; //生成顏色陣列 vector<Vec3b> colors; for (size_t i = 0; i < contours.size(); i++) { int r = theRNG().uniform(0, 255); int g = theRNG().uniform(0, 255); int b = theRNG().uniform(0, 255); colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r)); } //給marker著色 Mat finalResult = Mat::zeros(dist.size(),CV_8UC3);//三通道彩色影象 int index = 0; for(int row = 0;row<marker.rows;row++){ for(int col = 0;col<marker.cols;col++){ index = marker.at<int>(row,col); if(index>0&&index<=contours.size()){ finalResult.at<Vec3b>(row,col) = colors[index-1]; }else{ finalResult.at<Vec3b>(row,col) = Vec3b(255,255,255); } } } imshow("finalResult",finalResult);
三、圖片演示
案例1:分割蠶繭
案例二:分割任意影象