openCV2马拉松第19圈——Harris角点检測(自己实现)
收入囊中
- 使用OpenCV的connerHarris实现角点检測
- 自己实现Harris算法
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
E(u,v)=∑(x,y)∈W [I(x+u,y+v)−I(x,y)]2(w是我们的窗体,[u,v]是我们的shift,也就是移动)
我们想了解微小移动对E究竟有何影响
于是我们对I进行一阶泰勒展开
I(x+u,y+v)=I(x,y)+Ixu+Iyv+higherorder
terms
≈I(x,y)+Ixu+
Iyv
=I(x,y)+[Ix
Iy ][u v]T
再代入以下的公式
E(u,v)=∑[I(x+u,y+v)−I(x,y)]2(x,y)∈W
我们得到
因此,我们能够写成
当中,M是一个二阶矩矩阵,能够由我们原始图片的差分得到
我们来想像一下,假使梯度是沿着x或者y方向的,也就是说Ix = 0或者是Iy = 0,那么我们的M就是
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="350" height="120" alt="" />而M,由矩阵对角化能够写成左边的格式,我们能够得到两个特征值
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="450" height="225" alt="" />长轴短轴由特征值决定。椭圆方向由矩阵R决定,以下没实用到R,所以你能够忽略它
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
- det(M) =

- trace(M) =

