从零开始学cv-8:直方图操作进阶:直方图匹配,局部直方图均衡化,彩色直方图均衡化

news2024/11/18 8:37:21

文章目录

  • 一,简介
  • 二、直方图匹配
  • 三、局部直方图均衡化
  • 四、彩色直方图均衡化
    • 4.1 rgb彩色直方图均衡化
    • 4.2 ycrb 彩色直方图均衡化


一,简介

在上一篇文章中,我们探讨了直方图的基本概念,并详细讲解了如何利用OpenCV来查看图像直方图,以及如何实现直方图均衡化。在此基础上,本篇将继续深入,介绍直方图均衡化的高级应用,包括直方图匹配、局部直方图均衡化以及彩色图像的直方图均衡化技术。

二、直方图匹配

直方图均衡化能自动增强图像的整体对比度,但是往往结果难以受到控制。实际中常常需要增强某个特定灰度值范围内的对比度或使图像灰度值的分布满足特定需求这个时候就需要直方图匹配技术。
直方图匹配,亦称作直方图规定化,是一种旨在调整图像灰度分布的图像处理技术,目的是使其与指定参考图像的直方图相吻合。此技术有助于提升图像的视觉效果,尤其在需要特定灰度分布以凸显图像特征时尤为有效。直方图匹配的执行步骤包括:

  1. 参考图像直方图计算:选取一个参考图像,并计算其直方图。
  2. 累积分布函数(CDF)计算:计算参考图像直方图的累积分布函数。
  3. 目标图像直方图与CDF计算:对目标图像执行相同的操作,获取其直方图和CDF。
  4. 映射关系建立:通过比较目标图像与参考图像的CDF,建立灰度级之间的映射关系,通常通过查
    找目标图像CDF值在参考图像CDF中的对应灰度级来实现。
  5. 映射应用:依据建立的映射关系,将目标图像的每个像素值重新映射到新的灰度级。
  6. 生成匹配后的图像:应用映射后的灰度值,创建出具有参考图像直方图特征的新图像。

直方图匹配的应用领域包括:
图像风格转换:使一幅图像在视觉上更接近另一幅图像的风格。
图像增强:在特定应用场景中,通过匹配特定直方图来增强图像的特定特征。
图像复原:在图像复原过程中,利用直方图匹配调整灰度分布,以改善复原效果。
注意事项:
直方图匹配过程主要是改变目标图像的灰度分布,使其与参考图像的直方图相似,但这种改变并不涉及图像的实际内容,如形状、纹理或场景结构等。因此,尽管目标图像的灰度分布(即像素的亮度级别)会发生变化,图像中的物体、形状、颜色等视觉内容可能并不会与参考图像保持一致。换句话说,直方图匹配可能会改变图像的整体外观,但不会改变图像中对象的具体识别信息或场景的实质性内容,并且匹配过程可能会引入噪声或失真,因此需根据实际情况进行适当调整。

使用代码:

# 1.60 彩色图像的直方图匹配
import cv2
import numpy as np

# 读取并调整图像大小到640x480
img = cv2.resize(cv2.imread("sky1.jpg", flags=1),(640,480)) # flags=1 表示以彩色图像格式读取
imgRef = cv2.resize(cv2.imread("sky2.jpg", flags=1),(640,480))  # 读取并调整参考图像的大小,用于直方图匹配

# 获取图像的通道数
_, _, channel = img.shape

# 初始化输出图像,其大小和类型与原始图像相同
imgOut = np.zeros_like(img)

# 遍历每个通道
for i in range(channel):
    # 计算原始图像在当前通道的直方图,并返回直方图数组和每个箱子的边界
    histImg, _ = np.histogram(img[:, :, i], 256)
    # 计算参考图像在当前通道的直方图
    histRef, _ = np.histogram(imgRef[:, :, i], 256)
    
    # 计算原始图像的累积分布函数 (CDF)
    cdfImg = np.cumsum(histImg)
    # 计算参考图像的累积分布函数 (CDF)
    cdfRef = np.cumsum(histRef)
    
    # 对每个灰度级进行遍历
    for j in range(256):
        # 计算当前灰度级的CDF值与参考图像CDF值的差值的绝对值
        tmp = abs(cdfImg[j] - cdfRef)
        # 将numpy数组转换为列表
        tmp = tmp.tolist()
        # 找到差值最小的索引,即最接近的灰度级
        index = tmp.index(min(tmp))
        # 将原始图像中对应灰度级的像素值替换为匹配后的灰度级
        imgOut[:, :, i][img[:, :, i] == j] = index

# 显示原始图像
cv2.imshow("img", img)
# 显示参考图像
cv2.imshow("imgRef", imgRef)
# 显示直方图匹配后的图像
cv2.imshow("imgOut", imgOut)
# 等待按键后关闭所有窗口
cv2.waitKey(0)

效果:
在这里插入图片描述
可以实现类似图像风格迁移的效果,但速度较慢,可用来扩充数据集或者批量P图

三、局部直方图均衡化

局部直方图均衡化(Local Histogram Equalization)是一种针对传统直方图均衡化方法的改进,其目的是避免传统方法可能导致的局部对比度降低的问题。传统直方图均衡化会对整个图像的灰度分布进行全局调整,以实现灰度级的均匀分布,但这有时会牺牲图像中特定区域的对比度。相比之下,局部直方图均衡化通过在图像的不同区域实施差异化的均衡化策略,旨在保留这些区域的局部细节和对比度。

局部直方图均衡化的实施过程包括以下几个步骤:

  1. 图像分割:将输入图像划分为若干个小的区域,这些区域通常被称为块或窗口。
  2. 局部直方图计算:对每个小区域单独计算其局部直方图,以反映该区域的灰度分布特性。
  3. 局部累积分布函数(CDF)计算:对每个局部直方图计算累积分布函数,以获得每个灰度级在该区域中的分布情况。
  4. 局部映射关系建立:根据每个区域的CDF建立相应的灰度级映射关系,这些映射关系反映了均衡化后的灰度级分布。
  5. 局部映射应用:将每个小区域的像素值按照其CDF映射到新的灰度级,从而实现局部均衡化。
  6. 合成匹配后的图像:将所有小区域的均衡化结果合并,得到最终的均衡化图像。

局部直方图均衡化的优势在于:

  1. 保留局部对比度:通过局部处理,可以保留图像中的局部对比度,避免全局均衡化可能导致的细节丢失。
  2. 适应性:该方法能够更好地适应图像中不同区域的照明变化和对比度差异

注意:
在实施局部直方图均衡化时,选择合适的块大小对于取得理想效果至关重要。如果块大小设置过小,可能会丢失图像中的细节信息;相反,如果块过大,可能会引入额外的噪声。因此,确定一个既能保留必要细节又能有效抑制噪声的块大小是关键。
此外,由于局部直方图均衡化需要对每个小区域分别计算直方图和累积分布函数,这相对于全局直方图均衡化来说,计算效率可能会较低。全局均衡化只需要对整个图像进行一次直方图和CDF的计算,而局部均衡化则需要重复这个过程对每个区域进行处理。尽管如此,局部均衡化在保持图像局部对比度和适应图像局部特征方面具有显著优势,因此在需要精细调整图像对比度和细节保留的场景中,它仍然是首选的方法。

在opencv中有一个实现局部直方图均衡化的方法cv2.createCLAHE(clipLimit, tileGridSize)函数说明:

参数说明:
clipLimit 参数定义了一个对比度增强的阈值。当直方图中某个灰度级的对比度增强超过这个阈值时,该灰度级的对比度增强会被限制在 clipLimit 以下。。
tileGridSize: 这是一个整数元组,表示将图像分割成的小块的大小。例如,(8, 8) 表示将图像分割成 8x8 的块。每个小块的直方图将被单独计算和均衡化,然后将结果合并以形成最终的均衡化图像。

使用代码:

# 1.60 彩色图像的直方图匹配
import cv2
import numpy as np
path = r"E:\PS\2.png"
img = cv2.imread(path, 0)
equ1 = cv2.equalizeHist(img)  # 普通的直方图均衡化
clahe = cv2.createCLAHE(8, (8, 8))  # 局部直方图均衡化,创建clahe对象
equ2 = clahe.apply(img)  # 将clahe对象应用到img上,返回增强图片

cv2.imshow("equ1", equ1)
cv2.imshow("equ2", equ2)
cv2.waitKey(0)

效果:
左侧普通直方图均衡化,右侧局部直方图均衡化
在这里插入图片描述

四、彩色直方图均衡化

彩色直方图均衡化(Color Histogram Equalization)是一种针对彩色图像的直方图均衡化技术。与灰度图像的直方图均衡化类似,彩色直方图均衡化的目的是通过调整图像的像素分布,使得输出图像的直方图尽可能平坦,从而增强图像的全局对比度。然而,彩色直方图均衡化是在彩色图像的每个颜色通道上分别进行,而不是在整个图像上进行。
彩色直方图均衡化的实现步骤:

  1. 颜色分离:将彩色图像分离成三个或更多颜色通道(红、绿、蓝等)。
  2. 计算每个通道的直方图:对每个颜色通道分别计算直方图。
  3. 计算累积分布函数(CDF):对每个通道的直方图计算累积分布函数。
  4. 计算直方图均衡化映射:将每个通道的累积分布函数值乘以通道的最大灰度级,得到每个通道的新映射值。
  5. 应用映射:根据映射关系,将每个通道的像素值映射到新的灰度级。
  6. 合成匹配后的图像:将所有通道的映射结果合并成最终的匹配图像

在进行彩色直方图均衡化时,需要注意以下几点:首先,选择合适的颜色空间对于实现理想的图像处理效果至关重要,常见的选择包括RGB和HSV等。其次,由于需要对每个颜色通道单独计算直方图和累积分布函数,因此其计算效率可能不如全局直方图均衡化。尽管如此,彩色直方图均衡化仍是一种有用的工具,可以在保持图像颜色信息的同时提高对比度,从而实现更好的视觉效果。
本文将介绍两种实现彩色直方图均衡化的方法。

4.1 rgb彩色直方图均衡化

将图像rgb三色通道拆分,分开进行直方图均衡化,并将处理后的三通道灰度图按照通道维度拼接起来,获得新的三通道图像
实现代码:

# 1.60 彩色图像的直方图匹配
import cv2
import numpy as np
path = r"E:\PS\2.png"
img = cv2.imread(path)
(b, g, r) = cv2.split(img)  # 通道拆分
bH = cv2.equalizeHist(b)  # b通道直方图均衡化
gH = cv2.equalizeHist(g)  # g通道直方图均衡化
rH = cv2.equalizeHist(r)  # r通道直方图均衡化
result = cv2.merge((bH, gH, rH))  # 通道合并
cv2.imshow("result", result)
cv2.waitKey(0)

效果:
原图
在这里插入图片描述
处理后的图片:
在这里插入图片描述
图像亮度提升但部分颜色失真

4.2 ycrb 彩色直方图均衡化

YCbCr(Y’CbCr)是一种用于表示彩色图像中的颜色信息的色彩空间,它根据ITU-R BT.601标准定义,主要用于视频传输和显示。YCbCr色彩空间包括三个分量:Y’(亮度分量),它是一个灰度值,与颜色无关,通常用于彩色视频的亮度信号;Cb(蓝色色差分量),表示蓝色信号与Y’分量之间的差值,包含了蓝色分量的信息;Cr(红色色差分量),表示红色信号与Y’分量之间的差值,包含了红色分量的信息。通过Y’、Cb和Cr三个分量的组合,YCbCr色彩空间能够准确地表示彩色图像中的颜色信息,并在视频处理和显示中发挥重要作用。要对图像进行彩色直方图均衡化,首先先将图像转化到ycrb颜色空间,然后对其中的y通道(亮度通道)做局部直方图均衡化(crcb颜色通道最好不要动,颜色容易变)这样可以减少颜色的失真.。
实现代码:

