教程:使用Python進行基本影像資料分析!

趙鈺瑩發表於2018-08-28

本教程將介紹如何匯入影像並觀察其屬性、拆分圖層以及檢視灰度。在正式開始之前,我們先來了解一些關於畫素的基礎知識。

計算機將圖片以畫素形式儲存,這就像馬賽克一樣。如果畫素太大,很難製作光滑的邊緣和曲線。相反,我們使用的畫素越多越小,看起來就會越平滑,或者說畫素化程度越小,影像就會越好看,有時,這也被稱為影像解析度。

向量圖形是一種有點不同的儲存影像方法,旨在避免與畫素相關的問題。但是,即使是向量影像,最終也會顯示為畫素一樣的馬賽克。顏色畫素表示影像元素,描述每個畫素的簡單方法是使用三種顏色的組合,即紅色,綠色,藍色,這就是我們所說的RGB影像。

在RGB影像中,每個畫素分別與紅色,綠色,藍色的值相關聯的三個8位元數字表示。最後,如果使用放大鏡觀察縮放的圖片,我們會看到圖片由微小的光點或更具體的畫素組成,更有趣的是這些小光點實際上具有多個不同顏色。

每張照片都以數字形式由畫素組成,它們是構成圖片的最小資訊單位,通常是圓形或方形,它們通常佈置在二維網格中。

如果三個顏色都處於最大值,則意味著它們是255,那就會顯示為白色,如果三種顏色都處於最小值,或者值為0,則顏色顯示為黑色。反過來,這三者的組合將為我們提供特定的畫素顏色。由於每個顏色數字都是8個位元,因此值範圍為0-255。

由於每個值可以具有256個不同的強度或亮度值,因此三種顏色總共有1680萬個shade。

以下是Numpyand非常基本的影像資料分析步驟,其中一些涉及Python pacakges,如imageio,matplotlib等。

  • 匯入影像並觀察其屬性

  • 拆分圖層

  • Greyscale

  • 對畫素值使用邏輯運算子

  • 使用邏輯運算子進行運算

  • 衛星影像資料分析

匯入影像

現在讓我們載入影像並觀察各種屬性:

if __name__ == '__main__':
    import imageio
    import matplotlib.pyplot as plt
    %matplotlib inline
    pic = imageio.imread('F:/demo_2.jpg')
    plt.figure(figsize = (15,15))
    plt.imshow(pic)觀察影像的基本屬性
print('Type of the image : ' , type(pic))
print('Shape of the image : {}'.format(pic.shape))
print('Image Hight {}'.format(pic.shape[0]))
print('Image Width {}'.format(pic.shape[1]))
print('Dimension of Image {}'.format(pic.ndim))
Type of the image :  <class 'imageio.core.util.Image'>
Shape of the image : (562, 960, 3)
Image Hight 562
Image Width 960
Dimension of Image 3

ndarray的形狀表明它是一個三層矩陣,這裡的前兩個數字是長度和寬度,第三個數字(即3)是三層:Red, Green, Blue。 因此,如果我們計算RGB影像的大小,則總大小將計為height x width x 3

print('Image size {}'.format(pic.size))
print('Maximum RGB value in this image {}'.format(pic.max()))
print('Minimum RGB value in this image {}'.format(pic.min()))
Image size 1618560
Maximum RGB value in this image 255
Minimum RGB value in this image 0

這些值對於驗證很重要,因為8位元顏色強度不能超出0到255範圍。

現在,使用圖片分配變數,我們還可以訪問圖片的任何特定畫素值,並進一步訪問每個RGB通道。

'''
Let's pick a specific pixel located at 100 th Rows and 50 th Column.
And view the RGB value gradually.
'''
pic[ 100, 50 ]
Image([109, 143,  46], dtype=uint8)

在這種情況下:R = 109; G = 143; B = 46,我們可以意識到這個特殊畫素中有很多綠色。現在,我們可以通過給出三個通道的索引值來特別選擇其中一個數字:

  • 0紅色通道的索引值

  • 1綠色通道的索引值

  • 2藍色通道的索引值

