霍夫变换原理参考: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
#include
#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<
}
}
cout<
}
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
{
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");
}