首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

【计算机视觉】Canny Edge边际检测器

2013-11-09 
【计算机视觉】Canny Edge边缘检测器引言Canny提出一种新的边缘检测方法[1][2],它对受白噪声影响的阶跃型边

【计算机视觉】Canny Edge边缘检测器
引言

Canny提出一种新的边缘检测方法[1][2],它对受白噪声影响的阶跃型边缘是最优的。整个Canny边缘检测器算法分成四步.

Canny边缘检测算子Canny边缘分成四步:

    噪声去除。因为这个检测器用到了微分算子,所以对于局部的不连续是敏感的,某区域的噪声点很容易造成边缘的模糊。在我做的这个应用里,因为要检测的是文本的边缘,而文本的背景是比较规则的变形后的正方形方格,所以如果用wiki里建议的高斯滤波器,会造成整个图像都变成一种颜色,即全黑或者全白。因此如果换一种观点,把这些变形后的方格也看成图的一部分,因为字体的纹理和方格的纹理不同,所以可以看作是两种区域组合成的图像。由此我改用一般的镜子,增强图像边缘。

    计算图像的边缘梯度。这个是常规运算,用了Sobel算子,分别计算图像的x和y方向的梯度值,最后计算出图像各点的梯度值以及梯度角。计算得到梯度角需要进行近似,近似四个值{-45(或135), 0, 45,90}。

    非最大梯度值点抑制第2步计算后得到两组值,第一组是各点的梯度值,第二组是各点梯度角的近似值。这一个非最大梯度值点抑制是比较不好理解的一步。遍历各点,做如下操作。(1)如果该点(x, y)的梯度角是0,如果其梯度值比北(x - 1, y)和南(x + 1, y)的梯度值大,则认为(x,y)点是一个边缘点,否则抑制其值,该其梯度值为设定的背景值(0或255);(2)如果该点(x, y)的梯度角是90,如果其梯度值比西(x, y - 1)和东(x, y +1)的梯度值大,则认为(x, y)点是一个边缘点,否则抑制其值,该其梯度值为设定的背景值(0或255);(3)如果该点(x,y)的梯度角是135(或-45),如果其梯度值比东北(x - 1, y + 1)和西南(x + 1, y -1)的梯度值大,则认为(x, y)点是一个边缘点,否则抑制其值,该其梯度值为设定的背景值(0或255);(4)如果该点(x,y)的梯度角是45,如果其梯度值比西北(x - 1, y - 1)和东南(x + 1, y + 1)的梯度值大,则认为(x,y)点是一个边缘点,否则抑制其值,该其梯度值为设定的背景值(0或255)。

    产生边缘.在第3步里直接用边缘值和背景值对两种图像区域进行了划分。这么做对于图像不同区域像素值区别较大的场合比较方便,计算也快,但是对于图像不同区域像

