灰度图像直方图均衡化公式及实现

2023-11-09

图像的直方图:直方图是图像中像素强度分布的图形表达方式。它统计了每一个强度值所具有的像素个数

直方图均衡化:是通过拉伸像素强度分布范围来增强图像对比度的一种方法。是图像处理领域中利用图像直方图对对比度进行调整的方法。

均衡化指的是把一个分布(给定的直方图)映射到另一个分布(一个更宽更统一的强度值分布),所以强度值分布会在整个范围内展开。映射函数应该是一个累积分布函数(cumulative distribution function(cdf))。

直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。

这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。

灰度直方图均衡化算法实现步骤:

(1)、统计原始图像各灰度级的像素数目ni,0≤i<L, L是图像中所有的灰度数(通常为256);

(2)、图像中灰度为i的像素的出现概率是:px(i)=p(x=i)=ni/n,n是图像中所有的像素数,px(i)实际上是像素值为i的图像的直方图,归一化到[0, 1];

(3)、px的累积分布函数,是图像的累计归一化直方图:


(4)、直方图均衡化计算公式, cdfmin为累积分布函数最小值,M和N分别代表了图像的长宽像素个数,而L则是灰度级数(如图像为8位深度,则灰度级别共有2^8=256级数,这也是最常见的灰度级数),v为原始图像中为v的像素值:


彩色图像直方图均衡化:上面描述了灰度图像上使用直方图均衡化的方法,但是通过将这种方法分别用于图像RGB颜色值的红色、绿色和蓝色分量,从而也可以对彩色图像进行处理。实际上,对彩色分量rgb分别做均衡化,会产生奇异的点,图像不和谐。一般采用的是用yuv空间进行亮度的均衡即可。

以上内容主要参考:维基百科

以下是分别采用C++和OpenCV实现的code,从执行结果可知,C++和OpenCV的结果完全一致:

histogram_equalization.cpp:

#include "funset.hpp"
#include <chrono>
#include <vector>
#include <algorithm>
#include "common.hpp"

int histogram_equalization_cpu(const unsigned char* src, int width, int height, unsigned char* dst, float* elapsed_time)
{
	//TIME_START_CPU

	const int hist_sz{ 256 };
	std::vector<int> hist(hist_sz, 0), lut(hist_sz, 0);
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			++hist[src[y * width + x]];
		}
	}

	int i{ 0 };
	while (!hist[i]) ++i;

	int total{ width * height };
	if (hist[i] == total) {
		unsigned char* p = dst;
		std::for_each(p, p + total, [i](unsigned char& value) { value = i; });
		return 0;
	}

	float scale = (hist_sz - 1.f) / (total - hist[i]);
	int sum = 0;

	for (lut[i++] = 0; i < hist_sz; ++i) {
		sum += hist[i];
		lut[i] = static_cast<unsigned char>(sum * scale + 0.5f);
	}

	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			dst[y * width + x] = static_cast<unsigned char>(lut[src[y * width + x]]);
		}
	}

	//TIME_END_CPU

	return 0;
}
main.cpp:

#include "funset.hpp"
#include <random>
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <algorithm>
#include "common.hpp"

int test_image_process_histogram_equalization()
{
	const std::string image_name{ "E:/GitCode/CUDA_Test/test_data/images/lena.png" };
	cv::Mat mat = cv::imread(image_name, 0);
	CHECK(mat.data);

	const int width{ mat.cols/*1513*/ }, height{ mat.rows/*1473*/ };
	cv::resize(mat, mat, cv::Size(width, height));

	std::unique_ptr<unsigned char[]> data1(new unsigned char[width * height]), data2(new unsigned char[width * height]);
	float elapsed_time1{ 0.f }, elapsed_time2{ 0.f }; // milliseconds

	CHECK(histogram_equalization_cpu(mat.data, width, height, data1.get(), &elapsed_time1) == 0);
	//CHECK(histogram_equalization_gpu(mat.data, width, height, data2.get(), &elapsed_time2) == 0);

	//fprintf(stdout, "image histogram equalization: cpu run time: %f ms, gpu run time: %f ms\n", elapsed_time1, elapsed_time2);

	cv::Mat dst;
	cv::equalizeHist(mat, dst);
	cv::imwrite("E:/GitCode/CUDA_Test/test_data/images/histogram_equalization.png", dst);

	CHECK(compare_result(data1.get(), dst.data, width*height) == 0);
	//CHECK(compare_result(data1.get(), data2.get(), width*height) == 0);

	save_image(mat, dst, width, height/2, "E:/GitCode/CUDA_Test/test_data/images/histogram_equalization_result.png");

	return 0;
}
执行结果:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

