C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影

目录

 

1.概念

1.1直方图概念

​ 1.2直方图均衡化概念

 2.直方图计算

2.1直方图概念扩展

 2.2 画三通道直方图

 3.直方图的比较

3.1Correlation 相关性比较

 3.2Chi-Square 卡方比较

 3.3intersection十字交叉性

3.4Bhattacharyya distance 巴氏距离​

3.5相关API

3.6案例分析

4.直方图的反向投影(back projection)

4.1反向投影概述

4.2反向投影步骤

4.3实现步骤及相关API

4.4 代码演示


1.概念

1.1直方图概念

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第1张图片

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第2张图片 1.2直方图均衡化概念

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第3张图片

 图像直方图均衡化的实现:

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第4张图片

直方图均衡化API:

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第5张图片 直方图均衡化案例

void MyApi::histogramEqualize(Mat& image)
{
	Mat gray_image,dst;
	cvtColor(image, gray_image, COLOR_BGR2GRAY);
	imshow("灰度图", gray_image);
	equalizeHist(gray_image, dst);
	imshow("直方图均衡化后图像", dst);
}

 上图分别是原图、灰度图、直方图均衡化后的图

 2.直方图计算

2.1直方图概念扩展

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第6张图片

 C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第7张图片

 2.2 画三通道直方图

void MyApi::histogram_cal(Mat& image)
{
	//1.把多通道的图像分离单通道
	vector bgr_planes;
	split(image, bgr_planes);
	//imshow("单个通道",bgr_planes[0]);//我们可以输出bgr中的b通道的图像

	//2.计算直方图
	int histSize = 256;
	float range[] = { 0,256 };
	const float* histRanges = {range};
	Mat b_hist, g_hist, r_hist;
	calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
	calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
	calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);

	//归一化:为了避免有些像素值的统计值很大,因此为了方便观察归一化到一定的范围内
	int hist_h = 400;
	int hist_w = 512;
	int bin_w = hist_w / histSize;
	Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
	normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
	normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
	normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());

	//绘制直方图
	for (int i = 1; i < histSize; i++)
	{
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(b_hist.at(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(b_hist.at(i))), Scalar(255, 0, 0), 2, LINE_AA);
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(g_hist.at(i))), Scalar(0, 255, 0), 2, LINE_AA);
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(r_hist.at(i))), Scalar(0, 0, 255), 2, LINE_AA);
	}
	imshow("彩色图像直方图", histImage);
}

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第8张图片

 3.直方图的比较

对于输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间(图像大小要一致)然后可以通过计算H1与H2之间的距离得到两个直方图的相似程度,进而比较图像本身的相似程度。openCV提供了比较方法有四种:

  • Correlation 相关性比较
  • Chi-Square 卡方比较
  • intersection十字交叉性
  • Bhattacharyya distance 巴氏距离

3.1Correlation 相关性比较

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第9张图片

 3.2Chi-Square 卡方比较

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第10张图片

 3.3intersection十字交叉性

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第11张图片

3.4Bhattacharyya distance 巴氏距离C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第12张图片

3.5相关API

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第13张图片

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第14张图片

opencv4中compareHist中的method是改为如下:

相关性比较(HISTCMP_CORREL)值越接近1,相关性越高;越接近0,相关性越低;
卡方比较(HISTCMP_CHISQR)值越小越接近,为0时相似度最高;
巴氏距离(HISTCMP_BHATTACHARYYA),完全匹配为 0,完全不匹配为1

3.6案例分析

源文件函数如下:

string convertToString(double d)//double类型转为string类型
{
	ostringstream os;
	if (os << d)
		return os.str();
	return "invalid convertsion";
}