# 1.60 彩色图像的直方图匹配
import cv2
import numpy as np

path = r"E:\PS\2.png"

def hisEqulColor2(imga): #直方图均衡化算法
    ycrcb = cv2.cvtColor(imga, cv2.COLOR_BGR2YCR_CB) # 转换ycrb颜色空间
    channels = cv2.split(ycrcb)
    print(channels)
    clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(11,11))  # 局部直方图均衡化
    clahe.apply(channels[0], channels[0])
    cv2.merge(channels, ycrcb)
    cv2.cvtColor(ycrcb, cv2.COLOR_YCR_CB2BGR, imga)
    return imga
img = cv2.imread(path)
his = hisEqulColor2(img)
cv2.imshow("result", his)
cv2.imshow("img", img)
cv2.waitKey(0)

效果:
在这里插入图片描述
同上面方法相比颜色失真较少,并且不会过度拉伸图像,图像亮度提升可以使用伽马变换或对数变换

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

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

相关文章

MATLAB 大场景建筑物点云提取方法实现(75)

MATLAB 大场景建筑物点云提取方法实现(75) 一、算法介绍二、算法实现1.代码2.效果展示总结一、算法介绍 本章手动实现了一种建筑物点云提取方法,可以对室外的大规模场景点云中的建筑物进行有效提取,下面是实现的效果和具体的实现方法,直接复制粘贴代码即可使用, 二、算…

【基础算法总结】多源 BFS_多源最短路问题

多源 BFS_多源最短路问题 1.多源 BFS_多源最短路问题2.01 矩阵3.飞地的数量4.地图中的最高点5.地图分析 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃&…

springboot纹理生成图片系统--论文源码调试讲解

第2章 程序开发技术 2.1 MySQL数据库 开发的程序面向用户的只是程序的功能界面,让用户操作程序界面的各个功能,那么很多人就会问,用户使用程序功能生成的数据信息放在哪里的?这个就需要涉及到数据库的知识了,一般来说…

Maven继承和聚合特性

目录 Maven继承关系 1.继承概念 父POM 子模块 2.继承机制 3.示例 4.继承作用 背景 需求 5.注意事项 Maven聚合关系 1. 定义与概念 2. 实现方式 3. 特性与优势 4. 示例 5. 注意事项 Maven继承关系 1.继承概念 Maven 继承是指在 Maven 的项目中,定义…

沉浸式技术

沉浸式技术是一种通过创造逼真的虚拟或增强现实环境,使用户感到自己仿佛身处另一个世界的技术。它主要依赖于视觉、听觉、触觉等多种感官的调动,带来身临其境的体验。随着技术的发展,沉浸式技术正迅速改变着娱乐、教育、医疗等众多领域。本文…

Golang | Leetcode Golang题解之第345题反转字符串中的元音字母

题目&#xff1a; 题解&#xff1a; func reverseVowels(s string) string {t : []byte(s)n : len(t)i, j : 0, n-1for i < j {for i < n && !strings.Contains("aeiouAEIOU", string(t[i])) {i}for j > 0 && !strings.Contains("aei…

牛客周赛 Round 56

牛客周赛 Round 56 A 面包店故事 链接&#xff1a;https://ac.nowcoder.com/acm/contest/88392/A 来源&#xff1a;牛客网 题目描述 小镇上有一家面包店&#xff0c;面包以 &#x1d465; 元的价格出售&#xff0c;加 &#x1d466; 元可以多加几块培根。小歪带着 &#x1d4…

蔚来汽车拥抱AI

30多个传感器&#xff0c;车上实时收集数 为什么要造手机 领航辅助驾驶 端到端AEB

Spring动态代理与AOP

AOP中的Before是如何实现的&#xff1f; 在AOP&#xff08;面向切面编程&#xff09;中&#xff0c;Before注解通常用于定义一个在方法执行前执行的前置通知&#xff08;advice&#xff09;。在Spring框架中&#xff0c;实现Before功能的底层机制主要基于代理&#xff08;Prox…

