OpenCV C++学习笔记(6): 颜色识别定位
在 opencv-srf 网站上, 有一个颜色检测和物体跟踪的示例. 使用inRange来检测颜色, 并且Moments类来追踪这个颜色的物体.
这个例子只能追踪一个物体, 如果有多个同样颜色的物体, 用Moments只能找到这些物体最外面的框, 把这些物体当作一个, 找到他们的中心. 但这不是我想要的. 所以只好临摹了另外一个示例, 将两个凑在一起, 达成了目的.
首先, RGB颜色, 或者说OpenCV里用的BGR颜色空间, 并不适合颜色检测, 应该先转换到HSV颜色空间, 这样只控制Hue就可以来选择颜色了.
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV);
不同颜色的数值大约是: * Orange 0-22 * Yellow 22- 38 * Green 38-75 * Blue 75-130 * Violet 130-160 * Red 160-179
然后就可以使用inRange来把边界条件之间的东西找出来. 注意边界是HSV颜色空间的坐标, 所以要用low=Scalar(H_low,S_low,V_low)和 high=Scalar(H_high,S_high,V_high)来预先定义好.
inRange(imgHSV,low,high,imgThresholded);
然后是图形学里常规操作:
- 先缩后胀, 去除小体
erode(
imgThresholded,
imgThresholded,
getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
dilate(
imgThresholded,
imgThresholded,
getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
- 先胀后缩, 去除小孔
dilate(
imgThresholded,
imgThresholded,
getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
erode(
imgThresholded,
imgThresholded,
getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
如果是跟踪一个物体, 现在屏幕上就应该只有一个亮斑了.
但我要追踪是多个同样颜色的物体. 于是还临摹了下面一段, 这是从OpenCV官网用等高线标记物体的示例中摘抄的.
这个示例用等高线把物体多个标记出来. 我觉得可用.
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
threshold( imgThresholded, threshold_output, 200, 255, THRESH_BINARY );
findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
// 找到圆心
vector<vector<Point> > contours_poly( contours.size() );
vector<Point2f>center( contours.size() );
vector<float>radius( contours.size() );
Point2f point_center=Point2f(0,0);
for( size_t i = 0; i < contours.size(); i++ ){
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
minEnclosingCircle( contours_poly[i], center[i], radius[i] );
point_center +=center[i];
}
point_center /= int(center.size());
所以先用inRange把同一颜色的物体找出来, 然后再用findContours分别找到各个物体的外圈, 用minEnclosingCircle找到每个物体的最小包围圈, 赋值给center.
由于我还想给这些center按时钟位置排个序, 所以我又找了一下这些center的平均中心点.