OpenCV 图像处理五(直方图处理)

直方图是一种统计图,显示了图像中每个灰度级别(或颜色通道)的像素数量。通过分析图像的直方图,可以获得关于图像对比度、亮度和颜色分布等方面的重要信息。

一、直方图的意义

横坐标是图像中各像素点的灰度级,
纵坐标是具有该灰度级(像素值)的像素个数。

了解图像的对比度、亮度和色彩分布等信息。你可以使用OpenCV中的函数来计算和绘制图像的直方图,从而进行图像增强、颜色校正和特征提取等操作。

RANGE:强度值。表示要统计的灰度级范围,一般为[0, 255]。0 对应的是黑色,255 对应的是白色。
BINS:参数子集的数目。在处理数据的过程中,有时需要将众多的数据划分为若干个组,再进行分析。
DIMS:表示在绘制直方图时,收集的参数的数量。一般情况下,直方图中收集的数据
只有一种,就是灰度级。因此,该值为 1。

在这里插入图片描述

二、绘制直方图

2.1 直接使用Matplotlib.pyplot.hist()

import matplotlib.pyplot as plt
plt.hist(X,BINS)

 X:数据源,必须是一维的。图像通常是二维的,需要使用 ravel()函数将图像处理为一
维数据源以后,再作为参数使用。

 BINS:BINS 的具体值,表示灰度级的分组情况。

使用函数 ravel()对 a 进行降维处理:b = a.ravel()

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('img/resizeImgx.jpg')
color = ('b','g','r')
for i,col in enumerate(color):
    histr = cv.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

在这里插入图片描述
在这里插入图片描述

2.2 OpenCV的方法 cv2.calcHist()函数统计图像直方图

我们就接下来使用的是灰度图的直方图,用其标记图像中每个明亮值的个数。
cv.calcHist(img,chamels,mask,histSize,ranges[,hist[,accmulate]])

images:原图像。当传入函数时应该用中括号[]括起来,如:[img]。
.
channels:如果输入图像是灰度图,它的值就是 [0];如果是彩色图像的话,传入的参数可以是 [0],[1],[2] 它们分别对应着通道 B, G, R.
.
mask: 掩模图像。要统计整幅图像的直方图就把它设为 None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。(后边有例子)
.
histSize:BIN 的数目。也应该用中括号括起来,例如:[256]。
.
ranges: 像素值范围,通常为 [0,256]
.
accumulate: 可选参数,用于累积直方图。如果设置为 True,则直方图在每次调用函数时都会被累积

(1)随机数的形式模拟

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

x = np.random.randint(0, 256, (105, 105), dtype=np.uint8)
x=cv.imread("img1/test_img.jpg",0)
print("x")
x

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f1af229624e748058d476a80920e8075.png

plt.imshow(x, cmap="gray")

在这里插入图片描述

print("直方图")
y = x.ravel()
# 注意一定要是灰度的才是灰度的显示出来明亮关系的直方图
plt.hist(y, bins=256, range=(0, 256))

y = cv.calcHist([x], [0], None, [256], [0, 256])
plt.figure(figsize=(10, 8))
plt.plot(y)
plt.show()

在这里插入图片描述

(2)彩色图片

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