JSON Web Token (JWT): 理解与应用

JWT&#xff08;JSON Web Token&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用于在各方之间以JSON对象的形式安全地传输信息。JWT通常用于身份验证和授权目的&#xff0c;因为它可以使用JSON对象在各方…

4.5、配置vtp域

一、了解vtp域 VTP&#xff08;VLAN Trunking Protocol&#xff09;域是一个在网络中用于管理和同步VLAN配置信息的概念。它使得多个交换机可以在同一VTP域中共享VLAN信息&#xff0c;从而简化了VLAN的配置和管理。 三种主要模式 Server模式&#xff1a; 交换机可以创建、修…

Nginx的进程模型:Master-Worker架构解析

Nginx的进程模型&#xff1a;Master-Worker架构解析 一、Master-Worker架构概述二、Master进程的职责三、Worker进程的特点四、与Apache进程模型的对比 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Nginx作为高性能Web服务器&#xff0c…

代码随想录算法训练营day45:动态规划part12:115.不同的子序列;583. 两个字符串的删除操作;72. 编辑距离

目录 115.不同的子序列 分析&#xff1a; 583. 两个字符串的删除操作 72. 编辑距离 115.不同的子序列 力扣题目链接(opens new window) 给定一个字符串 s 和一个字符串 t &#xff0c;计算在 s 的子序列中 t 出现的个数。 字符串的一个 子序列 是指&#xff0c;通过删除…

初识Linux · 基本指令(1)

目录 前言&#xff1a; 基本指令 1.1 pwd 1.2 ls 1.3 mkdir cd clear 1.4 touch 1.5 ls部分补充 1.6 whoami 1.7 有关目录以及路径 前言&#xff1a; 今天是Linux系列的第一章节&#xff0c;对于Linux的主线学习大概会更新两个半月左右&#xff0c;中间穿插着算法…

vue中 在scoped下通过@import引入scss的作用域?

<style lang"scss" src"./index.scss" scoped></style>人工智能学习网站 https://chat.xutongbao.top

nbcio-boot基于flowable6.7.2的流程模型版本管理-前端与界面

更多技术支持与服务请加入我的知识星球。 这部分主要讲前端与功能界面方面 1、首先增加发布列表与修改状态api接口 // 查询流程发布列表 export function listPublish(query) {return request({url: /flowable/definition/publishList,method: get,params: query})}// 激活/挂…

pytorch之nn.Module使用介绍

在 PyTorch 中&#xff0c;nn.Module 是所有神经网络模型的基类&#xff0c;提供了许多重要的成员函数。以下是一些常用的成员函数及其功能&#xff1a; 1. __init__(self) 描述&#xff1a;初始化模块。在用户定义的模型中&#xff0c;通常用来定义层和其他模块。 示例&…

【hot100篇-python刷题记录】【最大子数组和】

R5-普通数组 印象题&#xff0c;讲思路&#xff1a; 1.0个元素&#xff0c;返回0 2.将从left到right的计算简化为为left-mid&#xff0c;mid1-right 以及left-mid-right 3者的最大值&#xff08;因为有负数&#xff09; 3.上面左右两边的计算可以递归调用本身函数&#xff0…

第二十二节、创建人物状态栏

一、可视化插件 在层级面板名字加上对应的图标&#xff0c;会显示颜色&#xff0c;需要运行一下 二、UI 1、创建一个画布 由于使用新的新输入系统&#xff0c;需要替换一下 2、设置锚点 作用是&#xff1a;当屏幕分辨率更改后&#xff0c;ui图标不会位移 3、设置填充 4、制…

tomcat 运行javaweb项 提示无法将资源添加到Web应用程序缓存解决方法

javaweb项目tomcat启动提示web资源缓存不足&#xff0c;具体如下&#xff0c;不影响项目运行 15-Aug-2024 13:35:20.200 警告 [localhost-startStop-1] org.apache.catalina.webresources.Cache.getResource 无法将位于[/WEB-INF/classes/web-vue2/ssdev/ux/login/style/font/f…