opencv_c++学习(十四)

news2024/9/29 20:04:43

一、图像直方图的统计与绘制

在这里插入图片描述
如果直方图各个数字之间分布比较均衡,则其对比度就相对较低,反之亦然。同时也可以通过直方图可以大致了解图像的亮暗等。

calcHist(const Mat * images, int nimages,  const int * channels, lnputArray mask, OutputArray hist, int dims, const int* histSize, const float ** ranges, bool accumullate = false)

images:待统计直方图的图像数组。
nimages:输入的图像数量。
channels:需要统计的通道索引数组。
mask:可选的操作掩码。
hist:输出的统计直方图结果,是一个dims维度的数组。
dims:需要计算直方图的维度,必须是整数。
histSize:存放每个维度直方图的数组的尺寸。
ranges:每个图像通道中灰度值的取值范围。
uniform:直方图是否均匀的标志符,默认状态下为均匀(true) 。
accumulate:是否累积统计直方图的标志。

直方图使用案例:

int main() {

	//读取图片
	Mat src1 = imread("1.png");
	if (!src1.data)
	{
		printf("不能打开空图片");
		return -1;
	}

	//将彩色图像转化为灰度图像
	Mat gray;
	cvtColor(src1, gray, COLOR_BGR2GRAY);

	//定义存放直方图计算结果的变量
	Mat hist;

	//定义通道的索引
	const int channels[1] = { 0 };

	//定义直方图的维度,为灰度图像的最大值
	const int bins[1] = { 256 };
	float inRanges[2] = { 0,255 };

	//像素灰度值的取值范围
	const float* ranges[1] = { inRanges };

	//计算直方图
	calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);

	//绘制直方图

	//直方图背景图的大小
	int hist_w = 512;
	int hist_h = 400;

	//直方图矩形柱的宽度
	int width = 2;

	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

	//分别绘制直方图的矩形柱

	//for (int i = 1; i < hist.rows; i++)
	//{
	//	//将原始数据缩放为15倍:hist.at<float>(i - 1) / 15)
	//	rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(hist.at<float>(i - 1) / 15)), Scalar(255, 255, 255), -1);
	//}
	
	//将直方图数据进行归一化操作
	Mat hist_INF;
	normalize(hist, hist_INF, 1, 0, NORM_INF, -1, Mat());

	for (int i = 1; i < hist_INF.rows; i++)
	{
		//将原始数据缩放为15倍:hist.at<float>(i - 1) / 15)
		rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(hist_h*hist_INF.at<float>(i - 1)) -1), Scalar(255, 255, 255), -1);
	}


	imshow("histImage", histImage);
	imshow("gray", gray);
	waitKey(0);
	return 0;

}

在这里插入图片描述

二、直方图均衡化

图像像素拉伸:

直方图均衡化函数:

equalizeHist(lnputArray src, OutputArray dst)

src:需要直方图均衡化的CV_8UC1图像。
dst:直方图均衡化后的输出图像,与src具有相同尺寸和数据类型。
使用样例如下:

void drawHist(Mat &hist, int type, string name)
{
	//直方图背景图的大小
	int hist_w = 512;
	int hist_h = 400;

	//直方图矩形柱的宽度
	int width = 2;

	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

	//归一化
	normalize(hist, hist, 1, 0, NORM_INF, -1, Mat());

	for (int i = 1; i < hist.rows; i++)
	{
		rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(hist_h*hist.at<float>(i - 1)) - 1), Scalar(255, 255, 255), -1);
	}

	imshow(name, histImage);

}

int main() {

	//读取图片
	Mat src1 = imread("1.png");
	if (!src1.data)
	{
		printf("不能打开空图片");
		return -1;
	}
	
	Mat gray, hist, hist2;

	//将彩色图像转化为灰度图像
	cvtColor(src1, gray, COLOR_BGR2GRAY);

	Mat equalImg;

	//将图像均衡化
	equalizeHist(gray, equalImg);

	//定义通道的索引
	const int channels[1] = { 0 };

	//定义直方图的维度,为灰度图像的最大值
	const int bins[1] = { 256 };
	float inRanges[2] = { 0,255 };

	//像素灰度值的取值范围
	const float* ranges[1] = { inRanges };

	//计算直方图
	calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);
	calcHist(&equalImg, 1, channels, Mat(), hist2, 1, bins, ranges);

	//绘制直方图
	drawHist(hist, NORM_INF, "hist");
	drawHist(hist2, NORM_INF, "hist2");

	imshow("1", gray);
	imshow("2", equalImg);

	waitKey(0);
	return 0;

}

三、直方图匹配

在这里插入图片描述
具体实现细节如下:


void drawHist(Mat &hist, int type, string name)
{
	//直方图背景图的大小
	int hist_w = 512;
	int hist_h = 400;

	//直方图矩形柱的宽度
	int width = 2;

	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

	//归一化
	normalize(hist, hist, 1, 0, type, -1, Mat());

	for (int i = 1; i < hist.rows; i++)
	{
		rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(20*hist_h*hist.at<float>(i - 1)) - 1), Scalar(255, 255, 255), -1);
	}

	imshow(name, histImage);

}


int main() {

	//读取图片
	Mat src = imread("1.png");
	Mat src1 = imread("1.png");
	if (src.empty() || src1.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	Mat hist, hist2;

	//定义通道的索引
	const int channels[1] = { 0 };

	//定义直方图的维度,为灰度图像的最大值
	const int bins[1] = { 256 };
	float inRanges[2] = { 0,255 };

	//像素灰度值的取值范围
	const float* ranges[1] = { inRanges };

	//计算直方图
	calcHist(&src, 1, channels, Mat(), hist, 1, bins, ranges);
	calcHist(&src1, 1, channels, Mat(), hist2, 1, bins, ranges);

	//绘制直方图
	drawHist(hist, NORM_INF, "hist");
	drawHist(hist2, NORM_INF, "hist2");

	//计算两张直方图的累计概率
	float hist1_cdf[256] = { hist.at<float>(0) };
	float hist2_cdf[256] = { hist2.at<float>(0) };
	for (int i = 0; i < 256; i++)
	{
		hist1_cdf[i] = hist1_cdf[i - 1] + hist.at<float>(i);
		hist2_cdf[i] = hist2_cdf[i - 1] + hist2.at<float>(i);
	}

	//构建累计概率误差矩阵
	float diff_cdf[256][256];
	for (int i = 0; i < 256; i++)
	{
		for (int j = 0; j < 256; j++)
		{
			diff_cdf[i][j] = fabs(hist1_cdf[i] - hist2_cdf[j]);
		}
	}

	//生成LUT映射表
	Mat lut(1, 256, CV_8U);

	for (int i = 0; i < 256; i++)
	{
		//查找源灰度级为1的映射灰度和i的累积概率差值最小的规定化灰度

		float min = diff_cdf[i][0];
		int index = 0;

		//寻找累积概率误差矩阵中每一行中的最小值
		for (int j = 0; j < 256; j++)
		{
			if (min > diff_cdf[i][j])
			{
				min = diff_cdf[i][j];
				index = j;
			}
		}
		lut.at<uchar>(i) = (uchar)index;
	}

	Mat result, hist3;
	LUT(src, lut, result);
	imshow("待匹配图像", src);
	imshow("匹配的模板图像", src1);
	imshow("直方图匹配结果", result);

	//计算直方图
	calcHist(&result, 1, channels, Mat(), hist3, 1, bins, ranges);
	drawHist(hist3, NORM_INF, "hist3");

	waitKey(0);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/545454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python Xpath】零基础也能轻松掌握的学习路线与参考资料

Python是一种面向对象的编程语言。Xpath是一种在XML文档中定位信息的方法。XPath是一种语言&#xff0c;可以用于xml和html文档中选择和查找节点。在Python中&#xff0c;我们可以使用xpath来解析html页面&#xff0c;从而提取所需的数据。 Python xpath学习路线&#xff1a; …

C++中的继承、以及赋值兼容转换。

一、继承的概念及定义 继承可以使代码复用&#xff0c;允许在保持原有类特性的基础上进行扩展。 举个例子&#xff1a;就好比我现在要封装老师、学生等这些人的属性和方法&#xff0c;但是这些人都有重复的属性和方法&#xff0c;比如name、age、sex等等&#xff0c;那么我可…

let、const、var的区别,解构赋值,箭头函数

let、const、var的区别 使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升。使用const声明的是常量,在后面出现的代码块中,不能在修改改常量的值。 var let const 函数级作用域 块级…

Go语言核心编程-运算符和进制转换

第 4 章 运算符 4.1 运算符的基本介绍 运算符是一种特殊的符号&#xff0c;用以表示数据的运算、赋值和比较等 运算符是一种特殊的符号&#xff0c;用以表示数据的运算、赋值和比较等 算术运算符赋值运算符比较运算符/关系运算符逻辑运算符位运算符其它运算符 4.2 算术运算符…

体验联网版 ChatGPT:优点和缺点同样明显,还藏着无限可能

ChatGPT 有点像古希腊的阿喀琉斯&#xff1a;它很强大&#xff0c;却有个致命的弱点——无法联网&#xff0c;这注定了它只能是一个停留在 2021 年的超人。 但很快&#xff0c;我们将等到一个「鱼和熊掌兼得」的时刻。 通过插件集的 Web browsing 功能&#xff0c;ChatGPT 就…

C++每日一练:贝博士的机械零件(补全题目)奇偶排序(巧妙快排)寻因找祖

文章目录 前言一、贝博士的机械零件1、题目2、解法 二、奇偶排序&#xff08;巧用快排&#xff09;三、寻因找祖 前言 今天的题目中寻因找祖最难了&#xff0c;明显的数学题&#xff0c;笔者这数学文盲水平肯定不会&#xff0c;用暴力搞了一波&#xff0c;只有50%。就去考察学…

(二十六)ATP应用测试平台——将一个微服务打包成含skywalking链路追踪的docker镜像

前言 延续前面的章节内容&#xff0c;本节内容我们以ht-atp的springboot应用为例&#xff0c;封装一个包含skywalking链路追踪的微服务docker应用。完成服务调用的链路追踪监控。skywalking采用字节码注入的方式实现代码的无侵入&#xff0c;探针采集数据粒度粗&#xff0c;但…

详解c++STL—容器set/multiset

目录 1、set基本概念 1.1、功能 1.2、本质&#xff1a; 1.3、set和multiset区别 2、set构造和赋值 2.1、功能描述 2.1、构造 2.3、赋值 2.4、示例 3、set大小和交换 3.1、功能描述 3.2、函数原型 3.2、示例 4、set插入和删除 4.1、功能描述 4.2、函数原型 4.3…

YOLO V3 SPP ultralytics 第一节:VOC 的标注文件(xml)转YOLO标注格式(txt)以及如何自定义YOLO数据样本

目录 1. 前言 2. 关于PASCAL VOC数据集xml --> YOLO txt格式 2.1 路径设定 2.2 读取xml 文件的函数 2.3 xml ---> yolo txt 2.4 yolo 的label文件 2.6 结果 2.7 代码 3. 自定义 YOLO 数据集 3.1 预备工作 3.2 打开labelimg 3.3 绘制 代码参考是b站的大佬&…

CNNs: ZFNet之CNN的可视化网络介绍

CNNs: ZFNet之CNN的可视化网络介绍 导言Deconvnet1. Unpooling2. ReLU3. Transpose conv AlexNet网络修改AlexNet Deconv网络介绍特征可视化 导言 上一个内容&#xff0c;我们主要学习了AlexNet网络的实现、超参数对网络结果的影响以及网络中涉及到一些其他的知识点&#xff0…

RedisInsight—Redis可视化工具

到处都是各种redis的可视化工具&#xff0c;但是那个是redis官网推荐的呢。 答案是&#xff1a;RedisInsight。 好用吗&#xff1f;自己看看吧。反正下载是挺烦躁的。 RedisInsight介绍 RedisInsight支持多种操作系统&#xff1a;Linux、Windows和macOS。 RedisInsight支持…

全网最牛最全面的jmeter教程之jmeter对图片验证码的处理

jmeter对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入&#xff0c;而且每次登录时图片验证码都是随机的&#xff1b;当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段&#xff0c;然后再登录接口中使用&#xff1b; 通过jmeter对图片验证码…

【数据结构】C语言实现堆及其应用

二叉树的顺序结构--堆 一、堆的概念与实现堆的概念堆结构定义堆的初始化与销毁堆的插入与向上调整堆的打印、判空、元素个数size、堆顶元素堆的删除与向下调整大根堆与小根堆的写法区别堆的两种建立方式建堆的时间复杂度推导 二、堆的应用堆的应用--topK堆的应用--堆排序优先级…

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

目录 深刻理解整形提升 左移和右移规则 如何理解"丢弃" 一个问题 0x01<<23 的值是多少 花括号 、--操作 表达式匹配&#xff1a;贪心算法 深刻理解整形提升 #include <stdio.h> int main() {char c 0;printf("sizeof(c): %d\n", sizeo…

C++系列之类与对象(上)

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注再收藏 &#x1f31e; 类 类的概念 C是基于面向对象的&#xff0c;是对象与对象之间的交互完成的&am…

docker构建PHP环境

docker构建PHP环境 文章目录 docker构建PHP环境下载镜像构建本地目录创建容器配置补充命令解释设置docker启动时启动容器 下载镜像 # php 镜像 docker pull php:7.4-fpm # nginx镜像 docker pul nginx:lates # 检查下载的镜像 docker images构建本地目录 本次构建是在win系统…

怎么查营业执照经营范围

怎么查营业执照经营范围 1.到企业公司所在地查询。一般工商局都要求公司将营业执照正本悬挂于企业办公室醒目位置,在公司工商营业执照正副本中均有描述。 2.登陆国家工商管理网站查询。可以登陆开具发票单位所在的工商行政管理局网站,输入企业名称就可以查询法人、企业类型、经…

第七章 中断

中断是什么&#xff0c;为什么要有中断 并发是指单位时间内的累积工作量。 并行是指真正同时进行的工作量。 一个CPU在一个时间只能执行一个进程&#xff0c;任何瞬间任务只在一个核心上运行。 而CPU外的设备是独立于CPU的&#xff0c;它与CPU同步运行&#xff0c;CPU抽出一点…

2023年十大最佳黑客工具!

​用心做分享&#xff0c;只为给您最好的学习教程 如果您觉得文章不错&#xff0c;欢迎持续学习 在今年根据实际情况&#xff0c;结合全球黑客共同推崇&#xff0c;选出了2023年十大最佳黑客工具。 每一年&#xff0c;我都会持续更新&#xff0c;并根据实际现实情况随时更改…

山西煤矿电子封条算法 opencv

山西煤矿电子封条通过pythonopencv网络模型AI视觉技术&#xff0c;pythonopencv算法模型实现对出入井人监察控制、调度室空岗识别、生产作业状态、摄像头遮挡、挪动角度识别、货运车辆出矿识别等。 OpenCV的全称是Open Source Computer Vision Library&#xff0c;是一个跨平台…