【python】OpenCV—Histogram Matching(9.2)

在这里插入图片描述

学习来自OpenCV基础(17)基于OpenCV、scikit-image和Python的直方图匹配

文章目录

  • 直方图匹配介绍
  • scikit-image 中的直方图匹配
  • 小试牛刀
  • 风格迁移

直方图匹配介绍

直方图匹配(Histogram Matching)是一种图像处理技术,旨在将一张图像的像素值分布调整到与另一张图像的像素值分布相匹配。这种技术在图像增强、颜色校正等任务中非常有用。以下是关于直方图匹配的详细解释:

在这里插入图片描述

一、定义与原理

定义: 直方图匹配又称为直方图规定化,是一种通过调整图像的像素值分布,使两张图像的直方图尽可能相似的图像增强方法。

原理: 基于直方图变换,通过调整图像的像素值,使得两张图像的直方图在形状和分布上尽可能一致。这通常涉及到将输入图像的像素值映射到输出图像的像素值,以实现两者之间的分布匹配

二、一般步骤

计算累积分布函数(CDF): 首先,计算原始图像和目标图像的直方图的累积分布函数(CDF)。CDF表示了从最小值到当前值的像素数占总像素数的比例。

像素值映射: 根据累积分布函数的关系,将原始图像的像素值映射到目标直方图的像素值。这个映射过程是直方图匹配的关键步骤。

应用映射函数: 对原始图像的所有像素应用映射函数,得到匹配后的图像。

三、数学表示

假设我们有一个输入图像 I I I 和一个目标图像 T T T,我们希望将输入图像的像素值映射到输出图像的像素值。这可以表示为:

O ( x , y ) = round ( T I ⋅ I ( x , y ) ) O(x, y) = \text{round}\left(\frac{T}{I} \cdot I(x, y)\right) O(x,y)=round(ITI(x,y))

其中, O ( x , y ) O(x, y) O(x,y) 是输出图像中的像素值, I ( x , y ) I(x, y) I(x,y) 是输入图像中的像素值, T T T 是目标图像的像素值范围。函数 round \text{round} round 将结果四舍五入到最近的整数。

四、应用场景

图像增强: 当图像的对比度较低或细节不明显时,可以使用直方图匹配来增强图像的视觉效果。

颜色校正: 当图像受到光照条件的影响或者摄像设备的色彩偏差时,可以使用直方图匹配来校正颜色。

风格迁移: 在计算机视觉中,可以使用直方图匹配来实现图像的风格迁移,将一个图像的风格应用于另一个图像。

五、注意事项

在进行直方图匹配时,需要注意不同图像之间的直方图可能具有不同的范围和分布,因此需要进行适当的归一化和调整。

直方图匹配可能无法完全消除图像之间的差异,因为它仅考虑了像素值的分布,而忽略了像素之间的空间关系

对于某些特定的应用场景,可能需要结合其他图像处理技术来进一步提高匹配效果。

scikit-image 中的直方图匹配

skimage.exposure.match_histograms 是 scikit-image 库中用于直方图匹配的一个函数。该函数用于将一个图像的直方图与另一个图像的直方图相匹配,从而实现图像亮度和对比度的调整。以下是该函数的中文文档,包含其功能描述、参数说明和示例。

skimage.exposure.match_histograms

一、功能描述:

该函数将源图像的直方图与目标图像的直方图进行匹配,从而改变源图像的像素值,使其直方图与目标图像的直方图尽可能相似。这在图像处理中常用于增强图像的对比度或使不同图像之间的亮度和对比度更加一致。

二、参数说明:

source: ndarray 类型,输入图像,即需要进行直方图匹配的源图像。

template: ndarray 类型,目标图像,即源图像直方图要匹配的目标。

multichannel: bool 类型,可选参数,默认为 False。如果为 True,则对多通道图像进行独立匹配。这要求源图像和目标图像具有相同数量的通道。

三、返回值:

matched:ndarray 类型,与源图像形状相同的数组,其中包含了匹配后的像素值。

小试牛刀

from skimage import exposure
import matplotlib.pyplot as plt
import argparse
import cv2


# 构造参数解析器并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-s", "--source", required=True, help="Path to the input source image")
ap.add_argument("-r", "--reference", required=True, help="Path to the input reference image")
args = vars(ap.parse_args())

# 加载源和参考图像
print("[INFO] Loading source and reference images...")
src = cv2.imread(args["source"])
ref = cv2.imread(args["reference"])

# 确定我们是否执行多通道直方图匹配,然后执行直方图匹配本身
print("[INFO] Performing histogram matching...")
multi = True if src.shape[-1] > 1 else False

