OpenCV学习 基础图像操作(十四):直方图均衡化和直方图规定化

基础原理

直方图操作是基于像素统计的基础图像操作,被广泛运用于调整图像的对比度,并由此衍生出很多变种和该经的方式.

图像相直方图

直方图(Histogram),又称质量分布图,是一种统计报告图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横坐标表示数据类型,纵轴表示分布情况。

图像直方图,常见的是指根据灰度来绘制灰度的直方图,当然我们也可以绘制RGB直方图,梯度直方图,方向直方图等等,简而言之就是通过直方图的形式来刻画图片的某一属性。

直方图均衡化

直方图均衡化顾名思义,是将分布不均衡的直方图变为均衡的,如下图所示,将左侧的直方图转换为右侧的直方图整个过程就称作直方图均衡化。

本质上是将分布不均匀的像素强度值,通过单调非线性函数的映射形成均匀的像素强度值分布。

其实现方式具体实现如下:

假设原图像为I_S目标图像为I_D,那么则有I_D=f(I_S)

其具体的计算过程如下:

  1. 统计图像的直方图信息,并划分到L-1层级上
  2. 针对每一层级,对统计的像素值进行归一化
  3. s的累积分布函数为
  4. 对tk取整扩展后

总结整个过程为:

直方图规定化

直方图均衡化能自动增强图像的整体对比度,但是往往结果难以受到控制。实际中常常需要增强某个特定灰度值范围内的对比度或使图像灰度值的分布满足特定需求。这个时候使用直方图规定化会有较好的结果。直方图规定化就是要调整原始图像的直方图去逼近规定的目标直方图

其具体的计算过程如下:

  1. 求出原始图像的直方图分布
  2. 求出目标图像的直方图分布
  3. 接下来就是如何建立原始灰度级数和规定直方图灰度级数的对应映射关系。映射规则一般有两种:单映射规则(SML)和组映射规则(GML)。
    单映射规则中,将k从小到大依次找到能使下式有最小值的l的值,这样就可以将原始图像灰度级数k和规定直方图灰度级数l对应映射起来。

    组映射规则中,设I(l)为整数函数,l=1,2,3,…,N-1,满足0I(0)≤I(l)≤…≤I(N-1)≤M-1。I(l)为不确定值,因此要确定能使下式达到最小的I(l)*值:

总结整个过程为:

自适应直方图均衡化

实际上“自适应”在这所指的是就是用滑动窗口来对局部的来做直方图均衡化,并且对这个局部区域内的对比度进行限制。

具体计算过程如下:

  1. 将图信息按窗口大小进行切分
  2. 在每个窗口内进行直方图均衡化

由于有局部噪声的存在,可能将局部的噪声放大,因此一般在使用自适应直方图均衡化时,常常会对其对比度进行一个限制,防止噪声过度放大,即在映射时添加限制,这种方法也称为对比度受限的自适应直方图均衡化。

API介绍

直方图统计

split(
const Mat &src, //输入图像
Mat* mvbegin //输出的多通道图像数组
)

calcHist(
const Mat* image,//输入图像指针
int images_nums,//输入图像的数目
const int* channels,//输入图像的通道数
InputArray mask,    //输入mask,可选,默认不用
OutputArray hist,   //输出的直方图数据
int dims,           //输出数据的维度
const int* histsize,//直方图的级数(输出多少个条)
const float* ranges,//值域范围(横坐标的范围)
bool uniform,       //是否归标准化
bool accumulate     //是否累加,如果是多通道的则需要设为true,默认为false
)

直方图均衡化

equalizeHist(
InputArray src,//输入图像,必须是8-bit的单通道图像
OutputArray dst//输出结果
)

直方图规定化(直方图匹配)

equalizeHist
(
InputArray 	src, //原图像
OutputArray dst, //目标图像
Stream &stream = Stream::Null() //异步实时处理的流,通常不用
)

自适应直方图均衡化

//创建自适应均衡化器
createCLAHE	(   double 	clipLimit = 40.0,      //对比度限制大小
                Size 	tileGridSize = Size(8, 8) //滑窗大小
            )	

//调用
CLAHE::apply(	InputArray 	src,     //原图像
                OutputArray dst      //目标图像
                )	

实践一下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 加载图像
image = cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE)

# 直方图均衡化
equalized = cv2.equalizeHist(image)

# 自适应直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
adaptive_equalized = clahe.apply(image)

