• 计算机视觉:基于Numpy的图像处理技术(一):灰度变换、直方图均衡化


    计算机视觉:基于Numpy的图像处理技术(一)灰度变换、直方图均衡化(一)🏳️‍🌈

    ​ 在这里我将以分辨率为590*326的图片hua.jpg来作为演示图片,如下图,是一个拿着战矛的机甲风人物。为了方便下面我将其称为“小花”

    hua

    一、Numpy操作图像数组📐

    ​ 将图像读入Numpy的数组对象后,可以对其进行数学操作。

    ​ 首先导入必备的numpy和cv2

    import numpy as np
    import cv2
    #读取图片
    pic = cv2.imread('hua.jpg')
    #使用numpy中的array方法将图片以数组形式读取
    arr = np.array(data)
    #读取图片的shape值(为一个元组)
    pic_shape = arr.shape
    print(arr)
    print(pic_shape)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ​ 运行后可以看到图片小花的矩阵和它的形状(326, 590, 3),shape为一个数组

    其中326为图像的宽度,590为图像的长度,3代表这个图像有三个通道RGB

    二、灰度变换👻

    from PIL import Image
    import numpy as np
    pic_arrL = np.array(Image.open('hua.jpg').convert('L'))
    print(pic_arrL)
    
    • 1
    • 2
    • 3
    • 4

    convert('L') 为灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。

    原型
    [[[41 23 46]
      [41 23 46]
      [41 23 46]
      ...
      [37 10 30]
      [37 10 30]
      [37 10 30]]
    
     [[40 22 45]
      [40 22 45]
      [40 22 45]
      ...
    灰度处理后
    [[32 32 32 ... 19 19 19]
     [31 31 31 ... 19 19 19]
     [31 31 31 ... 19 19 19]
     ...
     [18 18 18 ... 11 11 11]
     [18 18 18 ... 11 11 11]
     [18 18 19 ... 11 11 11]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    ​ 设任意函数f,它将0~255映射到自身(输出区间和输入区间相同)那么对载入的图像实现不同级别的灰度变换则可以通过设定函数f来进行实现

    from PIL import Image
    import numpy as np
    from pylab import *
    
    # 灰度图像
    # f(x) = 255 - x
    pic_arrL = np.array(Image.open('hua.jpg').convert('L'))
    # 输出最大最小值以确定图像像素范围
    print('对图像进行反向处理:\n', int(pic_arrL.min()),int(pic_arrL.max()))
    
    # f(x) = (100/255)x + 100
    im1 = (100.0/255) *pic_arrL +100 # 将图像想阻止控制在100~200
    print('将图像像素值变换到100...200区间:\n', int(im1.min()),int(im1.max()))
    
    # f(x) = 255*(x/255)^2
    im2 = 255.0 * (pic_arrL/255.0) ** 2 # 对像素值求平方后得到的图像
    print('对像素值求平方后得到的图像:\n', int(im2.min()),int(im2.max()))
    
    # 图像展示
    # pic_arrL
    figure()
    gray()
    subplot(131)
    imshow(pic_arrL)
    axis('off')
    title(r'$f(x) = 255 - x$')
    # im1
    subplot(132)
    imshow(im1)
    axis('off')
    title(r'$f(x) = \frac{100}{255}x + 100 $')
    # im2
    subplot(133)
    imshow(im2)
    axis('off')
    title(r'$f(x) = 255(\frac{x}{255})^2 $')
    show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    ​ 定义完公式后对图像进行运算,最终通过 pylab 库的方法将图像展示,其中title利用latex语法进行公式的呈现。如下图,将小花不同程度的灰度图展现了出来。

    image-20221119125943976

    三、直方图均衡化🔗

    1、概念

    ​ 指将一副图像的灰度直方图变平,使得变换后的图像中每个灰度值的分布概率都相同。

    ​ 作用:将灰度值归一化;可以增强图像的对比度。

    2、导包

    ​ 首先需要导入的工具包有

    • PIL🚀
    • pylab🚀
    • PCV🚀
    • matplotlib🚀

    ​ 其中PCV导入时若遇到导入后不能使用的问题,则需进入其github官网进行下载 https://github.com/jesolem/PCV ,如github速度很慢可以使用csdn的gitcode镜像进入。

    注意:不使用PCV来进行图像直方图均衡化请往下看

    mirrors / jesolem / pcv · GitCode

    image-20221119133427891

    在PCV目录下打开终端输入命令:python setup.py install

    结果会发现报错,原因在于有很多文件中有着python2版本中的print,需将其改为python3的格式(加一对小括号)

    image-20221119134841293

    如图如果在pycharm中运行可以直接点进文件链接进行跳转,并修改。例如此条:

    image-20221119133614170

    改为如下

    print (imname + "...skipped" )
    
    • 1

    3、图像直方图均衡化(非numpy方法)

    ​ 但是由于PCV这个包已经八九年没有更新了,对于python3来说属实不太友好,这里采用自己定义好的直方图均衡化的函数

    from PIL import Image
    from pylab import *
    # 添加中文字体支持
    plt.rcParams['font.sans-serif'] = ['SimHei']
    hua = array(Image.open('hua.jpg').convert('L'))
    
    
    def histeq(im,nbr_bins=256):
        """对一副灰度图像进行直方图均衡化"""
        imhist,bins = histogram(im.flatten(),nbr_bins,normed = True)
        # 累计分布函数
        cdf = imhist.cumsum()
        # 归一化(概率分布)
        cdf = 255*cdf/cdf[-1]
        # 线性插值
        im2 =interp(im.flatten(),bins[:-1],cdf)
        return im2.reshape(im.shape),cdf
    
    
    im2,cdf = histeq(hua,256)
    figure()
    subplot(2,2,1)
    axis('off')
    gray()
    title(u'原始图像')
    imshow(hua)
    
    subplot(2,2,2)
    axis('off')
    gray()
    title(u'直方图均衡化后图像')
    imshow(im2)
    
    subplot(2,2,3)
    axis('off')
    title(u'原始直方图')
    hist(hua.flatten(),128,density=True)
    
    subplot(2,2,4)
    axis('off')
    title(u'均衡化后的直方图')
    hist(im2.flatten(),128,density=True)
    show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    ​ 运行程序效果如下,小花的原始的图像直方图为“左高右低”。均衡化处理过后小花的图像直方图的分布变得平均了

    image-20221119184341783

    4、图像直方图均衡化(numpy方法)

    import cv2 as cv
    import numpy as np
    
    # 图像显示
    def picShow(pic_title, pic_data):
        cv.imshow(pic_title, pic_data)
        cv.waitKey(0)
        cv.destroyAllWindows()
    
    
    def pixGray(img):  # 直方图统计
        h = img.shape[0]
        w = img.shape[1]
    
        gray_level = np.zeros(256)
        gray_level2 = np.zeros(256)
    
        for i in range(1, h - 1):
            for j in range(1, w - 1):
                gray_level[img[i, j]] += 1  # 统计灰度级为img_gray[i,j]的个数
    
        for i in range(1, 256):
            gray_level2[i] = gray_level2[i - 1] + gray_level[i]  # 统计灰度级小于img_gray[i,j]的个数
        return gray_level2
    
    
    def imgEqualize(img):  # 直方图均衡化
        h, w = img.shape
        gray_level2 = pixGray(img)
        lut = np.zeros(256)
        for i in range(256):
            lut[i] = 255.0 / (h * w) * gray_level2[i]  # 得到新的灰度级
        lut = np.uint8(lut + 0.5)
        out = cv.LUT(img, lut)
        print('图像直方图均衡化 处理完毕')
        return out
    
    
    if __name__ == "__main__":
        pic = cv.imread('hua.jpg', 0)
        title = 'mulan'
        picture = np.hstack((pic, imgEqualize(pic)))
        picShow(title, picture)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    运行结果如图:

    image-20221119192350960

  • 相关阅读:
    React 自定义hooks最佳实践
    自动化测试框架实战详解
    服务器硬件基础知识:从零开始了解你的数字工作马
    nginx配置kibana访问用户名和密码认证、及无认证访问配置
    数据库系统概论-第3章关系数据库标准语言SQL①
    (附源码)基于微服务架构的餐饮系统的设计与实现-计算机毕设 86393
    蓝牙资讯|苹果iOS 18增加对AirPods Pro 2自适应音频的更多控制
    全方位详解Java:技术体系与实战项目
    【Prism系列】Region的用法
    【自制小工具】快速批量查询IP归属地(自动去重、按国内外汇总,并智能识别出错误IP)
  • 原文地址:https://blog.csdn.net/tianhai12/article/details/127941909