直方圖反向投影(Back Projection)
反向投影是反映直方圖模型在目標圖像中的分布情況
簡單點說就是用直方圖模型去目標圖像中尋找是否有相似的對象。通常用HSV色彩空間的HS兩個通道直方圖模型
反向投影步驟
1.建立直方圖模型
2.計算待測圖像直方圖并映射到模型中
3.從模型反向計算生成圖像
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
Mat src; Mat hsv; Mat hue;
int bins = 12;
void Hist_And_Backprojection(int, void*);
int main(int argc, char** argv) {
src = imread("D:/girl.jpg");
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
const char* window_image = "input image";
namedWindow(window_image, CV_WINDOW_NORMAL);
namedWindow("BackProj", CV_WINDOW_NORMAL);
namedWindow("Histogram", CV_WINDOW_NORMAL);
cvtColor(src, hsv, CV_BGR2HSV);
hue.create(hsv.size(), hsv.depth());
int nchannels[] = { 0, 0 };
//主要就是把輸入的矩陣(或矩陣數(shù)組)的某些通道拆分復制給對應的輸出矩陣(或矩陣數(shù)組)的某些通道中
//1-輸入矩陣,2-輸入矩陣的個數(shù),3-輸出矩陣,4-輸出矩陣的個數(shù),
//5-設置輸入矩陣的通道對應輸出矩陣的通道,規(guī)則如下:首先用數(shù)字標記輸入矩陣的各個通道。輸入矩陣個數(shù)可能多于一個并且每個矩陣的通道可能不一樣,
//第一個輸入矩陣的通道標記范圍為:0 ~src[0].channels() - 1,第二個輸入矩陣的通道標記范圍為:src[0].channels() ~src[0].channels() + src[1].channels() - 1,
//以此類推;其次輸出矩陣也用同樣的規(guī)則標記,第一個輸出矩陣的通道標記范圍為:0 ~dst[0].channels() - 1,第二個輸入矩陣的通道標記范圍為:dst[0].channels()
//~dst[0].channels() + dst[1].channels() - 1, 以此類推;最后,數(shù)組fromTo的第一個元素即fromTo[0]應該填入輸入矩陣的某個通道標記,而fromTo的第二個元素即
//fromTo[1]應該填入輸出矩陣的某個通道標記,這樣函數(shù)就會把輸入矩陣的fromTo[0]通道里面的數(shù)據(jù)復制給輸出矩陣的fromTo[1]通道。fromTo后面的元素也是這個
//道理,總之就是一個輸入矩陣的通道標記后面必須跟著個輸出矩陣的通道標記。
//6-即參數(shù)fromTo中的有幾組輸入輸出通道關系,其實就是參數(shù)fromTo的數(shù)組元素個數(shù)除以2.
mixChannels(&hsv, 1, &hue, 1, nchannels, 1);
createTrackbar("Histogram Bins:", window_image, &bins, 180, Hist_And_Backprojection);
Hist_And_Backprojection(0, 0);
imshow(window_image, src);
waitKey(0);
return 0;
}
void Hist_And_Backprojection(int, void*) {
float range[] = { 0, 180 };
const float *histRanges = { range };
Mat h_hist;
calcHist(&hue, 1, 0, Mat(), h_hist, 1, &bins, &histRanges, true, false);
normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());
Mat backPrjImage;
calcBackProject(&hue, 1, 0, h_hist, backPrjImage, &histRanges, 1, true);
imshow("BackProj", backPrjImage);
int hist_h = 400;
int hist_w = 400;
Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
int bin_w = (hist_w / bins);
for (int i = 1; i < bins; i++) {
rectangle(histImage,
Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255)))),
//Point(i*bin_w, (hist_h - cvRound(h_hist.at<float>(i) * (400 / 255)))),
Point(i*bin_w, hist_h),
Scalar(0, 0, 255), -1);
}
imshow("Histogram", histImage);
return;
}
