opencv:边缘检测之kirsch算子

边缘检测的方法有主要有两种:

一种是基于模板匹配的,简单来说即用多个方向的检测模板与图像进行卷积,然后取邻域像素点的最大值。这种方法简单方便,容易理解,容易得到平滑的边缘,但是由于采用非常有限方向的模板(一般是8个方向,但是由于对称性可以减少为4个),因此不能检测出所有的边缘方向。

一种是基于求图像梯度的方法,一阶二阶的梯度算子,,如sobel、prewitt、Robert等一阶算子和拉普拉斯算子。检测的灵敏度高,精度定位准确,但同时容易受到噪声点的影响。

kirsch算子属于模板匹配算子,采用八个模板来处理图像的检测图像的边缘,运算量比较大。

8个3×3模板如下:

通过矩阵变换发现经过kirsch算子得到的像素值直接的关系,事实上需要直接由邻域像素点计算得到的只有p0,,因此可以大大减少计算量。

//kirsch算子滤波void kirsch(const IplImage* src, CvMat* dst){if (src->nChannels != 1 && dst->type != 1){cvError(CV_BadNumChannels, "kirsch", "The channels of image must be 1" , __FILE__, __LINE__);return;}if (src->width != dst->width || src->height != dst->height){cvError(CV_StsUnmatchedSizes, "kirsch", "The sizes of input/output must be same" , __FILE__, __LINE__);return;}//保存当前像素的八个模板滤波的结果vector<double > r(8);vector<double > p(8);CvMat* temp = cvCreateMat(src->height + 2, src->width + 2, CV_64FC1);CvMat* src_copy = cvCreateMat(src->height, src->width, CV_64FC1);cvConvertScale(src, src_copy);cvCopyMakeBorder(src_copy, temp, cvPoint(1, 1), IPL_BORDER_REPLICATE);for (int y = 1; y != temp->rows – 1; ++y){for (int x = 1; x != temp->cols – 1; ++x){//8个邻域像素值p[0] = CV_MAT_ELEM(*temp, double , y – 1, x – 1);p[1] = CV_MAT_ELEM(*temp, double , y – 1, x);p[2] = CV_MAT_ELEM(*temp, double , y – 1, x + 1);p[3] = CV_MAT_ELEM(*temp, double , y, x + 1);p[4] = CV_MAT_ELEM(*temp, double , y + 1, x + 1);p[5] = CV_MAT_ELEM(*temp, double , y + 1, x);p[6] = CV_MAT_ELEM(*temp, double , y + 1, x – 1);p[7] = CV_MAT_ELEM(*temp, double , y, x – 1);r[0] = 0.625*(p[0] + p[1] + p[2]) – 0.375*(p[3] + p[4] + p[5] + p[6] + p[7]);r[1] = r[0] + p[7] – p[2];r[2] = r[1] + p[6] – p[1];r[3] = r[2] + p[5] – p[0];r[4] = r[3] + p[4] – p[7];r[5] = r[4] + p[3] – p[6];r[6] = r[5] + p[2] – p[5];r[7] = r[6] + p[1] – p[4];//排序std::sort(r.begin(), r.end());//if (r[1] != 0)//{//cout<<"r1 != 0"<<endl;//}*(( double*)CV_MAT_ELEM_PTR(*dst, y – 1, x – 1)) = 8*r[7];}}cvReleaseMat(&src_copy);cvReleaseMat(&src_copy);}

由lena得到的边缘图像:

所有的胜利,与征服自己的胜利比起来,都是微不足道

opencv:边缘检测之kirsch算子

相关文章:

你感兴趣的文章:

标签云: