数字图像的基本运算

作者: 水之心 | 来源:发表于2018-12-22 23:55 被阅读7次

    直方图

    直方图简单来说就是图像中每个像素值的个数统计,比如说一副灰度图中像素值为 0 的有多少个,1 的多少个……。直方图是一种分析图片的手段。

    Numpy 中直方图计算

    其中 ravel() 函数将二维矩阵展平变成一维数组:

    from matplotlib import pyplot as plt
    import cv2
    import numpy as np
    
    
    def getI(fname, show=False):
        img = plt.imread(fname)
        if show:
            plt.imshow(img)
            plt.show()
        return img
    
    
    fname = r'E:\Data\URLimg\猫\波斯猫\16.jpg'
    
    img = getI(fname, show=True)
    
    <Figure size 640x480 with 1 Axes>
    
    %%time
    hist, bins = np.histogram(img[:,:,0].ravel(), 256, [0, 256])  # 性能:26.5 ms
    
    Wall time: 28.5 ms
    
    %%time
    hist = np.bincount(img[:,:,0].ravel(), minlength=256)  # 性能:13 ms
    
    Wall time: 10 ms
    

    画出直方图

    fig, ax = plt.subplots(1, 2, figsize=(12, 5))
    colors = ['red', 'green', 'blue']
    
    
    for i in range(3):
        hist, x = np.histogram(img[:, :, i].ravel(), bins=256, range=(0, 256)) # bins 指定统计区间被等分的个数
        ax[0].plot(.5 * (x[:-1] + x[1:]), hist, label=colors[i], color=colors[i])
        
    ax[0].legend(loc='upper left')
    ax[0].set_xlim(0, 256)
    hist2, x2, y2 = np.histogram2d(img[:,:,0].ravel(), img[:,:,2].ravel(), bins=(100, 100), range=[(0,256), (0,256)])
    ax[1].imshow(hist2, extent=(0, 256, 0, 256), origin='lower', cmap='gray')
    ax[1].set_ylabel('red')
    ax[1].set_xlabel('blue')
    plt.show()
    
    output_5_0.png

    其实 Matplotlib 自带了一个计算并绘制直方图的功能,不需要用到上面的函数:

    plt.hist(img[:,:,0].ravel(), 256, [0, 256])
    plt.show()
    
    output_7_0.png

    OpenCV 中直方图计算

    cv2.calcHist(images, channels, mask, histSize, ranges)

    • images:要计算的原图,以方括号的传入,如:[img]
    • channels:度图写[0]就行,彩色图B/G/R分别传入[0]/[1]/[2]
    • mask:要计算的区域,计算整幅图的话,写 None
    • histSize:前面提到的 bins
    • ranges:前面提到的 range
    %%time
    hist = cv2.calcHist([img], [2, 1, 0], None, [30, 20, 10], [0, 256]*3)  # 性能:2.5 ms
    
    Wall time: 3.52 ms
    
    hist.shape
    
    (30, 20, 10)
    

    直方图均衡化

    一副效果好的图像通常在直方图上的分布比较均匀,直方图均衡化就是用来改善图像的全局亮度和对比度。其实从观感上就可以发现,前面那幅图对比度不高,偏灰白。

    OpenCV 中用 cv2.equalizeHist() 实现均衡化。我们把两张图片并排显示,对比一下:

    equ = cv2.equalizeHist(img[:,:,0])
    
    plt.imshow(np.hstack((img[:,:,0], equ)), cmap = 'gray')  # 并排显示
    plt.show()
    
    output_12_0.png
    fig, ax = plt.subplots(1, 2, figsize=(10, 5))
    
    ax[0].hist(img[:,:,0].ravel(), 256, [0, 256])
    ax[0].set_title('Hist')
    ax[1].hist(equ.ravel(), 256, [0, 256])
    ax[1].set_title('equalizeHist')
    plt.show()
    
    output_13_0.png

    可以看到均衡化后图片的亮度和对比度效果明显好于原图。不难看出来,直方图均衡化是应用于整幅图片的,这样会模糊掉一部分细节信息。自适应均衡化就是用来解决这一问题的:它在每一个小区域内(默认 8 \times 8)进行直方图均衡化。当然,如果有噪点的话,噪点会被放大,需要对小区域内的对比度进行了限制,所以这个算法全称叫:对比度受限的自适应直方图均衡化CLAHE(Contrast Limited Adaptive Histogram Equalization

    自适应均衡化

    # 自适应均衡化,参数可选
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    cl1 = clahe.apply(img[:,:,0])
    
    plt.imshow(np.hstack((img[:,:,0], equ, cl1)), cmap = 'gray')  # 并排显示
    plt.show()
    

    点运算

    即对应元素的四则运算:

    # 乘法
    plt.imshow(np.hstack([img*i for i in range(1,4)])) 
    plt.show()
    
    output_17_0.png
    # 除法
    plt.imshow(np.hstack([img/i for i in [2, 5, 7]]).astype('B'))
    plt.show()
    
    output_18_0.png
    # 加法
    plt.imshow(np.hstack([img+i for i in [2, 30, 70]]))
    plt.show()
    
    output_19_0.png
    # 减法
    plt.imshow(np.hstack([img-i for i in [2, 50, 70]]).astype('B'))
    plt.show()
    
    output_20_0.png
    # 组合运算
    plt.imshow(np.hstack([img*i-i for i in [2, 50, 70]]).astype('B'))
    plt.show()
    
    output_21_0.png
    #  指数运算
    plt.imshow(np.hstack([np.exp(img*i + 1e-9) for i in [2, 50, 70]]).astype('B'))
    plt.show()
    
    output_22_0.png
    # 对数运算
    plt.imshow(np.hstack([np.log(img*i + 1e-9) for i in [2, 50, 70]]).astype('B'))
    plt.show()
    
    output_23_0.png
    # 阈值处理
    plt.imshow(np.hstack([255*(img < i).astype('B') for i in [50, 150, 200]]))
    plt.show()
    
    output_24_0.png

    相关文章

      网友评论

        本文标题:数字图像的基本运算

        本文链接:https://www.haomeiwen.com/subject/vaqgkqtx.html