void MyApi::histogram_comp(Mat& image, Mat& test1, Mat& test2)
{
	//图像颜色空间转到HSV空间
	cvtColor(image, image, COLOR_BGR2HSV);
	cvtColor(test1, test1, COLOR_BGR2HSV);
	cvtColor(test2, test2, COLOR_BGR2HSV);

	//设置两个灰度等级
	int h_bins = 50;
	int s_bins = 60;
	int histSize[] = {h_bins,s_bins};

	float h_ranges[] = { 0, 180 };
	float s_ranges[] = { 0, 256 };
	const float* ranges[] = {h_ranges,s_ranges};
	int channels[] = { 0,1 };

	MatND hist_image;
	MatND hist_test1;
	MatND hist_test2;

	//计算直方图
	calcHist(&image, 1, channels, Mat(), hist_image, 2, histSize, ranges, true, false);
	normalize(hist_image, hist_image, 0, 1, NORM_MINMAX, -1, Mat());

	calcHist(&test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
	normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());

	calcHist(&test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);
	normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());

	//相互比较
	double imageimgae = compareHist(hist_image, hist_image, HISTCMP_CORREL);
	double imagetest1 = compareHist(hist_image, hist_test1, HISTCMP_CORREL);
	double imagetest2 = compareHist(hist_image, hist_test2, HISTCMP_CORREL);
	double test1test2 = compareHist(hist_test1, hist_test2, HISTCMP_CORREL);
	printf("test1与test2比较的相关性指标为:%f", test1test2);

	putText(image, convertToString(imageimgae), Point(50, 50), FONT_HERSHEY_COMPLEX,
		1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(test1, convertToString(imagetest1), Point(50, 50), FONT_HERSHEY_COMPLEX,
		1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(test2, convertToString(imagetest2), Point(50, 50), FONT_HERSHEY_COMPLEX,
		1, Scalar(0, 0, 255), 2, LINE_AA);

	namedWindow("image", WINDOW_AUTOSIZE);
	namedWindow("test1", WINDOW_AUTOSIZE);
	namedWindow("test2", WINDOW_AUTOSIZE);

	imshow("image", image);
	imshow("test1", test1);
	imshow("test2", test2);

}

 测试函数如下:

#include
#include
#include"myApi.h"
using namespace cv;
using namespace std;

int main(int argc, char** argv) {
	Mat src = imread("F:\\testImage\\test.png");
	if (src.empty()) {
		printf("could not load image...");
		return -1;
	}
	//如果图像过于大,不能完全显示整张图像可以使用namedWindow()可以实现对图像的自由缩放
	//namedWindow("input_window", WINDOW_FREERATIO);
	//imshow("input_window", src);
	Mat test1 = imread("F:\\testImage\\test1.png");
	Mat test2 = imread("F:\\testImage\\test2.png");

	MyApi ma;
	ma.histogram_comp(src,test1,test2);

	waitKey(0);
	return 0;
}

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第15张图片

 从左到右分别是image与test1比较的相似性、与test2比较的相似性、与image比较的相似性

4.直方图的反向投影(back projection)

4.1反向投影概述

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第16张图片

4.2反向投影步骤

  1. 建立直方图模型
  2. 计算待测图像直方图并映射到模型中
  3. 从模型反向计算生成图像

4.3实现步骤及相关API

  1. 加载图片imread
  2. 将图像从RGB色彩空间转换到HSV色彩空间cvtcolor
  3. 计算直方图和归一化calcHist与normalize
  4. Mat与MatND其中Mat表示二维数据,MatND表示三维或者多维数据,此处均可以用Mat表示
  5. 计算反向投影图像calcBackProject

4.4 代码演示

mixChannels()参数说明:

void mixChannels(
const Mat* src, //输入数组或向量矩阵,所有矩阵的大小和深度必须相同。
size_t nsrcs, //矩阵的数量
Mat* dst, //输出数组或矩阵向量,大小和
深度必须与src[0]相同
size_t ndsts,//矩阵的数量
const int* fromTo,//指定被复制通道与要复制到的位置组成的索引对
size_t npairs //fromTo中索引对的数目
);

#define INPUT_TITLE "Input Image"
#define OUTPUT_TITLE "Back Projection"
#define HIST_TITLE "Histogram"
 
#include
#include
 
using namespace std;
using namespace cv;
 
 
 
/*———————————本代码所需变量定义及初始化——————————— */
Mat src, hsv_src, hue, backProjectionImg;
int bins = 12;
int nchannels[] = { 0,0 };
 
/*—————————————本代码所需函数声明————————————— */
void Hist_And_BackProjection(int, void*);
 
 
int main() {
	/*—————————————全局变量的赋值————————————— */
	//1.图像载入
	src = imread("D:/hand.jpg");
	if (!src.data)
	{
		cout << "ERROR : could not load image.\n";
		return -1;
	}
	//2.将图像转化为HSV图像
	cvtColor(src, hsv_src, CV_BGR2HSV);
 
	//3.创建一个图像
	hue.create(hsv_src.size(), hsv_src.depth());
 
	//窗口命名
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(HIST_TITLE, CV_WINDOW_AUTOSIZE);
 
	//从输入图像中拷贝某通道到输出图像中特定的通道
	mixChannels(&hsv_src, 1, &hue, 1, nchannels, 1);
 
	//动态调整直方图的 bins ,并做反向投影
	createTrackbar("Histogram Bins", INPUT_TITLE, &bins, 180, Hist_And_BackProjection);
	Hist_And_BackProjection(0, 0);
 
	imshow(INPUT_TITLE, src);
 
	waitKey(0);
	return 0;
}
 
 
/*—————————————本代码所需函数实现————————————— */
void Hist_And_BackProjection(int, void*) {
 
	//局部变量
	float range[] = { 0,180 };
	const float *histRanges = { range };
	int hist_h = 400;
	int hist_w = 400;
	int bin_w = hist_w / bins;
	Mat h_hist;
	Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
 
	//直方图计算及归一化处理
	calcHist(&hue, 1, 0, Mat(), h_hist, 1, &bins, &histRanges, true, false);
	normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());
 
	//直方图反向投影
	calcBackProject(&hue, 1, 0, h_hist, backProjectionImg, &histRanges, 1, true);
 
	//画直方图分部图
	for (int i = 0; i < bins; i++)
	{
		/*rectangle(histImage,
			Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at(i - 1)*(400 / 255)))),
			Point(i*bin_w, (hist_h - cvRound(h_hist.at(i)*(400 / 255)))),
			Scalar(0, 0, 255),
			-1);*/
 
		rectangle(histImage,
			Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at(i - 1)*(400 / 255)))),
			Point(i*bin_w, hist_h),
			Scalar(0, 0, 255),
			-1);
	}
 
	imshow(OUTPUT_TITLE, backProjectionImg);
	imshow(HIST_TITLE, histImage);
 
}

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_第17张图片

你可能感兴趣的:(c++opencv图像处理,opencv,c++)