Canny边缘检测代码和Main程序
// Canny edge detection #include "stdio.h"#include "cv.h"#include "highgui.h"#define PI 3.1415926535#define ORI_SCALE 40.0#define MAG_SCALE 20.0#define MAX_MASK_SIZE 20float ratio = 0.1f;int WIDTH = 0;long seed = 132531;typedef struct image * IMAGE;int range (IMAGE im, int i, int j);void print_se (IMAGE p);IMAGE Input_PBM (char *fn);IMAGE Output_PBM (IMAGE image, char *filename);void get_num_pbm (FILE *f, char *b, int *bi, int *res);void pbm_getln (FILE *f, char *b);void pbm_param (char *s);struct image  *newimage (int nr, int nc);void freeimage (struct image  *z);void sys_abort (int val, char *mess);void CopyVarImage (IMAGE *a, IMAGE *b);void Display (IMAGE x);float ** f2d (int nr, int nc);void srand32 (long k);double drand32 ();void copy (IMAGE *a, IMAGE b);int trace (int i, int j, int low, IMAGE im,IMAGE mag, IMAGE ori);float gauss(float x, float sigma);float dGauss (float x, float sigma);float meanGauss (float x, float sigma);void hysteresis (int high, int low, IMAGE im, IMAGE mag, IMAGE oriim);void canny (float s, IMAGE im, IMAGE mag, IMAGE ori);void seperable_convolution (IMAGE im, float *gau, int width,float **smx, float **smy);void dxy_seperable_convolution (float** im, int nr, int nc, float *gau,  int width, float **sm, int which);void nonmax_suppress (float **dx, float **dy, int nr, int nc,IMAGE mag, IMAGE ori);void estimate_thresh (IMAGE mag, int *low, int *hi);void canny (float s, IMAGE im, IMAGE mag, IMAGE ori){int width;float **smx,**smy;float **dx,**dy;int i,j,n;float gau[MAX_MASK_SIZE], dgau[MAX_MASK_SIZE], z;        // Create a Gaussian and a derivative of Gaussian filter maskfor(i=0; i<MAX_MASK_SIZE; i++){  gau[i] = meanGauss ((float)i, s);  if (gau[i] < 0.005){width = i;break;  }  dgau[i] = dGauss ((float)i, s);}n = width+width + 1;WIDTH = width/2;printf ("Smoothing with a Gaussian (width = %d) ...\n", n);smx = f2d (im->info->nr, im->info->nc);smy = f2d (im->info->nr, im->info->nc);        //Convolution of source image with a Gaussian in X and Y directions seperable_convolution (im, gau, width, smx, smy);        //Now convolve smoothed data with a derivativeprintf ("Convolution with the derivative of a Gaussian...\n");dx = f2d (im->info->nr, im->info->nc);dxy_seperable_convolution (smx, im->info->nr, im->info->nc,dgau, width, dx, 1);free(smx[0]); free(smx);dy = f2d (im->info->nr, im->info->nc);dxy_seperable_convolution (smy, im->info->nr, im->info->nc, dgau, width, dy, 0);free(smy[0]); free(smy);        // Create an image of the norm of dx,dyfor (i=0; i<im->info->nr; i++)  for (j=0; j<im->info->nc; j++)  {      z = norm (dx[i][j], dy[i][j]);      mag->data[i][j] = (unsigned char)(z*MAG_SCALE);  }        //Non-maximum suppression - edge pixels should be a local maxnonmax_suppress (dx, dy, (int)im->info->nr, (int)im->info->nc, mag, ori);free(dx[0]); free(dx);free(dy[0]); free(dy);}int main ( ){int i,j;float s=1.0;int low= 0,high=-1;FILE *params;IMAGE im, magim, oriim;char name[128];// Try to read an imageprintf ("Enter path to the image file to be processed: ");scanf ("%s", name);printf ("Opening file '%s'\n", name);        //Read parameters from the file canny.parparams = fopen ("canny.par", "r");if (params){  fscanf (params, "%d", &low);  // Lower threshold   fscanf (params, "%d", &high); // High threshold   fscanf (params, "%f", &s);   // Gaussian standard deviation  printf ("Parameters from canny.par: HIGH: %d LOW %d Sigma %f\n",high, low, s);  fclose (params);}else printf ("Parameter file 'canny.par' does not exist.\n");im = get_image(name);display_image (im);// Create local image space magim = newimage (im->info->nr, im->info->nc);if (magim == NULL){  printf ("Out of storage: Magnitude\n");  exit (1);}oriim = newimage (im->info->nr, im->info->nc);if (oriim == NULL){  printf ("Out of storage: Orientation\n");  exit (1);}canny (s, im, magim, oriim); // Apply the filter          hysteresis (high, low, im, magim, oriim); //Hysteresis thresholding of edge pixelsfor (i=0; i<WIDTH; i++)  for (j=0; j<im->info->nc; j++)    im->data[i][j] = 255;for (i=im->info->nr-1; i>im->info->nr-1-WIDTH; i--)  for (j=0; j<im->info->nc; j++)    im->data[i][j] = 255;for (i=0; i<im->info->nr; i++)  for (j=0; j<WIDTH; j++)    im->data[i][j] = 255;for (i=0; i<im->info->nr; i++)  for (j=im->info->nc-WIDTH-1; j<im->info->nc; j++)    im->data[i][j] = 255;        display_image (im);save_image (im, "canny.jpg");return 0;}
参考文献

[1] Canny J. F. "Finding edges and lines in images" Technical Report AI-TR-720,MIT,Artifical Inteligence Labortay,Cambridg,MA,1983.

[2] Canny J. F. "a Computational Approach to Edge Detection", IEEE Trancsctions on Pattern Analysis and Machine Intelligence, 8(6):679-698,1996.

======================================================转载请注明出处:http://blog.csdn.net/utimes/article/details/8827781======================================================

热点排行