opencv23:Histogram直方图反向投影

目标

在本章中将学习

  • 直方图反投影

理论

这是由Michael J. Swain和Dana H. Ballard在他们的论文《 Indexing via color histograms》中提出的。

用简单的话来说,它用于图像分割或在图像中查找感兴趣的对象。简而言之,它创建的图像大小与输入图像相同(但只有一个通道),其中每个像素对应于该像素属于物体的概率。用更简单的话来说,与其余部分相比,输出图像将在可能有对象的区域具有更多的白色值。直方图反投影与camshift算法等配合使用。

在这里插入图片描述
反向投影矩阵中某点的值就是它对应的原图像中的点所在区间的灰度直方图值。所以我们可以看出,一个区间点越多,在反向投影矩阵中就越亮。

步骤如下:

  • 首先创建一个图像的直方图,其中包含感兴趣的对象。对象应尽可能填充图像以获得更好的效果。而且颜色直方图比灰度直方图更可取,因为对象的颜色对比灰度强度是定义对象的好方法
  • 然后,将该直方图“反投影”到需要找到对象的测试图像上,换句话说,计算出属于背景的每个像素的概率并将其显示出来
  • 在适当的阈值下产生的输出结果仅仅是获得背景

从这个过程可以看出,先求出原图像的直方图,再由直方图得到反向投影矩阵,由直方图到反向投影矩阵实际上就是一个反向的过程,所以叫反向。

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] )

  1. 然后找到比例, R = M I R=\frac{M} {I} R=IM
    即 使用R作为调色板,并使用每个像素创建新图像作为其目标的相应概率。B(x,y) = R[h(x,y),s(x,y)], 其中h和s表示像素点(x,y)处的色调(h),饱和度(s)。
h, s, v = cv2.split(hsvt)
B = R[h.ravel(), s.ravel()]
B = np.minimum(B,1)
B = B.reshape(hsvt.shape[:2])
  1. 现在用圆形核应用卷积, 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)
  1. 现在最大强度的位置给了物体的位置。如果期望图像中有一个区域,则对合适的值进行阈值处理将获得不错的结果。
ret, thresh = cv2.threshold(B,50,255,0) 

OpenCV的反投影

OpenCV提供了一个内建的函数cv2.calcBackProject()。它的参数几乎与cv2.calchist()函数相同。

dst = cv.calcBackProject( images, channels, hist, ranges, scale[, dst] )

  • images Source arrays. They all should have the same depth, CV_8U, CV_16U or CV_32F , and the same size. Each of them can have an arbitrary number of channels.
  • nimages Number of source images.
  • channels The list of channels used to compute the back projection. The number of channels must match the histogram dimensionality. The first array channels are numerated from 0 to images[0].channels()-1 , the second array channels are counted from images[0].channels() to images[0].channels() + images[1].channels()-1, and so on.
  • hist Input histogram that can be dense or sparse.
  • backProject Destination back projection array that is a single-channel array of the same size and depth as images[0] .
  • ranges Array of arrays of the histogram bin boundaries in each dimension. See calcHist .
  • scale Optional scale factor for the output back projection.
  • uniform Flag indicating whether the histogram is uniform or not (see above).

在传递给backproject函数之前,应该对对象直方图进行归一化。它返回概率图像。然后我们用圆盘内核对图像进行卷积并应用阈值。下面是我的代码和结果:

import numpy as np
import cv2
from matplotlib import pyplot as plt

roi = cv2.imread('roi.png')  # 感兴趣的图片 绿色草地
hsv = cv2.cvtColor(roi, cv2 .COLOR_BGR2HSV)

target = cv2.imread('messi.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)

cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()

以下是处理过的一个示例。将蓝色矩形内的区域用作示例对象,提取整个地面:

在这里插入图片描述

在这里插入图片描述
可以用于目标检测和分割

附加资源

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uncle_ll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值