x=cv.imread("img1/test_img.jpg")
color = ('b','g','r')
for i,col in enumerate(color):
    histr = cv.calcHist([x],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

在这里插入图片描述

在这里插入图片描述

(3)灰度图像

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

x=cv.imread("img1/test_img.jpg",0)
# print("直方图")
y = x.ravel()
# 注意一定要是灰度的才是灰度的显示出来明亮关系的直方图
plt.hist(y, bins=256, range=(0, 256))

y = cv.calcHist([x], [0], None, [256], [0, 256])
plt.figure(figsize=(5, 4))
plt.plot(y)
plt.show()

在这里插入图片描述
在这里插入图片描述

2.3 对比显示直方图的方法

2.3.1 柱状图和折线图

plt.hist函数是用来创建柱状图的,它将数据按照指定的bins和range进行分组,并以柱状图的形式展示各个分组的频数。

plt.plot函数则是用来创建折线图的,它将给定的数据点连接起来,形成一条折线。

2.3.2 两种不同库的函数

cv.calcHistplt.hist 都与图像处理和直方图相关,但它们是不同的库中的不同函数。

  1. cv.calcHist:

    • : OpenCV (cv2)
    • 用途: 用于计算图像的直方图。
    • 语法:
      hist = cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
      
    • 参数:
      • images: 输入图像列表。
      • channels: 通道的索引。例如,对于灰度图像,通常为 [0];对于彩色图像,可以是 [0, 1, 2] 分别表示蓝色、绿色和红色通道。
      • mask: 掩码图像。如果没有,则可以传递 None
      • histSize: 直方图的 bin 数量。
      • ranges: 像素值的范围,通常为 [0, 256]。
  2. plt.hist:

    • : Matplotlib (plt)
    • 用途: 用于绘制直方图。
    • 语法:
      n, bins, patches = plt.hist(x, bins=None, range=None, density=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, normed=None, *, data=None, **kwargs)
      
    • 参数:
      • x: 数据集。
      • bins: 直方图的 bin 数量。
      •  hist(数据源【一维x.ravel()】,像素级【一般256】)
        
      • range: 数据值的范围。
      • 其他参数用于调整直方图的外观,如颜色、标签等。

所以,cv.calcHist 用于计算图像的直方图,而 plt.hist 用于绘制直方图。通常,你可以使用 cv.calcHist 计算直方图,然后使用 plt.hist 绘制计算得到的直方图。

cv2.calcHist函数用于计算图像的直方图,它接受图像、通道索引、蒙版、直方图的大小和像素值范围作为参数,并返回计算得到的直方图。
而plt.hist函数是用于绘制直方图的函数,它接受图像数据、直方图的箱数(bin数)、像素值范围等参数,并直接在图像上绘制直方图。

2.4 使用掩模绘制直方图

掩膜是用选定的图像、图形或物体,对要处理的图像进行遮挡,来控制图像 处理的区域。

OpenCV中,掩膜(Mask)通常用于指定要处理的图像的特定区域。掩膜是一个与图像大小相同的二进制图像,其中像素值为1表示要处理的区域,而像素值为0表示要忽略的区域。

掩膜的主要用途是:提取感兴趣区域:用预先制作的感兴趣区掩模与待处理图像进行”与“操作,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0.
屏蔽作用:用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
结构特征提取:用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
然后将我们需要的地物或者标志突出显示出来

掩模处理
构造掩模图像
使用掩模绘制直方图

在这里插入图片描述

自身与运算,再掩膜与运算
maskedImage=cv.bitwise_and(imgOriginal,imgOriginal,mask=mask)

可以直接
在这里插入图片描述

在这里插入图片描述

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

imgOriginal=cv.imread("Pic/cc.jpg")
# 创建蒙版
mask=np.zeros(imgOriginal.shape[:2],dtype=np.uint8)
mask[400:600,600:800]=255

plt.imshow(mask,cmap=plt.cm.gray)
print("mask")
print(mask)
plt.colorbar()

在这里插入图片描述

# 创建蒙版图像
maskedImage=cv.bitwise_and(imgOriginal,imgOriginal,mask=mask)
print("maskedImage")
plt.imshow(maskedImage,cmap=plt.cm.gray)
plt.colorbar()

在这里插入图片描述

# 统计掩膜后的灰度
mask_histr=cv.calcHist([imgOriginal],[0],mask,[256],[0,256])

# 展示
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8),dpi=100)
axes[0,0].imshow(imgOriginal,cmap=plt.cm.gray)
axes[0,0].set_title("Original")
axes[0,1].imshow(mask,cmap=plt.cm.gray)
axes[0,1].set_title("Mask")
axes[1,0].imshow(maskedImage,cmap=plt.cm.gray)
axes[1,0].set_title("Masked Image")
axes[1,1].plot(mask_histr)
axes[1,1].set_title("Histogram")

plt.show()

在这里插入图片描述

2.5 直方图均衡化

“直方图均衡化”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。
在这里插入图片描述
直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。
这种方法提高图像整体的对比度,特别是有用数据的像素值分布比较接近时。

在X光图像中使用广泛,可以提高骨架结构的显示,
另外在曝光过度或不足的图像中可以更好的突出细节。

2.5.1 实现直方图均衡化过程

转化与合并–就是转化为下一级别的了

累计直方图的概率像素级。
然后得到的每一个旧像素级根据自身的累计直方图的概率
像素级。成为新的像素级
在这里插入图片描述

GPT给的过程
在这里插入图片描述

2.5.2 函数cv2.equalizeHist()实现直方图均衡化。

函数

dst = cv2.equalizeHist( src )

实现

# 提高图像对比度
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

img1 = cv.imread("img1/test_img.jpg", 0)

