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

openCV1-2 图像的直方图相关

通道合并与分离

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{Mat src = imread("D:\\souse\\opencv_tutorial_data-master\\images\\WindowsLogo.jpg");if (src.empty()) {return -1;}namedWindow("input", WINDOW_AUTOSIZE);imshow("input", src);vector<Mat> mv;//分离split(src, mv);imshow("input1", mv.at(0));imshow("input2", mv.at(1));imshow("input3", mv.at(2));Mat des;mv.at(0) = Scalar(0);//合并操作merge(mv, des);imshow("des",des);waitKey(0);std::cout << "Hello World!\n";return 0;
}

图像直方图统计

在这里插入图片描述
Bin:是直方图的基本统计单元,用于统计图像中特定范围内像素值的出现频率。

calcHist

CV_EXPORTS 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 );

函数cv::calcHist用于计算一个或多个数组的直方图。用于增加直方图 bin 的元组元素取自相应输入数组中相同位置的元素。下面的示例展示了如何为彩色图像计算二维色调 - 饱和度直方图:
@include snippets/imgproc_calcHist.cpp

@param images 源数组。它们都应该具有相同的深度,即CV_8U、CV_16U或CV_32F ,并且大小相同。每个数组可以有任意数量的通道。
@param nimages 源图像的数量。
@param channels 用于计算直方图的维度通道列表。第一个数组的通道从0到images[0].channels() - 1编号,第二个数组的通道从images[0].channels()到images[0].channels() + images[1].channels() - 1编号,依此类推。
@param mask 可选掩码。如果该矩阵不为空,它必须是与images[i]大小相同的8位数组。非零掩码元素标记在直方图中统计的数组元素。
@param hist 输出直方图,它是一个密集或稀疏的dims维数组。
@param dims 直方图维度,必须为正且不大于CV_MAX_DIMS(在当前OpenCV版本中等于32)。
@param histSize 每个维度的直方图大小数组。
@param ranges 每个维度的直方图 bin 边界的dims个数组的数组。
@param uniform 指示直方图是否均匀的标志。
@param accumulate 累加标志。如果设置了该标志,在分配直方图时,开始时不会将其清空。此功能使您能够从几组数组中计算单个直方图,或者及时更新直方图。

normalize

cv::normalize() 是 OpenCV 中用于归一化数组元素的函数,它可以将数组的值缩放到指定范围。以下是对该函数的详细解析:

void cv::normalize(InputArray src,            // 输入数组(如Mat)InputOutputArray dst,      // 输出数组(可与src相同,实现原地操作)double alpha = 1,          // 归一化后的最小值(或范数值,取决于norm_type)double beta = 0,           // 归一化后的最大值(仅用于NORM_MINMAX)int norm_type = NORM_L2,   // 归一化类型(如NORM_MINMAX、NORM_L1、NORM_L2等)int dtype = -1,            // 输出数组的类型(-1表示与输入相同)InputArray mask = noArray() // 可选掩码,非零元素参与计算
);

