OpenCV-Python -- Histogram - 4 : Histogram Backprojection

学习目标

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

理论

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

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

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

Numpy反向投影的计算

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

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    #roi is the object or region of object we need to find
    roi = cv2.imread('rose_red.png')
    hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)
    
    #target is the image we search in
    target = cv2.imread('rose.png')
    hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)
    
    # Find the histograms using calcHist. Can be done with np.histogram2d 
    also
    M = 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] )
    
  2. 计算比值: 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])
    
  3. 现在,我们应用圆盘卷积,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)
    
  4. 那么最大值的位置就是目标位置。如果我们期待一个图像中的区域,那么我们可以给合适的阈值,会得到很好的结果。

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

OpenCV中的反向投影计算

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

import cv2
import numpy as np

roi = 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 histogram
roihist = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )

# normalize histogram and apply backprojection
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)

# Now convolute with circular disc
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
cv2.filter2D(dst,-1,disc,dst)

# threshold and binary AND
ret,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)

运行结果如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值