python图像检测_一起学python-opencv三十一(图像特征检测和描述之角点检测)

821954dd7b4c71dad9483bc35143ab15c9c3eaff.png

python-opencv系列的最后主要还是把opencv官方文档里面前面没有提到的内容消化一下。

特征检测和描述1d17d93be5ec374dedd9890933dca19c1efb6771.png

上面谷歌翻译把features翻译成功能,应该是特征。9bf8e43313a8c143b68e4295928f033a297369aa.png

203f53ea5c39fb8a408820e182959d40d05650bc.png

在图像中寻找在其周围的所有区域中移动(少量)时具有最大变化的区域,这一句比较关键。4726805527d805c29fa69dab4ad47e16a490be98.png

Harris Corner Detection(哈里斯角点检测)ae8ed97498273f683e78f399e516520b8c95c371.png

5154f31d9c99448b66b37dd3294752a6def53c61.png

原理参考了https://blog.csdn.net/newthinker_wei/article/details/45603583

和https://blog.csdn.net/linqianbi/article/details/78930239a523c5d55dfb93f40e8e3fa97f9786e5516d8e05.png

其实在哈里斯之前,就有角点检测的方法:d520178289eaf5c6949dba7f83f9ee48a808f17f.png

这里的参数和上面稍有区别,注意一下。这个w是权重,这个目前不知道怎么设定。0e2a7e993cdd39cbff2615e909e3a5d4fd348e12.png

9da90cfc12c2a2d55df2a8ea8cf4d7518ee7f9b0.png

上面用到了多元泰勒展开,而且了一阶近似,舍弃了高阶小量。a1027c2f434fe1f54a52ec3a4dbccf5d958cc019.png

c9b2af004b82fbd98cf44f53029c539ccae9d132.png

b84d573b71fceccf150e7dfa1e9d7d7cb3f7176d.png

如果不能对角化(关于方阵可以对角化的充要条件,大家自己翻一翻书,一共有两条),我记得好像总是可以化为(Jordan)约当标准型的,不过这里也没用到它。22fd385a5842955aa453baa56d722fff19cff0fd.png

二次型标准化还有一种拉格朗日配方法,这些大学的线性代数都学过。52b47de1aa2819396ef7c0883e9141413e4340c1.png

1311240dfb759107a37f3335c08be10d2d8ecd96.png

9c9526fe6593f2929ddf66bc5256a0b5000d6354.png

0551f1f1e0a1ac804294689175971d6003458b9f.png

这段讲解得比较精彩。56c9cd9e93751d221c77f712a1141c968a804f5c.png

怎么想出来的其实上面的红字已经解释了,这个转载的没有认真看原文,不过b4e8d1cb66758e200c979f4eb5e77b1b1b484c89.png

这个式子的构造还是比较巧妙的。c6a6206f8299a56ec7766fedd5171d6316f1aee1.png

92d1c732ab94a3209524272df0db63c523635ec0.png

B  提取的角点是像素级的。做一些图的补充,如果上面还没有理解,可以再看看:32ed9c72c9a04d4fb4a397d79f6cf8b48eefe650.png

c228ffc6675fdafb9b2b4b665709176315dafdde.png

也就是w要么是一个均值核,要么是一个高斯核。72460480d2c5c70a98d53b1f1ec85b4350dc6856.png

d7edf4ccbd563084e5a4b5f7e177105bb878efb2.png

e8b3952cc10ad6037d61b1668064654cdd34f4dd.png

e31931c7ecfb49e857579bd5928139bf114ff335.png

5953265a66e75f943a6c7d6ce2d0a840f4c44887.png

b66bd12cb1b6a1221910b8dd6953d2ec04622af2.png

411da740a6fc44714866036ed09f94e2bfab67aa.png

和上面过程其实是一样的。ed1eac2859a5a8f7e547e738199d9e73cc680330.png

非极大值抑制前面在canny算子的时候就提到过。

