harris角点检测_角点检测shitomas

点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

本文由知乎作者lowkeyway授权转载,不得擅自二次转载。原文链接:https://zhuanlan.zhihu.com/p/87745981

如果真真得跑过Harris,你肯定会有这样的抱怨:太**的慢了。是的,J.Shi和C.Tomasi也是这么想的,所以,他们俩1994年在其论文“Good Features to Track”中,提出了一种对Harris角点检测算子的改进算法——Shi-Tomasi角点检测算子。

优化思路是什么?

既然是优化,我们先回忆一下Harris怎么做到的?

  1. 先上数据集:

86cc9d40f278e3fccb00190a1ebc174a.png

2. 从数据集中,引申出来Harris

a42967f5e63f262cece97a662e675edf.png

核心思想是:

  • 特征值都比较大时,即窗口中含有角点

  • 特征值一个较大,一个较小,窗口中含有边缘

  • 特征值都比较小,窗口处在平坦区域

所以,Harris引入了公式:

588f3f46-9c32-eb11-8da9-e4434bdf6706.svg

3. 简化算法

从数据集上看,角点的 5c8f3f46-9c32-eb11-8da9-e4434bdf6706.svg 都是比较大的,如果我们选择特征值中较小的一个大于最小阈值,是不是也会得到强角点?答案是肯定的。

64a1e2bedbff3a6b2ada58b54fe0965e.png

Harris 算法最原始的定义是将黑塞矩阵 648f3f46-9c32-eb11-8da9-e4434bdf6706.svg 的行列式值与 M 的迹相减,再将差值同预先给定的阈值进行比较。所以shi-tomas提出来的公式就为:

668f3f46-9c32-eb11-8da9-e4434bdf6706.svg

好了,有了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
运行结果
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
运行结果
16100cc2ef363f6ffbb72f019dd068b0.png
时间信息

上述内容,如有侵犯版权,请联系作者,会自行删文。

重磅!3DCVer-学术交流群已成立

欢迎加入我们公众号读者群一起和同行交流,目前有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、CV入门、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。

ac939c6147375df5fb59457934e39aa6.png

▲长按加群或投稿

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款 13bdb9585a365404fe8e2824c413a498.png  圈里有高质量教程资料、可答疑解惑、助你高效解决问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答这个问题。Harris角点检测算法是一种经典的角点检测算法,其原理是通过计算图像的局部灰度变化来寻找角点。以下是Python实现Harris角点检测算法的步骤: 1. 定义窗口大小和滑动步长。 2. 计算每个像素点的梯度值。 3. 计算每个像素点的M矩阵。 4. 计算每个像素点的响应值R。 5. 对响应值进行非极大值抑制。 6. 对剩余的角点进行阈值处理。 下面是Python实现Harris角点检测算法的代码示例: ```python import cv2 import numpy as np # 读取图像 img = cv2.imread('test.png', 0) # 定义窗口大小和滑动步长 win_size = 3 step_size = 1 # 定义参数k k = 0.04 # 计算x和y方向的梯度 dx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) dy = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # 计算M矩阵 M11 = cv2.boxFilter(dx*dx, -1, (win_size, win_size)) M12 = cv2.boxFilter(dx*dy, -1, (win_size, win_size)) M22 = cv2.boxFilter(dy*dy, -1, (win_size, win_size)) # 计算响应值R detM = M11 * M22 - M12 * M12 traceM = M11 + M22 R = detM - k * traceM * traceM # 非极大值抑制 R_max = np.max(R) R_th = 0.01 * R_max R_nms = np.zeros_like(R) for i in range(step_size, img.shape[0]-step_size): for j in range(step_size, img.shape[1]-step_size): if R[i, j] > R_th and R[i, j] == np.max(R[i-step_size:i+step_size+1, j-step_size:j+step_size+1]): R_nms[i, j] = R[i, j] # 显示角点 corners = np.where(R_nms > 0) for i in range(len(corners[0])): cv2.circle(img, (corners[1][i], corners[0][i]), 3, (0, 255, 0), -1) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 注意,这里的`test.png`是一个灰度图像,如果要使用彩色图像,需要先将其转换为灰度图像。 希望这个回答能够帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值