Opencv 使用线条绘制简单图形的近似照片

Opencv 使用线条绘制简单图形的近似照片,opencv,line,detection,approximation,Opencv,Line,Detection,Approximation,作为输入,我有一张简单符号的照片,例如: 我想检测其中的直线,比如直线的起点和终点。在这种情况下,假设符号的左上角为(0,0),则行的定义如下: 起点-终点(直线起点和终点的坐标) 1.(0,0); (0,10)(垂直线) 2.(0,10); (15,15) 3.(15,15); (0,20) 4.(0,20); (0,30) 我如何做到这一点(完全使用OpenCV)?我想是关于霍夫线的,但它们似乎适合完美的细直线,而在绘画中则不是这样。我可能也会处理二值化图像。您应该尝试霍夫线变换。这里有一个

作为输入,我有一张简单符号的照片,例如:

我想检测其中的直线,比如直线的起点和终点。在这种情况下,假设符号的左上角为(0,0),则行的定义如下:

起点-终点(直线起点和终点的坐标)
1.(0,0); (0,10)(垂直线)
2.(0,10); (15,15)
3.(15,15); (0,20)
4.(0,20); (0,30)


我如何做到这一点(完全使用OpenCV)?我想是关于霍夫线的,但它们似乎适合完美的细直线,而在绘画中则不是这样。我可能也会处理二值化图像。

您应该尝试
霍夫线变换。这里有一个来自

