iT邦幫忙

0

[OpenCV 學習筆記] 8. 灰階圖片的 Morphological Transformations!

  • 分享至 

  • xImage
  •  

在介紹了 黑白圖片的Morphological Transformations 後,本文接下來會將相關概念延伸,簡單介紹灰階圖片的 Morphological Transformations。
https://ithelp.ithome.com.tw/upload/images/20260908/20182893ExfuulinW8.png


灰階圖片的 Morphological Transformations:
首先,我們都知道灰階圖片是二維的矩陣,而其中每個元素為介於 0-255 間的整數,代表著該像素的亮度。
https://ithelp.ithome.com.tw/upload/images/20260909/20182893jcsGj5q0qf.png
但灰階圖片的亮度值有256個數字,不像黑白可以用 0 和 1 表示,這樣當捲積用的 window 在滑動時,要怎麼產生"膨脹(Dilate)" 或 "侵蝕(Erode)" 的效果呢?


Idea💡:
讓我們先從侵蝕(Erode)進行一些啟發式的探討吧! 我們知道數字越靠近255,則亮度越亮,而越靠近 0 時,亮度越暗,所以如果我們取 kernel 中像素最小的值取代掉 Kernel 中心點的值,則該中心點的像素就會變暗,當對每一點都這樣做時,整體來說圖像某些(白色的)地方就會變暗,視覺上就會看起來像是白色(偏亮)的部分縮小了,達到被黑暗"侵蝕"的效果,如下圖所示:
Grayscale_Erode
(圖片來源:https://commons.wikimedia.org/wiki/File:Grayscale_Morphological_Erosion.gif)

反之,透過類似的概念,將 kernel 中像素最大的值取代掉 Kernel 中心點的值,則看起來就像亮度偏亮的地方膨脹(黑色的部分被白色侵蝕)了,如下圖所示:
Grayscale_Dilate
(圖片來源:https://commons.wikimedia.org/wiki/File:Grayscale_Morphological_Dilation.gif)

以上大致就是灰階圖片的 Morphological Transformations 背後的直覺想法。


底下為簡單示範如何使用 OpenCV 套件進行 Morphological Transformations,其餘和Morphological Transformations相關的函數(Opening, Closing 等...)跟黑白圖片用的函數都是一樣的,所以就不在此贅述了。
程式碼1(Python):

import cv2
import numpy as np
import matplotlib.pyplot as plt

dog_pic = '../images/dog.png'  # 圖片位址

try:
    dog_img = cv2.imread(dog_pic) 

    dog_img_gray = cv2.cvtColor(dog_img, cv2.COLOR_BGR2GRAY)

    kernel = np.ones((10,10),np.uint8)

    erosion = cv2.erode(dog_img_gray, kernel, iterations = 1)
    dilation = cv2.dilate(dog_img_gray, kernel, iterations = 1)
    gradient = cv2.morphologyEx(dog_img_gray, cv2.MORPH_GRADIENT, kernel)

    pic_titles = ['origin','erosion', 'dilation', 'gradient']
    morphological_images= [dog_img_gray, erosion, dilation, gradient]

    for i in range(len(pic_titles)):

        plt.subplot(1, len(pic_titles) ,i+1), plt.imshow(morphological_images[i],  cmap='gray')
        plt.title(pic_titles[i])
        plt.xticks([]),plt.yticks([]) # 拿掉 X座標軸 和 y座標軸 刻度文字

    plt.show()

except Exception as ex:
    print(f"An unexpected error occurred: {ex}")

執行結果:
https://ithelp.ithome.com.tw/upload/images/20260909/201828939DDyyggFkR.png

  • 為了較方便明顯看出差異,所以 kernel 調大了點,可以發現 erosion 對偏白色的像素將其改成較暗,造成了明顯的侵蝕,所以狗狗圖像看起來像膨脹了。反過來 dilation 則是對偏黑色的像素將其改成較亮,所以狗狗圖像看起來像被侵蝕了🤣,但若透過 bitwise_img_gray = cv2.bitwise_not(dog_img_gray) 將原先的圖像 bitwise 後進行 Morphological Transformation,則看的出來 erosion 對圖像進行侵蝕, dilation 對圖像進行膨脹,因此我們可以猜測灰階圖片和其 bitwise_not 後的圖像也有類似的對偶的行為。

https://ithelp.ithome.com.tw/upload/images/20260909/20182893xcRxRbNZWl.png


抽象化:

若我們去觀察Wiki上延伸的抽象定義,可以發現 Erosion 是針對每一個 fixed point (x,y),將 f(x,y) 附近的值 f(a,b) 扣掉 b(a-x,b-y) 後[向量(a-x,b-y)落在 b 的 support B 內]去取 inf,而換成離散版本的話 inf 就會等同於 min,上述的 grayscale 就會是一個特例,下方為該抽象定義的示意圖,有興趣的讀者可以自行去參考 Wiki 上的抽象數學定義。
https://ithelp.ithome.com.tw/upload/images/20260909/20182893pbuFtCVSqJ.png


彩色圖片的 Morphological Transformations:
若我們將調用 OpenCV 進行 Morphological Transformations的來源圖片改成彩色圖片時,可以發現一樣有產生結果,可是其讀取的彩色圖片的像素是 bgr 向量,照理來說不像 real-valued 函數那樣可以比較大小,但這樣 OpenCV 套件是怎麼去輸出結果的呢? 我們可以很直覺的猜想是拆分成三個通道通道的圖片,對每個通道的圖片進行類似灰階圖片的 Morphological Transformations 後,最後再將其疊加,當作結果,底下為相關的程式實驗。


程式碼2(Python):

import cv2
import numpy as np

# 圖片位址
dog_pic = '../images/dog.png'

# 讀取圖片並取得各自分離成 r g b 三通道的圖片 
dog_img = cv2.imread(dog_pic) 

dog_img_blue_channel = (dog_img.copy())
dog_img_blue_channel[:,:,1:3] = 0 

dog_img_green_channel = (dog_img.copy())
dog_img_green_channel[:,:,0:1] = 0 
dog_img_green_channel[:,:,2:3] = 0 


dog_img_red_channel = (dog_img.copy())
dog_img_red_channel[:,:,0:2] = 0 

kernel = np.ones((3,3),np.uint8)

# 各自對圖片做 erode 
blue_erosion = cv2.erode(dog_img_blue_channel, kernel,iterations = 1)
green_erosion = cv2.erode(dog_img_green_channel, kernel,iterations = 1)
red_erosion = cv2.erode(dog_img_red_channel, kernel,iterations = 1)
origin_erosion = cv2.erode(dog_img, kernel,iterations = 1)

# 將通道分離的圖片做加總
bg_erosion =cv2.add(blue_erosion, green_erosion)
bgr_erosion = cv2.add(bg_erosion, red_erosion)

diff = cv2.absdiff(origin_erosion, bgr_erosion)

# diff 看起來為全黑圖片
# 而diff array > 0 的元素加總為 0 代表每一項都是 0,
# 可以相信說 opencv 套件對彩色圖片做 erode 相當於對分離成 r, g , b 三通道的圖片單獨個別作 erode 後相加
cv2.imshow('diff', diff) 
print('np.sum(diff):', np.sum(diff > 0)) 

cv2.imshow('before vs after', np.hstack([dog_img, origin_erosion, blue_erosion, green_erosion, red_erosion]))
cv2.imshow('bgr_erosion', bgr_erosion)

cv2.waitKey()
cv2.destroyAllWindows()

執行結果:
https://ithelp.ithome.com.tw/upload/images/20260902/20182893qHefXV5edL.png

實際上,我們可以從官網文件上看到

In case of multi-channel images, each channel is processed independently.

所以其實跟我們的直覺猜想不約而同。

但實際上彩色的 Morphological Transformations 除了像用上述的 Component-wise Morphology 手法外,網路上可以看到還有 Luminance-based 或 Vector-Based Morphology 的相關手法,本文就不額外多作調研了。


以上就是筆者對灰階圖片的 Morphological Transformations 相關介紹,謝謝~


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言