文章目录

一、常用图像特征描述

  • SIFT、SURF、HOG、Haar、LBP、KAZE、AKAZE、BRISK

关于详情查看 ​​OpenCV—python 角点特征检测之二(SIFT、SURF、ORB)​​ SIFT 是用于描述图像中的局部特征,在空间尺度(使用高斯卷积核实现多尺度空间)中寻找极值点(LoG近似DoG找到关键点),并且提取出其位置、尺度、旋转不变量,因此具有尺度和旋转不变的性质。


SURF

与sift的算法相似,只是sift算法更加稳定,检测得到的特征点更多。但是surf的运算简单,运算时间更短一些。
surf最大的特点是采用 HARR 特征以及​​积分图像​​。


HOG

方向梯度直方图。用来表示图像的物体特征,算法流程如下:
【图像预处理:伽马校正和灰度化】 -> 【计算每一个像素点的梯度值,得到梯度图】 -> 【计算梯度直方图】 -> 【对16*16大小的block归一化】 -> 【得到HOG特征向量】


Haar Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征。它分为三类:边缘特征、线性特征、中心特征和对角线特征。用黑白两种矩形框组合成特征模板,矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述在特定方向(水平、垂直、对角)上有明显像素模块梯度变化的图像结构。

OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_角点


LBP

LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子;它具有旋转不变性灰度不变性等显著的优点。它是首先由T. Ojala, M.Pietikäinen, 和D. Harwood 在1994年提出,用于纹理特征提取。而且,提取的特征是图像的局部的纹理特征; ​


KAZE

​KAZE Features​​​ 算法是由法国学者在在2012年的ECCV会议​​ (论文) ​​中提出的, 是一种比SIFT更稳定的特征检测算法。KAZE特征检测是在图像域中进行非线性扩散处理的过程。

SITF、SURF算法是通过线性尺度空间,在线性尺度空间来检测特征点的,容易造成边界模糊和细节丢失;而KAZE算法是通过构造非线性尺度空间,并在非线性尺度空间来检测特征点,保留了更多的图像细节。
KAZE算法主要包括以下步骤:
(1) 非线性尺度空间的构建;
(2) 特征点的检测与精确定位;
(3) 特征点主方向的确定;
(4) 特征描述子的生成。 ​


AKAZE

AKAZE是KAZE的加速版本。KAZE在构建非线性空间的过程中很耗时。
在非线性扩散滤波方面:AKAZE中将Fast Explicit Diffusion(FED)加入到金字塔框架可以dramatically speed-up。 在描述子方面:AKAZE使用了更高效的Modified Local Difference Binary(M-LDB),可以从非线性空间中利用梯度信息gradient information。M-LDB是旋转和尺度不变的,并且对内存的要求更低。 github地址:​​http://www.robesafe.com/personal/pablo.alcantarilla/kaze.html​​ 在AKAZE算法中默认使用二进制描述符,故汉明距离进行比较


BRISK

Binary Robust Invariant Scalable Keypoints。它是一种二进制的特征描述算子。它具有较好的旋转不变性、尺度不变性,较好的鲁棒性等。在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。
在图像配准应用中,速度比较:SIFT<SURF<BRISK<FREAK<ORB。 算法流程:

  1. 特征点检测(建立尺度空间、特征点检测、非极大值抑制、亚像素插值)
  2. 特征点描述(高斯滤波、局部梯度计算、特征描述符)
  3. 匹配方法(汉明距离进行比较)

图像特征描述子用于: Detection、Description、Matching

二、Harris角点检测

1988 年的文章《A CombinedCorner and Edge Detector》中就已经提出了焦点检测的方法,被称为Harris 角点检测。
关于理论详情请查看:​​​OpenCV—python 角点特征检测之一(cornerHarris、Shi-Tomasi、FAST)​

角度响应:
OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_opencv_02

InputArray src,     输入图像

OutputArray dst,     输出图像

int blockSize,     计算时候的矩阵大小

int ksize,        窗口大小

