自己动手写一个霍夫变换检测直线(线段)

霍夫变换最简单的使用就是检测直线了。
原理:
对于x-y坐标中的一条直线y=kx+b,任取其上两点(x1,y1)与(x2,y2),在参数坐标k-b中分别对应两条直线L1与L2,两者相交与一点(b,k)。原直线上所有点在参数平面中对应的直线都相交于这一点。
对于x=c这类直线无法用y=kx+b处理,一般使用参数方程rho=xcos(theta)+ysin(theta)表示,则参数平面中为众多三角函数曲线相交与一点(theta,rho)
对于参数平面细分(因为程序处理时候数据不会连续,是离散的),分别统计每个点挂载的曲线数量,即“有多少条直线在这一点相交”,取数量最多的那个点,对应原有的待检测直线
先用霍夫变换检测直线,确定“伪直线”,然后取原图中点,用最小二乘法求出“真直线”。

说明:
OpenCV中自带HoughLines和HoughLinesP等函数用于检测直线。
代码

/*读入一张图像
*检测其中的一条线段
*并将其标记出来
*策略:取图像上每一点做霍夫变换,然后统计交点
*用交点的信息推出直线的斜率与截距
*并用点线距离判别合法点
*再用最小二乘法模拟直线方程
***ChriZ!
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

//0 represent black
//1 represent white
#define LINE 0
#define ELSE 255
typedef Mat_ MatU;

double f(int xi, int yi, double theta){
    double ret=xi*cos(theta)+yi*sin(theta);
    return ret;
}

double dis(double k, double b, double xi, double yi){
    double up=fabs(k*xi-yi+b);
    double down=sqrt(k*k+1);
    return up/down;
}

int main(){
    string filename="C:/testdir/13.png";
    Mat imgg=imread(filename);

    MatU img;
    cvtColor(imgg, img, CV_RGB2GRAY);
   // Mat imhough=Mat(img.rows, img.cols, img.type());

  //  bitwise_not(img, img);
    //threshold(img, img, 128, 255, THRESH_BINARY);
    int x, y;
    double theta;
    //MatU test=MatU(img.rows, img.cols, img.type());
    //Matrix test=new Matrix(img.rows, img.cols);
    //int test[img.rows*4][img.cols];
    int test[314][800];
    for(x=0; x<314; x++){
        for(y=0; y<800; y++){
            test[x][y]=0;
        }
    }

    for(y=0; y150)   cout << rho << endl;
                    test[int(theta*100)][int(rho)+400]+=1;
                  //  数组下标非负,遭遇负数rho时要处理,所以统统加400,后面处理时再减400
                  //  test[theta][int(rho)]+=1;
                }
            }
        }
    }

    int max=-1;
    double mx=0, my=0;
    for(y=0; y<800; y++){
        for(x=0; x<314; x++){
            if(test[x][y]>max){
                max=test[x][y];
                mx=x/100.0;
                my=y-400;
            }
        }
    }
    //cout << "max=" << max << endl;
    //cout << "mx=" << mx << endl;
    double mk=-1.0/tan(mx);
    double mb=my*1.0/sin(mx);
    cout << "k=" << mk << endl << "b=" << mb << endl;

   
    double dk=1;//pivot valut

    vector store;
    double xmin=200, xmax=0;//[xmin,xmax]表示直线横坐标范围
    for(y=0; yx) xmin=x;
                    if(xmax 
   

  

自己动手写一个霍夫变换检测直线(线段)_第1张图片

你可能感兴趣的:(自己动手写一个霍夫变换检测直线(线段))