
3、Canny算法的实现流程
由于本文主要目的在于学习跟实现算法,而针对图像抓取、视频获得等内容不进行探讨。因此选择OpenCV算法库作为其它用途的谋求途径(关于OpenCV的使用,作者将另文表述)。首先展示本文将要处理的彩色照片。

图2 待处理的图像
3.1图像抓取和灰度化

编程时采取上文所叙述的第二种方法来实现图像的灰度化。其中ptr数组中保存的灰度化后的图像数据。具体的灰度化后的效果如图3所示。
IplImage*ColorImage=cvLoadImage("12.jpg",-1);//读入图像,获取彩图指针IplImage*OpenCvGrayImage;//定义变换后的灰度图指针unsignedchar*ptr;//指向图像的数据首地址if(ColorImage==NULL)return;inti=ColorImage->width*ColorImage->height;BYTEdata1;//中间过程变量BYTEdata2;BYTEdata3;ptr=newunsignedchar[i];for(intj=0;j<ColorImage->height;j++)//对RGB加权平均,权值参考OpenCV{for(intx=0;x<ColorImage->width;x++){data1=(BYTE)ColorImage->imageData[j*ColorImage->widthStep+i*3];//B分量data2=(BYTE)ColorImage->imageData[j*ColorImage->widthStep+i*3+1];//G分量data3=(BYTE)ColorImage->imageData[j*ColorImage->widthStep+i*3+2];//R分量ptr[j*ColorImage->width+x]=(BYTE)(0.072169*data1+0.715160*data2+0.212671*data3);}}OpenCvGrayImage=cvCreateImageHeader(cvGetSize(ColorImage),ColorImage->depth,1);cvSetData(GrayImage,ptr,GrayImage->widthStep);//根据数据生成灰度图cvNamedWindow("GrayImage",CV_WINDOW_AUTOSIZE);cvShowImage("GrayImage",OpenCvGrayImage);//显示灰度图cvWaitKey(0);cvDestroyWindow("GrayImage");

图3 灰度化后的图像
3.2图像的高斯滤波

根据前面所讲的边缘检测过程canny边缘检测原理canny边缘检测原理,下一个步骤就是对图像进行高斯滤波。可依照之前博文描述的方式获取一维以及二维的高斯滤波核。因此进行图像高斯滤波可有两种推动模式,以下详细进行介绍。
首先定义该个别的通用变量:
doublenSigma=0.4;//定义高斯函数的标准差intnWidowSize=1+2*ceil(3*nSigma);//定义滤波窗口的大小intnCenter=(nWidowSize)/2;//定义滤波窗口中心的索引
两种方式都必须用到的变量:
intnWidth=OpenCvGrayImage->width;//获取图像的像素尺寸intnHeight=OpenCvGrayImage->height;//获取图像的像素高度unsignedchar*nImageData=newunsignedchar[nWidth*nHeight];//暂时保存图像中的数据unsignedchar*pCanny=newunsignedchar[nWidth*nHeight];//为平滑后的图像数据分配内存double*nData=newdouble[nWidth*nHeight];//两次平滑的后面数据for(intj=0;j<nHeight;j++)//获取数据{for(i=0;i<nWidth;i++)nImageData[j*nWidth+i]=(unsignedchar)OpenCvGrayImage->imageData[j*nWidth+i];}

3.2.1根据一维高斯核进行两次滤波
1)生成一维高斯滤波系数
//////////////////////生成一维高斯滤波系数/////////////////////////////double*pdKernal_1=newdouble[nWidowSize];//定义一维高斯核函数doubledSum_1=0.0;//求和,用于进行归一化////////////////////////一维高斯函数公式//////////////////////////////////x*x/////////////////////-1*----------------/////////////////////12*Sigma*Sigma/////////////////////------------e//////////////////////////////////////////\/2*pi*Sigma///////////////////////////////////////////////////////////////////////////////////////for(inti=0;i<nWidowSize;i++){doublenDis=(double)(i-nCenter);pdKernal_1[i]=exp(-(0.5)*nDis*nDis/(nSigma*nSigma))/(sqrt(2*3.14159)*nSigma);dSum_1+=pdKernal_1[i];}for(i=0;i<nWidowSize;i++){pdKernal_1[i]/=dSum_1;//进行归一化}
2)分别进行x向跟y向的一维频域滤波,滤波后的数据保存在矩阵pCanny中