double k,       阈值:计算角度响应时候的参数大小,默认在0.04~0.06

int borderType = BORDER_DEFAULT   边界处理

)

头文件 ​​image_feature_all.h​​:声明类与公共函数

#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;


class ImageFeature {
public:
void harris_demo(Mat& image);
void shi_tomasi_demo(Mat& image);
void custome_corner_demo(Mat& image);
};

主函数​​main.cpp​​调用该类的公共成员函数

#include "image_feature_all.h"



int main(int argc, char** argv) {
const char* img_path = "D:\\Desktop\\xiaomuren.jpg";
Mat image = imread(img_path);
if (image.empty()) {
cout << "图像数据为空,读取文件失败!" << endl;
}
ImageFeature imgfeature;
imgfeature.harris_demo(image);
imgfeature.shi_tomasi_demo(image);
imgfeature.custome_corner_demo(image);

imshow("image", image);
waitKey(0);
destroyAllWindows();
return 0;
}

演示Harris角点检测

源文件 ​​feature_extract.cpp​​:实现类与公共函数

#include "image_feature_all.h"

void ImageFeature::harris_demo(Mat& image) {
Mat gray_img;
cvtColor(image, gray_img, COLOR_BGR2GRAY);
int thresh_ = 80;

Mat dst = Mat::zeros(gray_img.size(), CV_32FC1);
Mat norm_dst, norm_scale_dst;
int blocksize = 2;
int ksize = 3;
double k = 0.04;
cornerHarris(gray_img, dst, blocksize, ksize, k, BORDER_DEFAULT);
normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(norm_dst, norm_scale_dst);
cout << "norm_scale_dst.type()=" << norm_scale_dst.type() << endl;

Mat result_img = image.clone();
for (int row = 0; row < result_img.rows; row++) {
uchar* row_ptr = norm_scale_dst.ptr(row);
for (int col = 0; col < result_img.cols; col++) {
int value = (int)*row_ptr++;
if (value > thresh_) {
circle(result_img, Point(col, row), 2, Scalar(0, 0, 255), 1, 8, 0);
}
}
}
imwrite("D:\\Desktop\\harris_"+ to_string(thresh_)+".jpg", result_img);
}

OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_尺度空间_03

三、Shi-Tomasi角点检测

跟Harris角点检测的理论几乎完全一致,唯一不同的是在使用矩阵特征值 OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_角点_04

角度响应:OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_角点_05

InputArray

image,    输入图像

OutputArray corners,  输出角点vector<point2d>

int maxCorners,      返回角点的数目,若检测角点数目大于maxCorners,则返回前maxCorners数目。

double qualityLevel,   最小可接受的向量值 0.01,

double minDistance,  两个角点之间的最小距离(欧几里得距离)

InputArray mask = noArray(),

int blockSize = 3,    导数微分不同的窗口大小

bool useHarrisDetector = false, 是否使用Harris角点检测

double k = 0.04

);

void ImageFeature::shi_tomasi_demo(Mat& image) {
Mat gray_img;
cvtColor(image, gray_img, COLOR_BGR2GRAY);

int num_colors[] = { 10,20,40,80 };

double qualityLevel = 0.01;
double minDistance = 10;
int blockSize = 3;
bool useHarris = false;
double k = 0.04;

RNG rng(1125);
for (size_t i = 0; i < 4; i++)
{
Mat result_img = image.clone();
vector<Point2f> corners;
corners.reserve(num_colors[i]);
goodFeaturesToTrack(gray_img, corners, num_colors[i], qualityLevel, minDistance, Mat(), blockSize, useHarris, k);

// 可视化角点
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
for (size_t i = 0; i < corners.size(); i++) {
circle(result_img, corners[i], 2, color, 2, 8);
}
imshow("result_img"+to_string(num_colors[i]), result_img);
}
}

OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_角点_06

四、自定义角点检测器

