博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《图像处理实例》 之 拟合求交点
阅读量:4287 次
发布时间:2019-05-27

本文共 13125 字,大约阅读时间需要 43 分钟。


要求:找出下面图像中三个点的坐标

出处不说明,主要方法介绍


代码:

1 #include
2 #include
3 4 using namespace cv; 5 using namespace std; 6 vector
Rects; 7 int main(int argc, char** argv) { 8 9 Mat inputImage = imread("laser.png"); 10 Mat gaussImage1, guassImage2; 11 cvtColor(inputImage, inputImage, COLOR_BGR2GRAY); 12 //------------------------防止光照和斑点的干扰--------------------// 13 GaussianBlur(inputImage, gaussImage1, Size(3, 3), 0, 0, 4); 14 GaussianBlur(inputImage, guassImage2, Size(5, 5), 0, 0, 4); 15 absdiff(gaussImage1, guassImage2, inputImage); 16 threshold(inputImage, inputImage, 5, 255, THRESH_BINARY); 17 Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1)); 18 morphologyEx(inputImage, inputImage, MORPH_CLOSE, kernel); 19 morphologyEx(inputImage, inputImage, MORPH_OPEN, kernel); 20 //----------------------查找最合适的两条线--=------------------------// 21 //***********先用轮廓检测 22 //***********最小外接矩形 23 //***********找到最合适的两个外接矩形,其中这两个矩形的长宽中一个值为最大的// 24 vector
> contours; 25 vector
hierarchy; 26 findContours(inputImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1)); 27 28 for (size_t i = 0; i < contours.size(); i++)//找合适的轮廓 29 { 30 RotatedRect Rect; 31 double minLH; 32 Rects.push_back(minAreaRect(contours[i])); 33 if (Rects.size() == 3) 34 { 35 vector
num; 36 for (size_t i = 0; i < 3; i++) 37 { 38 num.push_back(max(Rects[i].size.height, Rects[i].size.width)); 39 } 40 minLH = min(min(num[0], num[1]), num[2]); 41 vector
::iterator it = Rects.begin(); 42 for (size_t i = 0; i < 3; i++,it++) 43 { 44 if (minLH == num[i]) Rects.erase(it); 45 break; 46 } 47 } 48 } 49 Mat showImage1 = Mat::zeros(inputImage.size(), CV_8UC3); 50 vector
lines; 51 for (size_t i = 0; i < contours.size(); i++)//拟合合适的直线 52 { 53 RotatedRect Rect = minAreaRect(contours[i]); 54 double maxHL = max(Rect.size.height, Rect.size.width); 55 double maxHLR = max(Rects[0].size.height, Rects[0].size.width); 56 double maxHLL = max(Rects[1].size.height, Rects[1].size.width); 57 Vec4f line; 58 if (maxHL == maxHLR || maxHL == maxHLL) 59 { 60 drawContours(showImage1, contours, static_cast
(i), Scalar(255, 0, 0), 1); 61 fitLine(contours[i], line, cv::DIST_L2, 0, 1e-2, 1e-2); 62 lines.push_back(line); 63 } 64 } 65 Mat showImage = Mat::zeros(inputImage.size(), CV_8UC3); 66 //获取点斜式的点和斜率 67 Point point0; 68 point0.x = lines[0][2]; 69 point0.y = lines[0][3]; 70 71 double k = lines[0][1] / lines[0][0]; 72 73 //计算直线的端点(y = k(x - x0) + y0) 74 Point point1, point2; 75 point1.x = 0; 76 point1.y = k * (0 - point0.x) + point0.y; 77 point2.x = 640; 78 point2.y = k * (640 - point0.x) + point0.y; 79 double b0 = point0.y - k * point0.x; 80 line(showImage, point1, point2, cv::Scalar(0, 255, 0), 1, 8, 0); 81 82 //获取点斜式的点和斜率 83 Point point3; 84 point3.x = lines[1][2]; 85 point3.y = lines[1][3]; 86 87 double k1 = lines[1][1] / lines[1][0]; 88 89 //计算直线的端点(y = k(x - x0) + y0) 90 Point point4, point5; 91 point4.x = 100; 92 point4.y = k1 * (100 - point3.x) + point3.y; 93 double b1 = point3.y - k1 * point3.x; 94 line(showImage, point3, point4, cv::Scalar(0, 0, 255), 1, 8, 0); 95 96 //----求直线交点 97 Point2f center; 98 center.x = (b1 - b0) / (k - k1); 99 center.y = k1 * center.x + b1;100 char countText[50];//定义数组长度的时候千万多比实际使用多一点,不然就一直崩溃!!!101 sprintf(countText, "Corn x is : %d", static_cast
(center.x));102 putText(showImage, countText, Point(30, 30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 255, 255), 2, 6);103 char countText1[50];//定义数组长度的时候千万多比实际使用多一点,不然就一直崩溃!!!104 sprintf(countText1, "Corn y is : %d", static_cast
(center.y));105 putText(showImage, countText1, Point(30, 100), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 255, 255), 2, 6);106 //----------------------拟合中间的直线,然后进行两条直线的焦点-----------------//107 //*******y = tan(angle)*x +b108 //*******先求k 和 b109 //*******直接利用交点公式计算 x = (b[1]-b[0])/(k[1]-k[0]) , y = k[1] * x + b[1]110 /*111 double k[2], b[2];112 Point center;113 k[0] = tan(Rects[0].angle);114 k[1] = tan(Rects[1].angle);115 b[0] = Rects[0].center.y - k[0] * Rects[0].center.x;116 b[1] = Rects[1].center.y - k[1] * Rects[1].center.x;117 CV_Assert(abs(k[1] - k[0]) == 0);118 center.x = (b[1] - b[0]) / (k[1] - k[0]);119 center.y = k[1] * center.x + b[1];120 */121 /*122 Mat showImage;123 showImage.create(inputImage.size(), inputImage.type());124 vector
lines;125 HoughLinesP(inputImage, lines, 1, CV_PI / 180, 50, 10, 5);126 for (size_t i = 0; i < lines.size(); i++)127 {128 Vec4i l;129 l = lines[i];130 line(showImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(100, 255, 200), 1, LINE_AA);131 }132 */133 waitKey(0);134 }

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 using namespace cv; 7 int count_Judge[2] = {
0,0}; 8 /** 9 * @brief 对输入图像进行细化 10 * @param src为输入图像,用cvThreshold函数处理过的8位灰度图像格式,元素中只有0与1,1代表有元素,0代表为空白 11 * @param maxIterations限制迭代次数,如果不进行限制,默认为-1,代表不限制迭代次数,直到获得最终结果 12 * @return 为对src细化后的输出图像,格式与src格式相同,元素中只有0与1,1代表有元素,0代表为空白 13 */ 14 Mat thinImage(const cv::Mat & src, const int maxIterations = -1) 15 { 16 assert(src.type() == CV_8UC1); 17 cv::Mat dst; 18 int width = src.cols; 19 int height = src.rows; 20 src.copyTo(dst); 21 int count = 0; //记录迭代次数 22 while (true) 23 { 24 count++; 25 if (maxIterations != -1 && count > maxIterations) //限制次数并且迭代次数到达 26 break; 27 std::vector
mFlag; //用于标记需要删除的点 28 //对点标记 29 for (int i = 0; i < height; ++i) 30 { 31 uchar * p = dst.ptr
(i); 32 for (int j = 0; j < width; ++j) 33 { 34 //如果满足四个条件,进行标记 35 // p9 p2 p3 36 // p8 p1 p4 37 // p7 p6 p5 38 uchar p1 = p[j]; 39 if (p1 != 1) continue; 40 uchar p4 = (j == width - 1) ? 0 : *(p + j + 1); 41 uchar p8 = (j == 0) ? 0 : *(p + j - 1); 42 uchar p2 = (i == 0) ? 0 : *(p - dst.step + j); 43 uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1); 44 uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1); 45 uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j); 46 uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1); 47 uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1); 48 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6) 49 { 50 int ap = 0; 51 if (p2 == 0 && p3 == 1) ++ap; 52 if (p3 == 0 && p4 == 1) ++ap; 53 if (p4 == 0 && p5 == 1) ++ap; 54 if (p5 == 0 && p6 == 1) ++ap; 55 if (p6 == 0 && p7 == 1) ++ap; 56 if (p7 == 0 && p8 == 1) ++ap; 57 if (p8 == 0 && p9 == 1) ++ap; 58 if (p9 == 0 && p2 == 1) ++ap; 59 60 if (ap == 1 && p2 * p4 * p6 == 0 && p4 * p6 * p8 == 0) 61 { 62 //标记 63 mFlag.push_back(p + j); 64 } 65 } 66 } 67 } 68 69 //将标记的点删除 70 for (std::vector
::iterator i = mFlag.begin(); i != mFlag.end(); ++i) 71 { 72 **i = 0; 73 } 74 75 //直到没有点满足,算法结束 76 if (mFlag.empty()) 77 { 78 break; 79 } 80 else 81 { 82 mFlag.clear();//将mFlag清空 83 } 84 85 //对点标记 86 for (int i = 0; i < height; ++i) 87 { 88 uchar * p = dst.ptr
(i); 89 for (int j = 0; j < width; ++j) 90 { 91 //如果满足四个条件,进行标记 92 // p9 p2 p3 93 // p8 p1 p4 94 // p7 p6 p5 95 uchar p1 = p[j]; 96 if (p1 != 1) continue; 97 uchar p4 = (j == width - 1) ? 0 : *(p + j + 1); 98 uchar p8 = (j == 0) ? 0 : *(p + j - 1); 99 uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);100 uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);101 uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);102 uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);103 uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);104 uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);105 106 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)107 {108 int ap = 0;109 if (p2 == 0 && p3 == 1) ++ap;110 if (p3 == 0 && p4 == 1) ++ap;111 if (p4 == 0 && p5 == 1) ++ap;112 if (p5 == 0 && p6 == 1) ++ap;113 if (p6 == 0 && p7 == 1) ++ap;114 if (p7 == 0 && p8 == 1) ++ap;115 if (p8 == 0 && p9 == 1) ++ap;116 if (p9 == 0 && p2 == 1) ++ap;117 118 if (ap == 1 && p2 * p4 * p8 == 0 && p2 * p6 * p8 == 0)119 {120 //标记 121 mFlag.push_back(p + j);122 }123 }124 }125 }126 127 //将标记的点删除 128 for (std::vector
::iterator i = mFlag.begin(); i != mFlag.end(); ++i)129 {130 **i = 0;131 }132 133 //直到没有点满足,算法结束 134 if (mFlag.empty())135 {136 break;137 }138 else139 {140 mFlag.clear();//将mFlag清空 141 }142 }143 return dst;144 }145 void FindLine(InputArray _src, vector
& lines, uchar method, uchar angle, double& b);146 147 int main(int argc, char*argv[]) {148 149 Mat inputImage = cv::imread("1.png");150 Mat src;151 cvtColor(inputImage, src, COLOR_BGR2GRAY);152 if (src.empty())153 {154 std::cout << "读取文件失败!" << std::endl;155 return -1;156 }157 158 //将原图像转换为二值图像 159 threshold(src, src, 0, 1, THRESH_BINARY | THRESH_OTSU);160 //图像细化 161 src = thinImage(src);162 //显示图像 163 src = src * 255;164 Mat kernel = getStructuringElement(MORPH_RECT, Size(2, 1));165 morphologyEx(src, src, MORPH_OPEN, kernel);166 vector
lines2;167 double b2;168 FindLine(src, lines2, 2, 0, b2);169 170 171 vector
lines;172 double b;173 FindLine(src, lines, 0, 0, b);174 175 176 vector
lines1;177 double b1;178 FindLine(src, lines1, 1, 0, b1);179 180 181 Mat showImage;182 cvtColor(src, showImage, COLOR_GRAY2BGR);183 line(showImage, lines2[0], lines2[1], Scalar(0, 0, 255), 1);184 line(showImage, lines[0], lines[1], Scalar(0, 0, 255), 1);185 line(showImage, lines1[0], lines1[1], Scalar(0, 0, 255), 1);186 187 waitKey(0);188 }189 //---------------------------------------有角度,通过寻找一个点换算直线--------------------------------------------//190 //-------@_src : input a image that Binary191 //-------@lines : output lines message, y = kx + b ,lines[0] stand for k ,lines[1] stand for b192 //-------@method : if method == 0 return left lines, method == 1 return right lines, else return horizon lines193 // default method == 0194 //-------@angle : if angle == true angle = 60 degree, else angle = 45 degree.default angle == true195 void FindLine(InputArray _src, vector
& lines, uchar method, uchar angle, double& b)196 {197 Mat src = _src.getMat();198 CV_Assert(src.depth() != 1);199 double k = 0;//y = kx + b 200 Point2f aimPoint[3];//aimPoint[0]/aimPoint[1]存储查询的点,防止误判, aimPoint[3]:直线另一个点201 if (method == 0)202 {203 204 for (size_t i = 0; i < src.rows; i++)205 {206 for (size_t j = 0; j < src.cols; j++)207 {208 //Point2f tempPoint(j, i);209 //aimPoint = src.at
(i, j) > 0 ? tempPoint : aimPoint;210 if (src.at
(i, j) > 0)211 {212 aimPoint[0] = aimPoint[1];213 aimPoint[1] = Point2f(j, i);214 215 break;216 }217 218 }219 }220 }221 else if (method == 1)222 {223 char flag[2] = { 0 ,0 };224 for (size_t i = 0; i < src.rows; i++)225 {226 for (size_t j = 0; j < src.cols; j++)227 {228 if (src.at
(i, src.cols - j - 1) > 0)229 {230 aimPoint[0] = aimPoint[1];231 aimPoint[1] = Point2f(src.cols - j - 1, i);232 break;233 }234 }235 }236 }237 else238 {239 int count[2];240 int a = 0, b = 0;241 for (size_t i = 0; i < src.rows; i++)242 {243 for (size_t j = 0; j < src.cols; j++)244 {245 if (src.at
(i, j) > 0)246 {247 count[0]++;248 }249 //count[0] = src.at
(i, j) > 0 ? count[0]++ : count[0];250 }251 if (count[0] > count[1])252 {253 aimPoint[1] = Point2f(0, i);254 aimPoint[0] = Point2f(0, i);255 count[1] = count[0];256 }257 count[0] = 0;258 }259 }260 //------------防止误判261 //if (abs(aimPoint[0].x - aimPoint[1].x) > 3) aimPoint[1] = aimPoint[0];262 count_Judge[0] = 0;263 count_Judge[1] = 0;264 for (size_t i = 0; i < src.cols; i++)265 {266 count_Judge[0] += src.at
(aimPoint[0].y, i) > 0 ? 1 : 0;267 }268 for (size_t i = 0; i < src.cols; i++)269 {270 count_Judge[1] += src.at
(aimPoint[0].y, i) > 0 ? 1 : 0;271 }272 if (count_Judge[0] >= count_Judge[1] || abs(aimPoint[0].y - aimPoint[1].y) > 2) aimPoint[1] = aimPoint[0];273 lines.push_back(aimPoint[1]);274 if (angle == 0)275 {276 if (method == 0)277 {278 b = aimPoint[1].y - sqrt(3) * aimPoint[1].x / 3;279 aimPoint[2] = Point2f(0, sqrt(3) * 0 + b);280 }281 else if (method == 1)282 {283 b = aimPoint[1].y + sqrt(3)*aimPoint[1].x / 3;284 aimPoint[2] = Point2f(src.cols, (b / sqrt(3)) / 3);285 }286 else287 {288 b = aimPoint[1].y;289 aimPoint[2] = Point2f(src.cols, b);290 }291 }292 else if (angle == 1)293 {294 if (method == 0)295 {296 b = aimPoint[1].y - aimPoint[1].x;297 aimPoint[2] = Point2f(0, 0 + b);298 }299 else if (method == 1)300 {301 b = aimPoint[1].y + aimPoint[1].x;302 aimPoint[2] = Point2f(src.cols, b / (1));303 }304 else305 {306 b = aimPoint[1].y;307 aimPoint[2] = Point2f(src.cols, b);308 }309 }310 else if (angle == 1)311 {312 if (method == 0)313 {314 b = aimPoint[1].y - sqrt(3)*aimPoint[1].x;315 aimPoint[2] = Point2f(0, sqrt(3) * 0 + b);316 }317 else if (method == 1)318 {319 b = aimPoint[1].y + sqrt(3)*aimPoint[1].x;320 aimPoint[2] = Point2f(src.cols, b / sqrt(3));321 }322 else323 {324 b = aimPoint[1].y;325 aimPoint[2] = Point2f(src.cols, b);326 }327 }328 lines.push_back(aimPoint[2]);329 }

转载地址:http://zitgi.baihongyu.com/

你可能感兴趣的文章
mvn不是内部或外部命令,也不是可运行的程序或批处理文件
查看>>
JAVA:JDBC连接MySQL数据库
查看>>
struts2流程简述
查看>>
struts2文件上传和下载
查看>>
值栈与OGNL
查看>>
struts2标签库--分类入门
查看>>
Struts2声明式异常处理
查看>>
Web.xml中jsp-config元素简述
查看>>
Struts2类型转换和自定义类型
查看>>
Java面向对象特征有那些
查看>>
hibernate单表继承映射
查看>>
继承结构中每个子类单独一张表
查看>>
HQL查询-分页-条件-连接-过滤使用
查看>>
hibernate加载策略之lazy
查看>>
hibernate抓取策略fetch
查看>>
Hibernate的N+1条SQL查询问题-------Iterate
查看>>
hibernate 缓存机制
查看>>
悲观锁
查看>>
Spring官网下载的步骤
查看>>
Spring入门之-------搭建步骤
查看>>