彩色圖到灰度圖究竟是怎麼變換的

  之前對彩色圖與灰度圖僅僅停留在前者是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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章