2014-07-17 77 views
1

我使用OpenCV的流域與我的形象:如何通過OpenCV流域獲取對象之間的輪廓?

#include "opencv2/opencv.hpp" 
#include <string> 

using namespace cv; 
using namespace std; 

class WatershedSegmenter{ 
private: 
    cv::Mat markers; 
public: 
    void setMarkers(cv::Mat& markerImage) 
    { 
     markerImage.convertTo(markers, CV_32S); 
    } 

    cv::Mat process(cv::Mat &image) 
    { 
     cv::watershed(image, markers); 
     markers.convertTo(markers,CV_8U); 
     return markers; 
    } 
}; 


int main(int argc, char* argv[]) 
{ 
    cv::Mat image = cv::imread("d:\\projekty\\OpenCV\\trainData\\base01.jpg"); //http://i.imgur.com/sEWFHfY.jpg 
    cv::Mat blank(image.size(),CV_8U,cv::Scalar(0xFF)); 
    cv::Mat dest; 
    imshow("originalimage", image); 

    // Create markers image 
    cv::Mat markers(image.size(),CV_8U,cv::Scalar(-1)); 
    //Rect(topleftcornerX, topleftcornerY, width, height); 
    //top rectangle 
    markers(Rect(0,0,image.cols, 5)) = Scalar::all(1); 
    //bottom rectangle 
    markers(Rect(0,image.rows-5,image.cols, 5)) = Scalar::all(1); 
    //left rectangle 
    markers(Rect(0,0,5,image.rows)) = Scalar::all(1); 
    //right rectangle 
    markers(Rect(image.cols-5,0,5,image.rows)) = Scalar::all(1); 
    //centre rectangle 
    int centreW = image.cols/4; 
    int centreH = image.rows/4; 
    markers(Rect((image.cols/2)-(centreW/2),(image.rows/2)-(centreH/2), centreW, centreH)) = Scalar::all(2); 
    markers.convertTo(markers,CV_BGR2GRAY); 
    imshow("markers", markers); 

    //Create watershed segmentation object 
    WatershedSegmenter segmenter; 
    segmenter.setMarkers(markers); 
    cv::Mat wshedMask = segmenter.process(image); 
    cv::Mat mask; 
    convertScaleAbs(wshedMask, mask, 1, 0); 
    double thresh = threshold(mask, mask, 1, 255, THRESH_BINARY); 
    bitwise_and(image, image, dest, mask); 
    dest.convertTo(dest,CV_8U); 

    imshow("final_result", dest); 
    cv::waitKey(0); 

    return 0; 
} 

但是,這給我的只有個別面膜。我也嘗試將標記創建爲兩點 - 結果只有一個掩碼。 OpenCV能否像例子http://biodynamics.ucsd.edu/ir/那樣通過輪廓分割單元格(對象)? 如果沒有,是否可以創建結果掩碼值爲:第1個對象,第2個,第99個,第99個99個?

+0

請參閱http://opencv-code.com/tutorials/count-and-segment-overlapping-objects-with-watershed-and-distance-transform/ – Borneq

+0

但這是工作的一半,不同顏色的物體,但不是輪廓 – Borneq

回答

2

執行

cv::watershed(image, markers);

markers圖像將是-1在區域的邊界,並且將1對應於被標記爲1的種子的區域中,和將2與被標記爲2的種子對應的區域,等等。所以你可以做這樣的事情:

cv::Mat region1 = markers==1; 
1

我使用以下方法提取分水嶺分割後的對象countours。分水嶺輸出是包含每個像素的分段代碼的一個標記圖像。我從標記圖像爲每個單個對象段創建一個二進制蒙版圖像。這可以在標記圖像的所有像素上的一次迭代中完成。對於核心「for循環」,請參閱opencv示例https://github.com/Itseez/opencv/blob/master/samples/cpp/watershed.cpp。我有存儲在vector <Mat>中的所有對象掩碼。然後,我在每個這樣的蒙版上運行findContours - >每個對象的輪廓。見http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html。你不需要使用邊緣檢測器Canny,因爲蒙版圖像已經是二進制的。