opencv如何实现哈里斯角点检测的呢?c5331644d56ffe8d1165e052875cb2af95cebbb5.png

f34378b4e5609b9d66d4169897a6b9591ef1c135.png

输入可以是uint8的,不过得是单通道的。得到的结果就是我们按照哈里斯角点检测计算出来的R。c2ccc43979cd9f3ba28d2b3dbdcb1f95130ece34.png

3cd33d0c1f4f71088d9c1ebd774a38a48bfb0776.png

上面取的阈值是c里面最大值的0.01。0e8cc6d6e0c3a7d635b445acfd6d8e69c4095e5d.png

红点比较难看到(瓷砖的角点),这是因为满足条件的像素太少了,一个像素的红点还是太难看到了,所以上面的例子做了一个局部最大值滤波,也就是膨胀处理,目的就是为了让红色区域可以看到。60e560237c47956ea85203e9927e644b9636f806.png

d5bf253e8c13332cb6c566e7678fbbd0a5f8fa23.png

这个就更容易看到了(这个膨胀其实可做可不做的),这个有些地方没有检测到,我们需要减小一下阈值试试。6cacc11e13ae5fa5eac1b584d1accbe0a8a40ee3.png

这个阈值需要我们手动调整,看到阈值太小,这个有些边界点也给检测出来了,这个时候可以增大k。47858f20e47bc7fa7422066ee53159451404993f.png

其实如果k足够小的话,这个就是边缘检测:686bbc7081bfbfa67ab7632dcfa93eb7d90ef621.png

有些没有检测到是因为blocksize上面取得都是2,太小了。1995cb3c7fe2927bbd9ca97af7ba25d6bdee62a5.png

我觉得最好还是blocksize和ksize也就是sobel算子的大小一致比较好。985aab76f281b01fc6adb12ceaa04f1353df5f6b.png

增大blocksize也有助于检测到角点:a5bd67fee9a0b10e873e23c24fe167b026fa240e.png

其实不加膨胀效果也还可以的:45841bafa02cea91231aa1057fa47ea50caec459.png

不过这样是无法精确定位的。因为我们得到的其实是很多团点,每一团点都不止一个点,而且每个点最多只能精确到一个像素单位,我们都是知道像素是一个矩形,要想继续精确定位的话,要借助函数:cv2.cornerSubPix()edcfd007881fe46aafe076d7dd823e3fd718d7b0.png

这个函数用迭代的方法找到亚像素级别的角点的精确位置。所谓亚像素级别,可以理解为把图片像素resize(用插值的方法),然后现在放大之后的图片上的一个像素在原图上就相当于是一个像素中的某一个矩形,最小单位就不再局限于一个像素了。寻找精确亚像素角点位置是基于从中心q指向q邻域内的点p的向量,这个向量和p点的梯度方向垂直,这里定义了上面一个目标函数。其中DIp是q邻域内的某个点p的图像梯度。q得值要使上面的目标函数最小。通过让目标函数置为0,我们可以建立一系列方程,最终解出q的位置。不过一般我们还是用数值算法,而数值算法一般的方式就是迭代,我们也许先选一个初始点为q,然后计算邻域内点梯度,设一阶梯度为G,二阶梯度为b,那么q我们可以通过下列式子计算出来(为什么这么算就不知道了,这个算法应该是有数学收敛性证明的):aef08b08f8918d47538fcb09be214171f5b69402.png

参数说明,image是单通道的,参考了https://blog.csdn.net/guduruyu/article/details/69537083e42df96c7f4b8461ecd5b21ec13fff6ab0b9e4c9.png

第二个参数也就是初始的q点位置了。第四个参数说的有问题,opencv官方说的是为了防止自相关矩阵出现可能的奇异现象才设置的这个参数,有点不懂,不过这个参数一般我们不需要动,给(-1,-1)就行。

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)

这个的意思应该就是最大迭代次数为100次,相邻两次迭代最大距离0.001,满足任意一个条件就可以停止了。这个函数的输出应该就是q点的位置了。