#包括“opencv2/highgui/highgui.hpp”
#包括“opencv2/imgproc/imgproc.hpp”
#包括
使用名称空间cv;
使用名称空间std;
int main()
{
Mat src=imread(“building.jpg”,0);
Mat-dst,cdst;
Canny(src、dst、50、200、3);
CVT颜色(dst、cdst、CV_GRAY2BGR);
矢量线;
//探测线
HoughLines(dst,lines,1,CV_PI/180,150,0,0);
//划线
对于(size_t i=0;i
有了这个,你应该能够调整并获得你想要的属性(顶点)。

试试这个

  • 应用于阈值图像

  • 对于找到的轮廓

  • 见一些参考资料:


      • 也许你可以做这个

      • 假设一个完美的二值化:
      • 运行HoughLinesP
      • (未实现)尝试对检测到的行进行分组
      • 我使用了以下代码:

            int main()
            {
                cv::Mat image = cv::imread("HoughLinesP_perfect.png");
                cv::Mat gray;
                cv::cvtColor(image,gray,CV_BGR2GRAY);
        
                cv::Mat output; image.copyTo(output);
        
        
        
                cv::Mat g_thres = gray == 0;
        
        
                std::vector<cv::Vec4i> lines;
                //cv::HoughLinesP( binary, lines, 1, 2*CV_PI/180, 100, 100, 50 );
                //  cv::HoughLinesP( h_thres, lines, 1, CV_PI/180, 100, image.cols/2, 10 );
                cv::HoughLinesP( g_thres, lines, 1, CV_PI/(4*180.0), 50, image.cols/20, 10 );
        
                for( size_t i = 0; i < lines.size(); i++ )
                {
                    cv::line( output, cv::Point(lines[i][0], lines[i][3]),
                            cv::Point(lines[i][4], lines[i][3]), cv::Scalar(155,255,155), 1, 8 );
                }
        
        
                cv::imshow("g thres", g_thres);
        
                cv::imwrite("HoughLinesP_out.png", output);
        
                cv::resize(output, output, cv::Size(), 0.5,0.5);
        
                cv::namedWindow("output"); cv::imshow("output", output);
        
                cv::waitKey(-1);
        
                std::cout << "finished" << std::endl;
        
                return 0;
        
            }
        
        intmain()
        {
        cv::Mat image=cv::imread(“HoughLinesP_perfect.png”);
        cv::席灰色;
        cv::CVT颜色(图像,灰色,cv_bgr2灰色);
        cv::Mat输出;image.copyTo(输出);
        cv::Mat g_thres=灰色==0;
        std::矢量线;
        //cv::HoughLinesP(二进制,行,1,2*cv_PI/180100100,50);
        //cv::HoughLinesP(h_thres,lines,1,cv_PI/180100,image.cols/2,10);
        cv::HoughLinesP(g_thres,lines,1,cv_PI/(4*180.0),50,image.cols/20,10);
        对于(size_t i=0;i=0)
        {
        行_过滤[覆盖]=行[i];
        }
        其他的
        {
        行过滤。向后推(行[i]);
        }
        }
        }
        对于(size\u t i=0;istd::我不能感谢您的意见。我决定试试你的想法,但正如我担心的那样,它似乎不合适。在调整一些参数后,您可以在这里看到我的结果:;我先用大津阈值对它进行了二值化,但它似乎不会影响结果。我想主要的问题是,由于边缘的原因,我必须平行线,但即使不是这样,它也会检测最直的线-调整参数可能会有所帮助,但它不是通用的。还有其他想法吗?谢谢!实际上可能就是这样。我会检查一下,稍后发布我的结果:)我按照你的建议做了,这正是我所需要的。再次感谢:)谢谢。这是一个非常有趣的方法,我认为它实际上可以工作。然而,对于我的例子来说,这种分组在计算上可能太昂贵了。然后,也许可以尝试一些细化,尝试HoughLinesP而不是HoughLines,因为它更适合非完美线。但是你可能不想分组,而只想选择最长的“相似”线,我想这并不需要花费太多的计算时间。是的,但是你仍然需要创建“相似”线的分组,所以这会变得更复杂。我将尝试使用Haris提出的方法,但我会记住您的方法。@user3704596使用简单的相似行聚类编辑了我的答案,只是为了完成谢谢您的努力!事实上,我检查了你的解决方案,效果很好。我决定使用另一个,因为它一次给出了近似的直线,这让我可以很容易地计算相邻直线之间的角度。谢谢
        
        float minimum_distance(cv::Point2f v, cv::Point2f w, cv::Point2f p) {
              // Return minimum distance between line segment vw and point p
              const float l2 = cv::norm(w-v) * cv::norm(w-v);  // i.e. |w-v|^2 -  avoid a sqrt
              if (l2 == 0.0) return cv::norm(p-v);   // v == w case
              // Consider the line extending the segment, parameterized as v + t (w - v).
              // We find projection of point p onto the line.
              // It falls where t = [(p-v) . (w-v)] / |w-v|^2
              //const float t = dot(p - v, w - v) / l2;
              float t = ((p-v).x * (w-v).x + (p-v).y * (w-v).y)/l2;
        
              if (t < 0.0) return cv::norm(p-v);       // Beyond the 'v' end of the segment
              else if (t > 1.0) return cv::norm(p-w);  // Beyond the 'w' end of the segment
              const cv::Point2f projection = v + t * (w - v);  // Projection falls on the segment
              return cv::norm(p - projection);
            }
        
            int main()
            {
                cv::Mat image = cv::imread("HoughLinesP_perfect.png");
                cv::Mat gray;
                cv::cvtColor(image,gray,CV_BGR2GRAY);
        
                cv::Mat output; image.copyTo(output);
        
        
        
                cv::Mat g_thres = gray == 0;
        
        
                std::vector<cv::Vec4i> lines;
                cv::HoughLinesP( g_thres, lines, 1, CV_PI/(4*180.0), 50, image.cols/20, 10 );
        
                float minDist = 100;
        
                std::vector<cv::Vec4i> lines_filtered;
                for( size_t i = 0; i < lines.size(); i++ )
                {
                    bool keep = true;
                    int overwrite = -1;
                    cv::Point2f a(lines[i][0], lines[i][6]);
                    cv::Point2f b(lines[i][7], lines[i][3]);
        
                    float lengthAB = cv::norm(a-b);
        
        
                    for( size_t j = 0; j < lines_filtered.size(); j++ )
                    {
                        cv::Point2f c(lines_filtered[j][0], lines_filtered[j][8]);
                        cv::Point2f d(lines_filtered[j][9], lines_filtered[j][3]);
        
                        float distCDA =  minimum_distance(c,d,a);
                        float distCDB =  minimum_distance(c,d,b);
        
                        float lengthCD = cv::norm(c-d);
        
        
                        if((distCDA < minDist) && (distCDB < minDist))
                        {
                            if(lengthCD >= lengthAB)
                            {
                                keep = false;
                            }
                            else
                            {
                                overwrite = j;
                            }
                        }
        
                    }
        
                    if(keep)
                    {
                        if(overwrite >= 0)
                        {
                            lines_filtered[overwrite] = lines[i];
        
                        }
                        else
                        {
                            lines_filtered.push_back(lines[i]);
                        }
                    }
                }
        
        
                for( size_t i = 0; i < lines_filtered.size(); i++ )
                {
                    cv::line( output, cv::Point(lines_filtered[i][0], lines_filtered[i][10]),
                            cv::Point(lines_filtered[i][11], lines_filtered[i][3]), cv::Scalar(155,255,155), 2, 8 );
                }
        
        
        
        
                cv::imshow("g thres", g_thres);
        
                cv::imwrite("HoughLinesP_out.png", output);
        
                cv::resize(output, output, cv::Size(), 0.5,0.5);
        
                cv::namedWindow("output"); cv::imshow("output", output);
        
                cv::waitKey(-1);
        
                std::cout << "finished" << std::endl;
        
                return 0;
        
            }