边缘检测 c语言,求助!canny边缘检测算子用c语言实现,运行后图片怎么显出来呢...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

#include"canny.h"

全局变量/

Bitmap bmp;

FILE *fp=0;

DWORD width =0,height=0,line_width=0;

WORD bit_count =0,pal_length=0,off_bits=0;

DWORD dw = 0;

WORD w = 0;//各种清零

//对非最大抑制后的图像进行边缘搜索/

void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, Bitmap sz)

{

//对8邻域像素进行查询

int xNum[8] = {1,1,0,-1,-1,-1,0,1};

int yNum[8] = {0,1,1,1,0,-1,-1,-1};

long yy,xx,k;

for(k=0;k<8;k++)

{

yy = y+yNum[k];

xx = x+xNum[k];

if(pResult[yy*sz.line_width+xx]==128 && pMag[yy*sz.line_width+xx]>=nThrLow )

{

//该点设为边界点

pResult[yy*sz.line_width+xx] = 255;

//以该点为中心再进行跟踪

TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);

}

}

}

int main()

{

//读取图像参数 /

if((fp=fopen("czh.bmp","rb"))==NULL)//打开文件

{

printf("can not open the bitmap");

return 0;

}

else printf("read OK");

fseek(fp,10,0);//移动位置指针,从零开始

fread(&off_bits,4,1,fp);//读文件

fseek(fp,18,0);

fread(&width,4,1,fp);

fread(&height,4,1,fp);

fseek(fp,28,0);

fread(&bit_count,2,1,fp);

pal_length=off_bits-54;

if(bit_count==8)

{

bmp.palette=(LPBYTE)malloc(pal_length*sizeof(BYTE));

if(!bmp.palette)

{printf("palette have no memory");

return 0;}

}

else

{

bmp.palette=0;

}

if(bmp.palette)

{

fseek(fp,54,0);

fread(bmp.palette,pal_length,1,fp);

}

Read the parameters of bitmap///

line_width=(width*bit_count +31)/32*4;

bmp.line_width=line_width;

bmp.width=width;

bmp.height=height;

bmp.bit_count=bit_count;

bmp.pal_length=pal_length;

bmp.ptr=(LPBYTE)malloc(line_width*height*sizeof(BYTE));

if(!bmp.ptr)

{

printf("can not allocate memory for the bitmap.\n");

bmp.width=0;

bmp.height=0;

bmp.bit_count=0;

}

fseek(fp,off_bits,0);

fread(bmp.ptr,line_width*height,1,fp);

fclose(fp);

printf("Bitmap Width :%ld\n",bmp.width);

printf("Bitmap Heigh :%ld\n",bmp.height);

printf("Bitmap BitCount:%d\n",bmp.bit_count);

///高斯滤波///

int nCenter; //数组中心点

double dDis; //数组中一点到中心点的距离

DWORD i;

double dValue; // 中间变量

double dSum=0.0;

double sigma=0.8;//高斯系数

//[-3*sigma,3*sigma]以内的数据,会覆盖绝大部分滤波系数,也就是3西伽马原则

int WindowSize=1+2*ceil(3*sigma);

nCenter=WindowSize/2;

double*Kernel=NULL; //高斯核数组

Kernel=(double*)malloc(WindowSize*sizeof(double));

for(i=0;i

{

dDis=double(i-nCenter);

dValue=exp(-(1/2)*dDis*dDis/(sigma*sigma))/(sqrt(2*3.1415926)*sigma);

Kernel[i]=dValue;

dSum+=dValue;

}

for(i=0;i

{

Kernel[i]/=dSum; //归一化高斯数组

}

///

//用上面产生的一维高斯滤波器Kernel[i]平滑灰度图像Gray

double dDotMul;//点乘

long x,y;

int nlen;

nlen=WindowSize/2;

//滤波系数总和

double dWeightSum;

double *Temp=NULL;//中间暂时寄存器

double *Gray=NULL;//灰度图

double *Result=NULL;//平滑后图像

Temp=(double*)malloc(bmp.line_width*bmp.height*sizeof(double));

Gray=(double*)malloc(bmp.line_width*bmp.height*sizeof(double));

Result=(double*)malloc(bmp.line_width*bmp.height*sizeof(double));

//把bmp图像数据区部分拷到Gray

// memcpy(Gray,bmp.ptr,line_width*height*sizeof(BYTE));

for(y=0;y

for(x=0;x

Gray[y*bmp.line_width+x]=(double)bmp.ptr[y*bmp.line_width+x];

//x方向滤波

for(y=0;y

{

for(x=0;x

{

dDotMul=0;

dWeightSum=0;

for(i=(-nlen);i<=nlen;i++)

{

if((i+x)>=0&&(i+x)

{

dDotMul+=(double)Gray[y*bmp.line_width+x+i]*Kernel[nlen+i];

dWeightSum+=Kernel[i-nlen];

}

}

Temp[y*bmp.line_width+x]=dDotMul/dWeightSum;

}

}

//y方向滤波

for(x=0;x

{

for(y=0;y

{

dDotMul=0;

dWeightSum=0;

for(i=(-nlen);i

{

if((i+y)>=0&&(i+y)

{

dDotMul+=(double)Temp[(y+i)*bmp.line_width+x]*Kernel[nlen+i];

dWeightSum+=Kernel[nlen+i];

}

}

Result[y*bmp.height+x]=(unsigned char)dDotMul/dWeightSum;

}

}

delete []Kernel;

Kernel=NULL;

delete []Temp;

Temp=NULL;

//方向导数,求梯度//

int *Gradx=(int *)malloc(bmp.height*bmp.line_width*sizeof(int));//x方向梯度

int *Grady=(int *)malloc(bmp.height*bmp.line_width*sizeof(int));//y方向梯度

int *Mag =(int *)malloc(bmp.height*bmp.line_width*sizeof(int));//梯度的幅值

//x方向的方向导数

for(y=1;y

{

for(x=1;x

{

Gradx[y*bmp.line_width+x]=(int)(Result[y*bmp.line_width+x+1]-Result[y*bmp.line_width+x-1]);

}

}

//y方向的方向导数

for(x=1;x

{

for(y=1;y

{

Grady[y*bmp.line_width+x]=(int)(Result[(y+1)*bmp.line_width+x]-Result[(y-1)*bmp.line_width+x]);

}

}

//求梯度

//中间变量

double dSqt1;

double dSqt2;

for(y=0;y

{

for(x=0;x

{

//二阶范数求梯度

dSqt1=Gradx[y*bmp.line_width+x]*Gradx[y*bmp.line_width+x];

dSqt2=Grady[y*bmp.line_width+x]*Grady[y*bmp.line_width+x];

Mag[y*bmp.line_width+x]=(int)(sqrt(dSqt1+dSqt2)+0.5);

}

}

//非最大抑制

BYTE* nResult=(BYTE*)malloc(bmp.line_width*bmp.height*sizeof(BYTE));

int nPos;//当前位置

int gx;//x方向的梯度

int gy;//y方向的梯度

//中间变量

int g1,g2,g3,g4;

double weight;

double dTemp,dTemp1,dTemp2;

//设置图像边缘为不可能的分界点

for(x=0;x

{

nResult[x]=0; //第一行

nResult[(bmp.height-1)*bmp.line_width+x]=0; //最后一行

}

for(y=0;y

{

nResult[y*bmp.line_width]=0; //第一列

nResult[y*bmp.line_width+bmp.line_width-1]=0; //最后一列

}

for(y=1;y

{ for(x=1;x

{

//当前点

nPos=y*bmp.line_width+x;

if(Mag[nPos]==0) //梯度幅值为0

nResult[nPos]=0;

else //幅值非零

{

//当前点的梯度幅度

dTemp=Mag[nPos];

//x,y方向导数

gx=Gradx[nPos];

gy=Grady[nPos];

//如果方向倒数y分量比x分量大,说明导数方向趋向于y分量

if(abs(gy)>abs(gx))

{

weight=abs(gx)/abs(gy);

g2=Mag[nPos-bmp.line_width];

g4=Mag[nPos+bmp.line_width];

if(gx*gy>0)

{

g1=Mag[nPos-bmp.line_width-1];

g3=Mag[nPos+bmp.line_width+1];

}

//如果想x,y两个方向的方向相反

//C是当前像素,与g1-g4的关系为:

//g2 g1

//C

//g3 g4

else

{

g1=Mag[nPos-bmp.line_width+1];

g3=Mag[nPos+bmp.line_width-1];

}

}

//如果方向导师x分量比y分量大

else

{

//插值比例

weight=abs(gy)/abs(gx);

g2=Mag[nPos+1];

g4=Mag[nPos-1];

//如果x,y两个方向的方向导数符号相同

//当前像素C与g1-g4的关系为

//g3

//g4 C g2

//g1

if(gx*gy>0)

{

g1=Mag[nPos+bmp.line_width+1];

g3=Mag[nPos-bmp.line_width-1];

}

else

{

g1=Mag[nPos-bmp.line_width+1];

g3=Mag[nPos+bmp.line_width-1];

}

}

//利用g1-g4对梯度进行插值

{

dTemp1=weight*g1+(1-weight)*g2;

dTemp2=weight*g3+(1-weight)*g4;

//当前像素的梯度是局部的最大值

//该点可能是边界点

if(dTemp>=dTemp1&&dTemp>=dTemp2)

{

nResult[nPos]=128;

}

else

{

nResult[nPos]=0;//不可能是边界点

}

}

}

}

}

///统计pMag的直方图,判定阈值

long k;

int nHist[256];//直方图数组

int nEdgeNum;

int nMaxMag;

int nHighCount;

nMaxMag=0;

double dRatHigh=0.8;

double dRatLow=0.4;

//初始化

for(k=0;k<256;k++)

{

nHist[k]=0;

}

//统计直方图,利用直方图计算阈值

for(y=0;y

{

for(x=0;x

{

if(nResult[y*bmp.line_width+x]==128)

{

nHist[Mag[y*bmp.line_width+x]]++;

}

}

}

nEdgeNum=nHist[0];

nMaxMag=0;

//统计经过“非最大值抑制”后有多少像素

for(k=1;k<256;k++)

{

if(nHist[k]!=0)

{

nMaxMag=k;

}

nEdgeNum+=nHist[k];

}

//梯度比高阈值小的像素点总数目

nHighCount=(int)(dRatHigh*nEdgeNum+0.5);

k=1;

nEdgeNum=nHist[1];

//计算高阈值

while((k

{

k++;

nEdgeNum+=nHist[k];

}

int nThrHigh, nThrLow;

nThrHigh=k;

nThrLow=(int)((nThrHigh)*dRatLow+0.5);

//利用函数寻找边界起点

for(y=0;y

{

for(x=0;x

{

nPos=y*bmp.line_width+x;

if((nResult[nPos]==128)&&(Mag[nPos]>=nThrHigh))

{

nResult[nPos]=255;

//以该点为中心再进行跟踪

TraceEdge(y,x,nThrLow,nResult,Mag,bmp);

}

}

}

//其他的点已经不可能

for(y=0;y

{

for(x=0;x

{

nPos=y*bmp.line_width+x;

if(nResult[nPos]!=255)

{

nResult[nPos]=0;

}

}

}

//覆盖源图像数据区

nPos=0;

BYTE t=0;

for(y=0;y

{ for(x=0;x

{

t=nResult[nPos];

SET_gray(bmp,y,x,t);

nPos++;

}

}

delete []Gray;

Gray=NULL;

delete []Gradx;

Gradx=NULL;

delete []Grady;

Grady=NULL;

delete []Mag;

Mag=NULL;

delete []nResult;

nResult=NULL;

//保存

if((fp=fopen("czh.bmp","wb"))=NULL)

{

printf("fail to save");

return 0;

}

w=19778;

fwrite(&w,2,1,fp);

dw=14;

fwrite(&dw,4,1,fp);

w=0;

fwrite(&w,2,1,fp);

fwrite(&w,2,1,fp);

if(bmp.bit_count==8) dw=1078;

else dw=54;

fwrite(&dw,4,1,fp);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值