冰壶轨迹记录仪(视觉组)——OpenCV颜色识别的应用(二)

冰壶轨迹记录仪(视觉组)——OpenCV颜色识别的应用(二),第1张

冰壶轨迹记录仪(视觉组)——OpenCV颜色识别的应用(二)

索引目录
  • 四、技术积累
    • 4.1 提取图片不同区域HSV特征值
    • 4.2 找到颜色区域并画出轮廓、中心点
    • 4.3 根据坐标计算距离和角度

四、技术积累 4.1 提取图片不同区域HSV特征值

将图片读取进来,并转为HSV格式。

img = imread(path);
cvtColor(img, imgHSV, COLOR_BGR2HSV);

创建追踪栏寻找特定区域的HSV特征值。

namedWindow("Trackbars", (640, 200)); // Create Window
createTrackbar("Hue Min", "Trackbars", &hmin, 179);
createTrackbar("Hue Max", "Trackbars", &hmax, 179);
createTrackbar("Sat Min", "Trackbars", &smin, 255);
createTrackbar("Sat Max", "Trackbars", &smax, 255);
createTrackbar("Val Min", "Trackbars", &vmin, 255);
createTrackbar("Val Max", "Trackbars", &vmax, 255);

拖动追踪栏的HSV特征值创建遮罩层,并同图片一起显示,直至找到完美匹配的特征值。

Scalar lower(hmin, smin, vmin);
Scalar upper(hmax, smax, vmax);
inRange(imgHSV, lower, upper, mask);
imshow("Image", img);
imshow("Mask", mask);
4.2 找到颜色区域并画出轮廓中心点

利用findContours函数找到所有符合的轮廓,contours里存有识别到的所有轮廓点。(这里的image为此前找到的遮罩层图像)

vector> contours;
vector hierarchy;
findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

计算轮廓的周长。

float peri = arcLength(contours[i], true);

拟合曲线使轮廓为多边形,输出点集与输入点集的最大间距为0.02倍的周长。

vector> conPoly(contours.size());
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);

使用boundingRect函数返回包含输入点集的最小矩形。

vector boundRect(contours.size());
boundRect[i] = boundingRect(conPoly[i]);

最后画出轮廓、矩形框及中心点。(其中boundRect[i].tl()为矩形框左上角的点,boundRect[i].br()为矩形框右下角的点)

Point myPoint(0, 0);
myPoint.x = boundRect[i].x + boundRect[i].width / 2;
myPoint.y = boundRect[i].y + boundRect[i].height / 2;
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 2);
circle(img, Point(myPoint.x, myPoint.y), 4, {255,0,255}, FILLED);

为了美观考虑可以将点连成线画出。(其中newPoints数组中存放着所有中心点坐标)

for (int i = 0; i < newPoints.size(); i++) {
	line(img, Point(newPoints[i - 1][0], newPoints[i - 1][1]), Point(newPoints[i][0], newPoints[i][1]), myColorValues[newPoints[i][2]]);
}
4.3 根据坐标计算距离和角度

距离用每两点距离和累加计算,角度用3.2节的函数带入每相邻三点计算。(其中newPoints数组中存放着所有中心点坐标)

void drawOnCanvas(vector> newPoints) {
	double Z_angle = 0;
	double Distance = 0;
	for (int i = 0; i < newPoints.size(); i++) {
		circle(img, Point(newPoints[i][0], newPoints[i][1]), 4, {255,0,255}, FILLED);
		if (i >= 2) {
			Distance = sqrt(pow(newPoints[i][1] - newPoints[i - 1][1], 2) + pow(newPoints[i][0] - newPoints[i - 1][0], 2));
			if (Distance > 2) {
				Z_angle += get_angle(newPoints[i - 2][0], newPoints[i - 2][1], newPoints[i][0], newPoints[i][1], newPoints[i - 1][0], newPoints[i - 1][1]);
			}
		}
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5670777.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存