1 理论
直方图反投影用于图像分割或者图像中查找感兴趣的对象。简而言之,它创建大小等同于输入图像的图像,但只有一个通道,其中每个像素对应于该像素属于目标物体的概率。
2 测试图像
1)目标区域:
2)测试图像:
3 反投影
3.1 Numpy
计算步骤如下:
1)计算目标图像和测试图像中的颜色直方图:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
target = cv.imread("tiankong_target.png")
hsv_target = cv.cvtColor(target, cv.COLOR_BGR2HSV)
test = cv.imread("tiankong.png")
hsv_test = cv.cvtColor(test, cv.COLOR_BGR2HSV)
hist_target = cv.calcHist([hsv_target], [0, 1], None, [180, 256], [0, 180, 0, 256])
hist_test = cv.calcHist([hsv_test], [0, 1], None, [180, 256], [0, 180, 0, 256])
2)求出比值 r = r = r=hist_target / / /hist_test:
r = hist_target / hist_test
3)反向投影 R R R,并以每个像素作为其对应目标概率创建一个新图像;应用概率 B ( x , y ) = min [ B ( x , y ) , 1 ] B(x, y) = \min [B (x, y), 1] B(x,y)=min[B(x,y),1]:
h, s, v = cv.split(hsv_test)
B = r[h.ravel(), s.ravel()]
B = np.minimum(B, 1)
B = B.reshape(hsv_test.shape[:2])
其中 h h h、 s s s分别表示色调和饱和度。
4)对 B B B应用卷积: B = D ∗ B B = D \ast B B=D∗B,其中 D D D表示圆盘内核:
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
cv.filter2D(B, -1, disc, B)
B = np.uint8(B)
cv.normalize(B, B, 0, 255, cv.NORM_MINMAX)
5)最大强度的位置给了我们物体的位置。如果期望图像中有一个区域,则对合适的值进行阈值处理:
ret, thresh = cv.threshold(B, 50, 255, 0)
完整代码:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
target = cv.imread("tiankong_target.png")
hsv_target = cv.cvtColor(target, cv.COLOR_BGR2HSV)
test = cv.imread("tiankong.png")
hsv_test = cv.cvtColor(test, cv.COLOR_BGR2HSV)
hist_target = cv.calcHist([hsv_target], [0, 1], None, [180, 256], [0, 180, 0, 256])
hist_test = cv.calcHist([hsv_test], [0, 1], None, [180, 256], [0, 180, 0, 256])
r = hist_target / hist_test
h, s, v = cv.split(hsv_test)
B = r[h.ravel(), s.ravel()]
B = np.minimum(B, 1)
B = B.reshape(hsv_test.shape[:2])
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
cv.filter2D(B, -1, disc, B)
B = np.uint8(B)
cv.normalize(B, B, 0, 255, cv.NORM_MINMAX)
ret, thresh = cv.threshold(B, 50, 255, 0)
cv.imshow("", thresh)
cv.waitKey()
输出如下:
3.2 Opencv
cv.calcBackProject():参数为图像的直方图,且在传递之前需要对直方图进行归一化;返回值为概率图像,然后应用圆盘内核进行卷积并运用阈值:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
target = cv.imread("tiankong_target.png")
hsv_target = cv.cvtColor(target, cv.COLOR_BGR2HSV)
test = cv.imread("tiankong.png")
hsv_test = cv.cvtColor(test, cv.COLOR_BGR2HSV)
hist_test = cv.calcHist([hsv_test], [0, 1], None, [180, 256], [0, 180, 0, 256])
cv.normalize(hist_test, hist_test, 0, 255, cv.NORM_MINMAX)
dst = cv.calcBackProject([hsv_test], [0, 1], hist_test, [0, 180, 0, 256], 1)
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
cv.filter2D(dst, -1, disc, dst)
_, thresh = cv.threshold(dst, 50, 255, 0)
thresh = cv.merge((thresh, thresh, thresh))
ret = cv.bitwise_and(test, thresh)
ret = np.hstack((test, thresh, ret))
cv.imshow("", ret)
cv.waitKey()
输出如下:
参考文献:
【1】Opencv中文文档
转载:https://blog.csdn.net/weixin_44575152/article/details/115637931
查看评论