灰度图像大多通过算子寻找边缘和区域生长融合来分割图像。
彩色图像增加了色彩信息,可以通过不同的色彩值来分割图像,常用彩色空间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