参数详解
src 输入数组(如直方图数据 b),通常是 Mat 类型。
dst 输出数组,可与 src 相同(原地操作)。若不同,需保证尺寸和通道数一致。
alpha 对于 NORM_MINMAX:归一化后的最小值。
对于其他归一化类型(如 NORM_L2):目标范数值。
beta 仅用于 NORM_MINMAX,表示归一化后的最大值。
norm_type 常用取值:
NORM_MINMAX:线性映射到 [alpha, beta] 范围。
NORM_L1:L1 范数(绝对值之和)归一化。
NORM_L2:L2 范数(欧几里得距离)归一化。
NORM_INF:无穷范数(最大值)归一化。
dtype
输出数组的类型。-1 表示与输入类型相同。
mask
可选掩码,仅掩码中非零元素参与计算。

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{Mat src = imread("D:\\souse\\opencv_tutorial_data-master\\images\\sp_noise.png");if (src.empty()) {cout << "读取失败"<<endl;return -1;}namedWindow("src", WINDOW_AUTOSIZE);imshow("src", src);//分离通道vector<Mat> mv;split(src, mv);//计算直方图int histSize=256;float range[] = { 0,255 };const float* hisRanges = range;Mat b, g, r;//原图像 原图像数量 通道 掩码 输出 维度  每个维度的bin数量  每个维度的取值范围 bin是否均匀分布 是否累积计算calcHist(&mv[0],1,0,Mat(),b,1,&histSize, &hisRanges);calcHist(&mv[1], 1, 0, Mat(), g, 1, &histSize, &hisRanges);calcHist(&mv[2], 1, 0, Mat(), r, 1, &histSize, &hisRanges);//绘制直方图Mat result= Mat::zeros(Size(600, 500), CV_8UC3);int margin = 50;//边缘大小int h = result.rows-2*margin;//最大高normalize(b, b, 0, h, NORM_MINMAX, -1, Mat());normalize(g, g, 0, h, NORM_MINMAX, -1, Mat());normalize(r, r, 0, h, NORM_MINMAX, -1, Mat());float step = 500.0 / 256;for (int i = 0; i < 255; i++) {// 绘制蓝色通道line(result,Point(step * i+50, 50 + h - b.at<float>(i, 0)),Point(step * (i + 1)+50, 50 + h - b.at<float>(i + 1, 0)),Scalar(255, 0, 0), 2, 8, 0);// 修复:添加绿色和红色通道的绘制(颜色参数修正)line(result,Point(step * i+50, 50 + h - g.at<float>(i, 0)),Point(step * (i + 1)+50, 50 + h - g.at<float>(i + 1, 0)),Scalar(0, 255, 0), 2, 8, 0);  // 绿色:(0,255,0)line(result,Point(step * i+50, 50 + h - r.at<float>(i, 0)),Point(step * (i + 1)+50, 50 + h - r.at<float>(i + 1, 0)),Scalar(0, 0, 255), 2, 8, 0);  // 红色:(0,0,255)}imshow("result", result);waitKey(0);
}

在这里插入图片描述

图像直方图均衡化

