OpenCV计算两幅图像的EMD度量
EMD度量:
相关基础
https://blog.csdn.net/wangdonggg/article/details/32329879
这位大哥说的很好了,先就不搬运了,后面有空再整理
函数介绍
https://docs.opencv.org/4.5.2/d6/dc7/group__imgproc__hist.html
Python版本
看到现在有的都是C++版本的代码,自己基于Python写了一个
import cv2 as cv2
import numpy
def get_hist(img_in):
img = img_in.copy()
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
# cv2.imshow("hsv", hsv)
# calcHist(&hsv[i], 1, ch, noArray(), hist[i], 2, histSize, ranges, true) # CPP
# mask = cv2.bitwise_xor(img, img)
channels = [0, 1, 2]
histSize = [8, 10, 10]
ranges = [0, 180, 0, 256, 0, 256]
hist = cv2.calcHist([hsv], channels, None, histSize, ranges)
# cv2.imshow("hist", hist)
hist = cv2.normalize(hist, hist, 1.0, 0.0, cv2.NORM_MINMAX)
# print(hist)
return hist
def hist2signature(hist):
histSize = hist.shape
assert len(histSize) == 3
signature = numpy.zeros(shape=(histSize[0] * histSize[1] * histSize[2], 4), dtype=numpy.float32)
for h in range(histSize[0]):
for s in range(histSize[1]):
for v in range(histSize[2]):
idx = (h + 1) * (s + 1) * (v + 1) - 1
signature[idx][0] = hist[h][s][v]
signature[idx][1] = h
signature[idx][2] = s
signature[idx][3] = v
return signature
if __name__ == '__main__':
path_rgb = r'./video/scivideo/vid_rgb_frame1.png'
img_rgb = cv2.imread(path_rgb)
# print(img_rgb)
# img_down = cv2.pyrUp(cv2.pyrDown(img_rgb))
img_down = cv2.pyrDown(img_rgb)
# cv2.imshow("img_rgb", img_rgb)
# 计算直方图
hist_gt = get_hist(img_rgb)
hist_down = get_hist(img_down)
# EMD算法要求的数据格式不是计算的hist,而是(val, h, s, v) * (h_bin*s_bin*v_bin) 因此需要转换
signature_hist = hist2signature(hist_down)
signature_gt = hist2signature(hist_gt)
# 计算 EMD
retval, lowerBound, flow = cv2.EMD(signature_hist, signature_gt, cv2.DIST_L2)
print(retval)
cv2.waitKey(0)
C++
先贴上别的大佬的实现吧