matched = exposure.match_histograms(src, ref, multichannel=multi)
# This was in skimage.transform between 0.14.2. It was moved to skimage.exposure with 0.16.0.

# cv2.imwrite("matched.jpg", matched)

# 显示输出图像
cv2.imshow("Source", src)
cv2.imshow("Reference", ref)
cv2.imshow("Matched", matched)
cv2.waitKey(0)

# 构造一个图形来显示应用直方图匹配前后每个通道的直方图图
(fig, axs) = plt.subplots(nrows=3, ncols=3, figsize=(8, 8))

# 循环遍历源图像、参考图像和输出匹配图像
for (i, image) in enumerate((src, ref, matched)):
    # 转换图像从BGR到RGB通道顺序
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 按RGB顺序循环通道名称
    for (j, color) in enumerate(("red", "green", "blue")):
        # 计算当前通道的直方图并绘制它
        (hist, bins) = exposure.histogram(image[..., j], source_range="dtype")
        axs[j, i].plot(bins, hist/hist.max())
        # 计算当前通道的累积分布函数并绘制它
        (cdf, bins) = exposure.cumulative_distribution(image[..., j])
        axs[j, i].plot(bins, cdf)
        # 将当前图形的y轴标签设置为当前颜色通道的名称
        axs[j, 0].set_ylabel(color)

# 设置轴标题
axs[0, 0].set_title("Source")
axs[0, 1].set_title("Reference")
axs[0, 2].set_title("Matched")

# 显示输出图
plt.tight_layout()
plt.show()

运行

python matching.py -s source.jpg -r reference.jpg

输入的 source.jpg

在这里插入图片描述

输入的 reference.jpg

在这里插入图片描述

直方图 matching 的结果

在这里插入图片描述

看看绘制的 RGB 三通道的直方图(蓝色)以及各自通道上的累积分布函数曲线(橙色)的绘制

请添加图片描述

风格迁移

看了小试牛刀,立刻想到了风格迁移,试试

source 图片还是蒙娜丽莎

在这里插入图片描述

reference 图片换成星空

在这里插入图片描述

看看匹配后的结果

在这里插入图片描述

看看RGB各通道的直方图和累积分布函数曲线

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文详解大模型微调全流程

节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

11-数组与指针深入理解——题型理解

11-数组与指针深入理解——题型理解 文章目录 11-数组与指针深入理解——题型理解一、理解题1二、理解题二三、理解题三四、理解题四五、理解题五六、理解题六 一、理解题1 #include <stdio.h>int main(void) {int (*p)[5] NULL; // 定义一个指向 拥有5个整型数据的数组…

Tessy学习系列(三):单元测试——官方例程isValueInRange

一、工程创建 &#xff08;1&#xff09;新建工程 注意&#xff1a;工程名称以及路劲不能包含空格和中文 &#xff08;2&#xff09;新建测试集与单元测试模块 新建测试集 新建单元测试模块 设置测试模块为单元测试模块并选择GNU GCC编译器如果需要其他的编译器&#xff0c;…

力扣每日一题 6/10

881.救生艇[中等] 题目&#xff1a; 给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&#xff0c;但条件是这些人的重量之和最多为 limit。 返回 承载所有人所需的最小船…

kubesz(一键安装k8s)

引言 Kubernetes&#xff08;K8s&#xff09;是一个开源的容器编排系统&#xff0c;用于自动化部署、扩展和管理容器化应用程序。kubeasz 是一个用于快速搭建 Kubernetes 高可用集群的项目&#xff0c;它基于 Ansible&#xff0c;通过提供一套简单、易用的配置&#xff0c;使得…

杨校老师项目之基于SpringBoot的理发店的预约管理系统

原系统是SSMJSP页面构成&#xff0c;先被修改为SpringBoot JSP页面 自助下载渠道: https://download.csdn.net/download/kese7952/89417001&#xff0c;或 点我下载 理发师信息&#xff1a; 理发师详细信息 公告信息 员工登录&#xff1a; 管理员登录

94、二叉树的迭代遍历

实现对二叉树的前后序非递归遍历 题解&#xff1a; 递归的实现就是&#xff1a;递去&#xff0c;归来。每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中&#xff0c;然后递归返回的时候&#xff0c;从栈顶弹出上一次递归的各项参数&#xff0c;所以这就是…

有点好玩的python运维脚本

