#pragma once
#include <vector>
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
class WinBox
{
public:
WinBox();
vector<Mat> computeHist(Mat& win, Size box);
Mat confidence(Mat& img, Size box, vector<Mat>& winHist, int scale = 1, int stride = 1);
private:
int histSize[2]; //bin数量,声明成数组形式
float hranges[2]; //直方图的最小值与最大值
float sranges[2]; //直方图的最小值与最大值
const float* ranges[2]; //hranges的地址值要赋给ranges[0]
int channels[2]; //通道
};
#include "WinBox.h"
WinBox::WinBox()
{
histSize[0] = 30; histSize[1] = 40;
hranges[0] = 0; hranges[1] = 180;
sranges[0] = 0; sranges[1] = 255;
ranges[0] = hranges; ranges[1] = sranges;
channels[0] = 0; channels[1] = 1;
}
//计算给定窗口win的分块直方图,并保存到winHist中
vector<Mat> WinBox::computeHist(Mat& win, Size box)
{
vector<Mat> winHist;
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
//从左上开始遍历2*2 box小块
Rect rect(j*box.width, i*box.height, 2*box.width, 2*box.height);
Mat box = win(rect), boxHist;
calcHist(&box, 1, channels, Mat(), boxHist, 2, histSize, ranges);
normalize(boxHist, boxHist, 0.0, 1.0, NORM_MINMAX);
winHist.push_back(boxHist);
}
}
return winHist;
}
//读取下一幅完整图像,用窗口win遍历图像(步长为1像素)
//计算当前窗口win下的直方图(9个),并和上幅图像得到的直方图(9个)依次进行对比
//将对比结果求均值,归一化,作为灰度值写入置信图的一个像素点
Mat WinBox::confidence(Mat& img, Size box, vector<Mat>& winHist, int scale, int stride)
{
//初始化矩形区域(也就是win大小)
Rect rect(0, 0, 4*box.width, 4*box.height);
//用窗口扫描图像
vector<vector<double>> row_size;
for (int i = 0; i < img.rows; i += stride)
{
if (i+4*box.height > img.rows) break;
vector<double> every_row;
for (int j = 0; j < img.cols; j += stride)
{
Rect rect_temp = rect + Point(j,i);
if (static_cast<int>(rect_temp.br().x) > img.cols) break;
else
{
Mat winTemp = img(rect_temp);
vector<Mat> winHistTemp = computeHist(winTemp, box);//计算所有2*2 box区域直方图
double sum = 0; //相似度的和
for (int t = 0; t < 9; ++t)
{
double value = cv::compareHist(winHist[t], winHistTemp[t], 0);
if (value < 0) value = 0;
sum += value;
}
sum /= 9.0; //求均值
sum *= 255.0;
every_row.push_back(sum);
}
}
row_size.push_back(every_row);
}
int nr = row_size.size();
int nc = row_size[0].size();
Mat backproj = Mat::zeros(nr, nc, CV_8UC1); //置信图
for (int i = 0; i < nr; ++i)
{
uchar* data = backproj.ptr<uchar>(i);
for (int j = 0; j < nc; ++j)
data[j] = static_cast<uchar>(row_size[i][j]);
}
//调整置信图
normalize(backproj, backproj, 0.0, 255.0, NORM_MINMAX);
resize(backproj, backproj, Size(img.cols*scale,img.rows*scale), 0, 0, 1);
return backproj;
}