zoukankan      html  css  js  c++  java
  • 彩色图到灰度图究竟是怎么变换的

      之前对彩色图与灰度图仅仅停留在前者是3通道后者是单通道的理解上。我也知道计算机看图片是将它们当成数组,但是一直搞不清楚将一张彩色图转变为灰度图是怎么操作的。当然,很多库函数都提供借口,包括OpenCV、PIL等。这里我参考https://blog.csdn.net/saltriver/article/details/79677116 手动实现将一张彩色图转换为灰色图。当然还是以帅气的哈士奇.jpg作为我的练习对象,看到它敲代码都有动力。

    from PIL import  Image
    import numpy as np
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    rgb_img = Image.open('Husky.jpg')
    grey_img = rgb_img.convert('L')
    
    rgb_img
    

    grey_img
    

    可以看到通过PIL的函数,可以轻松将图片转换为灰度图。
    这里的哈士奇照片实在太大了,将它变得小一些。

    rgb_img.thumbnail((800, 800))
    grey_img.thumbnail((800, 800))
    
    rgb_img
    

    grey_img
    

    最终的效果应该变为类似上面这张灰度图

    # 获取彩色图的数据
    rgb_arr = np.array(rgb_img)
    
    # 窥探下这个数组,第一印象它是一个3维的
    rgb_arr
    
    array([[[ 93, 153, 203],
            [ 91, 151, 201],
            [ 90, 149, 200],
            ...,
            [  3, 120, 189],
            [  2, 119, 188],
            [  4, 121, 190]],
    
           [[ 90, 151, 200],
            [ 89, 150, 199],
            [ 90, 150, 200],
            ...,
            [  2, 119, 188],
            [  2, 119, 188],
            [  2, 119, 188]],
    
           [[ 86, 149, 196],
            [ 86, 149, 196],
            [ 89, 151, 198],
            ...,
            [  1, 119, 188],
            [  1, 119, 188],
            [  1, 118, 187]],
    
           ...,
    
           [[ 24,  22,  24],
            [ 25,  22,  24],
            [ 29,  26,  26],
            ...,
            [ 10,   9,  14],
            [  9,   8,  13],
            [  6,   5,  10]],
    
           [[ 23,  24,  28],
            [ 27,  28,  32],
            [ 44,  45,  48],
            ...,
            [ 10,   9,  14],
            [  7,   6,  11],
            [  6,   5,  10]],
    
           [[ 38,  41,  47],
            [ 50,  53,  59],
            [ 64,  66,  71],
            ...,
            [  8,   7,  12],
            [  6,   5,  10],
            [  7,   6,  11]]], dtype=uint8)
    
    # 行 列 通道
    rgb_arr.shape
    
    (633, 800, 3)
    
    # 宽(列数) 高(行数)
    rgb_img.size
    
    (800, 633)
    
    # 可以用matlibplot.pyplot将数组显示为图片
    plt.imshow(rgb_arr)
    
    <matplotlib.image.AxesImage at 0x110cb71d0>
    

    接下来对数组进行操作,第一种想法是将3个通道的数据取平均。
    那么不禁要问,三个通道的数据是哪些?其实这也是我之前一直有些疑惑的地方。

    x = rgb_arr[0][0]
    
    # x代表图片中的1个像素点,它的颜色由[93, 153, 203]表示,因此这3个值为3个通道的值
    x
    
    array([ 93, 153, 203], dtype=uint8)
    
    # 那么不难想象,可以通过两个for循环对这些值取平均
    grey_arr = np.zeros(rgb_arr.shape[0:2])
    
    # grey_arr.shape (633, 800)
    
    for row in range(633):
        for col in range(800):
            grey_arr[row][col] = (int(rgb_arr[row][col][0]) + int(rgb_arr[row][col][1]) + int(rgb_arr[row][col][2])) / 3
    
    grey_arr = np.array(grey_arr, dtype=np.uint8)
    
    grey_arr
    
    array([[149, 147, 146, ..., 104, 103, 105],
           [147, 146, 146, ..., 103, 103, 103],
           [143, 143, 146, ..., 102, 102, 102],
           ...,
           [ 23,  23,  27, ...,  11,  10,   7],
           [ 25,  29,  45, ...,  11,   8,   7],
           [ 42,  54,  67, ...,   9,   7,   8]], dtype=uint8)
    
    out_img = Image.fromarray(grey_arr)
    out_img
    

    std_grey_arr = np.asarray(grey_img)
    
    std_grey_arr
    
    array([[140, 138, 136, ...,  92,  91,  93],
           [138, 137, 137, ...,  91,  91,  91],
           [135, 135, 137, ...,  91,  91,  90],
           ...,
           [ 22,  22,  26, ...,   9,   8,   5],
           [ 23,  27,  45, ...,   9,   6,   5],
           [ 40,  52,  66, ...,   7,   5,   6]], dtype=uint8)
    

    自行生成的数据和通过借口函数转换得到的标准灰度图的数据还是有一定差距,

    ## 通过给定不同权重的方法再试一次
    
    for row in range(633):
        for col in range(800):
            grey_arr[row][col] = 0.11 * rgb_arr[row][col][0] + 0.59 * rgb_arr[row][col][1] + 0.3 * rgb_arr[row][col][2]
    
    grey_arr = np.array(grey_arr, dtype=np.uint8)
    
    grey_arr
    
    array([[161, 159, 157, ..., 127, 126, 128],
           [158, 157, 158, ..., 126, 126, 126],
           [156, 156, 158, ..., 126, 126, 125],
           ...,
           [ 22,  22,  26, ...,  10,   9,   6],
           [ 25,  29,  45, ...,  10,   7,   6],
           [ 42,  54,  67, ...,   8,   6,   7]], dtype=uint8)
    
    out_img = Image.fromarray(grey_arr)
    
    out_img
    

    以上就是手动实现将RGB图片转为灰度图的过程,注意图片的数值类型为unit8

  • 相关阅读:
    Python数组操作将一维数组变成二维数组
    Python做一个计时器的动画
    tkinter添加背景音乐
    IDEA——配置代码检测
    Jenkins构建 前端node项目
    linux下python相关命令
    推荐几个IT交流社区
    jenkins常用插件
    linux上安装newman
    linux+jenkins+postman持续集成
  • 原文地址:https://www.cnblogs.com/shayue/p/10393542.html
Copyright © 2011-2022 走看看