图像直方图计算

1. 图像直方图(Image histogram)

图像直方图,又叫影像直方图,是一种用来表现数位影像中像素分布的直方图,根据统计影像中不同亮度的像素总数,我们可以画出一张代表这张影像的影像直方图,透过这张直方图我们可以一眼就看出这张图中像素的分布情形。

图像直方图由于其计算代价较小,且具有图像平移、旋转、缩放不变性等众多优点,广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类。

2 图像直方图的计算

直方图计算,即计算图像中每个像素值的出现次数,然后根据像素值范围,将像素值分成一定数量的区间,然后计算每个区间内的像素值出现次数,最后将这些出现次数绘制在一张直方图上。

2.1 彩色图像的直方图

使用 OpenCV-Python 的 calcHist 以及 matplotlib 库,我们可以这样计算并绘制一个彩色图像的直方图。

import cv2
import matplotlib.pyplot as plt

# 读取图像
img = cv2.imread('../data/park.jpg')

# 分离BGR颜色通道
b, g, r = cv2.split(img)

# 设置直方图大小
hist_size = 256

# 设置直方图范围,左闭右开区间,最大值为255
hist_range = [0, 256]

# 计算直方图
b_hist = cv2.calcHist([b], [0], None, [hist_size], hist_range)
g_hist = cv2.calcHist([g], [0], None, [hist_size], hist_range)  
r_hist = cv2.calcHist([r], [0], None, [hist_size], hist_range)

# 绘制直方图
fig, ax = plt.subplots(1, 1)    # 创建一个子图及布局,BGR三个通道都绘制到一个图上
ax.plot(b_hist, color='b', label='B')
ax.plot(g_hist, color='g', label='G')
ax.plot(r_hist, color='r', label='R')
ax.set_xlim(hist_range)   # 设置x轴范围
ax.legend() # 显示图例  
plt.show()  # 显示图像

直方图曲线

以条形图方式表达直方图:

import cv2
import matplotlib.pyplot as plt

# 读取图像
image_path = '../data/park.jpg'
image = cv2.imread(image_path)  # 读取彩色图像

# 计算直方图
b_hist = cv2.calcHist([image], [0], None, [256], [0, 256])
g_hist = cv2.calcHist([image], [1], None, [256], [0, 256])
r_hist = cv2.calcHist([image], [2], None, [256], [0, 256])

# 绘制直方图
plt.figure(figsize=(10, 6))

# 使用bar函数绘制直方图
plt.bar(range(256), b_hist.ravel(), color='blue', alpha=0.7)
plt.bar(range(256), g_hist.ravel(), color='green', alpha=0.7)
plt.bar(range(256), r_hist.ravel(), color='red', alpha=0.7)

# 设置标题和轴标签
plt.title('Histogram of the Image')
plt.xlabel('Intensity Value')
plt.ylabel('Frequency')

# 显示网格
plt.grid(axis='y', linestyle='--', alpha=0.7)

# 显示图表
plt.show()

BGR直方图

2.2 灰度图像直方图

灰度图像的直方图计算与彩色图像的直方图计算类似,可以读入灰度图进行计算。但是对于一个彩色图像,我们既可以通过 cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 直接读入灰度图,也可以通过 cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 将彩色图转化为灰度图。通过比较,这两个方法得到的灰度图可能非常相似(本例相似度为0.9996933300209153),但事实上并不一致。

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

# 读取图像
image_path = '../data/park.jpg'
image = cv2.imread(image_path) 
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
read_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

# 计算直方图
b_hist = cv2.calcHist([image], [0], None, [256], [0, 256])
g_hist = cv2.calcHist([image], [1], None, [256], [0, 256])
r_hist = cv2.calcHist([image], [2], None, [256], [0, 256])

cvt_gray_hist = cv2.calcHist([image_gray], [0], None, [256], [0, 256])
read_gray_hist = cv2.calcHist([read_gray], [0], None, [256], [0, 256])

# 绘制直方图
fig, axes = plt.subplots(3, 2, figsize=(15, 15))

# 显示图像
axes[0, 0].imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
axes[1, 0].imshow(image_gray, cmap='gray')
axes[2, 0].imshow(read_gray, cmap='gray')

# 使用bar函数绘制直方图
axes[0, 1].bar(range(256), b_hist.ravel(), color='blue', alpha=0.7)
axes[0, 1].bar(range(256), g_hist.ravel(), color='green', alpha=0.7)
axes[0, 1].bar(range(256), r_hist.ravel(), color='red', alpha=0.7)

axes[1, 1].bar(range(256), cvt_gray_hist.ravel(), color='gray')

axes[2, 1].bar(range(256), read_gray_hist.ravel(), color='gray')

# 显示网格
axes[0, 1].grid(axis='y', linestyle='--', alpha=0.7)
axes[1, 1].grid(axis='y', linestyle='--', alpha=0.7)
axes[2, 1].grid(axis='y', linestyle='--', alpha=0.7)

# 设置图表标题和坐标轴标签
axes[0, 0].set_title('Original Image')
axes[1, 0].set_title('Gray Image')
axes[2, 0].set_title('Read Gray Image')
axes[0, 1].set_title('BGR Histogram')
axes[1, 1].set_title('Converted Gray Histogram')
axes[2, 1].set_title('Read Gray Histogram')

# 显示图表
plt.show()

similarity = cv2.compareHist(cvt_gray_hist, read_gray_hist, cv2.HISTCMP_CORREL)
print(f"The similarity between the two images is:{similarity} ")

diff = cv2.absdiff(image_gray, read_gray)
plt.plot(diff)
plt.show()
total_nonzero = np.count_nonzero(diff)
print("Total non-zero elements:", total_nonzero)

图像比较

The similarity between the two images is:0.9996933300209153 

两种灰度图差异情况

Total non-zero elements: 16351

因此,直接通过 cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 读入的灰度图和 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 转换的灰度图,是不一样的,在开发时需要注意这个问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Humbunklung

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值