点击上方“3D视觉工坊”,选择“星标”
干货第一时间送达
本文由知乎作者lowkeyway授权转载,不得擅自二次转载。原文链接:https://zhuanlan.zhihu.com/p/87745981
如果真真得跑过Harris,你肯定会有这样的抱怨:太**的慢了。是的,J.Shi和C.Tomasi也是这么想的,所以,他们俩1994年在其论文“Good Features to Track”中,提出了一种对Harris角点检测算子的改进算法——Shi-Tomasi角点检测算子。
优化思路是什么?
既然是优化,我们先回忆一下Harris怎么做到的?
先上数据集:
![86cc9d40f278e3fccb00190a1ebc174a.png](https://img-blog.csdnimg.cn/img_convert/86cc9d40f278e3fccb00190a1ebc174a.png)
2. 从数据集中,引申出来Harris
![a42967f5e63f262cece97a662e675edf.png](https://img-blog.csdnimg.cn/img_convert/a42967f5e63f262cece97a662e675edf.png)
核心思想是:
特征值都比较大时,即窗口中含有角点
特征值一个较大,一个较小,窗口中含有边缘
特征值都比较小,窗口处在平坦区域
所以,Harris引入了公式:
3. 简化算法
从数据集上看,角点的 都是比较大的,如果我们选择特征值中较小的一个大于最小阈值,是不是也会得到强角点?答案是肯定的。
![64a1e2bedbff3a6b2ada58b54fe0965e.png](https://img-blog.csdnimg.cn/img_convert/64a1e2bedbff3a6b2ada58b54fe0965e.png)
Harris 算法最原始的定义是将黑塞矩阵 的行列式值与 M 的迹相减,再将差值同预先给定的阈值进行比较。所以shi-tomas提出来的公式就为:
好了,有了Harris做铺垫,shi-tomas就好理解多了。
老规矩,OpenCV也实现了shi-tomas算法:
CV_EXPORTS_W void goodFeaturesToTrack( InputArray image, OutputArray corners,
int maxCorners, double qualityLevel, double minDistance,
InputArray mask = noArray(), int blockSize = 3,
bool useHarrisDetector = false, double k = 0.04 );
(API没有用人名,而是用了他们发表的论文名称,这个纪念也是有意思)
srcGray,原灰度图像
corners检测到的角点vector
maxCorners设置最大角点数
qualityLevel最小可接受的向量值,常取0.01
minDistance两点之间的最小距离
Mat()未设置感兴趣区域
blockSize计算导数的窗口大小
useHarrisDetector是否使用Harris角点检测
k使用Harris角点检测时的k值,使用Harris角点检测时才有意义
好了,就这么多,让我们看看shi-tomas是不是要比Harris快。
C++
#include #include #include #includeusing namespace std;using namespace cv;static bool shiTomas(Mat imgOri);static bool harrisTest(Mat imgOri);RNG rng(12345);int main(){
Mat imgOri = imread("right13.jpg");if (imgOri.empty())
{
cout << "Cannot load this picture!" << endl;return false;
}
clock_t start, harrisTime, shiTomasTime;double totaltime;
Mat imgHarris = imgOri.clone();
Mat imgShiTomas = imgOri.clone();
start = clock();
harrisTest(imgHarris);
harrisTime = clock();
shiTomas(imgShiTomas);
shiTomasTime = clock();
imshow("imgOri", imgOri);
cout << "Harris takes [" << (double)(harrisTime - start) / CLOCKS_PER_SEC << "] s" << endl;
cout << "shiTomas takes [" << (double)(shiTomasTime - harrisTime) / CLOCKS_PER_SEC << "] s" << endl;
waitKey(0);return true;}static bool harrisTest(Mat imgOri){int blockSize = 2;int apertureSize = 3;double k = 0.04;
Mat imgGray, imgHarris;//showImgPara(imgGray); cvtColor(imgOri, imgGray, COLOR_BGR2GRAY);
imgHarris = Mat::zeros(imgOri.size(), imgOri.type());
cornerHarris(imgGray, imgHarris, blockSize, apertureSize, k);
Mat imgDst, imgDstScale;
imgDst = Mat::zeros(imgHarris.size(), imgHarris.type());
normalize(imgHarris, imgDst, 0, 255, NORM_MINMAX);
convertScaleAbs(imgDst, imgDstScale);for (int row = 0; row < imgDstScale.rows; row++)
{for (int col = 0; col < imgDstScale.cols; col++)
{int rsp = (int)imgDstScale.at<uchar>(row, col);if (rsp > 85)
{int b = rng.uniform(0, 256);int g = rng.uniform(0, 256);int r = rng.uniform(0, 256);
circle(imgOri, Point(col, row), 5, Scalar(b, g, r), 2);
}
}
}
imshow("imgHarris", imgOri);return true;}static bool shiTomas(Mat imgOri){int maxCorners = 500;double quality_level = 0.01;double minDistance = 0.04;
Mat imgGray, imgShiTomas;
cvtColor(imgOri, imgGray, COLOR_BGR2GRAY);
vector<Point2f> corners;
goodFeaturesToTrack(imgGray, corners, maxCorners, quality_level, minDistance, Mat(), 3, false);for (int i = 0; i < corners.size(); i++) {int b = rng.uniform(0, 256);int g = rng.uniform(0, 256);int r = rng.uniform(0, 256);
circle(imgOri, corners[i], 5, Scalar(b, g, r), 3, 8, 0);
}
imshow("imgShiTomas", imgOri);return true;}
![d28dcc7b4e8e2f42bd7f82f94d8c5cd4.png](https://img-blog.csdnimg.cn/img_convert/d28dcc7b4e8e2f42bd7f82f94d8c5cd4.png)
![6730ba0b4105ff53fd8d30b435533fb9.png](https://img-blog.csdnimg.cn/img_convert/6730ba0b4105ff53fd8d30b435533fb9.png)
Python:
注意:
1. 获取进程时间的接口:time.process_time()
#!/usr/bin/env python# -*- coding: utf-8 -*-# author:lowkeyway time:10/22/2019import sysimport numpy as npimport cv2 as cvimport timedef shiTomasTest(imgOri):
maxCorners = 500;
quality_level = 0.01;
minDistance = 0.04;
imgGary = cv.cvtColor(imgOri, cv.COLOR_BGR2GRAY)
corners = cv.goodFeaturesToTrack(imgGary, maxCorners, quality_level, minDistance)
for corner in corners:
b = np.random.randint(0, 256)
g = np.random.randint(0, 256)
r = np.random.randint(0, 256)
cv.circle(imgOri, (int(corner[0][0]), int(corner[0][1])), 2, (int(b), int(g), int(r)), 2)
cv.imshow("imgShiTomas", imgOri)def harrisTest(imgOri):
blockSize = 2
apertureSize = 3
k = 0.04
imgGary = cv.cvtColor(imgOri, cv.COLOR_BGR2GRAY)
imgHarris = cv.cornerHarris(imgGary, blockSize, apertureSize, k)
imgDst = np.zeros(imgHarris.shape, dtype=np.float32)
cv.normalize(imgHarris, imgDst, 0, 255, cv.NORM_MINMAX)
imgDstScale = cv.convertScaleAbs(imgDst)
for row in range(imgDstScale.shape[0]):
for col in range(imgDstScale.shape[1]):
if int(imgDstScale[row, col]) > 85:
b = np.random.randint(0, 256)
g = np.random.randint(0, 256)
r = np.random.randint(0, 256)
cv.circle(imgOri, (col, row), 2, (int(b), int(g), int(r)), 2)
cv.imshow("imgHarrisDst", imgOri)def main_func(argv):
imgOri = cv.imread("right13.jpg")
if imgOri is None:
print("Cannot load this picture!")
return False
imgHarris = np.copy(imgOri)
imgShiTomas = np.copy(imgOri)
start = time.process_time()
harrisTest(imgHarris)
harrisTime = time.process_time()
shiTomasTest(imgShiTomas)
shiTomasTime = time.process_time()
print("Harris takes {:.2f} s" .format(harrisTime - start))
print("Harris takes {:.2f} s" .format(shiTomasTime - harrisTime))
cv.imshow("imgOri", imgOri)
cv.waitKey(0)if __name__ == '__main__':
main_func(sys.argv)
![3b2037e589ec7215323962216c03b3af.png](https://img-blog.csdnimg.cn/img_convert/3b2037e589ec7215323962216c03b3af.png)
![16100cc2ef363f6ffbb72f019dd068b0.png](https://img-blog.csdnimg.cn/img_convert/16100cc2ef363f6ffbb72f019dd068b0.png)
上述内容,如有侵犯版权,请联系作者,会自行删文。
重磅!3DCVer-学术交流群已成立
欢迎加入我们公众号读者群一起和同行交流,目前有3D视觉、CV&深度学习、SLAM、三维重建、点云后处理、自动驾驶、CV入门、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。
▲长按加群或投稿
学习3D视觉核心技术,扫描查看介绍,3天内无条件退款![13bdb9585a365404fe8e2824c413a498.png](https://img-blog.csdnimg.cn/img_convert/13bdb9585a365404fe8e2824c413a498.png)