反向投影的工作原理
反向投影图中,某一位置(x,y)的像素值 = 原图对应位置(x,y)像素值在原图的总数目。 即若原图中(5,5)位置上像素值为 200,而原图中像素值为 200 的像素点有 500 个,则反向投影图中(5,5)位置上的像素值就设为 500。
具体步骤:
- 计算图像直方图:统计各像素值(或像素区间)在原图的总数量。
- 将直方图数值归一化到 [0,255] 。
- 对照直方图,实现反向投影。
反向投影的作用
反向投影用于在输入图像(通常较大)中查找与模板图像(通常较小甚至仅 1 个像素)最匹配的点或区域,也就是确定模板图像在输入图像中的位置。
计算反向投影:calcBackProject 函数
void calcBackProject(const Mat* images, int nimages, const int* channels, InputArray hist, OutputArray backProject, const float** ranges, double scale = 1, bool uniform = true);
- images,输入的图像(或图像集),它们需为相同深度(CV_8U 或 CV_32F)和相同尺寸,而通道数任意。
- nimages,输入图像个数。
- channels,需要统计图像的通道索引即第几个通道,第一幅图的通道索引可选范围 [0, images[0].channels() - 1],第二幅图的通道索引可选范围 [images[0].channels(), images[0].channels() + images[1].channels() - 1] 以此类推。
- hist,输入的直方图。
- backProject,反向投影图像,需为单通道,并且和 images[0] 有相同的大小和深度。
- ranges,直方图中 x 轴的取值范围。
- scale,缩放因子,backProject [i][j] = scale * hist [images[k] [i][j]],有默认值 1。
- uniform,直方图是否均匀化的标识符,有默认值 true。
代码示例:
#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
Mat src, hsvImg, hist;
vector<Mat>hsv;
int histSize = 5;
void ChangeHistSize(int, void*) {
if (histSize == 0) {
histSize = 1;
}
//计算 H 通道直方图 https://www.cnblogs.com/bjxqmy/p/12378312.html
int channels[] = { 0 };
float hr[] = { 0,180 };
const float *ranges[] = { hr };
calcHist(&hsv[0], 1, &channels[0], Mat(), hist, 1, &histSize, &ranges[0]);
normalize(hist, hist, 255, 0, NORM_L1);
imshow("hist", hist);
//计算反向投影
Mat backImg;
calcBackProject(&src, 1, &channels[0], hist, backImg, &ranges[0], 1);
imshow("backImg", backImg);
}
int main() {
src = imread("C:/Users/齐明洋/Desktop/证件照/1.jpg");
imshow("src", src);
//转换为 HSV 通道图像
cvtColor(src, hsvImg, COLOR_BGR2HSV);
imshow("hsvImg", hsvImg);
//通道分离
split(hsvImg, hsv);
imshow("hImg", hsv[0]);
namedWindow("backImg");
createTrackbar("histSize", "backImg", &histSize, 180, ChangeHistSize);
ChangeHistSize(0, 0);
waitKey(0);
}
效果演示:
借鉴博客:https://blog.csdn.net/fengye2two/article/details/79113560