颜色识别作为电赛中图像处理方面最常用的算法,应用非常广泛。
处理的流程:预处理 ->滤波-> 二值化 -> (膨胀-> )腐蚀 -> 寻找轮廓
一、预处理
将摄像头获取的图像从RGB空间转换到HSV空间。
二、滤波
这里我采用的是均值滤波。均值滤波是最快的滤波,可以根据图像直观上的效果调整内核大小。
三、二值化
这一步重要的是根据环境选取合适的阈值,要同时考虑目标和背景。
整定阈值可以通过再写一个滑动条调节程序来实现。
四、膨胀和腐蚀
二值化后的图像效果很好,目标在图片中很明确,则可以考虑只使用腐蚀。
腐蚀主要是消除二值化后的杂点,
五、找出最大轮廓
先用Canny算子检测出边缘轮廓,再使用findContours()函数检测轮廓,最后再找出最大轮廓。
附代码:
class color
{
private:
Point centre;
Mat grayimage;
Mat out_image;
Rect r;
public:
void color_recognite(Mat image,Scalar High,Scalar Low);
Point show_centre();
void show_grayimage(char* WINDOWNAME);
void show_image(char* WINDOWNAME);
};
void color:: color_recognite(Mat image, Scalar Low,Scalar High)
{
Mat input_image;
image.copyTo(input_image);
vector<vector<Point>> g_vContours;
vector<Vec4i> g_vHierarchy;
double maxarea = 0;
int maxAreaIdx = 0;
Mat g_grayImage,hsv,g_cannyMat_output;
cvtColor(input_image, hsv, COLOR_BGR2HSV);
blur(hsv, hsv, Size(5,5));
inRange(hsv, Low,High, g_grayImage);//二值化识别颜色
//腐蚀操作
Mat element = getStructuringElement(MORPH_RECT, Size(4, 4));
erode(g_grayImage, g_grayImage, element);
// 寻找轮廓
findContours(g_grayImage, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
//假设contours是用findContours函数所得出的边缘点集
RotatedRect box;
if(g_vContours.size()!=0)
{
maxarea=0;
for (int index =0; index< g_vContours.size(); index++)
{
double tmparea = fabs(contourArea(g_vContours[index]));
if (tmparea>maxarea)
{
maxarea = tmparea;
maxAreaIdx = index;//记录最大轮廓的索引号
}
}
for (int index =0; index< g_vContours.size(); index++)
{
if((fabs)(contourArea(g_vContours[index]))== maxarea)
{
r = boundingRect(g_vContours[index]);
centre.x = r.x + r.width/2;
centre.y = (r.y+r.height/2);
}
}
}
// cout<<g_vContours.size()<<endl;
rectangle(input_image, r, Scalar(0, 255, 0));
circle(input_image, centre, 2, Scalar(255,0,0),2);
grayimage=g_grayImage;
out_image=input_image;
}
这里我是定义了一个color类,便于调用
有不正确、不严谨的地方,恳请指正。