引言
直方图反向投影是一种基于图像颜色分布的图像处理技术,它通过计算图像中不同区域的颜色直方图,并将其与目标区域的直方图进行比较,从而实现目标的识别和分割。本文将介绍直方图反向投影的原理和应用,并探讨其在计算机视觉任务中的重要性。
原理
直方图反向投影的原理是基于颜色分布的统计学特征。首先,选择感兴趣的目标区域,计算该区域的颜色直方图,得到不同颜色的像素数量。然后,对整个图像计算颜色直方图。接下来,归一化目标区域的直方图和整个图像的直方图,使它们具有相同的尺度。最后,对于每个像素,计算它在归一化目标区域直方图中的概率,并将其映射到图像中,形成反向投影图像。
步骤及应用
直方图反向投影是一种图像处理技术,用于根据图像的颜色分布来识别感兴趣的目标区域。它基于图像的直方图和目标区域的直方图之间的相似性来进行识别。
具体步骤如下:
1.创建目标区域的直方图:首先选择感兴趣的目标区域,然后计算该区域的颜色直方图。颜色直方图是对图像中每个像素的颜色进行统计,得到不同颜色的像素数量。
2.计算整个图像的直方图:对整个图像计算颜色直方图。
3.归一化直方图:将目标区域的直方图和整个图像的直方图进行归一化,使它们具有相同的尺度。
4.计算反向投影图像:对于每个像素,计算它在归一化目标区域直方图中的概率。这可以通过将像素的颜色值映射到直方图的bin来实现。
5.根据反向投影图像进行目标识别:根据反向投影图像的结果,可以使用阈值或其他分割算法来分割出目标区域。
直方图反向投影在计算机视觉任务中具有广泛的应用。它可以用于图像分割,通过识别目标区域的颜色分布,将目标从背景中分割出来。此外,直方图反向投影还可以用于目标检测和跟踪。通过比较图像中不同区域的颜色分布,可以实现目标的快速检测和准确跟踪。
优势
与传统的基于边缘或纹理的图像处理技术相比,直方图反向投影具有以下优势:
- 不受光照变化的影响:由于直方图反向投影是基于颜色分布的统计特征,因此它相对于光照变化具有较强的鲁棒性。
- 简单而高效:直方图反向投影的实现相对简单,计算速度较快,适用于实时应用。
- 适用性广泛:直方图反向投影可以应用于不同类型的图像,包括自然图像、医学图像和遥感图像等。
Numpy算法实现
首先,我们需要先创建两幅颜色直方图,待搜索目标图像的直方图'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] )
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))
B=cv2.filter2D(B,-1,disc)
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()函数用于直方图反向投影实现。它的语法如下:
backProj = cv2.calcBackProject(images, channels, hist, ranges, scale)
参数说明:
- images:输入图像,可以是单张图像或图像列表。
- channels:指定用于计算直方图的通道列表。通道的索引从0开始。
- hist:目标区域的归一化直方图。
- ranges:每个通道的取值范围。
- scale:反向投影结果的缩放因子。
返回值:
- backProj:直方图反向投影结果。
cv2.calcBackProject()函数的原理是通过计算输入图像中每个像素点在归一化直方图中的概率,并将其映射到反向投影图像中。这样,反向投影图像中的每个像素点表示该像素点属于目标区域的概率。使用cv2.calcBackProject()函数时,通常需要先计算目标区域直方图,可以使用cv2.calcHist()函数来计算直方图。然后,通过对输入图像应用cv2.calcBackProject()函数,可以得到反向投影图像。反向投影图像可以用于目标检测、图像分割和跟踪等应用。
需要注意的是,cv2.calcBackProject()函数的输入图像和目标区域的直方图应该具有相同的色彩空间和维度。此外,通常还需要对反向投影图像进行阈值化或二值化处理,以便更好地分割目标区域。
下面是我使用的一幅图像进行的示例展示。我使用图中蓝色矩形中的区域作为取样对象,再根据这个样本搜索图中所有的类似区域(草地)。
import cv2
import numpy as np
roi = cv2.imread('tar.jpg')
hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)
target = cv2.imread('roi.jpg')
hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)
# calculating object histogram
roihist = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
dst=cv2.filter2D(dst,-1,disc)
# 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.hstack((target,thresh,res))
cv2.imwrite('res.jpg',res)
# 显示图像
cv2.imshow('1',res)
cv2.waitKey(0)
结论
直方图反向投影是一种基于颜色分布的图像处理技术,通过计算图像中不同区域的颜色直方图,并将其与目标区域的直方图进行比较,实现目标的识别和分割。它在图像分割、目标检测和跟踪等计算机视觉任务中具有广泛的应用。直方图反向投影相对于传统的图像处理技术具有许多优势,如不受光照变化的影响、简单高效以及适用性广泛。因此,直方图反向投影在计算机视觉领域具有重要的研究和应用价值。