要怎么计算了。det = Ix2*Iy2 - Ixy^2
trace = Ix2 + Iy2
[还有还有一种经验公式。
。我自己的实现就是採用了这一种]
1. 用sobel算子分别计算出水平梯度和垂直梯度
-1 0 1
-2 0 2
-1 0 1
-1 -2 -1
0 0 0
1 2 1
2. 计算高斯二阶矩阵,就是一个窗体里全部差分和
3.计算响应函数R
4.设置阀值
5.非极大值抑制,推断这个点的响应函数R是不是周围最大的
强调一下,harris对仿射变换仅仅有部分不变性质。平移和旋转具有covariant,可是scaling不具有。例如以下图
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
初识API
-
C++: void cornerHarris(InputArray src,
OutputArray dst, int blockSize, int ksize, double k, int borderType=BORDER_DEFAULT )
-
- src – 8比特或者是浮点数矩阵.
- dst – 存放harris响应函数,类型是CV_32FC1由于计算出的值比較大。size和src一样 .
- blockSize – 窗体大小.
- ksize – Sobel算子大小.
- k – 通常是0.04-0.06.
- borderType .
对每一个像素
计算
协方差矩阵
over
a
neighborhood. 用的是harris响应函数

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
/// Global variables
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;
char* source_window = "Source image";
char* corners_window = "Corners detected";
/// Function header
void cornerHarris_demo( int, void* );
/** @function main */
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], 1 );
cvtColor( src, src_gray, CV_BGR2GRAY );
/// Create a window and a trackbar
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
imshow( source_window, src );
cornerHarris_demo( 0, 0 );
waitKey(0);
return(0);
}
/** @function cornerHarris_demo */
void cornerHarris_demo( int, void* )
{
Mat dst, dst_norm, dst_norm_scaled;
dst = Mat::zeros( src.size(), CV_32FC1 );
/// Detector parameters
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
/// Detecting corners
cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );
/// Normalizing
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( dst_norm, dst_norm_scaled );
/// Drawing a circle around corners
for( int j = 0; j < dst_norm.rows ; j++ )
{ for( int i = 0; i < dst_norm.cols; i++ )
{
if( (int) dst_norm.at<float>(j,i) > thresh )
{
circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 );
}
}
}
/// Showing the result
namedWindow( corners_window, CV_WINDOW_AUTOSIZE );
imshow( corners_window, dst_norm_scaled );
}
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <cmath>
#include <iostream>
using namespace cv;
Mat harris(Mat &im, double sigma, int thresh, int radius){
Mat dx,dy,Ix,Iy,Ix2,Iy2,Ixy,cim;
Sobel( im, Ix, CV_64F, 1, 0, 3); //算法第一步。计算水平垂直差分
Sobel( im, Iy, CV_64F, 0, 1, 3);
int ksize = max(1, (int)(6*sigma));
if(ksize % 2 == 0)
ksize++;
GaussianBlur(Ix.mul(Ix), Ix2, Size(ksize, ksize), sigma); //算法第二步。计算二阶高斯差分矩阵
GaussianBlur(Iy.mul(Iy), Iy2, Size(ksize, ksize), sigma);
GaussianBlur(Ix.mul(Iy), Ixy, Size(ksize, ksize), sigma);
//Harris corner measure
//cim = (Ix2.*Iy2 - Ixy.^2)./(Ix2 + Iy2);
cim = (Ix2.mul(Iy2) - Ixy.mul(Ixy)) / (Ix2+Iy2); //算法第三步。计算响应函数,我使用了第二种
Mat structedElement(radius, radius, CV_8U, Scalar(1));
Mat mx,norm_cim;
normalize( cim, norm_cim, 0, 255, NORM_MINMAX, CV_8U, Mat() );
dilate(norm_cim, mx, structedElement);
norm_cim = ( norm_cim == mx) & (norm_cim>thresh); //算法第4第5步融合,非极大值抑制和阀值检測
return norm_cim;
}
int main( int, char** argv )
{
Mat src,gray;
src = imread( argv[1] );
cvtColor( src, gray, CV_RGB2GRAY );
Mat corners = harris(gray, 1.5, 30, 2);
for( int j = 0; j < corners.rows ; j++ ) {
for( int i = 0; i < corners.cols; i++ ) {
if( corners.at<unsigned char>(j,i) > 0)
{
circle( gray, Point( i, j ), 3, Scalar(0), 2, 8, 0 );
}
}
}
namedWindow("result", 1);
imshow("result", gray);
waitKey();
return 0;
}
另外附加福利
harris matlab版本号 http://www.cs.illinois.edu/~slazebni/spring13/harris.m
openCV2马拉松第19圈——Harris角点检測(自己实现)的更多相关文章
- OpenCV2马拉松第22圈——Hough变换直线检測原理与实现
计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/27220445 收入囊中 Hough变换 概率Ho ...
- OpenCV2马拉松第15圈——边缘检測(Laplace算子,LOG算子)
收入囊中 拉普拉斯算子 LOG算子(高斯拉普拉斯算子) OpenCV Laplacian函数 构建自己的拉普拉斯算子 利用拉普拉斯算子进行图像的锐化 葵花宝典 在OpenCV2马拉松第14圈--边缘检 ...
- OpenCV2马拉松第17圈——边缘检測(Canny边缘检測)
计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g 收入囊中 利用OpenCV Canny函数进行边缘检測 掌握Canny算法基本理论 ...
- MatLab角点检測(harris经典程序)
http://blog.csdn.net/makenothing/article/details/12884331 这是源博客的出处,鄙人转过来是为了更好的保存!供大家一起学习!已将原始的博客的文章的 ...
- opencv对图像进行边缘及角点检測
opencv对图像进行边缘及角点检測 先看结果: 代码: // ConsoleApplication1_812.cpp : Defines the entry point for the consol ...
- 使用nodeitk进行角点检測
前言 东莞,晴,33至27度.今天天气真好,学生陆续离开学校.忙完学生答辩事情,最终能够更新一下nodeitk.本文继续介绍node的特征识别相关内容,你会看到,採用nodeitk实现角点检測是一件十 ...
- OpenCV2马拉松第14圈——边缘检測(Sobel,prewitt,roberts)
收入囊中 差分在边缘检測的角色 Sobel算子 OpenCV sobel函数 OpenCV Scharr函数 prewitt算子 Roberts算子 葵花宝典 差分在边缘检測究竟有什么用呢?先看以下的 ...
- OpenCV2马拉松第2圈——读写图片
收入囊中 用imread读取图片 用nameWindow和imshow展示图片 cvtColor彩色图像灰度化 imwrite写图像 Luv色彩空间转换 初识API 图像读取接口 image = im ...
- OpenCV2马拉松第10圈——直方图反向投影(back project)
收入囊中 灰度图像的反向投影 彩色图像的反向投影 利用反向投影做object detect 葵花宝典 什么是反向投影?事实上没有那么高大上! 在上一篇博文学到,图像能够获得自己的灰度直方图. 反向投影 ...
随机推荐
- jquery报表插件收藏 MARK
Highcharts http://www.hcharts.cn/ 统计报表插件 jquery ui官网 http://jqueryui.com/selectmenu/#custom_render
- JS实现中英文混合文字溢出友好截取功能
在显示字符串的时候,避免字符串过长往往会对字符串进行截取操作,通常会用到js的 substr 或者 substring方法, 以及 字符串的length属性 substr() 方法可在字符串中抽取从 ...
- Node.js开发——MongoDB与Mongoose
为了保存网站的用户数据和业务数据,通常需要一个数据库.MongoDB和Node.js特别般配,因为MongoDB是基于文档的非关系型数据库,文档是按BSON(JSON的轻量化二进制格式)存储的,增删改 ...
- js权威指南学习笔记(一)类型、值和变量
1.数据类型:原始类型(primitive type) 和对象类型(object type) 原始类型包括数字.字符串和布尔值: 除数字.字符串.布尔值.null(空).undefined(未定义), ...
- Python基础-小程序练习(跳出多层循环,购物车,多级菜单,用户登录)
一. 从第3层循环直接跳出所有循环 break_flag = False count = 0 while break_flag == False: print("-第一层") wh ...
- C语言归并排序
这篇文章是学习了小甲鱼-数据结构与算法结合自考教材编写出的代码,希望自己逐渐在算法造诣上能更上一层楼. 归并排序(递归实现) “归并”一词在中文含义中就是合并的意思,而在数据结构中的定义是将两个或者两 ...
- 01_Nginx入门
[Nginx概述] Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-Like协议下发行.其特点是占有内存少,并发能力强,事实上Nginx ...
- PHP中empty、isset和is_null的使用区别
关于PHP中empty().isset() 和 is_null() 这三个函数的区别,之前记得专门总结过,上次又被问到,网上已经很多,就用几个例子来说明: 测试用例选取: <?php $a;$b ...
- arcgis silverlight api 图层介绍
Layer |--TiledMapServiceLayer | |--ArcGISTiledMapServiceLayer |--DynamicLayer | |--DynamicMapService ...
- Java Web----Servlet详解
这篇文章到上一篇,距离的有点遥远呀,隔了大概有两个月把,中间在家过了个年,哈哈~ 现在重新开始拾起,最近在看一本个人觉得很棒的书,<Java Web 整合开发王者归来>,现在写的这一系列基 ...