直线检测之极坐标表示

直线检测算法LSD有比较好的效果,相比Hough变换检测直线更高效,然而有个缺点是同一条直线上的线段会断开,此时想到将检测到的直线转化为极坐标表示,然后根据极坐标的相似程度对线段合并。这里图像上的直线与极坐标下角度的范围有着怎样的对应关系? 图像的坐标系Y轴向下,所以并不能直观地得到答案。

为此,写个小程序,来获得极坐标系下直线表示的角度与直线斜率的关系。取图像中心点为原点,以图像宽度的1/4为半径, θ 为角度( θ(0,2π) ),确定一条直线,并绘制出该直线,不同区域的直线以不同颜色区分。

// 说明: 建立极坐标系以图像中心为原点建立平面坐标系,极轴水平向右,第一象限为右上1/4圆,
// 第二象限为左上1/4圆, 依次类推。
//  极坐标系转换到平面坐标系,再到图像坐标系,注意转换关系
// 
    int _tmain(int argc, _TCHAR* argv[])
{

    int w = 600;
    int h = 600;
    Mat lines = Mat::zeros(Size(w,h), CV_8UC3);

    float theta = CV_PI/180; //角度间隔 为1°
    int _color = 0;

    float r = w/4;

    // 绘制360条直线,角度从1°到359°
    int j = 0;
    for (int i = 0 ; i< 360; i += 2)
    {

        float _sin = sin((double)theta*i);
        float _cos = cos((double)theta*i);

        if(fabs(_sin) < 1e-5 || fabs(_cos) < 1e-5 ) //特殊直线不处理了,即水平直线与垂直直线
            continue;

        _color = i/90; 

        float x0 = r*_cos + w/2;
        float y0 = h/2 - r*_sin;

        //u = 0, w;
        float y1 = h/2 - (r + w/2*_cos) /_sin; 
        float y2 = h/2 - (r - w/2*_cos) /_sin;

        float x1 = w/2 + (r - h/2*_sin)/_cos;
        float x2 = w/2 + (r + h/2*_sin)/_cos;

        Point2f pt1,pt2;
        pt1 = Point2f(0,y1);
        pt2 = Point2f(w,y2);

        if(x0 > w/2 && y0 < h/2 ){ 第一象限 直线与上边缘或者左边缘相交

            if(x1 > 0 && x1 < w)
                pt1 = Point2f(x1,0);
            else if(y1 > 0 && y1 < h)
                pt1 = Point2f(0,y1);
            else
                pt1 = Point2f(0,0);

            pt2 = Point2f(x0,y0);
        }

        if(x0 < w/2 && y0 < h/2 ) // 第二象限  直线与左边缘或者下边缘相交
        {
            if(y1 > 0 && y1 < h)
                pt1 = Point2f(0,y1);
            else if(x2 > 0 && x2 < w)
                pt1 = Point2f(x2,h);
            else
                pt1 = Point2f(0,0);

            pt2 = Point2f(x0,y0);
        }

        if(x0 < w/2 && y0 > h/2 ) // 第三象限 直线与下边缘或者右边缘相交
        {
            if(x2 > 0 && x2 < w)
                pt1 = Point2f(x2,h);
            else if(y2 > 0 && y2 < h)
                pt1 = Point2f(w,y2);
            else
                pt1 = Point2f(0,0);

            pt2 = Point2f(x0,y0);
        }

        if(x0 > w/2 && y0 > h/2 ) // 第四象限 直线与右边缘或者上边缘相交
        {
            if(y2 > 0 && y2 < h)
                pt1 = Point2f(w,y2);
            else if(x1 > 0 && x1 < w)
                pt1 = Point2f(x1,0);
            else
                pt1 = Point2f(0,0);

            pt2 = Point2f(x0,y0);
        }

        switch(_color)
        {
        case 0:
            line(lines,pt1,pt2,Scalar(255,0,0),1);
            break;
        case 1:
            line(lines,pt1,pt2,Scalar(0,255,0),1);
            break;
        case 2: 
            line(lines,pt1,pt2,Scalar(0,0,255),1);
            break;
        case 3:
            line(lines,pt1,pt2,Scalar(255,0,255),1);
            break;
        default:
            line(lines,pt1,pt2,Scalar(255,255,255),1);
        }
        char id[24];
        sprintf(id,"image/line_%03d.jpg",j++);
        imwrite(id,lines);
    }

    imwrite("line.jpg",lines);
    imshow("Polar Line",lines);
    waitKey();

    return 0;
}

结果如图:
这里写图片描述

以图像中心为极点,极轴为水平向右,则可得到该极坐标下角度 θ 与图像上直线斜率的对应关系。

针对图像上一条直线,以图像中心为原点,做一个与直线相切的圆,

  1. 切点(x,y)在圆的右上部分x> w/2,y< h/2,该直线在极坐标下的角度范围 (0,π/2) ;
  2. 切点(x,y)在圆的左上部分x< w/2,y< h/2,该直线在极坐标下的角度范围 (π/2,π) ;
  3. 切点(x,y)在圆的左下部分x< w/2,y> h/2,该直线在极坐标下的角度范围 (π,3π/2)
  4. 切点(x,y)在圆的右下部分x> w/2,y> h/2,该直线在极坐标下的角度范围 (3π/2,2π) .
原文地址:https://www.cnblogs.com/brother-louie/p/13976566.html