当前位置:首页 > 编程笔记 > 正文
已解决

<图像处理> Kitchen-Rosenfeld角点检测

来自网友在路上 154854提问 提问时间:2023-09-23 12:09:03阅读次数: 54

最佳答案 问答题库548位专家为你答疑解惑

Kitchen-Rosenfeld角点检测原理

Kitchen和Rosenfeld认为角点是那些边缘曲线曲率和梯度幅值都很大的点,因此他们提出了使用曲率k与梯度幅值g的乘积来计算角点响应函数C的方法:
C = k g = k ( I x 2 − I y 2 ) 1 / 2 = I x x I y 2 + I y y I x 2 − 2 I x y I x I y I x 2 + I y 2 ( 1 ) C=kg=k(I_x^2-I_y^2)^{1/2} = \frac {I_{xx}I_y^2+I_{yy}I_x^2-2I_{xy}I_xI_y}{I_x^2+I_y^2}(1) C=kg=k(Ix2Iy2)1/2=Ix2+Iy2IxxIy2+IyyIx22IxyIxIy1
C的极值点所对应的像素即为角点。 I x , I y I_x,I_y IxIy为图像I的一阶导数,即:
I x = ∂ I ∂ x , I y = ∂ I ∂ y I_x=\frac{\partial I}{\partial x},I_y=\frac{\partial I}{\partial y} Ix=xIIy=yI
I x x , I y y , I x y I_{xx},I_{yy},I_{xy} IxxIyyIxy为图像I的二阶导数,即:
I x x = ∂ 2 I ∂ x 2 , I y y = ∂ 2 I ∂ y 2 , I x y = ∂ 2 I ∂ x y I_{xx}=\frac{\partial^2 I}{\partial x^2},I_{yy}=\frac{\partial^2 I}{\partial y^2},I_{xy}=\frac{\partial^2 I}{\partial xy} Ixx=x22IIyy=y22IIxy=xy2I
由于(1)式的分母恒大于0,它不改变角点响应函数的相对值,因此在实际应用中,只计算分子部分。

检测步骤

  1. 计算图像一阶、二阶导数;
  2. 利用(1)式分子,计算角点响应函数;
  3. 对角点响应函数进行非极大值抑制,并设定阈值,得到角点。

该方法对噪声比较敏感,因为使用了基于灰度的二阶偏导。

OpenCV函数

void cv::preCornerDetect(InputArray src, OutputArray dst, int ksize, int borderType = BORDER_DEFAULT)	Parameters
src				输入图像,单通道8位整型或者32位浮点型;
dst				输出32位图像;
ksize			Sobel算子核尺寸;
borderType		边缘填充方法,但BORDER_WRAP不支持;

OpenCV源码分析

void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType )
{CV_INSTRUMENT_REGION();int type = _src.type();CV_Assert( type == CV_8UC1 || type == CV_32FC1 );CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(),ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type)))Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat();_dst.create( src.size(), CV_32FC1 );Mat dst = _dst.getMat();//Sobel算子计算一阶导数、二阶偏导Sobel( src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType );Sobel( src, Dy, CV_32F, 0, 1, ksize, 1, 0, borderType );Sobel( src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType );Sobel( src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType );Sobel( src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType );double factor = 1 << (ksize - 1);if( src.depth() == CV_8U )factor *= 255;factor = 1./(factor * factor * factor);
#if CV_SIMD128float factor_f = (float)factor;v_float32x4 v_factor = v_setall_f32(factor_f), v_m2 = v_setall_f32(-2.0f);
#endifSize size = src.size();int i, j;for( i = 0; i < size.height; i++ ){float* dstdata = dst.ptr<float>(i);const float* dxdata = Dx.ptr<float>(i);const float* dydata = Dy.ptr<float>(i);const float* d2xdata = D2x.ptr<float>(i);const float* d2ydata = D2y.ptr<float>(i);const float* dxydata = Dxy.ptr<float>(i);j = 0;//指令集加速
#if CV_SIMD128{for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes ){v_float32x4 v_dx = v_load(dxdata + j);v_float32x4 v_dy = v_load(dydata + j);v_float32x4 v_s1 = (v_dx * v_dx) * v_load(d2ydata + j);v_float32x4 v_s2 = v_muladd((v_dy * v_dy),  v_load(d2xdata + j), v_s1);v_float32x4 v_s3 = v_muladd((v_dy * v_dx) * v_load(dxydata + j), v_m2, v_s2);v_store(dstdata + j, v_s3 * v_factor);}}
#endif//计算每个像素的响应函数for( ; j < size.width; j++ ){float dx = dxdata[j];float dy = dydata[j];dstdata[j] = (float)(factor*(dx*dx*d2ydata[j] + dy*dy*d2xdata[j] - 2*dx*dy*dxydata[j]));}}
}

参考

  1. 《图像局部特征检测与描述》
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"<图像处理> Kitchen-Rosenfeld角点检测":http://eshow365.cn/6-12084-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!