OpenCV高端操作——直方图及直方图均衡化

一、直方图

简介:

是图像中像素强度分布的图形表达方式。

使用直方图对我们图像的像素点进行统计操作。像素点的区间0-255也就是直方图的横坐标,像素点的个数也就是直方图的纵坐标。

作用:例如视频中。通过标记帧和帧之间显著的边缘和颜色的统计变化,来检测视频中场景的变换。

python 复制代码
cv2.calcHist(images, channels, mask, histSize, ranges)

参数介绍:

images:

输入图像,必须用方括号包裹 (即使只有 1 张图)。示例:[img]

注意:图像需为 np.ndarray 类型,支持灰度图 / 彩色图

channels:

指定计算直方图的通道索引:

灰度图:只有 1 个通道,传 [0]

彩色图(BGR):蓝色 = 0、绿色 = 1、红色 = 2

mask:

掩码图像:

None:计算整张图的直方图

自定义掩码:仅计算掩码中值为 255 的区域的直方图

注意:掩码尺寸必须和输入图像完全一致,且为单通道 8 位图像

histSize:

直方图的 "分箱数"(bin 数量),即把像素值范围分成多少份

分箱数越多,直方图越精细;越少则越粗略

ranges:

像素值的取值范围: [0,256](注意是左闭右开,实际包含 0-255)

python 复制代码
import matplotlib.pyplot as plt
imporrt cv2

shan = cv2.imread('../data/shan.jpeg')
#将图像转换为一维数组
#这里使用了numpy的ravel 函数,将多维数组拉成一维数组。
a = shan.ravel()
#绘制直方图
plt.hist(a,bins=256) #使用matplotlib 的hist 函数绘制直方图。
#参数解释:
#- a:一维数组,即图像的像素值组成的数组。
#-bins=256:指定直方图的条数,即灰度级的数量。
plt.show()
#显示直方图
shan_hist = cv2.calcHist([shan],[0],None,[16],[0,256])
plt.plot(shan_hist)  #使用calcHist的值绘制曲线图
plt.show()

shan2 = cv2.imread('../data/shan.jpeg')
color = ('b','g','r')
for i,col in enumerate(color):
    hist = cv2.calcHist([shan2],[i],None,[256],[0,256])
    plt.plot(hist,color=col)
plt.show()

绘制这张图像所有像素值的整体直方图

python 复制代码
import matplotlib.pyplot as plt

shan = cv2.imread('../data/shan.jpeg')
#将图像转换为一维数组
#这里使用了numpy的ravel 函数,将多维数组拉成一维数组。
a = shan.ravel()
#绘制直方图
plt.hist(a,bins=256) #使用matplotlib 的hist 函数绘制直方图。

表示灰度图,将像素分为16个区间

python 复制代码
shan_hist = cv2.calcHist([shan],[0],None,[16],[0,256])
plt.plot(shan_hist)  #使用calcHist的值绘制曲线图
plt.show()

三个颜色通道所呈现的直方图统计

python 复制代码
shan2 = cv2.imread('../data/shan.jpeg')
color = ('b','g','r')
for i,col in enumerate(color):
    hist = cv2.calcHist([shan2],[i],None,[256],[0,256])
    plt.plot(hist,color=col)
plt.show()

掩膜的应用

1**.什么是掩膜**:掩膜是用选定的图像、图形或物体,对要处理的图像进行遮挡,来控制图像处理的区域,在数字图像处理中,通常使用二维矩阵进行掩膜,掩膜是由0和1组成的一个二进制图像,利用该掩膜对要处理的图像进行掩膜,其中值为1的区域被处理,0区域被屏蔽,不会处理

2.掩膜的作用:我们使用cv.calcHist()查找完整图像的直方图,当要查找图像某些区域的直方图,只需要在查找直方图的区域上创建一个白色的掩膜图像,否则创建黑色,将其作为掩码mask传递

为了对输入的图像的指定部分进行操作,需要通过mask来创建指定部分的全零数组, 再通过cv2.bitwise_and()来进行与操作从而实现获得指定区域的图像

python 复制代码
import cv2
import pandas as pd


shan = cv2.imread('../data/shan.jpeg')
cv2.imshow("shan",shan)
cv2.waitKey(0)
mask = np.zeros(shan.shape[:2],np.uint8)
mask[50:250,100:200] = 255
cv2.imshow("mask",mask)
cv2.waitKey(0)

