【计算机视觉】图像基本操作 图像直方图 直方图均衡化 图像滤波 plt绘制图表

【更新2023/12/7】博客涉及代码部分已开源在github,需要自取,您的star⭐就是对我最大的支持💖:https://github.com/Scienthusiasts/cv-exp/tree/main/exp1

1.什么是直方图

直方图是可以对整幅图的灰度分布进行整体了解的图示,通过直方图我们可以对图像的对比度、亮度和灰度分布等有一个直观了解。图像的直方图用来形象描绘该图像像素值的分布情况。我们用一定数目的小区间(bin)来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目。因此直方图不能显示图像中某像素所在的空间位置信息。同时也需要注意一点,不同的图像可能会有相同的直方图,所以不能用单独的直方图去恢复图像.

绘制灰度图像直方图

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import cv2

import sys;sys.path.append('../')
import utils

img = cv2.imread('luda04.jpg')[:,:, [0]]
# 图像reshape
img, h, w = utils.auto_reshape(img, 480)
# 计算直方图
img_eqhist = utils.histogram(img)
# 绘制直方图
utils.plot_hist(img, img_eqhist)

请添加图片描述

绘制彩色图像直方图

img = cv2.imread('luda04.jpg')[:,:, [2,1,0]]
# 图像reshape
img, h, w = utils.auto_reshape(img, 480)
# 计算直方图
img_eqhist = utils.histogram(img)
# 绘制直方图
utils.plot_hist(img, img_eqhist)

请添加图片描述

直方图均衡化

直方图均衡化可以用来改善图像的全局亮度和对比度。

直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。在对图像做进一步处理之前,直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。

均衡化前后效果对比
在这里插入图片描述
均衡化图像直方图:
请添加图片描述

2.高斯滤波

高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。 可以简单的理解为,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。

高斯滤波和高斯模糊:

高斯滤波也叫做高斯平滑和高斯滤波。为什么叫做高斯滤波呢?那是因为对图像进行滤波操作。那为什么要加上高斯呢,那是因为卷积核(掩膜)是由高斯分布计算出来的所以就需要加上高斯两字。其实滤波范围比模糊要大,滤波还有高通滤波、低通滤波等。为什么叫做高斯模糊呢,是因为通过这个操作可以让图片变得模糊。那为什么又叫高斯平滑呢,那是因为使图像更加平滑了(平滑是图片变得更加平缓,更加模糊,不那么尖锐)。

高斯滤波的基本原理参考我之前写的一篇博客【OpenCV学习2】图像滤波

3.utils.py自定义函数库:

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


# 图像reshape
def auto_reshape(img, lim):
    h, w = img.shape[:-1]
    if h > w:
        w =  int(lim * w / h) 
        h = lim
    else:
        h = int(lim * h / w)
        w = lim 
    img = cv2.resize(img, dsize=(w, h))
    return img, h, w


# 图像直方图
def histogram(img):
    channels = img.size // (img.shape[0] * img.shape[1])
    if(channels == 3):
        hist = np.zeros((3, 256))
        for i in range(3):
            for pix in img[:,:,i].reshape(-1):
                hist[i, pix] += 1
    else:
        hist = np.zeros(256)
        for pix in img.reshape(-1):
            hist[pix] += 1

    hist /= img.shape[0] * img.shape[1]
    return hist


# 可视化图像直方图
def plot_hist(img, hist):
    channels = img.size // (img.shape[0] * img.shape[1])

    plt.figure(figsize=(19, 4))
    plt.subplot(1,2 + channels,1)
    plt.imshow(img)
    plt.title('image')
    plt.axis('off')

    if channels == 3:
        c = ["red", "green", "blue"]
        plt.subplot(1,5,2)
        for i in range(3):
            plt.plot(hist[i], color=c[i], linewidth=1)
        plt.ylim(0)

        plt.grid(linestyle='-.')
        plt.legend(c)
        
        for i in range(channels):
            plt.subplot(1,5,i+3)
            plt.bar(range(256), hist[i], color=c[i])
            plt.subplots_adjust(left=0.05,bottom=0.1,right=0.98,top=0.95,wspace=0.4,hspace=0.07)
            plt.legend(c[i])
            plt.grid(linestyle='-.')
    else:
        plt.subplot(1,3,2)
        print(hist.shape)
        plt.plot(hist, color='black', linewidth=1)
        plt.ylim(0)

        plt.grid(linestyle='-.')
        plt.legend(["gray"])
        
        plt.subplot(1,3,3)
        plt.bar(range(256), hist, color='black')
        plt.subplots_adjust(left=0.05,bottom=0.1,right=0.98,top=0.95,wspace=0.4,hspace=0.07)
        plt.savefig('./histogram.jpg',dpi=200)
        plt.legend(["gray"])
        plt.grid(linestyle='-.')
    plt.savefig('./histogram.jpg',dpi=200)
    plt.show()



# 直方图均衡化
def histEqualize(img):
    channels = img.size // (img.shape[0] * img.shape[1])
    if channels == 3:
        b, g, r = [cv2.equalizeHist(img[:,:,i]) for i in range(3)]
        return cv2.merge((b, g, r))
    else:
        return cv2.equalizeHist(img)

# 可视化对比结果
def view_contrast(imgseries):
    length = len(imgseries)
    imgs = list(imgseries.values())
    labels = list(imgseries.keys())
    for i in range(length):
        plt.subplot(1, length, i+1)
        plt.imshow(imgs[i])
        plt.title(labels[i])
        plt.axis('off')
    plt.subplots_adjust(left=0.02,bottom=0.01,right=0.98,top=0.99,wspace=0.2,hspace=0.02)
    plt.show()

4.参考资料

https://blog.csdn.net/theworld666/article/details/123538401

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值