但是,在OpenCV中,影像不是RGB而是BGR,imageio.imread將影像載入為RGB(或RGBA),但OpenCV假定影像為BGR或BGRA(BGR是預設的OpenCV顏色格式)。

# A specific pixel located at Row : 100 ; Column : 50
# Each channel's value of it, gradually R , G , B
print('Value of only R channel {}'.format(pic[ 100, 50, 0]))
print('Value of only G channel {}'.format(pic[ 100, 50, 1]))
print('Value of only B channel {}'.format(pic[ 100, 50, 2]))
Value of only R channel 109
Value of only G channel 143
Value of only B channel 46

好的,現在讓我們快速檢視整個影像中的每個頻道。

plt.title('R channel')
plt.ylabel('Height {}'.format(pic.shape[0]))
plt.xlabel('Width {}'.format(pic.shape[1]))
plt.imshow(pic[ : , : , 0])
plt.show()

plt.title('G channel')
plt.ylabel('Height {}'.format(pic.shape[0]))
plt.xlabel('Width {}'.format(pic.shape[1]))
plt.imshow(pic[ : , : , 1])
plt.show()

plt.title('B channel')
plt.ylabel('Height {}'.format(pic.shape[0]))
plt.xlabel('Width {}'.format(pic.shape[1]))
plt.imshow(pic[ : , : , 2])
plt.show()

現在,我們可以更改RGB值的數量。例如,讓我們對紅色、綠色、藍色圖層設定跟隨行值的強度。

  • R頻道:行 - 100到110

  • G頻道:行 - 200到210

  • B頻道:行 - 300到310

我們將載入一次影像,以便可以同時顯示每個層的變化。

pic = imageio.imread('F:/demo_2.jpg')
pic[50:150 , : , 0] = 255 # full intensity to those pixel's R channel
plt.figure( figsize = (10,10))
plt.imshow(pic)
plt.show()

pic[200:300 , : , 1] = 255 # full intensity to those pixel's G channel
plt.figure( figsize = (10,10))
plt.imshow(pic)
plt.show()

pic[350:450 , : , 2] = 255 # full intensity to those pixel's B channel
plt.figure( figsize = (10,10))
plt.imshow(pic)
plt.show()

為了更清楚,讓我們也改變列部分,這次我們將同時更改RGB通道。

# set value 200 of all channels to those pixels which turns them to white
pic[ 50:450 , 400:600 , [0,1,2] ] = 200 
plt.figure( figsize = (10,10))
plt.imshow(pic)
plt.show()

拆分圖層

現在,我們知道影像的每個畫素都由三個整數表示,將影像分割成單獨的顏色分片只需拉出影像陣列的正確切片。

import numpy as np
pic = imageio.imread('F:/demo_2.jpg')
fig, ax = plt.subplots(nrows = 1, ncols=3, figsize=(15,5))
for c, ax in zip(range(3), ax):
    # create zero matrix
    split_img = np.zeros(pic.shape, dtype="uint8") # 'dtype' by default: 'numpy.float64'
    # assing each channel
    split_img[ :, :, c] = pic[ :, :, c]
    # display each channel
    ax.imshow(split_img)

灰度

黑白影像儲存在二維陣列中,有兩種型別的黑白影像:

  • Greyscale:灰色陰影範圍:0~255

  • Binary:畫素為黑色或白色:0或255

現在,Greyscaling是一個將影像從全色轉換為灰色陰影的過程。在影像處理工具中,例如:在OpenCV中,許多功能在處理之前使用灰度影像,這樣做是因為它簡化了影像,幾乎可以降噪並增加處理時間,因為影像中的資訊較少。

在python中有兩種方法可以將影像轉換為灰度,但使用matplotlib的簡單方法是使用此公式獲取原始影像的RGB值的加權平均值。