'''
cv2.bitwise-and():对图像(灰度图像或彩色图像均可)每个像素值进行二进制"与"操作,1&1=1,1&0=0,0&1=0,0&0=0
bitwise_and(src1,src2,dst=None,mask=None)参数:
src1、src2:为输入图像或标量,标src1和src2相与。
dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同
mask:图像掩膜,可选参数,用于指定要更改的输出图像数组的元素,mask为0的值,srC1和Src2相与的值都为0.
        非O的值,为src1和src2相与的值。
'''
shan_mask = cv2.bitwise_and(shan,shan,mask=mask)
cv2.imshow("shan_mask",shan_mask)
cv2.waitKey(0)
'''-----------------------'''
mask_hist_mask = cv2.calcHist([shan],[0],mask,[256],[0,256])
plt.plot(mask_hist_mask)
plt.show()

二、直方图均衡化

简介:

如果一幅图像整体很亮,那所有的像素值的取值个数应该都会很高。需要将此图像的直方图做一个横向拉伸,就可以扩大图像像素值的分布范围,提高图像的对比度,这就是直方图均衡化(通过将图像的像素值分布均匀化来实现这一目标

python 复制代码
cv2.equalizeHist(image)

参数:

image:

输入图像:必须是8 位单通道灰度图(不能是彩色图、浮点图、16 位图)

输入必须是 uint8 类型(0-255),否则报错;不支持直接处理彩色图的单通道

输出结果:

输出图像和输入图像尺寸、数据类型完全一致(np.ndarray(8 位单通道数组))

python 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt



black = cv2.imread('../data/hei.jpg',cv2.IMREAD_GRAYSCALE)
plt.hist(black.ravel(),bins=256) #numpy中的ravel将数组多维度拉成一维数组
plt.show()

black_equalize = cv2.equalizeHist(black)
plt.hist(black_equalize.ravel(),bins=256)
plt.show()

res = np.hstack((black,black_equalize))  #hstack:横向拼接,将多个数组按水平方向(列顺序)堆叠成一个新的数组。 vstack:纵向拼接
cv2.imshow('black_equalize',res)
cv2.waitKey(0)

三、自适应的直方图均衡化

简介:

直方图均衡化中,考虑的是图像全局的对比度,许多情况下,会由于均衡化而丢失许多信息,为了解决此问题,需要使用自适应的直方图均衡化,此时,整幅图片被分成许多小块,称为tiles(在OpenCV中tiles的大小默认是8x8),然后再对每一个小块分别进行直方图均衡化。如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的bin超过对比度的上限的话,就把其中的像素点均匀分散到其他bins中,然后在进行直方图均衡化。最后使用双线性差值,对每一小块进行拼接。

python 复制代码
cv2.createCLAHE(clipLimit, tileGridSize)

参数介绍:

clipLimit:对比度限制阈值(默认值40.0)(float型)

作用:限制每个小区域(tile)的直方图超出该阈值的部分,避免过度增强噪声;

值越小,对比度增强越温和(噪声越少);值越大,增强越明显(但易放大噪声)

tileGridSize:图像分块尺寸(将图像划分为多少个小区域)(默认值为(8,8))(tuple型)

作用:将整幅图像分成 tileGridSize[0]×tileGridSize[1] 个独立小块,分别做均衡化;

分块越多,细节增强越细腻,但计算量稍大;分块过少会丢失局部特征,效果接近普通均衡化

使用逻辑 :先创建 CLAHE 处理器,再调用 apply() 处理图像(输入输出均为 8 位单通道灰度图)

python 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt



clahe = cv2.createCLAHE(clipLimit=12,tileGridSize=(10,10))
black_clahe = clahe.apply(black)
res = np.hstack((black,black_equalize,black_clahe))
cv2.imshow(  'black_equalize',res)
cv2.waitKey(0)
相关推荐
玦尘、2 小时前
光伏发电短期功率预测——从数据到模型的完整技术实践(LSTM · TCN · CNN-LSTM · TCN-LSTM)
人工智能·cnn·lstm·tcn
java1234_小锋2 小时前
基于LangChain的RAG与Agent智能体开发 - 使用LangChain调用大语言模型
人工智能·语言模型·langchain·rag
人工智能AI技术2 小时前
GTC直击|C#对接NVIDIA物理AI,工业仿真一键落地实战教程
人工智能·c#
计算机科研狗@OUC2 小时前
(tip26) Interactive Spatial-Frequency Fusion Mamba for Multi-Modal Image Fusion
人工智能·深度学习
水如烟2 小时前
孤能子视角:“意识是基础物理学和量子物理学背后隐藏的架构“观点对照
人工智能
Just Jump2 小时前
构建一个高拟真的AI对话系统实战经验总结
人工智能·高拟真ai对话
Westward-sun.2 小时前
OpenCV 图像直方图详解:从基础计算到自适应均衡化
人工智能·opencv·计算机视觉
V搜xhliang02462 小时前
具身机器人在实际场景中的安全保障
人工智能·安全·计算机视觉·分类·机器人·知识图谱
Web3_Daisy2 小时前
Flap怎么玩?低门槛 Meme 币的发射与链上策略
大数据·人工智能·web3·区块链·比特币