彩色圖到灰度圖究竟是怎麼變換的
之前對彩色圖與灰度圖僅僅停留在前者是3通道後者是單通道的理解上。我也知道計算機看圖片是將它們當成陣列,但是一直搞不清楚將一張彩色圖轉變為灰度圖是怎麼操作的。當然,很多庫函式都提供藉口,包括OpenCV、PIL等。這裡我參考https://blog.csdn.net/saltriver/article/details/79677116 手動實現將一張彩色圖轉換為灰色圖。當然還是以帥氣的哈士奇.jpg作為我的練習物件,看到它敲程式碼都有動力。
from PIL importImage 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