灰度图像直方图均衡化公式及实现 的相关文章

  • OpenCV 中更新窗口的 waitKey() 的替代方法

    到目前为止我见过的所有示例和书籍都建议使用 waitKey 1 来强制重新绘制 OpenCV 窗口 这看起来很奇怪而且太老套了 不必要的时候为什么还要等待 1 毫秒呢 还有其他选择吗 我尝试了 cv updateWindow 但它似乎需要
  • OpenCV:处理每一帧

    我想使用 OpenCV 编写一个跨平台应用程序进行视频捕获 在所有示例中 我发现来自相机的帧是使用抓取功能进行处理并等待一段时间 我想处理序列中的每一帧 我想定义自己的回调函数 每次当一个新帧准备好处理时都会执行该函数 例如直播对于 Win
  • caffe安装:opencv libpng16.so.16链接问题

    我正在尝试在 Ubuntu 14 04 机器上使用 python 接口编译 caffe 我已经安装了 Anaconda 和 opencvconda install opencv 我还安装了咖啡中规定的所有要求 并更改了注释块makefile
  • 附加信息:OpenCV:使用 c# 的不同大小的对象

    目前 我的 EmguCV c 代码面临问题 我试图从数据库中识别我的图像 但它不起作用 一旦检测到我的脸 它就会崩溃 然后会出现此错误 附加信息 OpenCV 不同大小的对象 我尝试寻找这个错误 但我一无所知 这是我的代码 Action f
  • 从索贝尔确定图像梯度方向?

    我正在尝试使用 openCV 的 Sobel 方法的结果来确定图像梯度方向 我知道这应该是一个非常简单的任务 我从此处复制了许多资源和答案中的方法 但无论我做什么 所得方向始终在 0 57 度之间 我希望范围为 0 360 我相信所有的深度
  • OpenCV:使用 StereoCamera 系统对颜色标记进行 3D 姿态估计

    我有一个立体摄像系统并使用两者正确校准它 cv calibrateCamera and cv stereoCalibrate My reprojection error似乎没问题 凸轮0 0 401427 凸轮1 0 388200 立体声
  • OpenCV Android - 无法解析相应的JNI函数

    我正在尝试按照此处概述的本教程使用 Opencv 设置 Android Studio https www youtube com watch v OTw GIQNbD8 https www youtube com watch v OTw G
  • 如何在 opencv 3.0 Beta 中从文件读取 UMat?

    我想用UMat所以我的代码可以使用 OpenCL OpenCV 3 0 0 Beta 在 GPU 和 CPU 上运行 但我找不到将图像文件读入的方法UMat或转换一个Mat to UMat 如何将图像读入UMat 样品用于Mat to UM
  • 如何在 OpenCV 中将 Float Mat 写入文件

    我有一个矩阵 Mat B 480 640 CV 32FC1 包含浮点值 我想将此矩阵写入一个可以打开的文件Notepad https en wikipedia org wiki Windows Notepad or 微软Word https
  • opencv如何使用鼠标事件不规则地选择图像区域? c/c++ [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 最近在学习opencv 有没有办法使用鼠标事件选择图像区域 我已经尝试过三角形的了 如果我想选择特定区域而不是三角形怎么办 谢谢你 我对此进
  • VideoCapture 未检测到 uEye 摄像头

    我的 uEye 相机遇到了一个问题 使用我的笔记本电脑摄像头 id 0 或 USB 上的网络摄像头 id 1 此行完美运行 TheVideoCapturer open 1 TheVideoCapturer 属于 VideoCapture 类
  • Android API人脸检测与OpenCV/JavaCV人脸检测

    我在 Android 设备上使用了本地 Android 人脸检测 但它似乎很慢 而且我不太确定其可靠性 我还使用了 OpenCV 的人脸检测 但仅限于 PC 而不是 Android 设备 对于 Android 我猜我必须使用 JavaCV
  • 在 Python 中使用音频流 RTMP 通过管道和 OpenCV 到 FFmpeg

    我正在尝试使用音频流式传输 FFmpeg 我将在下面展示我的代码 导入模块 import subprocess as sp 创建变量 rtmpUrl rtmp a rtmp youtube com live2 key camera path
  • python openCV 中的人口普查变换

    我开始在一个与立体视觉相关的项目中使用 openCV 和 python 我找到了关于使用 openCV 在 C 中进行人口普查转换的文档页面 link http docs opencv org 3 1 0 d2 d7f namespacec
  • 从凸点获取角点

    我编写了算法来提取图像中显示的点 它们形成凸形 我知道它们的顺序 如何从这些点中提取角点 顶部 3 个和底部 3 个 我正在使用opencv 如果你已经有了物体的凸包 并且该包包含角点 那么你需要做的就是简化包直到它只有 6 个点 有很多方
  • 将向量 转换为大小为 (n x 3) 的 Mat,反之亦然

    我有 Point3d 向量 向量形式的点云 如果我使用 OpenCV 提供的转换 比如 cv Mat tmpMat cv Mat pts Here pts is vector
  • OpenCV Python cv2.mixChannels()

    我试图将其从 C 转换为 Python 但它给出了不同的色调结果 In C Transform it to HSV cvtColor src hsv CV BGR2HSV Use only the Hue value hue create
  • 计数物体和更好的填充孔的方法

    我是 OpenCV 新手 正在尝试计算物体的数量在图像中 我在使用 MATLAB 图像处理工具箱之前已经完成了此操作 并在 OpenCV Android 中也采用了相同的方法 第一步是将图像转换为灰度 然后对其进行阈值计算 然后计算斑点的数
  • 如何使用 OpencV 从 Firebase 读取图像?

    有没有使用 OpenCV 从 Firebase 读取图像的想法 或者我必须先下载图片 然后从本地文件夹执行 cv imread 功能 有什么办法我可以使用cv imread link of picture from firebase 您可以
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i

随机推荐

  • vue制作幻灯片时涉及的transition动画(动图)

    幻灯片使用频率很高 就是各个网站的轮播大图 为了使图片更加平滑的过渡 就考虑给幻灯片加上transition动画 先看实现的效果 然后再分析动画原理 上图可以看出 幻灯片是慢慢的滑出来 而不是一下一下的跳出来 1 transition动画原
  • 前端面试--大众点评

    学习了这么久 第一次面试前端 虽然只是电话面试 但是还是很紧张 主要问题 1 介绍你的项目 2 html的状态 3html5新增加的标签 4 css的display none和visibility区别 5 怎么清除浮动 6 jquery的选
  • 【TensorFlow 入门】7、定义图变量的方法

    1 tf Variable tf Variable init initial value trainable True collections None validate shape True name None 参数名称 参数类型 参数含
  • DNS服务器列表

    Public DNS IPv4 地址 首选 119 29 29 29 AliDNS 阿里公共 DNS IPv4 地址 首选 223 5 5 5 备用 223 6 6 6 114 DNS 常规公共 DNS 干净无劫持 首选 114 114 1
  • SpringCloud---Sentinel

    文章目录 限流 sentinel使用环境搭建 设置限流 默认直接模式 关联模式 链路模式 关闭URL PATH聚合 熔断 降级 设置模拟环境 满调用比例规则 Sentinel 异常处理模式 异常处理 自定义异常处理 热点 测试热点环境搭建
  • 用mysqldump备份及结合binlog日志恢复的全过程

    1 查看更新备份时的数据 mysql gt select from t1 id 1 2 3 2 因为我的存储引擎是Myisam 为了保证数据的一直我加了参数 l 备份时不能对数据更新 如果是innodb引擎加参数 single transc
  • Speed up calculation by running in parallel

    原文链接 https perlmaven com speed up calculation by running in parallel In this example we have a bunch of numbers We need
  • Inception V1 V2 V3 V4

    最开始卷积的层数不断增加 后来开始修改卷积核的形式 一 二Inception V1 同一层级进行多尺度卷积 扩展了宽度 同时加强对小目标的检测能力 A 引入1 1的卷积是为了降维 降低通道维度 B 在中间层加入辅助损失 辅助损失只用于训练
  • fastCGI的安装和使用

    一 安装 1 先安装2个包 spawn fcgi 1 6 4 tar gz fcgi 2 4 1 SNAP 0910052249 安装 fcgi 2 4 1 SNAP 0910052249 报错 fcgio cpp In destructo
  • Git合并不同url的项目

    本文由云 社区发表 作者 工程师小熊 摘要 为了让项目能实现Git Gerrit Jenkin的持续集成 我们把项目从Git上迁移到了Gerrit上 发现有的同事在老Git提交代码 因为Gerrit做了同步 在Gerrit上有新提交的时候就
  • json文件格式详解

    json文件格式详解 JSON JavaScript Object Notation 是一种轻量级的数据交换格式 易于人阅读和编写 同时也易于机器解析和生成 它基于JavaScript Programming Language Standa
  • Latex排列图片:自由定义N行M列的排列方式

    首先导包 usepackage graphicx usepackage float usepackage subfigure 图片排成一行 begin figure htbp centering subfigure 图1 begin min
  • 【解决weditor报错】Local server not started, start with

    前言 大家在使用weditor查找元素的时候 经常会遇到 Local server not started start with 这个错误 下面是我个人的一些解决方法 供大家参考 原因1 浏览器问题导致 浏览器的原因导致的界面未刷新 我的就
  • 解决从GitHub下载文件时缓慢的问题

    我们知道 访问GitHub在国内的速度还算过得去 但是从GitHub上下载文件的速度就非常慢了 以下方法就是为了解决下载速度缓慢的 截止2019 9 5前测试有效 1 用记事本打开hosts文件 路径为C Windows System32
  • Mysql 实践(一):部署和安装

    1 目标 卸载centos自带的mysql 安装mysql 5 6 33 2 步骤 1 下载mysql 下载地址 http dev mysql com downloads mysql 5 6 html downloads 我们下载 这些包
  • 基于SSM框架的实验室开放管理系统

    系统功能结构设计 在分析并得出使用者对程序的功能要求时 就可以进行程序设计了 管理员功能结构图 管理员主要负责填充图书和其类别信息 并对已填充的数据进行维护 包括修改与删除 管理员也需要审核老师注册信息 发布公告信息 管理自助租房信息等 用
  • flutter初学之悬浮按钮

    期望 想实现一个悬浮在整个页面的悬浮按钮 实现1 用FloatingActionButton实现 新增悬浮按钮 Widget createFixedAddWidget ProductEntryState state Dispatch dis
  • linux环境下查看因内存占用过大被杀掉的进程

    文章目录 前言 查询方法 通过系统日志查找 通过dmesg命令查找 进程被杀的原因 总结 前言 最近发生两次游戏服务器进程突然消失的事件 查询日志上下文没有找到有用的信息 日志显示运行到某处戛然而止 此处代码逻辑简单 排除异常逻辑导致的服务
  • data_support/utlist(关于编译器的一些宏宏设置)

    ifndef UTLIST H tlist 权限查看程序 define UTLIST H define UTLIST VERSION 1 9 8 include
  • 灰度图像直方图均衡化公式及实现

    图像的直方图 直方图是图像中像素强度分布的图形表达方式 它统计了每一个强度值所具有的像素个数 直方图均衡化 是通过拉伸像素强度分布范围来增强图像对比度的一种方法 是图像处理领域中利用图像直方图对对比度进行调整的方法 均衡化指的是把一个分布