Computer Vision Project 2 – Harris Corner Detector

  • 姓名: 王兴路
  • 学号: 3140102282
  • 指导老师: 宋明黎
  • 2016-12-16 19:30:22 星期五

Content:

ReadMe

Run Demo

This program implements Harris Corner Detector via Adaptive Nonmaxia Suppression.

  • Click Demo.bat to see Demo, the middle resule will be generated in current directory.
  • Run it though cmd/bash following usage below:
    • Usage 1:
  1. prj2.exe inputImgName k=(0.04) aperture_size(=3)
  2. guassian=(true)
  3. Ada_NMS=(true) R_thre_left=(5000) nms_left=(500) c_robust=(0.9)
    • Usage 2:
  1. prj2.exe inputImgName k=(0.04) aperture_size(=3)
  2. guassian=(true)
  3. Ada_NMS=(false) left=(500)
  • inputImgName is required. All other params are alternetive, the default is showed in Usage 1. For example, the following has been tested.
  1. prj2.exe roof.jpg
  2. prj2.exe roof.jpg 0.04 5

Develop Platform

  • OS system: Win10
  • VS 2013 + OpenCV 2.4.12

FileList

  1. .
  2. ├── 3140102282_WangXinglu_Prj2.pdf
  3. ├── Demo
  4. │ ├── *.jpg (sample input img)
  5. │ ├── Demo.bat (click to run)
  6. │ ├── *.dll (dependence)
  7. │ ├── prj2.exe
  8. │ └── SampleOut
  9. └── Src
  10. ├── prj2
  11. │ ├── harris.cpp
  12. │ ├── harris.h
  13. │ ├── main.cpp
  14. │ └── prj2.vcxproj
  15. ├── prj2.sdf
  16. ├── prj2.sln
  17. └── prj2.v12.suo

Functionality

  • 求解 R response: $R = |M|-k*Tr(M)$
  • 输出中间结果 $ \lambda_{max}$, $\lambda{min}$
  • 输出JET Pseudo Img可视化, 对R图进行$Rectify$+$log$操作,符合人类视觉的感受范围。
  • NMS部分实现Adapative NMS和一般的NMS两种算法。
  • 命令行解析参数,方便调参。包括k, aperture_size, 是否采用guassian核, 是否采用Ada_NMS, 以及对应的NMS参数。并且都有默认参数。

Implementation

Pipeline

  1. st=>start: Start
  2. read=>operation: Parse Argc
  3. cal=>operation: calculate
  4. R responese map
  5. & middle result
  6. nms=>operation: nms
  7. vis=>operation: visualze and imwrite
  8. ee=>end
  9. st->read->cal->nms->vis->ee

Second Moment Matrix M

课件上的公式没有将标量和矩阵分清

$$M = \sum\limits_{x,y} {\left\{ {G(x,y)\left[ {\begin{array}{*{20}{c}}
{{I_x}^2}&{{I_x}{I_y}}\\
{{I_x}{I_y}}&{{I_y}^2}
\end{array}} \right]} \right\}} $$

上面式子中$M$事实上是标量,正确的标量形式写法应当是:

$$M(i,j) = \sum\limits_{x,y} {\left\{ {G(x,y)\left[ {\begin{array}{*{20}{c}}
{{I_x}^2(i + x,j + y)}&{{I_x}{I_y}(i + x,j + y)}\\
{{I_x}{I_y}(i + x,j + y)}&{{I_y}^2(i + x,j + y)}
\end{array}} \right]} \right\}} $$

使用$Correlation$算符$\otimes$,以矩阵形式简写如下:

$$M_{N \times N \times 2 \times 2} = f\left( {\left[ {\begin{array}{*{20}{c}}
{{M_{11}}}&{{M_{12}}}\\
{{M_{21}}}&{{M_{22}}}
\end{array}} \right]} \right) = f\left( {\left[ {\begin{array}{*{20}{c}}
{G \otimes \left( {{I_x}^2} \right)}&{G \otimes \left( {{I_x}{I_y}} \right)}\\
{G \otimes \left( {{I_x}{I_y}} \right)}&{G \otimes \left( {{I_y}^2} \right)}
\end{array}} \right]} \right)$$

其中$f$是Reshape函数,实现维度变换。因为高维矩阵$M$在每一个像素点上都是一个$2 \times 2$的二阶动量矩阵。计算得$M_{ij}$后,需要将对应位置的值拼接起来形成二阶动量矩阵。

$$f:\left( {\begin{array}{*{20}{c}}
{{R_{N \times N}}}&{{R_{N \times N}}}\\
{{R_{N \times N}}}&{{R_{N \times N}}}
\end{array}} \right) \to {R_{N \times N \times 2 \times 2}}$$

Adapative Non Maxima Suppression

我们找到的Harris Corner点数量较多,且容易出现聚簇情况,需要对Harris Corner点的数量和位置分布进行处理,这就用到了Adaptive Non-Maximal Suppression。

该算法在这篇文章中提出[Multi-Image Matching using Multi-Scale Oriented Patches, Brown et al., CVPR 2005]

使用ANMS需要完成两个任务:

  • 从图像中抽取指定数量的interest points
  • 使interest points均匀分布在图像中。

算法原理如下:

设共有$N$个特征点,

  • $\mathbf{x}_i$代表特征点$i$的坐标
  • $v_i$代表特征点$i$的R response值。

对于特征$i$,定义抑制半径

$$
r_i = \min_{j \in I_i} \| \mathbf{x}_i - \mathbf{x}_j \|_2
$$

其中$I_i$是满足如下公式的所有特征点的集合

$$
I_i = \{ j \in \{1,\dots, n\} \mid v_i < c_\textrm{robust} v_j \}.
$$

对于每个点计算$r_i$,降序排序,取Top $NMS_left$ 个点,即为所求的需要保留的特征点。

从直观上解释,先不看$c_\textrm{robust}$, 如果一个不厉害的点很近的地方就有一个很厉害的点,那么这个点就应该排名靠。所以按照距离排序。

[========]

Experiments

可以看到:

  • Ada_NMS在自然场景照片中获得了很好的效,这张图没有一个点会重复。
  • Ada_NMS在规则格子图上效果相比NMS稍稍好一些。但是25个点不能恰好分布到25个格点。如果具体计算会发现,这是因为Ada_NMS只能够给临近的$4 \times 4$划出两个等级$1$和$\sqrt{2}$。
\ global local
NMS
Ada_NMS
NMS
Ada_NMS

Implemetation

  1. vector<Point_float_pair> Point_R;
  2. // minMaxLoc(R, &R_min, &R_max);
  3. for (int row = 0; row < R.rows; row++)
  4. {
  5. for (int col = 0; col < R.cols; col++)
  6. {
  7. float R_tmp = R.at<float>(row, col);
  8. if (R_tmp < 0 || R_tmp <1000)
  9. continue;
  10. Point_R.push_back(make_pair(Point(row, col), R_tmp));
  11. }
  12. }
  13. R_thre_left = min(R_thre_left, (int)Point_R.size());
  14. partial_sort(Point_R.begin(), Point_R.begin()+R_thre_left,Point_R.end(), Point_float_sort());
  15. Point_R.resize(R_thre_left);
  16. vector<Point_float_pair> Point_dist;
  17. for (int i = 0; i < Point_R.size(); ++i){
  18. float dist = m_infty;
  19. Point now_point = Point_R.at(i).first;
  20. for (int j = 0; j < Point_R.size(); ++j)
  21. {
  22. Point counter_point = Point_R.at(j).first;
  23. if (i != j && Point_R.at(i).second <c_robust * Point_R.at(j).second){ //0.01==>all 1 ; 10 ==> all inf
  24. float dist_tmp = norm(now_point - counter_point);
  25. if (dist_tmp < dist)
  26. dist = dist_tmp;
  27. }
  28. }
  29. Point_dist.push_back(make_pair(now_point, dist));
  30. }
  31. nms_left = min(nms_left, (int)Point_dist.size());
  32. partial_sort(Point_dist.begin(), Point_dist.begin() + nms_left, Point_dist.end(), Point_float_sort());
  33. Point_dist.resize(nms_left);
  34. Mat R_nms(R.size(), CV_32F, Scalar::all(0));
  35. for (int i = 0; i <Point_dist.size(); ++i){
  36. Point now_point = Point_dist.at(i).first;
  37. int row = now_point.x;
  38. int col = now_point.y;
  39. R_nms.at<float>(row, col) = 1;
  40. circle(img_harris, Point(col, row), 4, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)));
  41. }

