转载自:http://blog.csdn.net/likezhaobin/article/details/6892629
3、 Canny算法的实现流程
图2 待处理的图像
3.1 图像读取和灰度化
- IplImage*
ColorImage = cvLoadImage( "12.jpg", -1 ); //读入图像,获取彩图指针 - IplImage*
OpenCvGrayImage; //定义变换后的灰度图指针 - unsigned
char* ptr; //指向图像的数据首地址 - if
(ColorImage == NULL) -
return; - int
i = ColorImage->width * ColorImage->height; - BYTE
data1; //中间过程变量 - BYTE
data2; - BYTE
data3; - ptr
= new unsigned char[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 图像的高斯滤波
- double
nSigma = 0.4; //定义高斯函数的标准差 - int
nWidowSize = 1+2*ceil(3*nSigma); //定义滤波窗口的大小 - int
nCenter = (nWidowSize)/2; //定义滤波窗口中心的索引
- int
nWidth = OpenCvGrayImage->width; //获取图像的像素宽度 - int
nHeight = OpenCvGrayImage->height; //获取图像的像素高度 - unsigned
char* nImageData = new unsigned char[nWidth*nHeight]; //暂时保存图像中的数据 - unsigned
char*pCanny = new unsigned char[nWidth*nHeight]; //为平滑后的图像数据分配内存 - double*
nData = new double[nWidth*nHeight]; //两次平滑的中间数据 - for(int
j=0; j<nHeight; j++) //获取数据 - {
-
for(i=0; i<nWidth; i++) -
nImageData[j*nWidth+i] = (unsigned char)OpenCvGrayImage->imageData[j*nWidth+i]; - }
3.2.1 根据一维高斯核进行两次滤波
- //生成一维高斯滤波系数/
- double*
pdKernal_1 = new double[nWidowSize]; //定义一维高斯核数组 - double
dSum_1 = 0.0; //求和,用于进行归一化 - 一维高斯函数公式//
-
x*x / -
-1*---------------- / -
1 2*Sigma*Sigma / -
------------ e / -
/ -
\/2*pi*Sigma / - //
- for(int
i=0; i<nWidowSize; i++) - {
-
double nDis = (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; //进行归一化 - }
- for(i=0;
i<nHeight; i++) //进行x向的高斯滤波(加权平均) - {
-
for(j=0; j<nWidth; j++) -
{ -
double dSum = 0; -
double dFilter=0; //滤波中间值 -
for(int nLimit=(-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++) -
{ -
double dSum = 0.0; -
double dFilter=0; -
for(int nLimit=(-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] = (unsigned char)(int)dFilter/dSum; -
} - }
3.2.2 根据二维高斯核进行滤波
- //生成一维高斯滤波系数//
- double*
pdKernal_2 = new double[nWidowSize*nWidowSize]; //定义一维高斯核数组 - double
dSum_2 = 0.0; //求和,进行归一化 - ///二维高斯函数公式
-
x*x+y*y /// -
-1*-------------- /// -
1 2*Sigma*Sigma /// -
---------------- e /// -
2*pi*Sigma*Sigma /// - ///
- for(i=0;
i<nWidowSize; i++) - {
-
for(int j=0; j<nWidowSize; j++) -
{ -
int nDis_x = i-nCenter; -
int nDis_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(int j=0; j<nWidowSize; j++) //进行归一化 -
{ -
pdKernal_2[i+j*nWidowSize] /= dSum_2; -
} - }
- int
x; - int
y; - for(i=0;
i<nHeight; i++) - {
-
for(j=0; j<nWidth; j++) -
{ -
double dFilter=0.0; -
double dSum = 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] = (unsigned char)dFilter/dSum; -
} - }