基于Harris与Shi-Tomasi角点检测

  • 首先通过计算矩阵OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_opencv_07得到OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_角点_08
  • 然后自己设置阈值实现计算出阈值得到有效响应值的角点位置

使用 OpenCV 函数 cornerEigenValsAndVecs 来计算像素对应的本征值和本征向量来确定其是否是角点。
使用OpenCV 函数 cornerMinEigenVal 通过最小化本征值来进行角点检测。
用上述两个函数实现一个定制化的Harris detector,类似Shi-Tomasi检测子。

函数简介:

InputArray src,     


OutputArray dst,

int blockSize,

int ksize,

int borderType = BORDER_DEFAULT

)


InputArray src,

OutputArray dst,

int blockSize,

int ksize = 3,

int borderType = BORDER_DEFAULT

)

void ImageFeature::custome_corner_demo(Mat& image) {
Mat gray_dst;
cvtColor(image, gray_dst, COLOR_BGR2GRAY);

// 自定义harris角点检测:计算本征值本征向量,获取其最大最小值。
int blockSize = 3;
int kSize = 3;
double k = 0.04;

Mat harris_dst = Mat::zeros(image.size(), CV_32FC1);
Mat harris_tmp = Mat::zeros(image.size(), CV_32FC(6));
cornerEigenValsAndVecs(gray_dst, harris_tmp, blockSize, kSize, 4);

for (size_t row = 0; row < gray_dst.rows; row++) {
Vec6f* harris_tmp_ptr = harris_tmp.ptr<Vec6f>(row);
float* harris_dst_ptr = harris_dst.ptr<float>(row);
for (size_t col = 0; col < gray_dst.cols; col++) {
double lambda1 = harris_tmp_ptr[col][0];
double lambda2 = harris_tmp_ptr[col][1];
*harris_dst_ptr++ = (float)(lambda1 * lambda2 - k * pow((lambda1 + lambda2), 2));
}
}
double harris_minVal = 0, harris_maxVal = 0;
minMaxLoc(harris_dst, &harris_minVal, &harris_maxVal, 0, 0, Mat());

// 自定义harris角点检测:可视化
int qualityLevel = 40; //修改该参数,显示不同效果。
int max_qualityLevel = 100;
Mat Harris_copy = image.clone();
float t = harris_minVal + (((double)qualityLevel / max_qualityLevel) * (harris_maxVal - harris_minVal));
RNG rng;
for (size_t row = 0; row < image.rows; row++) {
float* harris_dst_ptr = harris_dst.ptr<float>(row);
for (size_t col = 0; col < image.cols; col++) {
float v = *harris_dst_ptr++;
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
if (v > t) {
circle(Harris_copy, Point(col, row), 1, color, 2, 8, 0);
}
}
}
imshow("custom_Harris", Harris_copy);


// 自定义Shi-Tomas角点检测: 最小化本征值来进行角点检测
double ShiTomas_minVal = 0, ShiTomas_maxVal = 0;
Mat ShiTomas_dst = Mat::zeros(image.size(), CV_32FC1);

cornerMinEigenVal(gray_dst, ShiTomas_dst, blockSize, kSize, 4);
minMaxLoc(ShiTomas_dst, &ShiTomas_minVal, &ShiTomas_maxVal, 0, 0, Mat());

// 自定义Shi-Tomas角点检测:可视化
float t2 = ShiTomas_minVal + (((double)qualityLevel / max_qualityLevel) * (ShiTomas_maxVal - ShiTomas_minVal));
Mat ShiTomasi_copy = image.clone();
for (int row = 0; row < gray_dst.rows; row++){
float* ShiTomas_dst_ptr = ShiTomas_dst.ptr<float>(row);
for (int col = 0; col < gray_dst.cols; col++){
float val = *ShiTomas_dst_ptr++;
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
if (val > t2) {
circle(ShiTomasi_copy, Point(col, row), 4, color, -1, 8, 0);
}
}
}
imshow("custom_ShiTomasi", ShiTomasi_copy);
}

OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)_尺度空间_09