文章目录
- GFTTDetector功能
- OpenCV中GFTTDetector类
- reference
欢迎访问个人网络日志🌹🌹知行空间🌹🌹
这是使用imgproc.hpp
中的goodFeaturesToTrack
函数封装的类,其使用和goodFeaturesToTrack
函数基本相似。
GFTTDetector功能
GFTTDetector
类用来提取对线的角点特征,角点检测(Corner Detection)也称为特征点检测,是图像处理和计算机视觉中用来获取图像局部特征点的一类方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模以及目标识别等领域中。
最常用的角点检测算法有梯度直方图HOG
,Haar
特征和Haris
角点检测,上面这三种在之前都介绍过,
1.Haar特征
2.梯度直方图HOG
3.HS角点检测
这些方法都是使用了图像中的局部信息提取了局部特征。
如同在HS角点检测
中介绍的,图像灰度的变化可以分成3种情况:
- 在两个方向上灰度变化剧烈,角点
- 在单个方向上灰度变化剧烈,边
- 在两个方向上灰度变化都不大,平坦区域
如下图:
对于给定图像
I
(
x
,
y
)
I(x, y)
I(x,y)上一个宽高为
w
×
h
w \times h
w×h的patch
窗口,计算该窗口平移一段微小距离时各个像素值差的平方和为:
E ( μ , v ) = ∑ x w ∑ y h ω ( x , y ) [ I ( x + μ , y + v ) − I ( x , y ) ] 2 E(\mu,v)=\sum_x^w\sum_y^h\omega(x,y)[I(x+\mu, y+v)-I(x,y)]^2 E(μ,v)=x∑wy∑hω(x,y)[I(x+μ,y+v)−I(x,y)]2
omega(x,y)
是窗口函数,可以使用窗口中的像素均值或者使用高斯函数。
根据泰勒公式展开上式:
I ( x + μ , y + v ) ≈ I ( x , y ) + I x ( x , y ) μ + I y ( x , y ) v I(x+\mu, y+v)\approx I(x,y)+I_x(x,y)\mu+I_y(x,y)v I(x+μ,y+v)≈I(x,y)+Ix(x,y)μ+Iy(x,y)v
故,
E ( μ , v ) ≈ [ u , v ] M ( x , y ) [ μ v ] E(\mu,v)\approx[u,v]M(x, y)\begin{bmatrix} \mu\\ v \end{bmatrix} E(μ,v)≈[u,v]M(x,y)[μv]
其中,
M ( x , y ) = [ I x 2 I x I y I x I y I y 2 ] = [ A C C B ] M(x, y)=\begin{bmatrix} I_x^2 & I_xI_y\\ I_xI_y &I_y^2 \end{bmatrix} = \begin{bmatrix} A & C\\ C & B \end{bmatrix} M(x,y)=[Ix2IxIyIxIyIy2]=[ACCB]
从 M ( x , y ) M(x, y) M(x,y)的定义可以看到,对于角点有左右边沿或上下边沿组成, I x I_x Ix或 I y I_y Iy总有一个近似于0,因此对于角点有,
M ( x , y ) = [ I x 2 0 0 I y 2 ] M(x, y)=\begin{bmatrix} I_x^2 & 0\\ 0 &I_y^2 \end{bmatrix} M(x,y)=[Ix200Iy2]
这里考虑的是左右上下边沿与图像高宽平行组成的角点,对于旋转和缩放的角点需要单独讨论。
在判断是否为角点时,为了减少运算量,通常并不会计算M
的特征值,而使用M
的行列式和迹来计算:
R = d e t ( M ) − α ( t r a c e ( M ) ) 2 R = det(M) - \alpha(trace(M))^2 R=det(M)−α(trace(M))2
α \alpha α是一个经验常数,用来控制检测到角点的数量, α \alpha α值越小检测到的角点越多,相应的质量也会下降。
- 当 I x I_x Ix和 I y I_y Iy都很大时, R R R取较大正值,说明是角点
- 当 I x I_x Ix与 I y I_y Iy一大一小时, R R R取较大负值,说明是边
- 当 I x I_x Ix与 I y I_y Iy都很小时, R R R绝对值较小,说明是平坦区域
GFTTDetector
中使用的是Shi-Tomasi
角点检测器,其直接使用
R
=
m
i
n
(
I
x
,
I
y
)
R=min(I_x, I_y)
R=min(Ix,Iy)作为角点的度量,减少了超参数和运算量。
OpenCV中GFTTDetector类
调用GFTTDetector
类中的静态函数create
可以创建cv::Ptr<GFTTDetector>
。
create
函数参数为:
static Ptr<GFTTDetector> cv::GFTTDetector::create (
int maxCorners = 1000,
double qualityLevel = 0.01,
double minDistance = 1,
int blockSize = 3,
bool useHarrisDetector = false,
double k = 0.04
)
maxCorners
控制最多检测到的角点数量qualityLevel
控制角的质量水平,例如最好的是1500
,qualityLevel
为0.01
,则quality measure
小于1500*0.01
的将被舍弃minDistance
角点之间的最小距离blockSize
计算梯度相关矩阵时使用的邻域大小useHarrisDetector
是否使用Harris角点检测k,Harris
角点检测的超参数
代码示例:
#include <memory>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
class TestGFTTDetector
{
public:
typedef std::shared_ptr<TestGFTTDetector> Ptr;
TestGFTTDetector();
~TestGFTTDetector() = default;
void compute(cv::Mat &image);
private:
cv::Ptr<cv::GFTTDetector> gftt_ptr_;
std::vector<cv::KeyPoint> keypoints_;
};
TestGFTTDetector::TestGFTTDetector()
{
gftt_ptr_ = cv::GFTTDetector::create(1000, 0.1, 10);
}
void TestGFTTDetector::compute(cv::Mat &image)
{
cv::Mat mask(image.size(), CV_8UC1, 255);
gftt_ptr_->detect(image, keypoints_, mask);
for(auto &kp : keypoints_) {
cv::circle(image, kp.pt, 3, cv::Scalar(255, 0, 0));
}
std::cout << "keypoints_.size: " << keypoints_.size() << std::endl;
cv::imshow("gftt_detector_result", image);
cv::waitKey(0);
cv::goodFeaturesToTrack()
}
int main(int argc, char **argv)
{
TestGFTTDetector::Ptr gftt = std::make_shared<TestGFTTDetector>();
cv::Mat image = cv::imread(argv[1]);
gftt->compute(image);
return 0;
}
检测结果如下:
可以看到检测的结果还是很好的,不过中间大六边形上面的两个角点还是没有检测到,感兴趣可以改小 k k k的值试一下。
使用的图片在OpenCV
代码仓库中opencv-4.5.5/samples/data/blox.jpg
欢迎访问个人网络日志🌹🌹知行空间🌹🌹
reference
- 1.https://senitco.github.io/2017/06/18/image-feature-harris/
- 2.https://docs.opencv.org/4.5.5/df/d21/classcv_1_1GFTTDetector.html