- 四、技术积累
- 4.1 提取图片不同区域HSV特征值
- 4.2 找到颜色区域并画出轮廓、中心点
- 4.3 根据坐标计算距离和角度
将图片读取进来,并转为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函数返回包含输入点集的最小矩形。
vectorboundRect(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]); } } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)