计算机视觉讨论群162501053
转载请注明:http://blog.csdn.net/abcd1992719g/article/details/26824529

收入囊中

  • 使用OpenCV的connerHarris实现角点检測
  • 自己实现Harris算法
以下是自己实现的一个效果图

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

由于阀值设置比較高,所以房屋周围没有找出来
葵花宝典
在此之前,我们讲过边缘的检測,边缘检測的基本原理就是x方向或者y方向梯度变化非常大。角点,顾名思义。就是两个方向的梯度变化都非常大。

左1,平滑区域。没有边缘和角点,窗体在不论什么方向移动都无变化
左2。边缘区域,在边缘方向移动没有变化
左3,角点区域。在不论什么方向移动都有显著的变化
以下我们定义

E(u,v)=∑(x,y)∈[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+
Iy

=I(x,y)+[Ix
Iy
][u v]T

再代入以下的公式

E(u,v)=∑[I(x+u,y+v)−I(x,y)]2(x,y)∈

我们得到

因此,我们能够写成


当中,M是一个二阶矩矩阵,能够由我们原始图片的差分得到

我们来想像一下,假使梯度是沿着x或者y方向的,也就是说Ix = 0或者是Iy = 0,那么我们的M就是

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWJjZDE5OTI3MTln/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

假设a或者b非常接近0,也就是说他们非常小,那么这就不是个角点。角点的地方a,b肯定都非常大
我们发现。E是一个关于U,V的二次曲线,令E(u,v) = CONST,那么E就是一个椭圆

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,所以你能够忽略它

在这里,我们的特征值就派上用场了,当两个特征值都非常大非常相近。说明我的椭圆非常小,整个E变化非常剧烈。那么我就找到了我的角点。

以下是 Harris给出的公式

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
 neighborhood. 用的是harris响应函数

荷枪实弹
以下是官方sample,我就不多解释了。纯粹是API的调用。要注意的就是得到响应函数后进行了归一化到[0,255]
#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角点检測(自己实现)的更多相关文章

  1. OpenCV2马拉松第22圈——Hough变换直线检測原理与实现

    计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/27220445 收入囊中 Hough变换 概率Ho ...

  2. OpenCV2马拉松第15圈——边缘检測(Laplace算子,LOG算子)

    收入囊中 拉普拉斯算子 LOG算子(高斯拉普拉斯算子) OpenCV Laplacian函数 构建自己的拉普拉斯算子 利用拉普拉斯算子进行图像的锐化 葵花宝典 在OpenCV2马拉松第14圈--边缘检 ...

  3. OpenCV2马拉松第17圈——边缘检測(Canny边缘检測)

    计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g 收入囊中 利用OpenCV Canny函数进行边缘检測 掌握Canny算法基本理论 ...

  4. MatLab角点检測(harris经典程序)

    http://blog.csdn.net/makenothing/article/details/12884331 这是源博客的出处,鄙人转过来是为了更好的保存!供大家一起学习!已将原始的博客的文章的 ...

  5. opencv对图像进行边缘及角点检測

    opencv对图像进行边缘及角点检測 先看结果: 代码: // ConsoleApplication1_812.cpp : Defines the entry point for the consol ...

  6. 使用nodeitk进行角点检測

    前言 东莞,晴,33至27度.今天天气真好,学生陆续离开学校.忙完学生答辩事情,最终能够更新一下nodeitk.本文继续介绍node的特征识别相关内容,你会看到,採用nodeitk实现角点检測是一件十 ...

  7. OpenCV2马拉松第14圈——边缘检測(Sobel,prewitt,roberts)

    收入囊中 差分在边缘检測的角色 Sobel算子 OpenCV sobel函数 OpenCV Scharr函数 prewitt算子 Roberts算子 葵花宝典 差分在边缘检測究竟有什么用呢?先看以下的 ...

  8. OpenCV2马拉松第2圈——读写图片

    收入囊中 用imread读取图片 用nameWindow和imshow展示图片 cvtColor彩色图像灰度化 imwrite写图像 Luv色彩空间转换 初识API 图像读取接口 image = im ...

  9. OpenCV2马拉松第10圈——直方图反向投影(back project)

    收入囊中 灰度图像的反向投影 彩色图像的反向投影 利用反向投影做object detect 葵花宝典 什么是反向投影?事实上没有那么高大上! 在上一篇博文学到,图像能够获得自己的灰度直方图. 反向投影 ...

随机推荐

  1. 破解b站极验验证码

    这就是极验验证码,通过拖动滑块移动拼图来验证.我们观察到点击滑块时拼图才会出现,所以我们可以在点击滑块之前截取图像,点击滑块再截取一次图像,将前后两次图像做比较就可以找到图片改动的位置.获得位置后,我 ...

  2. DDD中的EFCore

    EFCore在DDD中的使用 在DDD中,我们对聚合根的操作都会通过仓储去获取聚合实例. 因为聚合根中可能会含有实体属性,值对象属性,并且,在DDD中,我们所设计的领域模型都是充血模型.所以,在对聚合 ...

  3. JAVA实现多线程处理批量发送短信、APP推送

    /** * 推送消息 APP.短信 * @param message * @throws Exception */ public void sendMsg(Message message) throw ...

  4. php根据IP获取所在省份-百度api接口

    这里用的file_put_contents,你也可以用别的,直接怼代码: //拼接传递的参数 $getData = array( 'query' => '127.0.0.1', 'resourc ...

  5. 比较2个文件内容不同行的shell脚本

    第一种:grep命令法 命令如下:grep -vxFf file1 file2 > a.txt 其中file2是大文件,file1是小文件 第一种:comm命令法 命令如下:comm  file ...

  6. Linux 上安装Docker 并部署netcor2.1

    述 容器,顾名思义是用来存放并容纳东西的器皿: 而容器技术伴着Docker的兴起也渐渐的映入大家的眼帘,它是一个抽象的概念,同时也是默默存在世上多年的技术,不仅能使应用程序间完全的隔离,而且还能在共享 ...

  7. PHP学习2——基本语法

    主要内容: 二进制 数据类型 变量 常量 赋值 语句结构 函数 网站的核心功能是展现信息,文字,图片,视频,音频,对于计算机来说都是数据,这些数据按照二进制进行存储. 二进制 就是1100,0100, ...

  8. Oracle数据库查看已添加的索引和创建索引

    /** *查看目标表中已添加的索引 * */ --在数据库中查找表名 select * from user_tables where table_name like 'tablename%'; --查 ...

  9. 三:SSM框架整合思路

    一:jar包 1.spring(包括springmvc) 2.mybatis 3.mybatis-spring整合包 4.数据库驱动 5.第三方连接池 6.json依赖包jackson 二:整合思路 ...

  10. <td>标签scope属性

    HTML <td> 标签的 scope 属性 HTML <td> 标签 实例 下面的例子把两个 th 元素标识为列的表头,把两个 td 元素标识为行的表头: <table ...