Y' = 0.299 R + 0.587 G + 0.114 B
pic = imageio.imread('F:/demo_2.jpg')
gray = lambda rgb : np.dot(rgb[... , :3] , [0.299 , 0.587, 0.114])
gray = gray(pic)  
plt.figure( figsize = (10,10))
plt.imshow(gray, cmap = plt.get_cmap(name = 'gray'))
plt.show()

然而,GIMP將顏色轉換為灰度影像軟體有三種演算法來完成任務。

灰度的Lightness 等級計算為

Lightness = ½ × (max(R,G,B) + min(R,G,B))

灰度的Luminosity 等級計算為

Luminosity = 0.21 × R + 0.72 × G + 0.07 × B

灰度的Average 計算為

Average Brightness = (R + G + B) ÷ 3

讓我們嘗試一下演算法,Luminosity效果如何?

pic = imageio.imread('F:/demo_2.jpg')
gray = lambda rgb : np.dot(rgb[... , :3] , [0.21 , 0.72, 0.07])
gray = gray(pic)  
plt.figure( figsize = (10,10))
plt.imshow(gray, cmap = plt.get_cmap(name = 'gray'))
plt.show()
'''
Let's take a quick overview some the changed properties now the color image.
Like we observe some properties of color image, same statements are applying
now for gray scaled image.
'''
print('Type of the image : ' , type(gray))
print()
print('Shape of the image : {}'.format(gray.shape))
print('Image Hight {}'.format(gray.shape[0]))
print('Image Width {}'.format(gray.shape[1]))
print('Dimension of Image {}'.format(gray.ndim))
print()
print('Image size {}'.format(gray.size))
print('Maximum RGB value in this image {}'.format(gray.max()))
print('Minimum RGB value in this image {}'.format(gray.min()))
print('Random indexes [X,Y] : {}'.format(gray[100, 50]))
 Type of the image : <class 'imageio.core.util.Image'>
Shape of the image : (562,960)
Image Height 562
Image Widht 960
Dimension of Image 2
Image size 539520
Maximum RGB value in this image 254.9999999997
Minimum RGB value in this image 0.0
Random indexes [X,Y] : 129.07

使用邏輯運算子處理畫素值

我們可以使用邏輯運算子建立相同大小的bullion ndarray。但是,這不會建立任何新陣列,它只是將值返回到其主變數。例如,如果考慮在RGB影像中濾除一些低值畫素或高值或(任何條件),可以先將RGB轉換為灰度。

首先載入影像並在螢幕上顯示:

pic = imageio.imread('F:/demo_1.jpg')
plt.figure(figsize = (10,10))
plt.imshow(pic)
plt.show()

接下來,我們考慮轉儲該影像,比如我們想要過濾所有低於20 的畫素值。為此,我們將使用邏輯運算子執行此任務,返回所有索引的True值。

low_pixel = pic < 20
# to ensure of it let's check if all values in low_pixel are True or not
if low_pixel.any() == True:
    print(low_pixel.shape)
(1079, 1293, 3)

正如上文所說,傳統上不使用宿主變數,但我之所以提到是因為它只保留True值。 所以,如果我們看到low_pixel和pic的 shape,我們會發現它們都具有相同的 shape。

print(pic.shape)
print(low_pixel.shape)
(1079, 1293, 3)
(1079, 1293, 3)

我們使用全域性比較運算子為所有小於200的值生成低值濾波器。但是,我們可以使用此low_pixel陣列作為索引將這些低值設定為某些特定值,這些值可能高於或低於先前的畫素值。

# randomly choose a value
import random
# load the orginal image
pic = imageio.imread('F:/demo_1.jpg')
# set value randomly range from 25 to 225 - these value also randomly choosen
pic[low_pixel] = random.randint(25,225)
# display the image
plt.figure( figsize = (10,10))
plt.imshow(pic)
plt.show()

圖層蒙版

影像蒙版是一種影像處理技術,用於去除具有模糊邊緣,透明或頭髮部分的照片背景。