python运维脚本 1. 常用端口扫描2. 文件整理 1. 常用端口扫描 在计算机网络中&#xff0c;端口是一个通信端点&#xff0c;允许不同的进程或服务通过网络连接和交换数据。端口通过数值来标识&#xff0c;并与特定的协议相关联。未采取适当安全措施而保持端口开放&#xff0c;可…

上位机图像处理和嵌入式模块部署(f407 mcu vs h750)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在目前工业控制上面&#xff0c;f103和f407是用的最多的两种stm32 mcu。前者频率低一点&#xff0c;功能少一点&#xff0c;一般用在低端的嵌入式设…

搞懂银行的各类号码 — Account Number, Routing Number 和 Swift Code

1. 前言2. 名词解释 2.1. Debit Card Number 储蓄卡卡号2.2. Account Number 账户号码2.3. Routing Number 路由号码2.4. SWIFT Code SWIFT 号码3. 查找信息 3.1. 支票3.2. 网上银行3.3. 手机银行4. SWFIT Code 4.1. 看懂 SWIFT Code4.2. 询问银行4.3. Google 大神4.4. 部分常用…

GitLab代码导出 gitlab4j-api 实现

目录 GitLab简介 GitLab 的主要特点包括&#xff1a; GitLab代码导出 gitlab4j-api 添加 gitlab4j-api 依赖 使用 gitlab4j-api 获取特定命名空间下的所有项目 说明 注意事项 GitLab简介 GitLab 是一个开源的代码仓库和协作平台&#xff0c;主要用于版本控制和源代码管理…

堆和栈(heap and stack)

1、堆&#xff1a;一块内存空间&#xff0c;可以从中分配一个小buffer&#xff0c;用完后再把它放回去。 2、栈&#xff1a;也是一块内存空间&#xff0c;cpu的sp寄存器指向它&#xff0c;它可以用于函数调用、局部变量、多任务系统里保存现场。 PUSH [r3-r6,lr]; #将r3到r6寄…

未来几年,同样的性能,推理功耗降低为现在的几万分之一,有可能吗

未来几年,同样的性能,推理功耗降低为现在的几万分之一,有可能吗 一.数据二.抓取LLM排行榜,相同的MMLU精度,模型参数量缩减倍数三.其它 有人说未来几年,推理功耗能降低为现在的几万分之一,好奇怎么能做到呢 一.数据 二.抓取LLM排行榜,相同的MMLU精度,模型参数量缩减倍数 import…

Docker Swarm集群部署管理

Docker Swarm集群管理 文章目录 Docker Swarm集群管理资源列表基础环境一、安装Docker二、部署Docker Swarm集群2.1、创建Docker Swarm集群2.2、添加Worker节点到Swarm集群2.3、查看Swarm集群中Node节点的详细状态信息 三、Docker Swarm管理3.1、案例概述3.2、Docker Swarm中的…

1035 插入与归并(测试点6)

solution 类型判断&#xff1a;插入排序中已排序的部分有序&#xff0c;未排序的和原数组元素相同&#xff1b;否则为归并排序测试点6&#xff1a;对于归并排序的子序列长度&#xff0c;不能简单视为前k个有序则子序列长度就是k 例如该测试用例的归并排序的子序列长度应该为2&…

C# BindingSource 未完

数据绑定导航事件数据验证自定义示例示例总结 在 C#中&#xff0c; BindingSource 是一个非常有用的控件&#xff0c;它提供了数据绑定的基础设施。 BindingSource 允许开发者将数据源&#xff08;如数据库、集合、对象等&#xff09;与用户界面控件&#xff08;如文本框、下…

测试基础12:测试用例设计方法-边界值分析

课程大纲 1、定义 经验发现&#xff0c;较多的错误往往发生在输入或输出范围的边界上&#xff0c;因为边界值是代码判断语句的点&#xff0c;一般容易出问题&#xff08;数值写错、多加或丢失等号、写错不等号方向…&#xff09;。所以增加对取值范围的边界数据的测试&#xff…

Vue3父组件如何访问子组件属性和方法

本篇内容主要是父组件如何访问子组件的属性和方法 文章目录 子组件 //son.vue代码const list (info) >{console.log(info) }const name ref("XXXX")//子组件向父组件暴露了一个方法&#xff0c;然后父组件就可以去使用子组件里面的一些属性和方法了 //子组件向…

车载电子电气架构 - 智能座舱技术及功能应用

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

【Vue】请求动态渲染数据

目标 请求获取数据存入 vuex, 映射渲染 安装 axios yarn add axios准备actions 和 mutations App.vue页面中调用 action, 获取数据 验证数据是否存储成功 动态渲染 cart-item.vue