看一下官方给的例子:73dbac1aaf252a2e5c38f26b1c81b7b947ff45a3.png

adae73d9d1e9e61ab93d837caa1339ed72b628bd.png

我有点粗心,现在才反应过来,上面膨胀居然没有用探针????b95c290a1a0e5e6397d76112b6afb5f689a51db6.png

我对比了不加这句和加这句的:

没加:bfd78f93329829db68aa9c2a1689c499d1c960de.png

加了:c0fa029090b3a7a0b285c446c9c0781e6d45bcaa.png

还是明显可以看出来还是有膨胀的效果的,字体明显粗了。上面用了一个函数来测量连通区域的数据(虽然前面其实我们已经学过很多函数可以做这个事情):593a4dd14cfd04b6e382b922d8118d9aec4dbbee.png

这个统计可以选择输出的数据,一般我们都是默认就行,如果有需要,可以选择自己想要的。标签会把不同的连通区域标记为不同的值,0是背景,我们在前面分水岭那里见过。c45724b7fa111519c6b78b3d33aade38e3bada03.png

来试一下:4dcc51e3a744a8bdd7c698bdca698e9af94b5e4d.png

最后这里却会报错:eb081c046a41161bd9d0f7abf900b16e14a13486.png

奇怪呢,这种索引方式我们也用过的呀:0a365b02910ffe623cae56889eb4f0ac4b078dbf.png

不要急,看一下报错信息就知道了,7250b13929387a13658e7f5031b717cfd94786a2.png

原因出在我们用rint的结果还是浮点类型的。整段代码:57ecc85808aedc35947fa7ae4dd58c7b08cad73c.png

83d092b0d3ced1d15ec211d2442361327f282655.png

结果:5ffb94ffa9e028a485ee7387c2aaada91cf0abfe.png

f8ba5a40593ba790f96908ab4ef8bf63425506ab.png

红点和绿点都很小,我们需要放大看才能看清:d954f2bd0ba0a5a9537b2ca5574a3ab3ec0bfc52.png

在画图中看得再清楚一些:49339d3a62c794f96ea79fc4d33eae89e72958c4.png

这是我截取其中的一部分:这个还是可以看到明显的绿点的。我们上面其实没有体现亚像素,这是因为我们取整了,其实精度是可以达到亚像素的,只不过亚像素的话就没办法显示了,所以我们还是取整用像素级别显示了。这里还要提醒一点,关闭图片最好用键盘,这样一个python程序才是finish了,不然的话python程序其实并没有结束,即使关闭sublime,还是再运行,在任务管理器就会看到:b75c56db460c5c77961dd91b16f773e3fa6d1916.png

前面也说过现在有更先进的角点检测方法。

Shi-Tomasi角点检测62f18435e4bcb81ff46a73f3d3350b1c68b03689.png

也就是说其实只是改进了最后的评价函数。这个函数是:6a2b660ead24a8b22f9558044b54e236d2df8137.png

8ecd4248d6ad0c98a78d8c304af87999cc3e21b1.png

3733b88488818adac55a3ddc37a851738a10521b.png

第四个参数给的其实就是经过角点计算出来的最大值的百分比。这个还可以指定角点个数的最大值,你可以给很大。例子:963b2a9a91ca75d2b91685bd7b35fc812dc546fa.png

8a17e39d7253b46f88c859877c4cf16016b064d5.png

be2d8e2e6409d766e842543f55c03ad724f65412.png

这个有些边缘也显示了,可以加大百分比:3c7c490b05562df630f02920ddadec21458d0b20.png

但是有些角点就漏掉了,总之,调参基本也不可能一蹴而就。这个的结果如果想再精确的话,可以再进行亚像素处理。02db465212d3c374a43c60fa2625cc1caeaab796.png

以上就是角点检测的内容。b01bf84f72b404a8875ee6cf5a267652c2be2f64.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值