# 均衡化
dst = cv.equalizeHist(img1)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8), dpi=100)
axes[0, 0].imshow(img1, cmap=plt.cm.gray)
axes[0, 0].set_title("Original")
axes[0, 1].hist(img1.ravel(), 256, [0, 256])
axes[1, 0].imshow(dst, cmap=plt.cm.gray)
axes[1, 0].set_title("Histogram Equalization")
axes[1, 1].hist(dst.ravel(), 256, [0, 256])
axes[1, 1].set_title("Histogram")
plt.show()

在这里插入图片描述

2.6 自适应均衡化

图像中存在过于暗的区域或者亮度变化明显的区域,使用全局直方图均衡化就可能造成细节的丢失。

如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。
对于每个小块来说,如果直方图中的bin超过对比度的上限的话,就把其中的像素点均匀分散到其他bins中,然后在进行直方图均衡化。

 cv2.createCLAHE(clipLimit, tileGridSize)
  1. clipLimit:对比度限制的阈值。
  2. tileGridSize:用于直方图均衡化的网格大小。
  • clipLimit: 控制对比度的限制,它决定了对比度增强的程度。较大的值会导致更强烈的对比度增强。
  • tileGridSize: 定义了图像被分割成的小块的大小。这些小块将分别进行直方图均衡化,以避免在整个图像上过度增强对比度。更大的块大小意味着更大范围内的对比度增强。
    防止均衡化过大,对比度限制,分散到其他像素点上
# 自适应均衡化
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

img1 = cv.imread("img1/test_img.jpg", 0)

# 均衡化
clahe = cv.createCLAHE(clipLimit=1.0, tileGridSize=(8, 8))
dst = clahe.apply(img1)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(15, 12), dpi=100)
axes[0, 0].imshow(img1, cmap=plt.cm.gray)
axes[0, 0].set_title("Original")
axes[0, 1].hist(img1.ravel(), 256, [0, 256])
axes[1, 0].imshow(dst, cmap=plt.cm.gray)
axes[1, 0].set_title("Histogram Equalization")
axes[1, 1].hist(dst.ravel(), 256, [0, 256])
axes[1, 1].set_title("Histogram")
plt.show()

在这里插入图片描述
cv2.createCLAHE函数用于创建对比度受限自适应直方图均衡化器,它可以限制每个像素的对比度增强,以避免过度增强噪声。
cv2.equalizeHist函数用于应用全局直方图均衡化,它会平衡整个图像的直方图,增强图像的对比度。
因此,cv.createCLAHE可以更好地处理局部对比度不均匀的图像,而cv2.equalizeHist适用于全局对比度增强。

  • 53
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
灰度直方图是一种常用的图像处理方法,可以用于图像增强、图像分割、图像匹配等方面。在OpenCV中,可以使用cv::calcHist函数计算图像的灰度直方图。具体操作如下: 1. 将图像转换为灰度图像,使用cv::cvtColor函数。 2. 定义直方图参数,如灰度级数目、直方图范围等。 3. 使用cv::calcHist函数计算图像的灰度直方图。 4. 可以使用cv::normalize函数将直方图归一化。 5. 可以使用cv::plot函数将直方图绘制出来。 下面是一个示例代码,计算并绘制图像的灰度直方图: ```cpp #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main() { // 读取图像 Mat image = imread("lena.jpg"); // 转换为灰度图像 Mat gray_image; cvtColor(image, gray_image, COLOR_BGR2GRAY); // 定义直方图参数 int histSize = 256; // 灰度级数目 float range[] = { 0, 256 }; const float* histRange = { range }; // 计算直方图 Mat hist; calcHist(&gray_image, 1, 0, Mat(), hist, 1, &histSize, &histRange, true, false); // 归一化直方图 normalize(hist, hist, 0, 1, NORM_MINMAX, -1, Mat()); // 绘制直方图 int hist_w = 512, hist_h = 400; int bin_w = cvRound((double)hist_w / histSize); Mat hist_image(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0)); for (int i = 1; i < histSize; i++) { line(hist_image, Point((i - 1) * bin_w, hist_h - cvRound(hist.at<float>(i - 1) * hist_h)), Point(i * bin_w, hist_h - cvRound(hist.at<float>(i) * hist_h)), Scalar(255, 0, 0), 2, LINE_AA); } // 显示图像和直方图 imshow("Image", image); imshow("Gray Image", gray_image); imshow("Histogram", hist_image); waitKey(); return 0; } ``` 在这个示例代码中,首先读取图像并转换为灰度图像,然后计算直方图并归一化,最后绘制出直方图并显示出来。你可以根据自己的需求修改参数和代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

你会魔法吗✧(≖ ◡ ≖✿)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值