深度学习系列:目标检测(Object Detection)原理与实现(转载)

原文链接:http://blog.csdn.net/marvin521/article/details/9058735
感谢分享

基于阈值图像处理的目标检测
从今天起开始要写一些关于目标检测的文章,涵盖从简单的阈值图像处理检测、霍夫变换(hough transform)检测、模版匹配检测(刚体匹配)、AAM+ASM+ACM(非刚体)匹配检测到近代机器学习方法检测,尽量贴一些代码,这些很实用。本篇就从阈值图像处理检测开始。阈值顾名思义就是一个分界值,做图像处理的都明白阈值的用途,但是考虑到各种观众,干脆把OpenCV中的各种阈值标识符和对应代码示意都贴出来,如(图一)所示:

这里写图片描述
仔细阅读下(图一)中的各种伪代码,就很容易明白阈值函数的工作机制,其中src(x,y)是图像像素点值。下面就给出一个处理答题卡的例子,(图二)是从网上找到的一个答题卡样图,我们的目标是检测到哪些选项被涂黑了,然后根据坐标判定是哪个数字,其实根据坐标是有依据的,因为答题卡四个角有一些对准线,对齐后用扫描仪扫描后紧跟着经过算法处理就可以判断出考生选项,本篇文章就简化流程,考虑到涂的选项是黑色的,因此我们使用第二个阈值方法,经过处理后如(图三)所示。
这里写图片描述 这里写图片描述
代码如下:

import numpy as np  
import cv2  
img=cv2.imread('anwser_sheet.jpg')  
grey=cv2.cvtColor(img,cv2.cv.CV_BGR2GRAY)  
retval,grey=cv2.threshold(grey,90,255,cv2.cv.CV_THRESH_BINARY_INV)  

grey=cv2.erode(grey,None)  
grey=cv2.dilate(grey,None)  

contours,hierarchy=cv2.findContours(grey.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)  
newimg=np.zeros_like(grey)   
cv2.drawContours(newimg, contours, -1, 255)  
cv2.imshow('test',newimg)  
cv2.imwrite("processed.jpg",newimg)  
cv2.waitKey()

代码流程先是读取图像文件,接着转成灰度图,接着做个开运算(腐蚀后再膨胀),接着阈值处理,最后把目标轮廓画出,根据目标块的坐标可以大概的推算出对应的数字,接着秀一下打印出某个涂项,比如最后一个,那么只需要把
cv2.drawContours(newimg, contours, -1, 255) 改成 cv2.drawContours(newimg, contours, 0, 255)

第三个参数为负数表示打印所有轮廓,0表示打印最后一个选项,打印是倒着数的。

基于阈值图像处理的目标检测一般只适应于自己能控制颜色和亮度的项目中,这也为什么规定答题卡要尽量使用黑色的(同一颜色方便阈值处理),另外这种方法也可以用在目标的三维重建上,如(图五)所示,用阈值的方法找到汽车上的标定点对后续点云的获取很有帮助,进而完成整个汽车模型的三位重建,此方法虽然简单,但对这几种场景很实用,通过简单的图像处理(各个阶段去噪)后,然后简单的查找下各种闭合小轮廓就OK了,好了,今天就说到这,比较简单,后续会越来越复杂些,用到的数学知识也越来越多。
这里写图片描述

基于霍夫变换和广义霍夫变换的目标检测
上节讨论了基于阈值处理的目标检测,今天就来讨论下基于霍夫投票的目标检测,霍夫投票打算分成两个小节,第一个小节简单的说下霍夫变换和广义霍夫变换(generalized hough transform),他们投票的权重都是相等的,下一节讨论概率空间中的霍夫投票,顾名思义他们的投票权重是不确定的。

先来看下霍夫变换(hough transform),霍夫变换一般适用于有解析表达式的几何形状目标检测,例如直线、圆、椭圆等。用个统一的解析表达式来表达他们:f(x,alpha)=0,其中x 是图形上点,alpha则是解析表达式参数,比如欧式坐标系中直线的参数就是斜率m和截距c(或者极坐标系中的theta和ρ),圆的参数则是原点和半径。霍夫变换的核心就是把图像空间的直线变换到参数空间(也叫霍夫空间),比如一个直线y=mx+c,给定一个点(x’,y’),把它代入直线方程,得到y’=mx’+c,其实此时仍然是一条直线(在参数空间的直线,斜率是-x’,截距是y’),图像空间和霍夫空间的对应关系如(图一)所示:
这里写图片描述
(图一)中左图是图像空间,右图是霍夫空间(参数空间),对于图像空间中线段pq上任意一点带入直线方程后,都可以在霍夫空间中得到另外一条直线,二者是对偶的,比如如(图一)所示,把两个端点带入后,在右图中得到的两个对偶直线,而且斜率是负的。现在问题来了,机器是怎么知道pq是一条直线(假设还有其他噪声点存在的话)?我们不知道斜率也不知道截距,我们要做的就先假设图像中有一条直线,其方程为y=mx+c,我们要求他的参数,然后把图像空间中的每个点都代入直线方程,然后在霍夫空间里都产生了一条对偶直线,因为图像空间中的那条直线上的点共用一个斜率m和截距c,因此他们的对偶直线必然相交于一点,也就是说m,c的值是唯一的,在右图中也能体现出来。