現在,我們將建立一個圓盤形狀的蒙版。首先,我們將測量從影像中心到每個邊界畫素值的距離。我們設定一個比較方便的半徑值,然後使用邏輯運算子建立一個圓盤,以下為程式碼:

if __name__ == '__main__':
    # load the image
    pic = imageio.imread('F:/demo_1.jpg')
    # seperate the row and column values
    total_row , total_col , layers = pic.shape
    '''
    Create vector.
    Ogrid is a compact method of creating a multidimensional-
    ndarray operations in single lines.
    for ex:
    >>> ogrid[0:5,0:5]
    output: [array([[0],
                    [1],
                    [2],
                    [3],
                    [4]]),
            array([[0, 1, 2, 3, 4]])]
    '''
    x , y = np.ogrid[:total_row , :total_col]
    # get the center values of the image
    cen_x , cen_y = total_row/2 , total_col/2
    '''
    Measure distance value from center to each border pixel.
    To make it easy, we can think it's like, we draw a line from center-
    to each edge pixel value --> s**2 = (Y-y)**2 + (X-x)**2
    '''
    distance_from_the_center = np.sqrt((x-cen_x)**2 + (y-cen_y)**2)
    # Select convenient radius value
    radius = (total_row/2)
    # Using logical operator '>'
    '''
    logical operator to do this task which will return as a value
    of True for all the index according to the given condition
    '''
    circular_pic = distance_from_the_center > radius
    '''
    let assign value zero for all pixel value that outside the cirular disc.
    All the pixel value outside the circular disc, will be black now.
    '''
    pic[circular_pic] = 0
    plt.figure(figsize = (10,10))
    plt.imshow(pic)
    plt.show()

衛星影像處理

衛星影像及其處理系統非常有用,我們可以用於做一些分析任務。

# load the image
pic = imageio.imread('F:\satimg.jpg')
plt.figure(figsize = (10,10))
plt.imshow(pic)
plt.show()

我們來看一些基本資訊:

print(f'Shape of the image {pic.shape}')
print(f'hieght {pic.shape[0]} pixels')
print(f'width {pic.shape[1]} pixels')
Shape of the image (3725, 4797, 3)
hieght 3725 pixels
width 4797 pixels

這張圖片上有一些有趣的東西,像許多其他的影像視覺化一樣,每個RGB層中的顏色都有自己的意思。例如,紅色的強度將表示畫素中的地理資料點的高度,藍色的強度表示方位的度量,綠色表示斜率。這些顏色將有助於以更快,更有效的方式傳達此資訊,而不是顯示數字。

  • 紅色畫素表示:Altitude·

  • 藍色畫素表示:Aspect

  • 綠色畫素表示: Slope

通過觀察彩色影像,我們可以分辨出海拔是多少,斜率是多少,以及Slope是什麼,這就是為顏色載入更多含義以表示更科學的分析的想法。

檢測每個通道的畫素

# Only Red Pixel value , higher than 180
pic = imageio.imread('F:\satimg.jpg')
red_mask = pic[:, :, 0] < 180
pic[red_mask] = 0
plt.figure(figsize=(15,15))
plt.imshow(pic)
# Only Green Pixel value , higher than 180
pic = imageio.imread('F:\satimg.jpg')
green_mask = pic[:, :, 1] < 180
pic[green_mask] = 0
plt.figure(figsize=(15,15))
plt.imshow(pic)
# Only Blue Pixel value , higher than 180
pic = imageio.imread('F:\satimg.jpg')
blue_mask = pic[:, :, 2] < 180
pic[blue_mask] = 0
plt.figure(figsize=(15,15))
plt.imshow(pic)
# Composite mask using logical_and
pic = imageio.imread('F:\satimg.jpg')
final_mask = np.logical_and(red_mask, green_mask, blue_mask)
pic[final_mask] = 40
plt.figure(figsize=(15,15))
plt.imshow(pic)

未完待續......這只是該教程的第一章節,其他內容將會在後續章節中呈現。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31077337/viewspace-2213026/,如需轉載,請註明出處,否則將追究法律責任。

相關文章