# 直方图匹配
def histogram_matching(source, template):
    oldshape = source.shape
    source = source.ravel()
    template = template.ravel()

    s_values, bin_idx, s_counts = np.unique(source, return_inverse=True, return_counts=True)
    t_values, t_counts = np.unique(template, return_counts=True)

    s_quantiles = np.cumsum(s_counts).astype(np.float64)
    s_quantiles /= s_quantiles[-1]
    t_quantiles = np.cumsum(t_counts).astype(np.float64)
    t_quantiles /= t_quantiles[-1]

    interp_t_values = np.interp(s_quantiles, t_quantiles, t_values)

    return interp_t_values[bin_idx].reshape(oldshape)

template_image = cv2.imread('shan.jpeg', cv2.IMREAD_GRAYSCALE)
matched = histogram_matching(image, template_image)

# 显示结果
plt.figure(figsize=(10, 8))

plt.subplot(2, 3, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')

plt.subplot(2, 3, 2)
plt.title('Histogram Equalized')
plt.imshow(equalized, cmap='gray')

plt.subplot(2, 3, 4)
plt.title('Adaptive Histogram Equalized')
plt.imshow(adaptive_equalized, cmap='gray')

plt.subplot(2, 3, 5)
plt.title('Histogram Matched')
plt.imshow(matched, cmap='gray')

plt.subplot(2, 3, 3)
plt.title('Source')
plt.imshow(image, cmap='gray')

plt.subplot(2, 3, 6)
plt.title('Template')
plt.imshow(template_image, cmap='gray')

plt.tight_layout()
plt.show()

参考链接

直方图均衡化、自适应直方图均衡化_直方图均衡化和自适应均衡化的区别-CSDN博客

限制对比度自适应直方图均衡化算法原理、实现及效果-CSDN博客

直方图均衡化以及直方图匹配_自适应直方图均衡化比直方图均衡化好在哪里-CSDN博客

OpenCV--021:直方图规定化_opencv 直方图规定化-CSDN博客

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

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

相关文章

在马达驱动上的MOS产品选型分析与应用

电机的应用非常广泛,可以说大部分动的产品内部都有电机的身影,其主要的应用领域有风机、泵、散热风扇、电动工具、智能家居、以及汽车应用等等。随着各国出台了更加严格的用电标准,节能电机成为了市场关注的热点,而BLDC电机具有高…

用大模型搭建一个自己的新闻小助手

背景 信息快速增长的时代,及时获取到有价值的资讯是一件很必要的事情。已经有各类新闻app和获取信息的渠道了,为什么还需要在构建一个小助手来获取新闻资讯呢?其实原因很简单各类新闻app服务的是具体一类人群,个人和人群还是有偏…

【leetcode 203】 移除链表元素

题目 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,5]示例 2: 输入&…

【class18】人工智能初步----语音识别(4)

【class17】 上节课,我们学习了: 语音端点检测的相关概念,并通过代码切分和保存了音频。 本节课,我们将学习这些知识点:1. 序列到序列模型2. 循环神经网络3. 调用短语音识别接口 知其然,知其所以然 在调用语…

香橙派 AIpro 昇腾 Ascend C++ 分类模型适配

香橙派 AIpro 昇腾 Ascend C 分类模型适配 flyfish 文章目录 香橙派 AIpro 昇腾 Ascend C 分类模型适配前言一、PyTorch官网resnet模型处理方式1、PyTorch模型 导出 onnx格式2、完整测试 输出top1结果3、完整测试 输出top5结果 二、YOLOv8官网resnet模型Python处理方式三、昇腾…

NSSCTF-Web题目3

目录 [BJDCTF 2020]easy_md5 1、知识点 2、题目 3、思路 [ZJCTF 2019]NiZhuanSiWei 1、知识点 2、题目 3、思路 第一层 第二层 第三层 [BJDCTF 2020]easy_md5 1、知识点 弱比较,强比较、数组绕过、MD5加密 2、题目 3、思路 1、首先我们跟着题目输入&a…

微信好友,如此的陌生,渐渐都成了只是人名!也许没有利益关系导致!

微信里一直聊天聊的挺好的朋友,不知怎么到后来却联系少了,最后渐渐的变成躺在微信备注里的一个陌生朋友! 以前通过工作认识了一个朋友,初次见面的印象不是很深刻了,只记得当时给我的印象是对方很有礼貌,特别…

快团团帮卖团长如何修改供货大团长复制帮卖团的信息?

一、功能说明 在复制帮卖团中,帮卖团长可以选择:①修改团购内容 ②同步大团长的团购内容 二、具体操作步骤 点击“编辑后帮卖”,在团购设置中设置开启/关闭“同步大团长内容” 开启“同步大团长内容”后,大团长修改图文后&#xf…

