C++ 霍夫直线检测

霍夫变换原理参考:http://blog.csdn.net/jia20003/article/details/7724530

位图文件格式参考:http://www.cnblogs.com/kingmoon/archive/2011/04/18/2020097.html

本程序用标准C++语法读取读取一张400*400大小的单色图片,并用霍夫变换检测其中的直线。

待检测图像:

程序输出图像:

程序的主要步骤:

1,读入一个400*400的单色位图,找到数据区,赋值到一个二维矩阵 pic【400】【400】。

2,从0度到180度枚举角度theta,对pic【400][400]做霍夫变换并提取theta角度下长度达到thrd个连续像素点的线段,把线段中的点赋值到 pic2【400】【400】中。

3,依据pic2【400】【400】写文件lineout.bmp。

程序里有两个小麻烦:

1,由于单色位图每个像素只占1bit,C语言中最小的数据类型(char,bool)也占一字节,所以要整字节读出,并作位分离,处理完后又要做位合并再写图像

2,每行像素为400个,400 /8=50字节,但是通过ultraEdit观看发现实际每行像素用了52字节,大概每行要四字节对齐吧,因为50不是4的倍数,所以补到52字节。

代码:

#include<iostream>
#include<cmath>
#define PI acos(-1.0)
using namespace std;
int pic[400][400];
int pic2[400][400];
int bit_test[8]={1,2,4,8,16,32,64,128};
struct pos{int x,y;};
pos RT[600][600];
int RTnum[600];
float mysin[360],mycos[360];
void init_sincos()
{
    for(int i=0;i<360;i++)
    {
        mysin[i]=sin(float(i)*PI/180.0);            
        mycos[i]=cos(float(i)*PI/180.0);            
    }
}
bool adjacent(pos a,pos b)
{
    if(abs(a.x-b.x)<=2&&abs(b.y-a.y)<=2)
        return 1;
    return 0;     
}
void txtshow()
{
    int i,j,k;
    freopen("out.txt","w",stdout);
    for(i=0;i<400;i++)
    {
        for(j=0;j<50;j++)
        {
            for(k=0;k<8;k++)
            {
                cout<<pic[i][8*j+k];
            }                  
        }                  
        cout<<endl;
    }
    fclose(stdout);
    system("out.txt");
}
int main()
{
    int i,j,k,row,col;
    init_sincos();
    //读取图片 
    char *p_img_path="line.bmp";
    char img_path[100];
    int plen=strlen(p_img_path);
    for(i=0;i<=plen;i++)
        img_path[i]=p_img_path[i];
    
    char* pchBuf = NULL;
    int nLen=62+400*52;
    pchBuf=(char*)malloc(nLen+1);
    
    FILE *pF=fopen(img_path,"rb");
    nLen=fread(pchBuf,1,nLen,pF);
        //图片转存到pic数组中 ,图像在位图数据区中其实是上下颠倒的。 
    for(i=0;i<400;i++)
    {
        for(j=0;j<50;j++)
        {
            for(k=0;k<8;k++)
            {
                pic[399-i][8*j+k]=((pchBuf[62+i*52+j]&bit_test[7-k])>0);                  
            }
        }                  
    }
    //txtshow();
    //图像修改
    double r,theta; 
    int intr;    
    for(k=0;k<=180;k++)
    {
        for(i=0;i<600;i++)
            RTnum[i]=0;
        //寻找角度为theta的边,边长为r             
        for(i=0;i<400;i++)//i 行号,y
        {
            for(j=0;j<400;j++)//j 列号,x 
            {
                if(pic[i][j]==1)
                    continue;
                r=mysin[k]*float(i)+mycos[k]*float(j);
                intr=fabs(r);
                RT[intr][RTnum[intr]].x=j;
                RT[intr][RTnum[intr]].y=i;
                RTnum[intr]++;                  
            }                     
        } 
        //找完直线显示
        pos a,b;
        int s1,s2,pnum;
        int thrd=30;
        for(intr=0;intr<600;intr++) 
        {
             if(RTnum[intr]>=thrd)
             {
                 s1=s2=0;
                 pnum=1;
                 a=RT[intr][0];
                 for(i=1;i<RTnum[intr];i++)
                 {
                     b=RT[intr][i];
                     if(adjacent(a,b))
                     {
                         pnum++;             
                     }          
                     else
                     {
                         s2=i-1;
                         if(pnum>=thrd)
                         {
                             for(j=s2-pnum+1;j<=s2;j++)
                             {
                                 pic2[RT[intr][j].y][RT[intr][j].x]=1;                          
                             }              
                         }    
                         pnum=1;
                     }          
                     a=b;        
                 }
                 if(pnum>=thrd)
                 {
                     s2=i-1;
                     for(j=s2-pnum+1;j<=s2;j++)
                     {
                         pic2[RT[intr][j].y][RT[intr][j].x]=1;                          
                     }              
                 } 
             }                  
        }
    }
    fclose(stdout); 
    //保存到图像 
    FILE *pF2=fopen("outline.bmp","wb");
    for(i=0;i<62;i++)
        fputc(pchBuf[i],pF2);//转存图像文件头 
    for(i=0;i<400;i++)       //转存图像像素信息 
    {
        for(j=0;j<50;j++)
        {
            char tempc=0;
            for(k=0;k<8;k++)
            {
               tempc+=pic2[399-i][8*j+k]*bit_test[7-k];                
            }
            fputc(~(tempc),pF2);
        }                  
        fputc(0,pF2);fputc(0,pF2);
    }
    
    fclose(pF);
    free(pchBuf);   
    fclose(pF2);  

    system("outline.bmp");
}


  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
霍夫直线检测是一种经典的图像处理算法,用于检测图像中的直线。其基本原理是将图像上所有可能的直线通过霍夫变换映射到霍夫空间中,并对霍夫空间进行分析,找出其中符合条件的直线。在C语言中,我们可以使用OpenCV库中的函数实现霍夫直线检测。具体实现步骤如下: 1. 读入一张图像并转换为灰度图像。 2. 对灰度图像进行边缘检测,得到边缘图像。 3. 对边缘图像进行霍夫变换,将边缘图像上的每一个点映射到霍夫空间中的一条直线上。 4. 对霍夫空间进行分析,找出其中数量最多的直线,即为检测到的直线。 5. 在原始图像上绘制出检测到的直线。 下面是示例代码: ``` // 读入图像并转换为灰度图像 Mat image = imread("image.jpg"); Mat gray; cvtColor(image, gray, COLOR_BGR2GRAY); // 边缘检测 Mat edges; Canny(gray, edges, 50, 200, 3); // 霍夫变换检测直线 vector<Vec2f> lines; HoughLines(edges, lines, 1, CV_PI/180, 150); // 在原始图像上绘制直线 for (size_t i = 0; i < lines.size(); i++) { float rho = lines[i][0], theta = lines[i][1]; Point pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a * rho, y0 = b * rho; pt1.x = cvRound(x0 + 1000 * (-b)); pt1.y = cvRound(y0 + 1000 * (a)); pt2.x = cvRound(x0 - 1000 * (-b)); pt2.y = cvRound(y0 - 1000 * (a)); line(image, pt1, pt2, Scalar(0, 0, 255), 3, LINE_AA); } imshow("Hough Lines", image); waitKey(0); ``` --相关问题--:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值