1. 程式人生 > >Harris角點檢測實現詳解

Harris角點檢測實現詳解

本篇文章是對Harris角點檢測基於OpenCV 3.2.0的C++實現總結與記錄,程式程式碼力圖實現最基本的演算法步驟而無關優化,目的在於理解演算法,關於Harris角點的基本原理,本篇不予贅述,網上搜索即可,下面只列出出自Computer Vision:Algorithm and Application的演算法步驟:
1, Compute the horizontal and vertical derivatives of the image Ix and Iy by convolving the original image with derivatives of Gaussians.
2, Compute the three images corresponding to the outer products of these gradients.
3, Convolve each of these images with a larger Gaussian.
4, Compute a scalar interest measure using one of the formulas discussed above.
5, Find local maxima above a certain threshold and report them as detected feature point locations.

首先觀察這5個實現步驟,發現我們會需要x方向的高斯核、y方向的高斯核與原始高斯核,於是先實現這幾個高斯核再說。

/***
 * 引數ksize: 高斯核大小,若ksize==5,則高斯核為5*5大小
 * 引數sigma: 高斯標準差
 * 返回值:x方向上的高斯核
 * 注1:二維高斯一階導數公式為:G`(x, sigma) = -x/(sigma*sigma)*G(x, y, sigma)
 * 注2:x方向上的座標計算(5*5)為[-2 -1 0 1 2; -2 -1 0 1 2; -2 -1 0 1 2; -2 -1 0 1 2; -2 -1 0 1 2]
 */
