反向投影法是用已知图像的某些特征来突出其它图像中此类特征的一种方法,基于直方图。html
主要步骤以下:测试
一、统计已知图像某个特征的色度直方图,一般用色度-饱和度(Hue-Saturation)来统计二维直方图,并把直方图表示为几率的形式。ui
二、选取测试图像,对于图像中的每个像素,查看它的色度在已统计直方图上的几率,用这个几率来重建整张图像。spa
三、最后把重建出的图像归一化,会发现用于统计直方图的特征被突出出来。3d
举OpenCV的例子,已知图像以下:code
咱们称之为模型。选取图中的手做为要统计的特征,它的mask以下:htm
因而能够统计获得手的Hue-Saturation直方图和联合几率分布(看作相互独立)的热度图:blog
测试图片是另外一张手的图像:图片
而后执行第三步:get
能够发现手被突出出来了,这是由于,相同物体在不一样的图像中的色值一般是相近的,所以能够经过这种方式来突出它。
Python代码以下:
import cv2 import numpy as np import matplotlib.pyplot as plt #获取mask、model、test图像数据,并进行预处理 mask = plt.imread('mask.jpg')[:,:,0] mask = ((mask<120)*255).astype(np.uint8) n = np.sum(mask>100) model = cv2.cvtColor(plt.imread('model.jpg'),cv2.COLOR_RGB2HSV)#把RGB颜色空间转换为HSV test = cv2.cvtColor(plt.imread('test.jpg'),cv2.COLOR_RGB2HSV) #根据色度和饱和度(明度不考虑),统计model颜色信息,并绘制直方图和它们联合分布的热度图 hist_size = 50 #直方图划分的区间数量 hist_h = cv2.calcHist([model],[0],mask,[hist_size],[0,256])/n hist_s = cv2.calcHist([model],[1],mask,[hist_size],[0,256])/n hot_values = np.matmul(hist_s, hist_h.T) fig = plt.figure() ax1 = fig.add_subplot(121) ax2 = fig.add_subplot(122) ax1.bar(range(len(hist_h)),hist_h[:,0]) ax1.bar(range(len(hist_s)),hist_s[:,0]) hot = ax2.imshow(hot_values) plt.colorbar(hot) plt.show() #使用热度图重建test图像 projection = np.zeros([test.shape[0],test.shape[1]]) for i in range(projection.shape[0]): for j in range(projection.shape[1]): h_pos = (test[i,j,0]/256*hist_size).astype(np.uint8) s_pos = (test[i,j,1]/256*hist_size).astype(np.uint8) projection[i,j] = hist_h[h_pos] * hist_s[s_pos] projection = projection / np.max(projection) plt.imshow(projection,cmap='gray') plt.show()
咱们还能够用RGB来统计,创建RGB的三维联合分布,而后对测试图像进行重建,效果以下:
能够看出突出效果并无H-S模型来得好。代码以下:
import cv2 import numpy as np import matplotlib.pyplot as plt mask = plt.imread('mask.jpg')[:,:,0] mask = ((mask<120)*255).astype(np.uint8) n = np.sum(mask>100) model = plt.imread('model.jpg') test = plt.imread('test.jpg') hist_size = 50 #直方图划分的区间数量 hist_r = cv2.calcHist([model],[0],mask,[hist_size],[0,256])[:,0]/n hist_g = cv2.calcHist([model],[1],mask,[hist_size],[0,256])[:,0]/n hist_b = cv2.calcHist([model],[2],mask,[hist_size],[0,256])[:,0]/n plt.bar(range(len(hist_r)),hist_r) plt.bar(range(len(hist_g)),hist_g) plt.bar(range(len(hist_b)),hist_b) plt.show() projection = np.zeros([test.shape[0],test.shape[1]]) for i in range(projection.shape[0]): for j in range(projection.shape[1]): r_pos = (test[i,j,0]/256*hist_size).astype(np.uint8) g_pos = (test[i,j,1]/256*hist_size).astype(np.uint8) b_pos = (test[i,j,2]/256*hist_size).astype(np.uint8) projection[i,j] = hist_r[r_pos] * hist_g[g_pos] * hist_b[b_pos] projection = projection / np.max(projection) plt.imshow(projection,cmap='gray') plt.show()
参考自:https://docs.opencv.org/master/da/d7f/tutorial_back_projection.html