本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.直方图的反向投影
先计算某一特征的直方图模型,然后在目标图像中寻找是否有相似的对象。因此,我们可以利用直方图的反向投影来实现图像分割,目标检测等任务。
通常用HSV色彩空间的H和S两个通道的直方图模型。
常用步骤:
- 读入原始图像(也可以是某一图像的目标区域,即我们想要提取的特征所在的区域)。
- 使用
cv::cvtColor将原始图像转换到HSV色彩空间。 - 使用
cv::mixChannels(用法见本文第2部分)将h通道从HSV格式的图像中提取出来。 - 使用
cv::calcHist计算h通道的直方图。并使用cv::normalize进行归一化处理。 - 使用
cv::calcBackProject(用法见本文第3部分)进行直方图反向投影,对另一图像(或原始图像)进行相似特征的检测。
👉直方图的反向投影原理详解:
假设有灰度图像:
\[Image = \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 7 \\ 9 & 8 & 0 & 1 \\ 5 & 6 & 7 & 6 \\ \end{bmatrix}\]这个图像的直方图为:
| [0,2] | [3,5] | [6,7] | [8,10] |
|---|---|---|---|
| 4 | 4 | 6 | 2 |
接下来计算反向投影矩阵(反向投影矩阵的大小和原灰度图像矩阵的大小相同)。原图像中坐标为$(0,0)$的灰度值为1,1位于区间[0,2]中,区间[0,2] 对应的直方图值为4,所以反向投影矩阵中坐标为$(0,0)$的值记为4,剩余位置以此类推:
\[Proj\_Image=\begin{bmatrix} 4 & 4 & 4 & 4 \\ 4 & 6 & 6 & 6 \\ 2 & 2 & 4 & 4 \\ 4 & 6 & 6 & 6 \\ \end{bmatrix}\]2.cv::mixChannels
cv::mixChannels主要就是把输入的矩阵(或矩阵数组)的某些通道拆分复制给对应的输出矩阵(或矩阵数组)的某些通道中。
1
2
3
4
5
6
7
8
void mixChannels(
const Mat* src,
size_t nsrcs,
Mat* dst,
size_t ndsts,
const int* fromTo,
size_t npairs
);
参数解释见下:
const Mat* src:输入图像(可多个,但必须是一样的大小和位图深度)。size_t nsrcs:输入图像的个数。Mat* dst:输出图像(同样可多个,和输入图像的大小以及位图深度保持一致)。size_t ndsts:输出图像的个数。const int* fromTo:偶数下标的用来标识输入矩阵,奇数下标的用来标识输出矩阵。如果偶数下标为负数,那么相应的输出矩阵为零矩阵。例如{0,1,1,3},表示将输入图像的第0个通道复制到输出图像的第1个通道;将输入图像的第1个通道复制到输出图像的第3个通道。如果输出图像有多个,则通道数索引可标记为:0,1,...,src[0].channels()-1,src[0].channels(),...,src[1].channels()-1,...。输出图像是多个的情况一样,不再赘述。size_t npairs:fromTo中的序号对数(两个算1对)。
3.cv::calcBackProject
1
2
3
4
5
6
7
8
9
10
void calcBackProject(
const Mat* images,
int nimages,
const int* channels,
InputArray hist,
OutputArray backProject,
const float** ranges,
double scale = 1,
bool uniform = true
);
参数解释:
const Mat* images:输入图像(即待检测图像)。可多个,但是图像大小和位图深度(只能是CV_8U、CV_16U、CV_32F中的一个)必须一样。int nimages:输入图像的数量。const int* channels:用于计算反向投影的通道列表(通道的索引标识类似于cv::mixChannels的第5个参数)。InputArray hist:目标特征的直方图。OutputArray backProject:输出的检测结果图像。为单通道,并且和输入图像的大小以及位图深度一致。const float** ranges:直方图中每个维度bin的取值范围。double scale = 1:输出反向投影的比例因子。bool uniform = true:直方图是否均匀分布,即每一个竖条的宽度是否相等。