失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > OpenCV-Python -- Histogram - 4 : Histogram Backprojection

OpenCV-Python -- Histogram - 4 : Histogram Backprojection

时间:2023-10-28 01:45:30

相关推荐

OpenCV-Python -- Histogram - 4 : Histogram Backprojection

学习目标

这一节,我们学习直方图反向投影(histogram backprojection)。

理论

该理论由Michael J. Swain , Dana H. Ballard发表在他们的论文中,Indexing via color histograms.

那么,直方图反向投影是什么意思呢?常被用于图像分割或者寻找图像中感兴趣区域。简单来说,首先创建与输入图像相同大小的单通道图像,图像中每一个像素与该像素属于目标的概率有关。简而言之,输出图像中目标区域具有更大的白色区域(相对于背景区域)。这仅仅是直觉上的理解。直方图反向投影常与CameShift算法一起使用。

那么该算法如何操作呢?首先创建包含目标的图像直方图(本节的例子,我们留下地面,去掉其余的对象)。若要得到很好的效果,那么需要目标区域足够大。那么彩色直方图将更加优于灰度直方图,因为色彩更好的定义目标。然后我们对该图像应用直方图反向投影,最终定位到目标区域。换句话说,我们估计每一个像素属于目标(地面,ground)的概率。

Numpy反向投影的计算

首先,我们计算目标的直方图(令为M),以及搜索的目标图像 (令为I)。

import cv2import numpy as npfrom matplotlib import pyplot as plt#roi is the object or region of object we need to findroi = cv2.imread('rose_red.png')hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)#target is the image we search intarget = cv2.imread('rose.png')hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)# Find the histograms using calcHist. Can be done with np.histogram2d alsoM = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )I = cv2.calcHist([hsvt],[0, 1], None, [180, 256], [0, 180, 0, 256] )

计算比值: R = M I R=\frac{M}{I} R=IM​,然后将R作为画板,并创建新的图像,每一个像素表示与目标相关的概率,比如B(x,y)=R[h(x,y),s(x, y)],这里h是hue,s是饱和度(saturation)。然后,应用条件,B(x,y) = min(B(x,y),1).

h,s,v = cv2.split(hsvt)B = R[h.ravel(),s.ravel()]B = np.minimum(B,1)B = B.reshape(hsvt.shape[:2])

现在,我们应用圆盘卷积,B=D*B,D是距离核。

disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))cv2.filter2D(B,-1,disc,B)B = np.uint8(B)cv2.normalize(B,B,0,255,cv2.NORM_MINMAX)

那么最大值的位置就是目标位置。如果我们期待一个图像中的区域,那么我们可以给合适的阈值,会得到很好的结果。

ret,thresh = cv2.threshold(B,50,255,0)

OpenCV中的反向投影计算

OpenCV中提供了计算直方图的内置函数,cv2.calcBackProject(). 它的参数几乎与cv2.calcHist()的参数一致。他的其中一个参数是目标的直方图,我们需要寻找该目标。并且,传入的直方图必须是归一化的。返回概率图像。然后使用卷积对图像进行卷积,最后应用阈值,下面是代码和输出:

import cv2import numpy as nproi = cv2.imread('rose_red.png')hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)target = cv2.imread('rose.png')hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)# calculating object histogramroihist = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )# normalize histogram and apply backprojectioncv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)# Now convolute with circular discdisc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))cv2.filter2D(dst,-1,disc,dst)# threshold and binary ANDret,thresh = cv2.threshold(dst,50,255,0)thresh = cv2.merge((thresh,thresh,thresh))res = cv2.bitwise_and(target,thresh)res = np.vstack((target,thresh,res))cv2.imwrite('res.jpg',res)

运行结果如下:

如果觉得《OpenCV-Python -- Histogram - 4 : Histogram Backprojection》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。