灰度圖像大多通過算子尋找邊緣和區域生長融合來分割圖像。
彩色圖像增加了色彩信息,可以通過不同的色彩值來分割圖像,常用彩色空間HSV/HSI, RGB, LAB等都可以用於分割!
筆者主要介紹inrange() 來划分顏色區域。先看看OpenCV的文檔:
C++: void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)
C: void cvInRangeS(const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst)
- src – first input array.
- lowerb – inclusive lower boundary array or a scalar.
- upperb – inclusive upper boundary array or a scalar.
- dst – output array of the same size as src and CV_8U type
-
For two-channel arrays:
-
and so forth.
意思主要是:
src:輸入圖像,CV2常用Mat類型;
lowerb:lower boundary下限,scalar類型的像素值,單通道scalar取一個值就行,彩圖3通道scalar三個值;
upperb:上限,類型與lowerb同理;
dst:輸出圖像,尺寸與src一致,類型是CV_8U,但沒有指定通道數。
對於多通道的輸入,輸出結果是各個通道的結果相與,當各通道結果都在上下限之內時,輸出為255,否則為0。因此也有人將輸出理解為掩碼模板!
看個例子吧:
1 int hmax = 360; 2 int hmax_Max = 360; 3 //飽和度 4 int smin = 0; 5 int smin_Max = 255; 6 int smax = 255; 7 int smax_Max = 255; 8 //亮度 9 int vmin = 106; 10 int vmin_Max = 255; 11 int vmax = 250; 12 int vmax_Max = 255; 13 //顯示原圖的窗口 14 string windowName = "src"; 15 //輸出圖像的顯示窗口 16 string dstName = "dst"; 17 //輸出圖像 18 Mat dst; 19 //回調函數 20 void callBack(int, void*) 21 { 22 //輸出圖像分配內存 23 dst = Mat::zeros(img.size(), CV_32FC3); 24 //掩碼 25 Mat mask; 26 inRange(hsv, Scalar(hmin, smin / float(smin_Max), vmin / float(vmin_Max)), Scalar(hmax, smax / float(smax_Max), vmax / float(vmax_Max)), mask); 27 //只保留 28 for (int r = 0; r < bgr.rows; r++) 29 { 30 for (int c = 0; c < bgr.cols; c++) 31 { 32 if (mask.at<uchar>(r, c) == 255) 33 { 34 dst.at<Vec3f>(r, c) = bgr.at<Vec3f>(r, c); 35 } 36 } 37 } 38 //輸出圖像 39 imshow(dstName, dst); 40 //保存圖像 41 dst.convertTo(dst, CV_8UC3, 255.0, 0); 42 imwrite("HSV_inRange.jpg", dst); 43 } 44 void test_main() 45 { 46 //輸入圖像 47 img = imread("E:\\素材圖片\\1.png",1); 48 if (!img.data || img.channels() != 3) 49 return ; 50 imshow(windowName, img); 51 //彩色圖像的灰度值歸一化 52 img.convertTo(bgr, CV_32FC3, 1.0 / 255, 0); 53 //顏色空間轉換 54 cvtColor(bgr, hsv, COLOR_BGR2HSV); 55 //定義輸出圖像的顯示窗口 56 namedWindow(dstName, WINDOW_NORMAL); 57 //調節色相 H 58 createTrackbar("hmin", dstName, &hmin, hmin_Max, callBack); 59 createTrackbar("hmax", dstName, &hmax, hmax_Max, callBack); 60 //調節飽和度 S 61 createTrackbar("smin", dstName, &smin, smin_Max, callBack); 62 createTrackbar("smax", dstName, &smax, smax_Max, callBack); 63 //調節亮度 V 64 createTrackbar("vmin", dstName, &vmin, vmin_Max, callBack); 65 createTrackbar("vmax", dstName, &vmax, vmax_Max, callBack); 66 callBack(0, 0); 67 waitKey(0); 68 return; 69 }
函數外的為全局變量,頭文件自己加上就行。
放兩張不同的圖片分割結果:
第一種是通過調節H值將紅色和綠色分割開,SV的值我選擇保持默認。(忽略結果圖右下角的輸入法。。。)
第二種調節H值並沒有什么改善,但是可以調節S飽和度,將車牌前景和背景對比的更加強烈。(忽略結果圖右下角的輸入法。。。)
更多調節策略歡迎大家評價~~
附上完整可運行代碼路徑,還是不能運行的注意 readme。 https://github.com/chenzhefan/inrange_color