harris角点_(三十七)角点检测----shi-tomas

8d08194d6b12426580697c59bb041e8c.png

时间为友,记录点滴。

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

优化思路是什么?

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

  1. 先上数据集:

a21622416e311567d65175b5de849cd4.png

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

80d65dae30e88d419c8ddf1f77ba2e69.png

核心思想是:

  • 特征值都比较大时,即窗口中含有角点
  • 特征值一个较大,一个较小,窗口中含有边缘
  • 特征值都比较小,窗口处在平坦区域

所以,Harris引入了公式:

3. 简化算法

从数据集上看,角点的

都是比较大的,如果我们选择特征值中较小的一个大于最小阈值,是不是也会得到强角点?答案是肯定的。

a975ab2e6d0cd44f8b9b90fd77f6f0e2.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<Point>
  • maxCorners设置最大角点数
  • qualityLevel最小可接受的向量值,常取0.01
  • minDistance两点之间的最小距离
  • Mat()未设置感兴趣区域
  • blockSize计算导数的窗口大小
  • useHarrisDetector是否使用Harris角点检测
  • k使用Harris角点检测时的k值,使用Harris角点检测时才有意义

好了,就这么多,让我们看看shi-tomas是不是要比Harris快。

C++

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include<time.h>

using 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;
}

2dbd64ea13daf5bcf32afbf77c00e9de.png
运行结果

5c354a41697dc6bba5fa5bf9c1d8b10f.png
在效果相差不大的情况下,时间还是差别比较大的。

Python:

注意:

1. 获取进程时间的接口:time.process_time()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:lowkeyway time:10/22/2019

import sys
import numpy as np
import cv2 as cv
import time

def 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)

64b748164b7f8f14d6d7069e3015499b.png
运行结果

db50e7f909d38f797921cf88e2012354.png
时间信息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值