blog.csdnimg.cn/direct/9e84666228f141ea877bfe614947d21a.png)

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{Mat src = imread("D:\\souse\\opencv_tutorial_data-master\\images\\age_gender.jpg");if (src.empty()) {cout << "读取失败" << endl;return -1;}namedWindow("src", WINDOW_AUTOSIZE);imshow("src", src);//=========================////转灰度图像Mat gray, des;cvtColor(src, gray, COLOR_BGR2GRAY);imshow("gray", gray);//均衡化equalizeHist(gray, des);imshow("des", des);//=========================////分离通道vector<Mat> mv;split(src, mv);//计算直方图int histSize = 256;float range[] = { 0,255 };const float* hisRanges = range;Mat b, g, r,g_z,d_z;//原图像 原图像数量 通道 掩码 输出 维度  每个维度的bin数量  每个维度的取值范围 bin是否均匀分布 是否累积计算calcHist(&mv[0], 1, 0, Mat(), b, 1, &histSize, &hisRanges);calcHist(&mv[1], 1, 0, Mat(), g, 1, &histSize, &hisRanges);calcHist(&mv[2], 1, 0, Mat(), r, 1, &histSize, &hisRanges);calcHist(&gray, 1, 0, Mat(), g_z, 1, &histSize, &hisRanges);calcHist(&des, 1, 0, Mat(), d_z, 1, &histSize, &hisRanges);//绘制直方图Mat result = Mat::zeros(Size(600, 500), CV_8UC3);Mat result1 = Mat::zeros(Size(600, 500), CV_8UC3);int margin = 50;//边缘大小int h = result.rows - 2 * margin;//最大高normalize(b, b, 0, h, NORM_MINMAX, -1, Mat());normalize(g, g, 0, h, NORM_MINMAX, -1, Mat());normalize(r, r, 0, h, NORM_MINMAX, -1, Mat());normalize(g_z, g_z, 0, h, NORM_MINMAX, -1, Mat());normalize(d_z, d_z, 0, h, NORM_MINMAX, -1, Mat());float step = 500.0 / 256;for (int i = 0; i < 255; i++) {// 绘制蓝色通道line(result,Point(step * i + 50, 50 + h - b.at<float>(i, 0)),Point(step * (i + 1) + 50, 50 + h - b.at<float>(i + 1, 0)),Scalar(255, 0, 0), 2, 8, 0);// 修复:添加绿色和红色通道的绘制(颜色参数修正)line(result,Point(step * i + 50, 50 + h - g.at<float>(i, 0)),Point(step * (i + 1) + 50, 50 + h - g.at<float>(i + 1, 0)),Scalar(0, 255, 0), 2, 8, 0);  // 绿色:(0,255,0)line(result,Point(step * i + 50, 50 + h - r.at<float>(i, 0)),Point(step * (i + 1) + 50, 50 + h - r.at<float>(i + 1, 0)),Scalar(0, 0, 255), 2, 8, 0);  // 红色:(0,0,255)line(result1,Point(step * i + 50, 50 + h - g_z.at<float>(i, 0)),Point(step * (i + 1) + 50, 50 + h - g_z.at<float>(i + 1, 0)),Scalar(0, 0, 255), 2, 8, 0);  // 红色:(0,0,255)line(result1,Point(step * i + 50, 50 + h - d_z.at<float>(i, 0)),Point(step * (i + 1) + 50, 50 + h - d_z.at<float>(i + 1, 0)),Scalar(0, 255, 0), 2, 8, 0);  // 红色:(0,0,255)}imshow("result", result);imshow("result1", result1);waitKey(0);}

绿色是灰度图,红色是均衡化处理之后的
在这里插入图片描述

http://www.xdnf.cn/news/8041.html

相关文章:

  • 微服务架构中的 RabbitMQ:异步通信与服务解耦(二)
  • SQLMesh 宏操作符详解:提升 SQL 查询的灵活性与效率
  • Spring Boot与Eventuate Tram整合:构建可靠的事件驱动型分布式事务
  • 高等数学-积分
  • ElasticSearch操作
  • HarmonyOS 鸿蒙应用开发基础:父组件调用子组件方法的几种实现方案对比
  • HarmonyOS 鸿蒙应用开发基础:@Watch装饰器详解及与@Monitor装饰器对比分析
  • HarmonyOS实战:高德地图自定义定位图标展示
  • Redis 5.0.10 集群部署实战(3 主 3 从,三台服务器)
  • 深度学习模型部署:使用Flask将图像分类(5类)模型部署在服务器上,然后在本地GUI调用。(全网模型部署项目步骤详解:从模型训练到部署再到调用)
  • RAGFlow知识检索原理解析:混合检索架构与工程实践
  • Dify大语言模型应用开发环境搭建:打造个性化本地LLM应用开发工作台
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的管理与运营策略研究
  • 格雷希尔快速封堵接头,解决新能源汽车的气密性检测和三电系统的综合测试
  • java 基础知识巩固
  • 深度解析:Spark、Hive 与 Presto 的融合应用之道
  • SpringBoot Day_03
  • Docker 与微服务架构:从单体应用到容器化微服务的迁移实践
  • 谷歌medgemma-27b-text-it医疗大模型论文速读:多语言大型语言模型医学问答基准测试MedExpQA
  • 基于STM32F4的cubemx关于RTC配置说明
  • Docker架构详解
  • Win 系统 conda 如何配置镜像源
  • 【二刷力扣】【力扣热题100】今天的题目是:两数之和
  • Spring核心原理:动态数据源切换的企业级解决方案
  • springboot03
  • MqSQL
  • Oracle 11G RAC重启系统异常
  • WPF读取json文件,用到combox控件
  • 设计双向链表--LeetCode
  • 如果验证集缺失或测试集缺失应该怎么办?