小言_互联网的博客

Opencv直方图反投影

356人阅读  评论(0)

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=DB,其中 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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场