直线的霍夫变换检测核心思想就是这些,但是考虑到斜率截距式直线表示法不能表示所有直线,比如直线X=CONSTANT时,斜率无线大,霍夫空间里无法表示此点,因此我们把直线方程转换成极坐标表示的形式:这里写图片描述
思想还是一样,区别就是把参数m,c转换成了theta和ρ),另外图像空间中的点对应的霍夫空间的几何形状不是直线,而是曲线,如(图二)所示:
这里写图片描述
(图二)中右图的亮点就是我们要求的参数,但是怎么求的,求交点?那也太麻烦了,霍夫投票方法此时就要登场了,你霍夫空间中的曲线也是个图像嘛,我有的是内存,对于个曲线上的每个点我都用一个字典来表示你们,字典索引就用霍夫空间的坐标(theta和ρ)来检索,字典的值表示该坐标上有多少个曲线点(字典的学名叫累加器:accumulator)。对于(图二)中的那个亮点对应的字典值肯定很大,其实我们就是找大的最大值,峰值表示图像空间中的很多点共用一个参数。该算法的实现步骤如下伪代码所示:

For each edge pixel (x,y)  in image

   For θ= -90 to 90

       ρ= x cosθ+ y sin θ

       ++ H(iθ, jρ);

    end

end

直观来说就是你给我一个图像空间中的点,我就在霍夫空间中计算很多字典,然后相同位置上加1,简单的说就是把霍夫空间分割了,分割的越精细越好,但是分的越细计算量也越大,毕竟图像点很多,这个平衡读者根据情况自己把握吧。累加器的示意图如(图三)所示:这里写图片描述
圆和椭圆也都是类似步骤,只不过圆有三个参数,而椭圆有5个参数,计算量更大。此算法实现在opencv里也有,直接调用一个函数即可,在此不多说,直接给一个OpenCV自带的图像进行检测直线的结果和他的霍夫空间示意图,如(图四)和(图五)所示:
这里写图片描述
这里写图片描述
(图五)霍夫空间中的峰值点可能不严格的在同一个坐标上,也就说图像空间中直线上的点并不严格的在同一直线上,我们要容许一部分误差的存在,判断峰值点是个技巧活。

下面进入广义霍夫变换(Generalized Hough Transform)。

前面也说了,霍夫变换只适用于具有解析表达式的形状,对于一般形状则无能为力,一般形状没有解析表达式,没有解析表达式,那我们怎么进入霍夫空间里呢?没有霍夫空间,那我们怎么投票?不投票怎么来检测物体?有条件就上,没条件创造条件也要上。一般物体虽然没有解析表达式,但是他们有边缘,说的多一些,MARR教授一开始就说边缘是人眼检测判断物体的重要条件之一,所以计算机视觉早期出现了很多边缘检测算法。有了边缘就可以创造出切向量,切向量可以做参数吗?仔细考虑一下,信息太少,ballard在1980年提出了广义霍夫变换(generalized hough transform),它利用了如(图六)所示的参数:
这里写图片描述
(图六)中的alpha表示参数,可以看出参数很多,参数空间肯定是高维的,不过不管他多少维,方法和上面类似,参数空间中投票嘛,考虑到这个方法选择了一个参考点,把图像中的点到参考点的距离和相对方位信息作为参数来检测物体,细心的同学可能感觉出来了,他和Hu moment(Hu矩)有些相似的地方,他们都需要一些模版来提取形状参数,但是它比Hu moment用到的信息多,而且是在霍夫空间中投票,可以抵抗一些噪声、遮挡因素的影响,因此他的鲁棒性更好。投票流程如(图七)所示,其中A[a]为投票字典(累加器):
这里写图片描述
它的检测效果如(图八)所示:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/hanzy88/article/details/79348134