分享个自用的 Nginx 加强 WordPress 防护的规则

Nginx WordPress 的组合是目前非常普及的组合了,我们完全可以借助 Nginx 规则来加强 WordPress 的防护,提高 WordPress 的安全性,今天明月就给大家分享个自用的 Nginx 针对 WordPress 的防护规则,部分规则大家只需要根据自己的需要…

计算机图形学入门02:线性代数基础

1.向量(Vetors) 向量表示一个方向,还能表示长度(向量的摸)。一般使用单位向量表示方向。 向量加减:平行四边形法则、三角形法则。比卡尔坐标系描述向量,坐标直接相加。 1.1向量点乘(…

腾讯云联络中心ivr调用自定义接口

1&#xff0c;java代码&#xff1a;http接口 RequestMapping(value "/getMsg5", method RequestMethod.POST) public Map<String, String> index(RequestBody Map<String, String> params) {String id params.get("id");HashMap<String…

Java-Stream流-概述、创建、使用:遍历/匹配、筛选、聚合、映射、归约、排序、提取/组合

Java8-Stream&#xff1a; 一、Stream流概述1.Stream流的特点&#xff1a;2.使用步骤&#xff1a;3.常用方法示例&#xff1a; 二、Stream流创建1.常见的创建Stream的方法2. stream()或parallelStream()方法的使用和选择 三、Stream流使用Optional案例中使用的实体类1.遍历/匹配…

【哈希】闭散列的线性探测和开散列的哈希桶解决哈希冲突(C++两种方法模拟实现哈希表)(1)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; C进阶 &#x1f389;其它专栏&#xff1a; C初阶 | Linux | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 哈希函数与哈希 之 闭散列的线性探测解决哈希冲突 的相关内容。 如…

CAS原理技术

CAS原理技术 背景介绍结构体系术语接口原理基础模式1. 首次访问集成CAS Client的应用2. 再次访问集成CAS Client的同一应用3. 访问集成CAS Client的其他应用 代理模式1. 用户在代理服务器上执行身份认证2. 通过代理应用访问其他应用上授权性资源 背景 本文内容大多基于网上其他…

快速版-JS基础01书写位置

1.书写位置 2.标识符 3.变量 var&#xff1a;声明变量。 &#xff08;1&#xff09;.变量的重新赋值 &#xff08;2&#xff09;.变量的提升 打印结果&#xff1a;console.log(变量名) 第一个是你写在里面的。 第二个是实际运行的先后之分&#xff0c;变量名字在最前面。变量…

牛客NC392 参加会议的最大数目【中等 贪心+小顶堆 Java/Go/PHP 力扣1353】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/4d3151698e33454f98bce1284e553651 https://leetcode.cn/problems/maximum-number-of-events-that-can-be-attended/description/ 思路 贪心优先级队列Java代码 import java.util.*;public class Solution {/**…

《MySQL怎样运行的》—InnoDB数据页结构

在上一篇文章中我们讲了&#xff0c;InnoDB的数据页是InnoDB管理存储空间的基本单位&#xff0c;一个页的大小基本为16kb 那你有没有疑问&#xff0c;就是说这个InnoDB的数据页的结构是什么样的&#xff0c;还有他这些结构分别有那些功能~接下来我们一一讲解 数据页的总览结构…

GPT-4o和GPT-4有什么区别?我们还需要付费开通GPT-4?

GPT-4o 是 OpenAI 最新推出的大模型&#xff0c;有它的独特之处。那么GPT-4o 与 GPT-4 之间的主要区别具体有哪些呢&#xff1f;今天我们就来聊聊这个问题。 目前来看&#xff0c;主要是下面几个差异。 响应速度 GPT-4o 的一个显著优势是其处理速度。它能够更快地回应用户的查…

java中的Collections类+可变参数

一、概述 Collections类是集合类的工具类&#xff0c;与数组的工具类Arrays类似 二、可变参数(变&#xff1a;数量) 格式&#xff1a;参数类型名...参数&#xff0c;可变参数就是一个数组 注意&#xff1a;可变参数必须放在参数列表的最后并且一个参数列表只能有一个可变参…

Golang | Leetcode Golang题解之第101题对称二叉树

题目&#xff1a; 题解&#xff1a; func isSymmetric(root *TreeNode) bool {u, v : root, rootq : []*TreeNode{}q append(q, u)q append(q, v)for len(q) > 0 {u, v q[0], q[1]q q[2:]if u nil && v nil {continue}if u nil || v nil {return false}if …