zoukankan      html  css  js  c++  java
  • 【数字图像处理】霍夫变换实现

    理论部分来源:霍夫变换

    作者:https://home.cnblogs.com/u/php-rearch/

    一、霍夫变换(Hough)

      A-基本原理

    一条直线可由两个点A=(X1,Y1)和B=(X2,Y2)确定(笛卡尔坐标)

    另一方面,也可以写成关于(k,q)的函数表达式(霍夫空间):

    对应的变换可以通过图形直观表示:

    变换后的空间成为霍夫空间。即:笛卡尔坐标系中一条直线,对应霍夫空间的一个点

    反过来同样成立(霍夫空间的一条直线,对应笛卡尔坐标系的一个点):

    再来看看A、B两个点,对应霍夫空间的情形:

    一步步来,再看一下三个点共线的情况:

    可以看出如果笛卡尔坐标系的点共线,这些点在霍夫空间对应的直线交于一点:这也是必然,共线只有一种取值可能。

    如果不止一条直线呢?再看看多个点的情况(有两条直线):

    其实(3,2)与(4,1)也可以组成直线,只不过它有两个点确定,而图中A、B两点是由三条直线汇成,这也是霍夫变换的后处理的基本方式选择由尽可能多直线汇成的点

    看看,霍夫空间:选择由三条交汇直线确定的点(中间图),对应的笛卡尔坐标系的直线(右图)。

     到这里问题似乎解决了,已经完成了霍夫变换的求解,但是如果像下图这种情况呢?

    k=∞是不方便表示的,而且q怎么取值呢,这样不是办法。因此考虑将笛卡尔坐标系换为:极坐标表示

    在极坐标系下,其实是一样的:极坐标的点→霍夫空间的直线,只不过霍夫空间不再是[k,q]的参数,而是的参数,给出对比图:

    是不是就一目了然了?

    给出霍夫变换的算法步骤:

    二、霍夫变换的实现

    霍夫变换:在霍夫空间中,一个r和theta可以确定一条直线。

    本质上在由r与theta组成的二维空间进行投票。

    r:r的最大值取图像对角线长度。

    theta:0-360度,可分也可不分。

    #define PI 3.14159265 
    #define r      200    //120^2+160^2 = 40000  //斜边长度
    #define count 90      //360度分成90份
    #define Use_ROWS 120  //图像高度
    #define Use_Line 160  //图像宽度 
    
     
    //数据初始化
    int jiaodu=0;
    float Cos[count]={0},Sin[count]={0};
    for(int theta = 0,int i=0;theta<=360;i++)
        {
            Cos[i]=cos(theta*PI/180);
            Sin[i]=sin(theta*PI/180);        
            theta+=4;
        }
    
    //二维投票箱
    int res[count][r]={0};
    
    /////////////////////////////////////////////////////////////////////// memset(Image,
    255, sizeof(Image)); memset(res, 0, sizeof(res)); //二值化 int Threshold,i,j; Threshold = GetOSTU(Image_Use); for(i = 0; i < Use_ROWS; i++) { for(j =0; j < Use_Line; j++) { if(Image_Use[i][j] >= Threshold) Image_Use[i][j]=255;//白为背景 else Image_Use[i][j]=0; //黑为物体 } } //双向梯度 for(int i = 1; i < Use_ROWS- 1; i++) { for(int j = 1; j < Use_Line -1; j++) { Image_Use[i][j] = sqrt((Image_Use[i][j+1] - Image_Use[i][j])*(Image_Use[i][j+1] - Image_Use[i][j])+(Image_Use[i+1][j] - Image_Use[i][j])*(Image_Use[i+1][j] - Image_Use[i][j])); } } // 直线检测 for(int i = 0; i<Use_ROWS;i++) for(int j=0; j<Use_Line;j++) if(Image_Use[i][j]==255)//当该像素点为边缘点时 { for(int theta = 0;theta<=360;) { jiaodu = theta/4;//这里设置360度,分成多少份 int resu = (int)(i*Cos[jiaodu]+j*Sin[jiaodu]); res[jiaodu][resu] +=1; theta+=4; } } ////////////////////////////////// //找出次数最多的结果 int result = res[0][0]; for(int i=0;i<count;i++) for(int j=0;j<r;j++) { if(result<res[i][j]) result = res[i][j]; } //直线提取 int td =(int)(result * 0.8); int s1[30] = {0},s2[30]={0},d=0; for(int i=0;i<count;i++) { for(int j=0;j<r;j++) { if(res[i][j]>td) { s1[d] = i; //角度 s2[d] = j; //距离 d++; } } } d--; for(int i = 0; i < Use_ROWS; i++) { for(int s = 0 ;s<d;d++) { j = (int)((-1.0/tan[s1[s]])*i+(s2[s])/Sin[s1[s]])); Image[i][j] = 0; } }
    ///////////////////////////////////////////////////////
  • 相关阅读:
    hdu_2224_The shortest path(dp)
    hdu_4824_Disk Schedule(dp)
    hdu_5680_zxa and set(想法题)
    hdu_5683_zxa and xor(非正解的暴力)
    hdu_1429_胜利大逃亡(续)(BFS状压)
    hdu_1254_推箱子(双BFS)
    hdu_1969_pie(二分)
    hdu_2446_Shell Pyramid(数学,二分)
    hdu_2141_Can you find it?(二分)
    5.2 nc + JMX查看分布式程序数据
  • 原文地址:https://www.cnblogs.com/-wenli/p/12167119.html
Copyright © 2011-2022 走看看