Mat  myGetGaussianKernel_x(int
ksize, float sigma) { Mat kernel = myGetGaussianKernel(ksize, sigma); // 首先得到原始高斯核 Mat kernel_x(ksize, ksize, CV_32F, Scalar(0.0)); // 定義一階高斯核 for (int x = -ksize/2; x <= ksize/2; ++x) // 若為5*5大小,則x = (-2:1:2) { for (int i = 0; i < ksize; ++i) { kernel_x.at<float
>(i, x + ksize/2) = -x/(sigma * sigma) * kernel.at<float>(i, x + ksize/2); } } return kernel_x; } /*** * 引數ksize: 高斯核大小,若ksize==5,則高斯核為5*5大小 * 引數sigma: 高斯標準差 * 返回值:y方向上的高斯核 * 注1:二維高斯一階導數公式為:G`(y, sigma) = -y/(sigma*sigma)*G(x, y, sigma) * 注2:y方向上的座標計算(5*5)為[-2 -2 -2 -2 -2; -1 -1 -1 -1 -1; 0 0 0 0 0; 1 1 1 1 1; 2 2 2 2 2] */ Mat myGetGaussianKernel_y(int ksize, float sigma) { Mat kernel = myGetGaussianKernel(ksize, sigma); // 首先得到原始高斯核 Mat kernel_y(ksize, ksize, CV_32F, Scalar(0.0)); // 定義一階高斯核 for (int y = -ksize/2; y <= ksize/2; ++y) // 若為5*5大小,則y = (-2:1:2) { for (int i = 0; i < ksize; ++i) { kernel_y.at<float>(y + ksize/2, i) = -y/(sigma * sigma) * kernel.at<float>(y + ksize/2, i); } } return kernel_y; } /*** * 引數ksize: 高斯核大小,若ksize==5,則高斯核為5*5大小 * 引數sigma: 高斯標準差 * 返回值:高斯核 */ Mat myGetGaussianKernel(int ksize, float sigma) { if (ksize % 2 == 0) { cerr << "invalid kernel size." << endl; return Mat(1, 1, CV_32F, Scalar(-1)); } Mat kernel(ksize, ksize, CV_32F, Scalar(0.0)); Mat kernel_1d(ksize, 1, CV_32F, Scalar(0.0)); for (int x = -ksize/2; x <= ksize/2; ++x) { kernel_1d.at<float>(x + ksize/2, 0) = exp(-(x * x)/(2 * sigma * sigma)) / (sigma * sqrt(2 * CV_PI)); } kernel = kernel_1d * kernel_1d.t(); // 這裡用兩個一維相乘得到 return kernel; }

各種高斯核得到之後,就開始進行Harris角點檢測的步驟了,下面上程式碼以及註釋:

/***
 *引數img:要進行角點檢測的輸入
 *引數featurePts:儲存角點位置
 */
void HarrisCornerDetector(Mat img, vector<Point> &featurePts)
{
    img.convertTo(img, CV_64FC1);
    Mat img_x, img_y;
    // 1, Compute the horizontal and vertical derivatives of the image Ix and Iy by convolving the original image with derivatives of Gaussians.
    Mat gau_x = myGetGaussianKernel_x(5, 1.0);
    Mat gau_y = myGetGaussianKernel_y(5, 1.0);
    filter2D(img, img_x, img.depth(), gau_x);
    filter2D(img, img_y, img.depth(), gau_y);

    // 2, Compute the three images corresponding to the outer products of these gradients.
    // 3, Convolve each of these images with a larger Gaussian.
    Mat img_x2, img_y2, img_xy;
    Mat gau = myGetGaussianKernel(9, 2.0); // 此處的高斯核要larger,所以我定義了9*9, sigma = 2.0的高斯核,larger的影響是這兩個引數的增大使角點更為稀疏
    filter2D(img_x.mul(img_x), img_x2, img_x.depth(), gau);
    filter2D(img_y.mul(img_y), img_y2, img_y.depth(), gau);
    filter2D(img_x.mul(img_y), img_xy, img_x.depth(), gau);

    //4, Compute a scalar interest measure using one of the formulas discussed above.
    Mat cim(img.rows, img.cols, CV_64FC1, Scalar(0.0));
    for (int i = 0; i < cim.rows; ++i)
    {
        for (int j = 0; j < cim.cols; ++j)
        {
            // 這個公式採用了det(A)/tr(A)
            cim.at<double>(i, j) = (img_x2.at<double>(i, j) * img_y2.at<double>(i, j)
                                    - img_xy.at<double>(i, j) * img_xy.at<double>(i, j))
                                    /(img_x2.at<double>(i, j) + img_y2.at<double>(i, j));
        }
    }
    // 5, Find local maxima above a certain threshold and report them as detected feature point locations.
    for (int i = 1; i < cim.rows - 1; ++i)
    {
        for (int j = 1; j < cim.cols - 1; ++j)
        {
            // 下面的for迴圈就是進行3*3視窗的非最大值抑制以及閾值處理
            double lmax = cim.at<double>(i, j);
            for (int x = -1; x <= 1; ++x)
            {
                for (int y = -1; y <= 1; ++y)
                {
                    if (cim.at<double>(i + x, j + y) > lmax)
                    {
                        lmax = cim.at<double>(i + x, j + y);
                    }
                }
            }
            double thresh = 30.0;
            // 選擇區域性最大值且最大值大於閾值的點作為角點
            if (cim.at<double>(i, j) == lmax && lmax > thresh)
            {
                // 這裡要注意一下i和j互換一下,這裡的i表示行數,在畫角點時代表的是OpenCV座標系的y座標,相應的j代表的是x座標
                featurePts.push_back(Point(j, i));
            }
        }
    }
}

下面進行測試:

#include <iostream>
#include <vector>
#include <cmath>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

Mat  myGetGaussianKernel(int ksize = 5, float sigma = 1.0);
Mat  myGetGaussianKernel_x(int ksize = 5, float sigma = 1.0);
Mat  myGetGaussianKernel_y(int ksize = 5, float sigma = 1.0);
void HarrisCornerDetector(Mat img, vector<Point> &featurePts);

int main()
{
    Mat img = imread("lena.tiff", IMREAD_GRAYSCALE);
    vector<Point> featurePts;
    HarrisCornerDetector(img, featurePts);
    for (int i = 0; i < featurePts.size(); ++i)
    {
        circle(img, featurePts[i], 5, Scalar(255));
    }
    imshow("Harris Corner", img);
    waitKey(0);
    return 0;
}

以下為測試結果:
這裡寫圖片描述

相關推薦

Harris檢測實現

本篇文章是對Harris角點檢測基於OpenCV 3.2.0的C++實現總結與記錄,程式程式碼力圖實現最基本的演算法步驟而無關優化,目的在於理解演算法,關於Harris角點的基本原理,本篇不予贅述,網上搜索即可,下面只列出出自Computer Vision:Al

Harris檢測演算法

Harris角點演算法 特徵點檢測廣泛應用到目標匹配、目標跟蹤、三維重建等應用中,在進行目標建模時會對影象進行目標特徵的提取,常用的有顏色、角點、特徵點、輪廓、紋理等特徵。現在開始講解常用的特徵點檢測,其中Harris角點檢測是特徵點檢測的基礎,提出了應用鄰近畫素

Harris檢測原理外加原始碼分析

 網上有很多Harris角點檢測的資料,但是或多或少有一些缺陷,有的講清楚了原理,卻沒有給出程式碼的實現,有的給出了程式碼的實現,卻沒給出原理性的解釋。為此,我找出了幾篇部落格,將他們綜合整理在一起,有一套理論到程式碼的完整實現過程,這才是學一門演算法或運算元的正確方法。

Python 實現Harris 檢測

具體原理見Feature extraction & image processing for computer vision (3rd edition) 4.4.1.4小節 # Harris Corner Detector # Code - 4.18

Harris檢測原理與opencv(python)實現

在學習時主要參考了1.http://blog.csdn.net/xiaowei_cqu/article/details/7805206和opencv-python官方的關於harris的文件(http://opencv-python-tutroals.readthedocs

Harris檢測原理及C++實現

1. 首先,我們不禁要問什麼是harris角點?        對於角點,到目前為止還沒有明確的數學定義。但是你可以認為角點就是極值點,即在某方面屬性特別突出的點。一般的角點檢測都是對有具體定義的、或者是能夠具體檢測出來的興趣點的檢測。這意味著興趣點可以是角點,是在某些

Harris檢測實現(cv::Mat && c++)

原文連結或Google “A COMBINED CORNER AND EDGE DETECTOR”可以找到Harris角點檢測的論文。 簡單的概括一下,Harris角點檢測的原理為,通過計算論文中的R來判斷某一個畫素點是否為角點,通常情況下,當R為正數且較大時,該點為角點。

Harris檢測原理及實現

一、原理 二、實現 close all; clear all; I=imread('test.tif'); [posX,posY]=harris(I); figure;imshow(I); hol

第十一節、Harris檢測原理

str 物體 per 權重 模式 windows www http 特定 OpenCV可以檢測圖像的主要特征,然後提取這些特征、使其成為圖像描述符,這類似於人的眼睛和大腦。這些圖像特征可作為圖像搜索的數據庫。此外,人們可以利用這些關鍵點將圖像拼接起來,組成一個更大的圖像,比

opencv-檢測Harris檢測

trunc get data 圖像旋轉 ror 協方差矩陣 -a double 特定 轉自:https://blog.csdn.net/poem_qianmo/article/details/29356187 先看看程序運行截圖: 一、引言:關於興趣點(i

Opencv Harris檢測

demo one pla fault end ges for using opencv #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namesp

OpenCv-C++-Harris檢測

首先,感謝賈志剛老師的課程教學。 理論部分: 我現在將程式碼放入: #include<opencv2/opencv.hpp> #include<iostream> #include<math.h> using namespace cv; using

OpenCV-Python系列·第二十五集:Harris檢測

Tip:Harris角點檢測 # -*- coding: utf-8 -*- """ Created on Sat Sep 22 21:18:41 2018 @author: Administrat

Harris檢測原理

1. 首先,我們不禁要問什麼是harris角點?        對於角點,到目前為止還沒有明確的數學定義。但是你可以認為角點就是極值點,即在某方面屬性特別突出的點。一般的角點檢測都是對有具體定義的、或者是能夠具體檢測出來的興趣點的檢測。這意味著興趣點可以是角點,是在某些屬性

OpenCV入門:Harris檢測

Harris角點檢測 #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; /* Harris角點檢測:void cornerH

MATLAB——Harris檢測

為完成對棋盤標板的角點檢測,特此記錄。 角點:最直接的定義為在水平、垂直兩個方向上變化均較大的點 最常用的角點檢測演算法為Harris角點檢測方法,原理如下: 計算影象I(x,y)在X和Y兩個方向的梯度Ix、Iy 計算影象兩個方向梯度的乘積 使用高斯函式對Ix^2、

Harris檢測+sift描述匹配

    最近用到:Harris檢測影象中邊緣處的特徵點,並且需要兩張圖特徵點匹配起來。Harris只是一個角點檢測的演算法,最終只得到特徵點座標,想要匹配需要描述,而Harris是單尺度的,自己寫描述函式又有些麻煩。找到MATLAB和opencv都有整合的函式:

【OpenCV3經典程式設計100例】(24)2D特徵:Harris檢測cornerHarris()

一、2d特徵相關知識Learn about how to use the feature points detectors, descriptors and matching inside OpenCV

Harris檢測原理分析

http://blog.csdn.net/newthinker_wei/article/details/45603583 http://www.360doc.com/content/15/1212/23/20007814_519967668.shtml 本文將該文拷

harris檢測計算詳細步驟

說明 某人說,演算法看不懂,公式不明白,舉個栗子咯,能看到具體數值的那種。 好吧,舉個最簡單的角點檢測演算法吧。以下程式碼為matlab。 步驟 一、生成影象 構造一個棋盤影