for(i=0;i<nHeight;i++)//进行x向的高斯滤波(加权平均){for(j=0;j<nWidth;j++){doubledSum=0;doubledFilter=0;//滤波中间值for(intnLimit=(-nCenter);nLimit<=nCenter;nLimit++){if((j+nLimit)>=0&&(j+nLimit)<nWidth)//图像不能超出边界{dFilter+=(double)nImageData[i*nWidth+j+nLimit]*pdKernal_1[nCenter+nLimit];dSum+=pdKernal_1[nCenter+nLimit];}}nData[i*nWidth+j]=dFilter/dSum;}}for(i=0;i<nWidth;i++)//进行y向的高斯滤波(加权平均){for(j=0;j<nHeight;j++){doubledSum=0.0;doubledFilter=0;for(intnLimit=(-nCenter);nLimit<=nCenter;nLimit++){if((j+nLimit)>=0&&(j+nLimit)<nHeight)//图像不能超出边界{dFilter+=(double)nData[(j+nLimit)*nWidth+i]*pdKernal_1[nCenter+nLimit];dSum+=pdKernal_1[nCenter+nLimit];}}pCanny[j*nWidth+i]=(unsignedchar)(int)dFilter/dSum;}}
3.2.2根据二维高斯核进行滤波
1)生成二维高斯滤波系数
//////////////////////生成一维高斯滤波系数//////////////////////////////////double*pdKernal_2=newdouble[nWidowSize*nWidowSize];//定义一维高斯核函数doubledSum_2=0.0;//求和,进行归一化///////////////////////二维高斯函数公式////////////////////////////////////////x*x+y*y///////////////////-1*--------------///////////////////12*Sigma*Sigma///////////////////----------------e///////////////////2*pi*Sigma*Sigma//////////////////////////////////////////////////////////////////////////////////////////for(i=0;i<nWidowSize;i++){for(intj=0;j<nWidowSize;j++){intnDis_x=i-nCenter;intnDis_y=j-nCenter;pdKernal_2[i+j*nWidowSize]=exp(-(1/2)*(nDis_x*nDis_x+nDis_y*nDis_y)/(nSigma*nSigma))/(2*3.1415926*nSigma*nSigma);dSum_2+=pdKernal_2[i+j*nWidowSize];}}for(i=0;i<nWidowSize;i++){for(intj=0;j<nWidowSize;j++)//进行归一化{pdKernal_2[i+j*nWidowSize]/=dSum_2;}}
2)采用高斯核进行高斯滤波,滤波后的数据保存在矩阵pCanny中
intx;inty;for(i=0;i<nHeight;i++){for(j=0;j<nWidth;j++){doubledFilter=0.0;doubledSum=0.0;for(x=(-nCenter);x<=nCenter;x++)//行{for(y=(-nCenter);y<=nCenter;y++)//列{if((j+x)>=0&&(j+x)<nWidth&&(i+y)>=0&&(i+y)<nHeight)//判断边缘{dFilter+=(double)nImageData[(i+y)*nWidth+(j+x)]*pdKernal_2[(y+nCenter)*nWidowSize+(x+nCenter)];dSum+=pdKernal_2[(y+nCenter)*nWidowSize+(x+nCenter)];}}}pCanny[i*nWidth+j]=(unsignedchar)dFilter/dSum;}}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-142042-1.html
臭猴子
没有激烈冲突