IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影 -> 正文阅读

[C++知识库]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直方图概念

?1.2直方图均衡化概念

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

直方图均衡化API:

?直方图均衡化案例

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直方图概念扩展

?

?2.2 画三通道直方图

void MyApi::histogram_cal(Mat& image)
{
	//1.把多通道的图像分离单通道
	vector<Mat> 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<float>(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);
	}
	imshow("彩色图像直方图", histImage);
}

?3.直方图的比较

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

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

3.1Correlation 相关性比较

?3.2Chi-Square 卡方比较

?3.3intersection十字交叉性

3.4Bhattacharyya distance 巴氏距离

3.5相关API

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<opencv2/opencv.hpp>
#include<iostream>
#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;
}

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

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

4.1反向投影概述

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<iostream>
#include<opencv2\opencv.hpp>
 
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<float>(i - 1)*(400 / 255)))),
			Point(i*bin_w, (hist_h - cvRound(h_hist.at<float>(i)*(400 / 255)))),
			Scalar(0, 0, 255),
			-1);*/
 
		rectangle(histImage,
			Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1)*(400 / 255)))),
			Point(i*bin_w, hist_h),
			Scalar(0, 0, 255),
			-1);
	}
 
	imshow(OUTPUT_TITLE, backProjectionImg);
	imshow(HIST_TITLE, histImage);
 
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:19:43  更:2021-09-04 17:21:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:45:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码