• 《图像处理实例》 之 拟合求交点



     

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

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

     


     

    代码:

      1 #include<opencv2/opencv.hpp>
      2 #include<iostream>
      3 
      4 using namespace cv;
      5 using namespace std;
      6 vector<RotatedRect> 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<vector<Point>> contours;
     25     vector<Vec4i> 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<double> 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<RotatedRect>::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<Vec4f> 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<int>(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<int>(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<int>(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 +b
    108     //*******先求k 和 b
    109     //*******直接利用交点公式计算 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<Vec4i> 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 <opencv2/opencv.hpp>  
      2 #include <opencv2/core/core.hpp>  
      3 #include <iostream>  
      4 #include <vector>  
      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<uchar *> mFlag; //用于标记需要删除的点  
     28                                     //对点标记  
     29         for (int i = 0; i < height; ++i)
     30         {
     31             uchar * p = dst.ptr<uchar>(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<uchar *>::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<uchar>(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<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
    129         {
    130             **i = 0;
    131         }
    132 
    133         //直到没有点满足,算法结束  
    134         if (mFlag.empty())
    135         {
    136             break;
    137         }
    138         else
    139         {
    140             mFlag.clear();//将mFlag清空  
    141         }
    142     }
    143     return dst;
    144 }
    145 void FindLine(InputArray _src, vector<Point2f>& 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<Point2f> lines2;
    167     double b2;
    168     FindLine(src, lines2, 2, 0, b2);
    169 
    170 
    171     vector<Point2f> lines;
    172     double b;
    173     FindLine(src, lines, 0, 0, b);
    174 
    175 
    176     vector<Point2f> 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 Binary
    191 //-------@lines  : output lines message, y = kx + b ,lines[0] stand for k ,lines[1] stand for b
    192 //-------@method : if method == 0 return left lines, method == 1 return right lines, else return horizon lines
    193 //                   default method == 0
    194 //-------@angle     : if angle == true angle = 60 degree, else angle = 45 degree.default angle == true
    195 void FindLine(InputArray _src, vector<Point2f>& 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<uchar>(i, j) > 0 ? tempPoint : aimPoint;
    210                 if (src.at<uchar>(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<uchar>(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     else
    238     {
    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<uchar>(i, j) > 0)
    246                 {
    247                     count[0]++;
    248                 }
    249                 //count[0] = src.at<uchar>(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<uchar>(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<uchar>(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         else
    287         {
    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         else
    305         {
    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         else
    323         {
    324             b = aimPoint[1].y;
    325             aimPoint[2] = Point2f(src.cols, b);
    326         }
    327     }
    328     lines.push_back(aimPoint[2]);
    329 }

     

  • 相关阅读:
    c# linq查询的等于大于符号是什么意思?
    c# Socket tcpClient处理连接超时方式timeout
    不同网段服务器与客户端连接问题解决方法TCP/IP_C/S
    Http请求响应及SpringMVC相关注解解析
    Nginx部署项目,转发规则,负载均衡配置
    Linux redis设置后台启动
    Linux centos7安装Jdk nginx redis
    SpringCloud整合SpringSecurity JWT进行认证 ,鉴权
    C#中class与struct的区别概述
    列举ASP.NET 页面之间传递值的几种方式
  • 原文地址:https://www.cnblogs.com/wjy-lulu/p/7381364.html
Copyright © 2020-2023  润新知