1. 程式人生 > 其它 >OpenCV使用分水嶺演算法實現影象分割

OpenCV使用分水嶺演算法實現影象分割

一、概述

  案例:使用分水嶺演算法實現影象的分割實現

  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:分割蠶繭

 

案例二:分割任意影象