OPENCV 圖像分割 前置動作 流程(SOP) 整理

OPENCV 圖像分割 前置動作 流程(SOP) 整理

OPENCV 圖像分割 前置動作 流程(SOP) 整理


GITHUB: https://github.com/jash-git/CPP_opencv249_ex [ opencv_ex33 ]


01.彩色圖像邊緣銳化(加強)

    ◎把彩色圖的背景由白色變黑
    ◎用filter2D函數對彩色圖片做二階拉式濾波 [PS要把格式從CV_8UC3 設定(轉換)成 CV_32F]
    ◎將原彩色圖像和二階拉式濾波相減 [PS要把原圖格式從CV_8UC3 設定(轉換)成 CV_32F]
    ◎上述相減結果即是答案 [PS要把圖像格式從CV_32F 設定(轉換)成 CV_8UC3]

02.彩色圖像求二值化

    //---
    //彩色轉灰階+二值化
    Mat binaryImg;
    cvtColor(src, resultImg, CV_BGR2GRAY);
    threshold(resultImg, binaryImg, 40, 255, THRESH_BINARY | THRESH_OTSU);//40閥值,要額外做實驗取得,所以環境很重要,實務上要用定光源
    imshow("binary image", binaryImg);
    //---彩色轉灰階+二值化

03.計算輪廓距離+數據正規化+第二次的二值化 [只留下距離邊緣最遠的點]

    /*
    Distance Transform 經常應用在二值影像,其運算結果則為一灰階影像,

    其強度並非表示亮度值,而是表示物件內部每一點與物件邊緣的距離。

    如果以 1 表示物件像素,0 是背景像素,則 distance transform 定義為

    對於每一個物件區域的像素,計算其與最近的背景像素的距離,並以此距離值取代原像素值。 
 
    輪廓距離
    void distanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize)
        src:輸入圖,8位元單通道(通常為二值化圖)。
        dst:輸出圖,32位元單通道浮點數圖,和src的尺寸相同。
        distanceType:距離型態,可以選擇CV_DIST_L1、CV_DIST_L2或CV_DIST_C。
        maskSize:遮罩尺寸,可以選3、5或CV_DIST_MASK_PRECISE,當 distanceType為CV_DIST_L1或CV_DIST_C,這個參數限制為3(因為3和5的結果相同)。
    */
    distanceTransform(binaryImg, distImg, CV_DIST_L2, 3);
    normalize(distImg, distImg, 0, 1, NORM_MINMAX);
    imshow("distance result", distImg);

    threshold(distImg, distImg, .4, 1, THRESH_BINARY);//只留下距離邊緣最遠的點
    imshow("distance binary image", distImg);


04.使用侵蝕演算法去除過小雜點

    Mat k1 = Mat::ones(13, 13, CV_8UC1);
    /*
    侵蝕
    erode(const Mat &src, Mat &dst, Mat kernel, Point anchor=Point(-1,-1), int iterations=1)
        src:輸入圖,可以多通道,深度可為CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
        dst:輸出圖,和輸入圖尺寸、型態相同。
        kernel:結構元素,如果kernel=Mat()則為預設的3×3矩形,越大侵蝕效果越明顯。
        anchor:原點位置,預設為結構元素的中央。
        iterations:執行次數,預設為1次,執行越多次侵蝕效果越明顯。
    */
    erode(distImg, distImg, k1, Point(-1, -1));
    imshow("distance binary_erode image", distImg); 


05.透過找邊緣函數標記所有[距離邊緣最遠的點]的座標位置

    Mat dist_8u;
    distImg.convertTo(dist_8u, CV_8U);
    vector< vector<Point> > contours;
    findContours(dist_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); 

06.最後利用分水嶺API分割出每一塊圖片位置

    /*
    OpenCV分水嶺
    void watershed(InputArray image, InputOutputArray markers)
        image:輸入圖,8位元3通道圖。
        markers:輸入輸出標記圖,32位元單通道圖,尺寸必須和image相同。
    */
    watershed(src, markers);
    Mat mark = Mat::zeros(markers.size(), CV_8UC1); 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *