当前位置: 首页 > news >正文

OpenCV(十八):图像直方图

目录

1.直方图统计

2.直方图均衡化

3.直方图匹配


1.直方图统计

       直方图统计是一种用于分析图像或数据的统计方法,它通过统计每个数值或像素值的频率分布来了解数据的分布情况。

在OpenCV中,可以使用函数cv::calcHist()来计算图像的直方图。

calcHist() 函数的原型如下:

void calcHist(const Mat* images, int nimages, const int* channels,

InputArray mask, OutputArray hist, int dims,

const int* histSize, const float** ranges,

bool uniform = true, bool accumulate = false);

参数说明:

  • images: 输入图像数组,可以是单张图像或多张图像的数组。

  • nimages: 输入图像的数量。

  • channels: 要计算直方图的通道索引数组。例如,对于灰度图像,只有一个通道,因此 channels 设置为 {0};而对于彩色图像,可以指定 {0, 1, 2} 对应于 B、G、R 三个通道。

  • mask: 掩码图像,用于指定计算直方图的区域。如果不需要使用掩码,可以传入空的 Mat()。

  • hist: 输出的直方图,用于存储计算结果。

  • dims: 直方图的维度,通常为 1。

  • histSize: 直方图的大小,即每个维度的条目数量。

  • ranges: 直方图的范围,可以使用 {0, 256} 表示像素值范围为 [0, 256)。

  • uniform: 指示直方图条目是否均匀分布,默认为 true。

  • accumulate: 指示是否累积直方图,默认为 false。

下面是一个示例代码,展示如何使用cv::calcHist()函数计算图像的直方图:

#include <opencv2/opencv.hpp>
void hist(Mat image){
// 定义直方图参数
int histSize = 256; // 直方图条目数量
const int channels[1]={0};//通道索引
float range[] = { 0, 256 }; // 像素值范围
const float* histRange = { range };
bool uniform = true; // 直方图条目是否均匀分布
bool accumulate = false; // 直方图是否累积
// 计算直方图
cv::Mat hist;
cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);// 绘制直方图
int histWidth = 512;
int histHeight = 400;
int binWidth = cvRound((double)histWidth / histSize);
cv::Mat histImage(histHeight, histWidth, CV_8UC4, cv::Scalar(0, 0, 0));
cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
for (int i = 1; i < histSize; ++i){
cv::line(histImage, cv::Point(binWidth * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))),
cv::Point(binWidth * (i), histHeight - cvRound(hist.at<float>(i))),
cv::Scalar(255, 255, 255), 2, 8, 0);
}
// 显示直方图
cv::imwrite("/sdcard/DCIM/histImage.jpg", histImage);
}

示例代码中将原图像image转换为单通道灰度图像。然后定义了直方图的参数,包括直方图条目数量、像素值范围、均匀性和累积性。接下来使用 cv::calcHist() 函数计算了图像的直方图,存储在 hist 中。最后,通过绘制直方图数据到 histImage 中,实现了直方图的可视化。

2.直方图均衡化

        直方图均衡化是一种用于增强图像对比度的图像处理技术。它通过重新分布图像像素值的频率分布来增强图像的亮度和细节。

在OpenCV中,可以使用cv::equalizeHist()函数来进行直方图均衡化。该函数的原型如下:

void equalizeHist(InputArray src, OutputArray dst);

参数说明:

  • src:需要直方图均衡化的CV 8UC1图像。

  • dst: 直方图均衡化后的输出图像,与src具有相同尺寸和数据类型

下面是一个示例代码,展示如何使用cv::equalizeHist()函数来进行直方图均衡化:

#include <opencv2/opencv.hpp>
void drawHist(Mat &hist,string name){//归一化并绘制直方图函数int histSize = 256;  // 直方图条目数量// 绘制直方图int histWidth = 512;int histHeight = 400;int binWidth = cvRound((double)histWidth / histSize);cv::Mat histImage(histHeight, histWidth, CV_8UC4, cv::Scalar(0, 0, 0));cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());for (int i = 1; i < histSize; ++i){cv::line(histImage, cv::Point(binWidth * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))),cv::Point(binWidth * (i), histHeight - cvRound(hist.at<float>(i))),cv::Scalar(255, 255, 255), 2, 8, 0);}// 显示直方图cv::imwrite("/sdcard/DCIM/"+name+".jpg", histImage);}
void EqualImage(Mat image){//灰度化Mat gray;cvtColor(image,gray,COLOR_BGR2GRAY);//将灰度图进行直方图均衡化Mat equalImg;equalizeHist(gray,equalImg);cv::imwrite("/sdcard/DCIM/equalImg.jpg", equalImg);// 定义直方图参数int histSize = 256;  // 直方图条目数量const int channels[1]={0};//通道索引float range[] = { 0, 256 };  // 像素值范围const float* histRange = { range };bool uniform = true;  // 直方图条目是否均匀分布bool accumulate = false;  // 直方图是否累积// 计算直方图cv::Mat hist;cv::calcHist(&equalImg, 1, channels, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);drawHist(hist,"hist1");}

示例代码中将原图像image转换为单通道灰度图像,然后将灰度图进行直方图均衡化,之后定义了直方图的参数,包括直方图条目数量、像素值范围、均匀性和累积性。接下来使用 cv::calcHist() 函数计算了图像的直方图,存储在 hist 中。最后,通过绘制直方图数据到 histImage 中,实现了直方图的可视化。

3.直方图匹配

       直方图匹配(Histogram Matching)是一种图像处理技术,用于将一副图像的直方图映射到另一副图像上,从而使它们的亮度分布或颜色分布相似。该技术常用于图像增强、风格转换、颜色校正等应用中。

以下是一个使用OpenCV实现直方图匹配的示例代码:


#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;void drawHist(Mat &hist,string name){//归一化并绘制直方图函数int histSize = 256;  // 直方图条目数量// 绘制直方图int histWidth = 512;int histHeight = 400;int binWidth = cvRound((double)histWidth / histSize);cv::Mat histImage(histHeight, histWidth, CV_8UC4, cv::Scalar(0, 0, 0));cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());for (int i = 1; i < histSize; ++i){cv::line(histImage, cv::Point(binWidth * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))),cv::Point(binWidth * (i), histHeight - cvRound(hist.at<float>(i))),cv::Scalar(255, 255, 255), 2, 8, 0);}// 显示直方图cv::imwrite("/sdcard/DCIM/"+name+".jpg", histImage);}
void  Histogram_matching(Mat img1,Mat img2){Mat hist1,hist2;//计算两张图像直方图const int channels[1]={0};float inRanges[2]={0,255};const float *ranges[1]={inRanges};const int bins[1]={256};calcHist(&img1,1,channels,Mat(),hist1,1,bins,ranges);calcHist(&img2,1,channels,Mat(),hist2,1,bins,ranges);//归一化两张图像的直方图drawHist(hist1,"hist1");drawHist(hist2,"hist2");//计算两张图像直方图的累计概率float hist1_cdf[256]={hist1.at<float>(0)};float hist2_cdf[256]={hist2.at<float>(0)};for(int i=1;i<256;i++){hist1_cdf[i]=hist1_cdf[i-1]+hist1.at<float>(i);hist2_cdf[i]=hist2_cdf[i-1]+hist1.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]);}}uchar lutone[256];for(int i=0;i<256;i++){//查找源灰度级为i的映射灰度//和i的累积概率差值最小的规定化灰度float min=diff_cdf[i][0];int index=0;//寻找累积概率误差矩阵中每一行中的最小值for(int j=1;j<256;j++){if(min>diff_cdf[i][j]){min=diff_cdf[i][j];index=j;}}lutone[i]=index;}//生成LUT映射表Mat lut(1,256,CV_8UC1,lutone);Mat result,hist3;LUT(img1,lut,result);imwrite("/sdcard/DCIM/result.png",result);calcHist(&result,1,channels,Mat(),hist3,1,bins,ranges);drawHist(hist3,"hist3");}

示例代码:计算原始图像和目标图像的直方图,归一化直方图,计算累计直方图,构建累积概率误差矩阵,根据最小差值构建映射表,最后将原始图像的灰度级根据映射表调整为目标图像的灰度级。下面是原始图像和直方图匹配后图片,可以看出直方图匹配后的图片使得图像中的细节更加清晰可见。

                  

              原图                                            直方图匹配的结果

相关文章:

OpenCV(十八):图像直方图

目录 1.直方图统计 2.直方图均衡化 3.直方图匹配 1.直方图统计 直方图统计是一种用于分析图像或数据的统计方法&#xff0c;它通过统计每个数值或像素值的频率分布来了解数据的分布情况。 在OpenCV中&#xff0c;可以使用函数cv::calcHist()来计算图像的直方图。 calcHist(…...

mac pro 查看隐藏文件夹

在Mac上查看隐藏文件夹可以使用以下方法&#xff1a; 使用终端&#xff1a; 打开终端应用程序&#xff0c;位于“应用程序”文件夹的“实用工具”子文件夹中。 在终端中&#xff0c;输入以下命令&#xff0c;然后按回车键&#xff1a; defaults write com.apple.finder AppleS…...

软件测试/测试开发丨Selenium 高级定位 Xpath

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27036 一、xpath 基本概念 XPATH是一门在XML文档中查找信息的语言 XPATH使用路径表达式在XML文档中进行导航 XPATH的应用非常广泛&#xff0c;可以用于UI自…...

各类注意力机制Attention——可变形注意力

目录 《Attention is all you need 》稀疏Attention残差Attention通道注意力空间注意力时间注意力可变形注意力 《Attention is all you need 》 稀疏Attention 残差Attention 通道注意力 空间注意力 时间注意力 实际上序列类任务也属于时间注意力&#xff0c;比如transformer…...

桥接模式:连接抽象与实现

欢迎来到设计模式系列的第八篇文章&#xff01;在之前的几篇文章中&#xff0c;我们已经学习了许多常见的设计模式&#xff0c;今天我们将继续探讨另一个重要的设计模式——桥接模式。 桥接模式简介 桥接模式是一种结构型设计模式&#xff0c;它主要用于将抽象部分与实现部分…...

同步推送?苹果计划本月推出 iOS17和iPadOS17,你的手机支持吗?

据报道&#xff0c;苹果公司计划在本月推出 iOS 17 和 iPadOS 17 正式版更新。与去年不同的是&#xff0c;这次更新将同时发布&#xff0c;而不是分别发布。根据彭博社的一位消息人士马克・古尔曼的说法&#xff0c;苹果公司认为 iOS 17 和 iPadOS 17 的第八个测试版已经非常接…...

方案展示 | RK3588开发板Linux双摄同显方案

iTOP-RK3588开发板使用手册更新&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 RK3588开发板载4路MIPI CAMERA摄像头接口、MIPI CSI DPHY的4.5Gbps、2.5Gops的MIPI CSI CPHY&#xff0c;四路同时输入&#xf…...

数据库-多表设计

概述&#xff1a; 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本分为三种&#xff1a; 一对…...

一个简单的文件系统(MinixFS)实现解析

1. Minix文件系统概要 Minix file system 是 Andrew S. Tanenbaum 在 1980 年代发明的文件系统, 并随着 Minix 操作系统一起于 1987 年发布。 Linus 编写 Linux 内核第一个版本的时候, 使用的也是 Minix FS, Linux 至今依然提供了对 Minix FS 的支持。Minix FS 结构简单, 易于…...

地图投影-2亚当斯方形

说明 亚当斯方形 II 投影显示了一个方形的世界。它是 Oscar S. Adams 于 1925 年提出的两种投影之一。该投影为等角投影&#xff0c;但方形的四个角除外。在 Adams 最初的设计中&#xff0c;该投影将赤道和中央经线显示为方形的对角线。 此投影的一个有利属性是可以进行细分或…...

atcoder库中类欧(类欧几里得算法)floor_sum用法

https://atcoder.jp/contests/practice2/tasks/practice2_c 求 ∑ i 0 N − 1 f l o o r ( ( A i B ) / m ) \sum_{i 0}^{N - 1} floor((A \times i B) / m) ∑i0N−1​floor((AiB)/m) 直接使用即可&#xff1a; ansfloor_sum(n, m, A, B); //注意顺序...

后端面试话术集锦第 十一 篇:mybatis面试话术

这是后端面试集锦第十一篇博文——mybatis面试话术❗❗❗ 1. 介绍下mybatis,说说它的优缺点是什么? Mybatis是一个半ORM(对象关系映射)的持久层框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程…...

SpringBoot运维实用篇、打包、运行、高级配置、多环境开发、日志

文章目录 SpringBoot运维实用篇YW-1.SpringBoot程序的打包与运行程序打包程序运行SpringBoot程序打包失败处理命令行启动常见问题及解决方案SpringBoot项目快速启动&#xff08;Linux版&#xff09; YW-2.配置高级YW-2-1.临时属性设置YW-2-2.配置文件分类YW-2-3.自定义配置文件…...

springdoc-openapi-ui 整合 knife,多模块分组,脚手架

pom文件&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.o…...

04-MySQL02

1、什么是索引下推&#xff1f; 索引下推&#xff08;index condition pushdown &#xff09;简称ICP&#xff0c;在Mysql5.6的版本上推出&#xff0c;用于优化查询。 需求: 查询users表中 "名字第一个字是张&#xff0c;年龄为10岁的所有记录"。 SELECT * FROM u…...

实现跨境电商测评和采退、LU卡、LU货最安全的系统方案

首先你要有一个稳定的测评环境系统&#xff0c;这个是做自养号退款、撸货、撸卡的基础。测评环境系统有很多&#xff0c;从早期的虚拟机&#xff0c;模拟机&#xff0c;云手机&#xff0c;VPS等等。这些系统方案先不说成本高&#xff0c;最重要的是成功率很低&#xff0c;所以一…...

软件生命周期及流程

软件生命周期&#xff1a; 软件生命周期(SDLC&#xff0c;Systems Development Life Cycle)是软件开始研制到最终被废弃不用所经历的各个阶段. 需求分析阶段--输出需求规格说明书&#xff08;原型图&#xff09; 测试介入的晚--回溯成本高 敏捷开发模型&#xff1a; 从1990年…...

nginx使用详解

文章目录 一、前言二、nginx使用详解2.1、nginx特点2.2 静态文件处理2.3 反向代理2.4 负载均衡2.5 高级用法2.5.1 正则表达式匹配2.5.2 重定向 三、总结 一、前言 本文将详细介绍nginx的各个功能使用&#xff0c;主要包括 二、nginx使用详解 2.1、nginx特点 高性能&#xff…...

YOLOV7 添加 CBAM 注意力机制

用于学习记录 文章目录 前言一、CBAM1.1 models/common.py1.2 models/yolo.py1.3 yolov7/cfg/training/CBAM.yaml2.4 CBAM 训练结果图 前言 一、CBAM CBAM: Convolutional Block Attention Module 1.1 models/common.py class ChannelAttention(nn.Module):def __init__(sel…...

【SpringSecurity】七、SpringSecurity集成thymeleaf

文章目录 1、thymeleaf2、依赖部分3、定义Controller4、创建静态页面5、WebSecurityConfigurerAdapter6、权限相关7、当用户没有某权限时&#xff0c;页面不展示该按钮 1、thymeleaf 查了下读音&#xff0c;leaf/li:f/&#xff0c;叶子&#xff0c;前面的单词发音和时间time一…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...