Demo & Experiments

其中$R_{psu}$的具体操作是:

  • 将所有负响应置为R图中除去负数的最小值
  • $log$操作
  • 使用pseudo map 展示

可以看到$R_{psu}$中深蓝色的,即为原本为负数的平坦区域

$\lambda_{max}$ $\lambda_{min}$ $R_{psu}$
$R$ $R_{NMS}$ $img_{harris}$
$\lambda_{max}$ $\lambda_{min}$ $R_{psu}$
$R$ $R_{NMS}$ $img_{harris}$

Median or Guassian

从测试图片看没有明显差别(Gassian略好):

Median Guassian

k

k增大,检测到的点数变少,效果变差。(不稳定,最符合Corner特性的点没有被保留)

0.04 0.20 0.24 0.28

aperture_size

k增大,检测到的点数变少,效果变好。(稳定,响应大的点保留,最符合Corner特性的点保留)

3 9

Reference

https://stackedit.io/editor#fn:footnote

https://www.zybuluo.com/AntLog/note/63228

https://www.learnopencv.com/applycolormap-for-pseudocoloring-in-opencv-c-python/

http://stackoverflow.com/questions/23680073/finding-local-maxima-in-an-image

http://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html#min



cv_prj2的更多相关文章

随机推荐

  1. MongoDB是一个介于关系数据库和非关系数据库之间的产品

    MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型.M ...

  2. 解决String TestContext下使用junit4抛出异常(java.lang.NoClassDefFoundError)的问题

    Spring版本2.5.5,JUnit 版本 4.8.1,使用了 Spring TestContext 的 SpringJUnit4ClassRunner.一直使用这个版本的JUnit,在写简单的测试 ...

  3. 关于js作用域链,以及闭包中的坑

    eg:链式作用域,想在外部读取blogName的值得方法 <script>var authorName="山边小溪";function doSomething(){   ...

  4. Kibana安装与基本用法

    Kibana也是一个开源和免费的工具,他可以帮助您汇总.分析和搜索重要数据日志并提供友好的web界面.他可以为Logstash 和ElasticSearch 提供日志分析的Web界面 它是一个基于浏览 ...

  5. 【初学者教程】在电脑上安装Python,写第一个程序

    欢迎来到Python的世界 1.存在Python 2和Python 3两个版本,我该用哪个?如果书是关于2的,下载2:如果书是关于3的,就下载3.建议用Python 3,不过用2也是可以的. 2.下载 ...

  6. Matlab Map

    http://blog.csdn.net/yuzhiyuxia/article/details/7305225 >> weekmap = containers.Map({'Monday', ...

  7. 批量部署ssh信任关系

    要求1:大批量部署SSH信任关系,在A文件分发服务器上大批量部署WEB层面信任关系文件分发服务器为:10.0.3.9 登录用户为:zhangsan WEB层IP段:10.0.3.10~10.0.3.6 ...

  8. [AS3]as3画笔实例实现橡皮擦功能源代码

    [AS3]as3画笔实例实现橡皮擦功能源代码 //主容器 var main:Sprite = new Sprite(); main.mouseEnabled = false; addChild(mai ...

  9. 《IT蓝豹》挑战独立开发项目能力

    做了5年的android开发,今天没事写写刚入行不久的时候第一次独立开发项目的心得体会,    当时我刚工作8个月,由于公司运营不善倒闭了,在2011年3月份我开始准备跳槽,    看了一周andro ...

  10. 如何在EF CodeFirst中使用唯一约束(Unique)

    一直用EF Fluent Api 做MapConfiguration 所以遇到了唯一约束这个瓶颈 使用唯一约束的两种方式: 方式1 自定义唯一约束 [AttributeUsage(AttributeT ...