直方圖反向投影(Back Projection)
反向投影是反映直方圖模型在目標(biāo)圖像中的分布情況
簡(jiǎn)單點(diǎn)說(shuō)就是用直方圖模型去目標(biāo)圖像中尋找是否有相似的對(duì)象糟袁。通常用HSV色彩空間的HS兩個(gè)通道直方圖模型
反向投影步驟
1.建立直方圖模型
2.計(jì)算待測(cè)圖像直方圖并映射到模型中
3.從模型反向計(jì)算生成圖像
#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ù)組)的某些通道拆分復(fù)制給對(duì)應(yīng)的輸出矩陣(或矩陣數(shù)組)的某些通道中
//1-輸入矩陣判族,2-輸入矩陣的個(gè)數(shù),3-輸出矩陣项戴,4-輸出矩陣的個(gè)數(shù)形帮,
//5-設(shè)置輸入矩陣的通道對(duì)應(yīng)輸出矩陣的通道,規(guī)則如下:首先用數(shù)字標(biāo)記輸入矩陣的各個(gè)通道周叮。輸入矩陣個(gè)數(shù)可能多于一個(gè)并且每個(gè)矩陣的通道可能不一樣辩撑,
//第一個(gè)輸入矩陣的通道標(biāo)記范圍為:0 ~src[0].channels() - 1,第二個(gè)輸入矩陣的通道標(biāo)記范圍為:src[0].channels() ~src[0].channels() + src[1].channels() - 1,
//以此類推仿耽;其次輸出矩陣也用同樣的規(guī)則標(biāo)記合冀,第一個(gè)輸出矩陣的通道標(biāo)記范圍為:0 ~dst[0].channels() - 1,第二個(gè)輸入矩陣的通道標(biāo)記范圍為:dst[0].channels()
//~dst[0].channels() + dst[1].channels() - 1, 以此類推项贺;最后君躺,數(shù)組fromTo的第一個(gè)元素即fromTo[0]應(yīng)該填入輸入矩陣的某個(gè)通道標(biāo)記峭判,而fromTo的第二個(gè)元素即
//fromTo[1]應(yīng)該填入輸出矩陣的某個(gè)通道標(biāo)記,這樣函數(shù)就會(huì)把輸入矩陣的fromTo[0]通道里面的數(shù)據(jù)復(fù)制給輸出矩陣的fromTo[1]通道棕叫。fromTo后面的元素也是這個(gè)
//道理林螃,總之就是一個(gè)輸入矩陣的通道標(biāo)記后面必須跟著個(gè)輸出矩陣的通道標(biāo)記。
//6-即參數(shù)fromTo中的有幾組輸入輸出通道關(guān)系俺泣,其實(shí)就是參數(shù)fromTo的數(shù)組元素個(gè)數(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;
}