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);