说在前面
- opencv版本:4.0.1
- 操作系统:win10
- vs版本:2017
- 官方文档:Creating your own corner detector
- 其他说明:自学,记录,demo
Func
-
主要是这俩函数
void cv::cornerEigenValsAndVecs ( InputArray src,//输入图像 OutputArray dst,//输出结果,与输入大小相同,类型为 CV_32FC(6) 六通道、浮点型 int blockSize,//窗口大小 int ksize,//Sobel算子参数 int borderType = BORDER_DEFAULT // )
对每一个像素(假设坐标为(x,y)),定义一个大小为blockSize*blockSize(例如3)的窗口,并计算:
M = [ ∑ S ( p ) ( d I / d x ) 2 ∑ S ( p ) d I / d x d I / d y ∑ S ( p ) d I / d x d I / d y ∑ S ( p ) ( d I / d y ) 2 ] M = \begin{bmatrix} \sum _{S(p)}(dI/dx)^2 & \sum _{S(p)}dI/dx dI/dy \\ \sum _{S(p)}dI/dx dI/dy & \sum _{S(p)}(dI/dy)^2 \end{bmatrix} M=[∑S(p)(dI/dx)2∑S(p)dI/dxdI/dy∑S(p)dI/dxdI/dy∑S(p)(dI/dy)2]
那么在dst中对应(x,y)的值为:
( λ 1 , λ 2 , x 1 , y 1 , x 2 , y 2 ) (\lambda_1, \lambda_2, x_1, y_1, x_2, y_2) (λ1,λ2,x1,y1,x2,y2)
其中
λ 1 , λ 2 \lambda_1, \lambda_2 λ1,λ2为矩阵M的特征值;
( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1, y_1),( x_2, y_2) (x1,y1),(x2,y2)为矩阵M的特征向量。void cv::cornerMinEigenVal ( InputArray src, //输入图像 OutputArray dst, //输出结果,与输入图像的大小相同,类型为CV_32FC1,存储上面那个M的最小特征值 int blockSize, //窗口大小 int ksize = 3, //Sobel算子参数 int borderType = BORDER_DEFAULT )
Code
-
计算cornerEigenValsAndVecs和Mc(也就是Harris角点检测中的R值)
cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize ); /* calculate Mc */ Mc = Mat( src_gray.size(), CV_32FC1 ); for( int i = 0; i < src_gray.rows; i++ ) { for( int j = 0; j < src_gray.cols; j++ ) { float lambda_1 = myHarris_dst.at<Vec6f>(i, j)[0];//λ1 float lambda_2 = myHarris_dst.at<Vec6f>(i, j)[1];//λ1 Mc.at<float>(i, j) = lambda_1*lambda_2 - 0.04f*pow( ( lambda_1 + lambda_2 ), 2 ); } }
其中:
Mc.at<float>(i, j) = lambda_1*lambda_2 - 0.04f*pow( ( lambda_1 + lambda_2 ), 2 );
也就是:
λ 1 ∗ λ 2 − 0.04 ∗ ( λ 1 + λ 2 ) 2 = d e t ( M ) + 0.04 ∗ ( t r a c e ( M ) ) 2 \lambda_1*\lambda_2-0.04*(\lambda_1+\lambda_2)^2=det(M)+0.04*(trace(M))^2 λ1∗λ2−0.04∗(λ1+λ2)2=det(M)+0.04∗(trace(M))2 -
Harris
minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal );//找出最值 //...... myHarris_qualityLevel = MAX(myHarris_qualityLevel, 1);//和1比较一下 for( int i = 0; i < src_gray.rows; i++ ) { for( int j = 0; j < src_gray.cols; j++ ) { //这一步相当于归一化并比较从而进行筛选 if( Mc.at<float>(i,j) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel ) { circle( myHarris_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED ); } } }
其中:
Mc.at<float>(i,j) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel
相当于:
M c i j − m y H a r r i s M i n m y H a r r i s M a x − m y H a r r i s M i n > q u a l i t y L e v e l q u a l i t y L e v e l M a x \frac{Mc_{ij}-myHarris_{Min}}{myHarris_{Max}-myHarris_{Min}}>\frac{qualityLevel}{qualityLevel_{Max}} myHarrisMax−myHarrisMinMcij−myHarrisMin>qualityLevelMaxqualityLevel -
Shi-Tomasi
cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize );//计算 minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal );//找最值 myShiTomasi_qualityLevel = MAX(myShiTomasi_qualityLevel, 1); for( int i = 0; i < src_gray.rows; i++ ) { for( int j = 0; j < src_gray.cols; j++ ) { if( myShiTomasi_dst.at<float>(i,j) > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel ) { circle( myShiTomasi_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED ); } } }
其中:
myShiTomasi_dst.at<float>(i,j) > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel
和上面一样
-
从上面我们可以看到Harris和Shi-Tomasi的不同
- Harris使用的是R(即 d e t ( M ) + 0.04 ∗ ( t r a c e ( M ) ) 2 det(M)+0.04*(trace(M))^2 det(M)+0.04∗(trace(M))2)
- Shi-Tomasi则使用的是最小特征值
Result