目录
一、前言
二、什么是反投影图像
三、反投影图像的概念
四、反向投影的工作原理
五、反向投影需注意的细节
六、代码编写
如果对直方图或者直方图均衡化的概念比较模糊的话,建议先了解直方图的基本原理及概念:
python+OpenCv笔记(十二):直方图(灰度直方图、掩膜的应用、直方图均衡化、自适应直方图均衡化)https://blog.csdn.net/qq_45832961/article/details/122374068
我们先不谈反投影图像抽象的概念,可以先用示例做一个简单且清晰的了解:
1.
例如,现在有一张手掌的图片,我们对其进行直方图绘制(假设bins设置为4),如图:
这是之前做过的一个示例,而且很容易理解,直方图中清晰地展示了如果将灰度0~255划分为4个区间(bins),那么这张手掌灰度图按照这4个区间划分都有多少个像素点,这就是图像到直方图的一个过程。
反投影图像恰恰是这一步的逆过程,即通过直方图又生成了一张图像,但生成的图像只有4种颜色(即直方图有多少个bins,生成的反投影图像就有多少种颜色),比如说原图中某一块区域的灰度值都在0到20这个区间内,如果bins=4,那么反投影图像中那一块区域的颜色是同一种颜色。
并且,一个bins(区间)内像素越多,在反投影图像中呈现出的颜色就越亮,反之越暗。
现在,我们设置bins=12,在代码中运行的结果如下:
归一化后的直方图:
反投影图像:
由上面可知,反投影图像由12种灰度值组成,且落在同一个区间内的像素值越多,那么反投影后原区域就会越亮,比如整个手掌部分由于灰度值接近,且像素很多,那么反投影后手掌部分就会变得很亮,像素点很少的bins反投影后甚至会呈现黑色。
(注:由于示例原因,直方图中很多bins的像素点数为0,所以反投影后的图像看起来不像是由12种灰度值组成,其实是因为那些区间并不存在像素点)
2.
但是,反投影图像更常见的用途是查找特征,在meanshift算法中会用到。
比如说我们现在有模板图像以及生成的模板图像的直方图(见上),我们需要在原图像中用上面的结果来检测特征,先看一下结果:
在原图像中反投影后:
可以看到,一个手掌已经被清晰地展现了出来。
使用统计学的语言, 新图像中储存的数值代表了测试图像中该像素属于皮肤区域的 概率 。比如以上图为例, 亮起的区域是皮肤区域的概率更大(事实确实如此),而更暗的区域则表示更低的概率(注意手掌内部和边缘的阴影影响了检测的精度)。
这其中涉及backproject算法,具体算法以及流程可以阅读后文。
总结:
原图像————直方图————反投影图像
现在,我们可以理解一下反投影图像的抽象概念:
一、利用反向投影backproject查找特征的大致流程:
二、具体细化的流程
直方图反向投影流程
假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的: |
1.从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像 |
2.生成临时图像的直方图 |
3.用临时图像的直方图和模板图像的直方图对比,对比结果记为c |
4.直方图对比结果c,就是结果图像(0,0)处的像素值 |
5.切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像 |
6.重复1~5步直到输入图像的右下角,就形成了直方图的反向投影。 |
三、计算过程示例
(1)模板灰度图像的矩阵如下:
(2)模板灰度图像的直方图为:
bin指定的区间为:[0,3), [4,7), [8,11), [12,16)
Histogram = 4 4 6 2
(3)反向投影图为的矩阵为:
例如位置(0,0)上的像素值为0,对应的bin为[0,3), 所以反向直方图在该位置上的值为这个bin的值4。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 输入模板图像与原图像
src = cv.imread("E:\\hand.jpg")
img = src.copy()
src2 = cv.imread("E:\\hand2.jpg")
img2 = src2.copy()
# 计算直方图
# 转换色彩空间
hsv_roi = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# 计算直方图
roi_hist = cv.calcHist([hsv_roi], [0], None, [13], [0, 180])
# 归一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)
# 原图像转换色彩空间
hsv_roi2 = cv.cvtColor(img2, cv.COLOR_BGR2HSV)
# 反投影
dst = cv.calcBackProject([hsv_roi2], [0], roi_hist, [0, 255], 1)
# 显示图像
plt.figure(figsize=(10, 6), dpi=100)
plt.plot(roi_hist)
plt.grid()
plt.show()
cv.imshow("backProject", dst)
cv.waitKey(0)
模板图像与原图像:
模板图像的直方图:
在原图像中检测的特征: