本算法只适用于此类chart图:
该算法主要用于对该chart图的实拍图片的斜边ROI获取,目的是自动在中心视场、0.3视场、0.7视场分别获取ROI窗口,并在窗口内获取斜边ROI。该算法用到opencv。
算法逻辑:
1.打开图片,转换为灰度图,用opencv获取轮廓
int main() { Mat img = imread("C:\\Users\\zx80-165\\Desktop\\789.jpg"); namedWindow("img"); imshow("原始图像", img); Mat imgGray,edge; cvtColor(img, imgGray, CV_BGR2GRAY);//转灰度 blur(imgGray, edge, Size(3, 3));//滤波 imshow("11", edge); GaussianBlur(edge, edge, Size(5, 5), 0);//高斯滤波 imshow("22", edge); Canny(edge, edge,10,70);//获取轮廓 imshow("轮廓图", edge); waitKey(0); }
2.设置ROI窗口,通过百分比来获取,ROI窗口大小自定义
想法图:获取9个ROI窗口,并在窗口里找到斜边。
1 void AutoROI::autolinkRect() 2 { 3 cv::Mat m = imageSource.clone(); 4 int withd, height, Xoffset, Yoffset; 5 int rows = m.rows; 6 int cols = m.cols; 7 int R = sqrt(rows*rows + cols * cols) / 2; 8 double r_R = (rows / 2.000) / R; 9 double c_R = (cols / 2.000) / R; 10 CvPoint p = CvPoint(0, 0); 11 LinkCvPoint linkP; 12 withd = AreaW; 13 height = AreaH; 14 15 //0视场 16 p.x = cols / 2; 17 p.y = rows / 2; 18 Xoffset = p.y - height / 2; 19 Yoffset = p.x - withd / 2; 20 linkP.p = p; 21 linkP.withd = withd; 22 linkP.height = height; 23 linkP.Xoffset = Xoffset; 24 linkP.Yoffset = Yoffset; 25 setLinkCvRect(0, linkP); 26 27 //0.3视场 28 //左 29 p.x = cols / 2 - round(R*0.3); 30 p.y = rows / 2; 31 Xoffset = p.y - height / 2; 32 Yoffset = p.x - withd / 2; 33 linkP.p = p; 34 linkP.withd = withd; 35 linkP.height = height; 36 linkP.Xoffset = Xoffset; 37 linkP.Yoffset = Yoffset; 38 setLinkCvRect(1, linkP); 39 //右 40 p.x = cols / 2 + round(R*0.3); 41 p.y = rows / 2; 42 Xoffset = p.y - height / 2; 43 Yoffset = p.x - withd / 2; 44 linkP.p = p; 45 linkP.withd = withd; 46 linkP.height = height; 47 linkP.Xoffset = Xoffset; 48 linkP.Yoffset = Yoffset; 49 setLinkCvRect(2, linkP); 50 //上 51 p.x = cols / 2; 52 p.y = rows / 2 - round(R*0.3); 53 Xoffset = p.y - height / 2; 54 Yoffset = p.x - withd / 2; 55 linkP.p = p; 56 linkP.withd = withd; 57 linkP.height = height; 58 linkP.Xoffset = Xoffset; 59 linkP.Yoffset = Yoffset; 60 setLinkCvRect(3, linkP); 61 //下 62 p.x = cols / 2; 63 p.y = rows / 2 + round(R*0.3); 64 Xoffset = p.y - height / 2; 65 Yoffset = p.x - withd / 2; 66 linkP.p = p; 67 linkP.withd = withd; 68 linkP.height = height; 69 linkP.Xoffset = Xoffset; 70 linkP.Yoffset = Yoffset; 71 setLinkCvRect(4, linkP); 72 73 //0.7视场 74 //左上 75 p.x = cols / 2 - round(R*0.7*c_R); 76 p.y = rows / 2 - round(R*0.7*r_R); 77 78 Xoffset = p.y - height / 2; 79 Yoffset = p.x - withd / 2; 80 linkP.p = p; 81 linkP.withd = withd; 82 linkP.height = height; 83 linkP.Xoffset = Xoffset; 84 linkP.Yoffset = Yoffset; 85 86 setLinkCvRect(5, linkP); 87 88 89 p.x = cols / 2 + round(R*0.7*c_R); 90 p.y = rows / 2 - round(R*0.7*r_R); 91 92 Xoffset = p.y - height / 2; 93 Yoffset = p.x - withd / 2; 94 linkP.p = p; 95 linkP.withd = withd; 96 linkP.height = height; 97 linkP.Xoffset = Xoffset; 98 linkP.Yoffset = Yoffset; 99 setLinkCvRect(6, linkP); 100 101 //左下 102 p.x = cols / 2 - round(R*0.7*c_R); 103 p.y = rows / 2 + round(R*0.7*r_R); 104 105 Xoffset = p.y - height / 2; 106 Yoffset = p.x - withd / 2; 107 linkP.p = p; 108 linkP.withd = withd; 109 linkP.height = height; 110 linkP.Xoffset = Xoffset; 111 linkP.Yoffset = Yoffset; 112 setLinkCvRect(7, linkP); 113 p.x = cols / 2 + round(R*0.7*c_R); 114 p.y = rows / 2 + round(R*0.7*r_R); 115 116 Xoffset = p.y - height / 2; 117 Yoffset = p.x - withd / 2; 118 linkP.p = p; 119 linkP.withd = withd; 120 linkP.height = height; 121 linkP.Xoffset = Xoffset; 122 linkP.Yoffset = Yoffset; 123 setLinkCvRect(8, linkP); 124 125 }
3.在ROI框里面寻找轮廓,算法思路是,找白点,以ROI中心点为起点,同时向四周跑,碰到白点停下来,并以该白点为中心点,生成一个斜边ROI。
3.1 找点函数
1 void AutoROI::findPoint(CvPoint * p, int flag, cv::Mat m, int *count)//点,flag,图, 2 { 3 BOOL ok = true; 4 int rows = m.rows / 2; 5 int cols = m.cols / 2; 6 switch (flag) 7 { 8 case 0: 9 { 10 while (ok) 11 { 12 if (m.at<uchar>(rows, cols) == 255)//255表示白点 13 { 14 p->x = rows; 15 p->y = cols; 16 *count = *count - 1; 17 18 19 //cout << "x=" << rows << ",y=" << cols << endl; 20 ok = false; 21 } 22 cols--; 23 } 24 break; 25 } 26 case 1: 27 { 28 while (ok) 29 { 30 if (m.at<uchar>(rows, cols) == 255) 31 { 32 p->x = rows; 33 p->y = cols; 34 *count = *count - 1; 35 //cout << "x=" << rows << ",y=" << cols << endl; 36 ok = false; 37 } 38 cols++; 39 } 40 break; 41 } 42 case 2: 43 { 44 while (ok) 45 { 46 if (m.at<uchar>(rows, cols) == 255) 47 { 48 p->x = rows; 49 p->y = cols; 50 *count = *count - 1; 51 //cout << "x=" << rows << ",y=" << cols << endl; 52 53 ok = false; 54 } 55 rows--; 56 } 57 break; 58 } 59 case 3: 60 { 61 while (ok) 62 { 63 if (m.at<uchar>(rows, cols) == 255) 64 { 65 p->x = rows; 66 p->y = cols; 67 *count = *count - 1; 68 //cout << "x=" << rows << ",y=" << cols << endl; 69 ok = false; 70 } 71 rows++; 72 } 73 break; 74 } 75 default: 76 break; 77 } 78 }
3.2 生成斜边ROI函数
该函数与QT-鼠标点击获取ROI-用于摄像头模组定点对焦中写的差不多,这里就不多叙述了。