iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
AI/ ML & Data

AI 影像處理 30天系列 第 2

[AI 影像處理 30天] [Day 02] 電腦視覺幼幼班:Python OpenCV 介紹 OpenCV 的基礎用法

  • 分享至 

  • xImage
  •  

如果想要跟著一起練習歡迎使用這個連結進入Kaggle練習 (按下網頁右上方的Copy & Edit)

1. OpenCV 簡介

https://ithelp.ithome.com.tw/upload/images/20240829/20168901QEHVvuBSi0.png

  • 1.1 什麼是 OpenCV?
    OpenCV(Open Source Computer Vision Library)是由英特爾研究院發起的一個開源的計算機視覺和機器學習軟件庫。它提供了一個共同的基礎設施來開發計算機視覺應用程序,並加速機器感知的商業化應用。
    OpenCV 包含了超過2500個優化算法,涵蓋了傳統的計算機視覺和機器學習算法,以及最新的深度學習技術。這些算法可以用於檢測和識別人臉、識別物體、分類人類行為、跟蹤攝像機運動、跟蹤移動物體、提取3D模型、產生3D點雲、拼接圖像以產生高分辨率圖像、從圖像數據庫中找到相似圖像、去除紅眼、跟蹤眼球運動、識別場景等等。

2. 安裝和環境設置

  • 2.1 在 Python 中安裝 OpenCV
    OpenCV可以通過pip(Python包管理器)輕鬆安裝。以下是安裝步驟:
  1. 打開命令行或終端。

  2. 運行以下命令安裝OpenCV:

    pip install opencv-python
    

    這將安裝OpenCV的主要模塊。

  3. 如果你需要額外的模塊(如contrib模塊),可以運行:
    opencv-contrib-python:這是擴展版本,除了包含核心功能外,還包括了許多額外的模塊和算法。這些附加功能可能包括高級的特徵檢測器、跟踪算法、深度學習模塊等。當然這篇只會針對一些基礎的功能去進行介紹,如果有興趣更進階的內容歡迎在下方留言鼓勵我們會再進行整理~

    pip install opencv-contrib-python
    
  4. 安裝完成後,可以通過運行以下命令來驗證安裝:

    import cv2
    print(cv2.__version__)
    

    如果安裝成功,這將打印出OpenCV的版本號。

3. 基本圖像操作

  • 3.1 讀取圖像
    使用 OpenCV 的 cv2.imread() 函數來讀取圖像。此函數可以將圖像文件讀取為多維數組。

    import cv2
    
    # 讀取圖像
    image = cv2.imread('path/to/image.jpg')
    
  • 3.2 顯示圖像
    使用 cv2.imshow() 函數顯示圖像。此函數會創建一個窗口來顯示圖像。

    cv2.imshow('Image', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

📌這邊注意若是在Colab或是Kaggle以及Jupyter Notebook這類型的編輯介面最簡單的解決方案便是使用像是matplotlib的套件來進行顯示。

from matplotlib import pyplot as plt
# OpenCV 默認使用 BGR 色彩空間,matplotlib 使用 RGB,需轉換
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 使用 matplotlib 顯示圖像
plt.imshow(image_rgb)
plt.axis('off')  # 不顯示坐標軸
plt.show()

若是你有打開我們的Kaggle筆記就可以看到這隻可愛的狗狗~
https://ithelp.ithome.com.tw/upload/images/20240829/20168901GV2DwHVbFq.jpg

  • 3.3 保存圖像
    使用 cv2.imwrite() 函數將圖像保存到文件。
# 保存圖像
cv2.imwrite('path/to/save/image.jpg', image)

如果你有跟著我們的kaggle Notebook一起實作你就可以看到在右邊的框框中Output有張image.jpg的輸出!
https://ithelp.ithome.com.tw/upload/images/20240829/20168901j2WjU1X644.jpg

  • 3.4 圖像的基本屬性(尺寸、通道等)

這邊要來講一點點數學啦~圖像在計算機中通常以向量的形式存儲,每個像素包含一個或多個通道,每個通道代表圖像的一種顏色成分(例如,紅色、綠色和藍色)。通道數是指圖像中每個像素的數據組成。以下是一些常見的通道數:

  • 單通道圖像:灰度圖像只有一個通道,每個像素代表一個灰度值(0-255)
  • 三通道圖像:RGB 彩色圖像有三個通道,每個通道代表一種顏色(紅、綠、藍)
  • 四通道圖像:RGBA 彩色圖像有四個通道,其中三個通道代表顏色(紅、綠、藍),第四個通道是 Alpha 通道,表示透明度。
# 將圖像從 BGR 轉換為 RGB(因為 OpenCV 讀取的圖像默認為 BGR)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 分離 RGB 通道
red_channel, green_channel, blue_channel = cv2.split(image_rgb)

# 創建一行三列的子圖
_, axs = plt.subplots(1, 3, figsize=(15, 5))

# 使用 imshow 在每個子圖上顯示不同的顏色通道
axs[0].imshow(255 - red_channel, cmap='Reds')
axs[0].set_title('Red Channel')
axs[0].axis('off')

axs[1].imshow(255 - green_channel, cmap='Greens')
axs[1].set_title('Green Channel')
axs[1].axis('off')

axs[2].imshow(255 - blue_channel, cmap='Blues')
axs[2].set_title('Blue Channel')
axs[2].axis('off')

# 顯示圖像
plt.show()

透過上方的程式可以產生下方的這張圖。
https://ithelp.ithome.com.tw/upload/images/20240829/20168901whe7Ws58Gh.jpg
大家應該都有一點印象RGB的表示法,(255, 255, 255)表示白色,而(0, 0, 0)表示黑色。這裡使用的是加色法,也就是說將紅色、綠色和藍色光加在一起會變成白色。假如圖片的尺寸是100x100,那麼每個顏色通道(如red_channel)也會是一個100x100的矩陣,矩陣中的每個數值代表該通道在該像素位置上的強度。
https://ithelp.ithome.com.tw/upload/images/20240829/20168901J8P173WIlA.jpg

接著我們來看看這張圖的大小吧~

height, width, channels = image.shape
print(f'圖像高度: {height} 像素')
print(f'圖像寬度: {width} 像素')
print(f'圖像通道數: {channels}')

可以看到這張圖片為一張500X375的圖片因此我們前面說的red_channel大小當然也是500X375。看到這邊應該對於圖片在電腦中的屬性有個基本的認識了吧~那我們就不等人了繼續往下吧!!

4. 圖像處理基礎

  • 4.1 調整圖像大小
    使用 cv2.resize() 函數調整圖像大小。
width = 750
height = 1000

resized_image = cv2.resize(image, (width, height))
  • 4.2 裁剪圖像
    前面得知,圖片是一個向量因此我們只要指定想要的區域就可以進行裁切了!
x1, x2, y1, y2 = [100, 150, 140, 170]
# 裁剪圖像
cropped_image = image[y1:y2, x1:x2]

# 使用 matplotlib 顯示圖像
plt.imshow(cropped_image)
plt.axis('off')  # 不顯示坐標軸
plt.show()

如果我們用上方的向量進行裁切就可以獲得狗狗的大臉🤣(好像有點恐怖
https://ithelp.ithome.com.tw/upload/images/20240829/20168901jCzdTjJbOa.jpg

  • 4.3 旋轉和翻轉圖像
    若要旋轉或翻轉可以透過cv2.rotate() 和 cv2.flip() 函數旋轉和翻轉圖像。
# 旋轉圖像
rotated_image = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)

# 翻轉圖像
flipped_image = cv2.flip(image, 1) # 1:水平翻轉, 0:垂直翻轉, -1:同時水平和垂直翻轉

_, axs = plt.subplots(1, 2, figsize=(15, 5))
# 使用 matplotlib 顯示圖像
axs[0].imshow(rotated_image)
axs[0].set_title('rotated_image')
axs[0].axis('off')

axs[1].imshow(flipped_image)
axs[1].set_title('flipped_image')
axs[1].axis('off')

https://ithelp.ithome.com.tw/upload/images/20240829/20168901us6PkZdhsc.jpg

  • 4.4 調整亮度和對比度
    可以使用 cv2.convertScaleAbs() 函數來調整圖像的亮度和對比度。
# 調整亮度和對比度
adjusted_image = cv2.convertScaleAbs(image, alpha=1.2, beta=90)  # alpha: 對比度, beta: 亮度
# 使用 matplotlib 顯示圖像
plt.imshow(cropped_image)
plt.axis('off')  # 不顯示坐標軸
plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/20168901fb0dUpcSWD.jpg

5. 繪圖功能

這邊直接用一張圖來看看大部分會使用到的功能吧~

# 定義要展示的繪圖功能及其參數
drawings = [
    {
        "title": "Draw Line",
        "function": lambda img: cv2.line(img, (50, 50), (200, 200), (255, 0, 0), 3)
    },
    {
        "title": "Draw Rectangle",
        "function": lambda img: cv2.rectangle(img, (50, 100), (200, 200), (0, 255, 0), 3)
    },
    {
        "title": "Draw Circle",
        "function": lambda img: cv2.circle(img, (150, 150), 50, (0, 0, 255), -1)
    },
    {
        "title": "Add Text",
        "function": lambda img: cv2.putText(img, 'Hello OpenCV', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
    }
]

# 創建水平顯示的子圖
fig, axs = plt.subplots(1, len(drawings), figsize=(20, 5))

# 使用 for 迴圈來應用不同的繪圖功能並展示圖像
for ax, drawing in zip(axs, drawings):
    # 從原始圖像創建副本
    temp_image = image_rgb.copy()
    
    # 應用繪圖功能
    drawing["function"](temp_image)
    
    # 顯示圖像
    ax.imshow(temp_image)
    ax.set_title(drawing["title"])
    ax.axis('off')  # 不顯示坐標軸

# 顯示所有圖像
plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/20168901hFaGlfd1F7.jpg

6. 色彩空間轉換

  • 6.1 RGB 與 BGR
    在 OpenCV 中,圖像的色彩空間默認為 BGR(藍綠紅),而不是通常使用的 RGB(紅綠藍)。這意味著在使用 OpenCV 讀取圖像後,圖像數據會存儲為 BGR 格式。因此,使用 matplotlib 顯示圖像時,通常需要將 BGR 轉換為 RGB。
# 將 BGR 轉換為 RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 顯示 RGB 圖像
plt.imshow(image_rgb)
plt.axis('off')
plt.show()
  • 6.2 轉換為灰度圖像
    灰度圖像是單通道圖像,包含每個像素的亮度信息,而沒有顏色信息。可以使用 cv2.cvtColor() 函數將彩色圖像轉換為灰度圖像。
# 將彩色圖像轉換為灰度圖像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 顯示灰度圖像
plt.imshow(gray_image, cmap='gray')
plt.axis('off')
plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/201689017OucfupXH2.jpg

  • 6.3 HSV 色彩空間
    HSV(色相、飽和度、明度)色彩空間對於色彩範圍檢測和色彩處理任務非常有用。使用 cv2.cvtColor() 可以將 BGR 圖像轉換為 HSV。
# 將 BGR 圖像轉換為 HSV
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 顯示 HSV 圖像的每個通道
h, s, v = cv2.split(hsv_image)
_, axs = plt.subplots(1, 3, figsize=(15, 5))

axs[0].imshow(h, cmap='hsv')
axs[0].set_title('Hue')
axs[0].axis('off')

axs[1].imshow(s, cmap='gray')
axs[1].set_title('Saturation')
axs[1].axis('off')

axs[2].imshow(v, cmap='gray')
axs[2].set_title('Value')
axs[2].axis('off')

plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/20168901lJstuViQ7T.jpg

7. 簡單的圖像處理技巧

  • 7.1 圖像平滑(模糊)
    圖像平滑技術,也稱為圖像模糊,是數字圖像處理中一個非常重要的操作。它主要用於降低圖像中的噪聲,減少細節,為後續的圖像處理任務做準備。OpenCV提供了多種平滑方法,每種方法都有其特定的用途和優勢。

這邊看完或許你還會有點霧颯颯,為什麼要做圖像平滑?最主要在於許多圖像處理算法(如邊緣檢測)對噪聲很敏感,預先進行平滑可以提高這些算法的準確性和穩定性,並且在進行特徵提取或模式識別之前,平滑處理可以突出重要特徵。又或著更平易近人的例子像是在醫學影像如X光片或MRI掃描中,平滑可以幫助醫生更好地分析圖像。

  • 均值模糊 (Mean Blur):方法取核心區域內所有像素的平均值作為中心像素的新值。其優點在於簡單快速,不過可能會過度模糊圖像邊緣。
  • 高斯模糊 (Gaussian Blur):使用高斯分佈作為權重,中心像素權重最大,周圍像素權重隨距離遞減。其優點在於效果更自然,可以更好地保持邊緣信息。
  • 中值模糊 (Median Blur):用核心區域內所有像素的中位數替換中心像素。
# 均值模糊
#這裡的(5, 5)表示使用5x5的核心大小。核心越大,模糊效果越強。
blurred_image = cv2.blur(image, (5, 5))

# 高斯模糊
gaussian_blurred = cv2.GaussianBlur(image, (5, 5), 0)

# 中值模糊
median_blurred = cv2.medianBlur(image, 5)

# 顯示模糊效果
_, axs = plt.subplots(1, 3, figsize=(15, 5))
axs[0].imshow(blurred_image)
axs[0].set_title('Mean Blur')
axs[0].axis('off')

axs[1].imshow(gaussian_blurred)
axs[1].set_title('Gaussian Blur')
axs[1].axis('off')

axs[2].imshow(median_blurred)
axs[2].set_title('Median Blur')
axs[2].axis('off')

plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/20168901thsjrQ1QCm.jpg
使用上方的程式,你可以更全面地理解和比較不同的圖像平滑技術。也可以嘗試調整核心大小或其他參數,觀察它們如何影響結果。例如,可以將cv2.blur(noisy_image, (5, 5))中的(5, 5)改為(3, 3)或(7, 7),看看均值模糊的效果如何變化。

  • 7.2 邊緣檢測
    邊緣檢測是一種常見的圖像處理技術,用於檢測圖像中的邊緣。Canny 邊緣檢測算法是其中最流行的算法之一。
# 轉換為灰度圖像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 應用 Canny 邊緣檢測
edges = cv2.Canny(gray_image, 100, 200)

# 顯示邊緣檢測結果
plt.imshow(edges, cmap='gray')
plt.axis('off')
plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/20168901MBrrnmSNF2.jpg

  • 7.3 閾值處理
    閾值處理是將圖像轉換為二值圖像的過程。這對於物體檢測和分割非常有用。他的核心思想是根據像素強度將圖像分為兩類。它通過選擇一個閾值(threshold),將所有高於該閾值的像素設為一個值(通常是白色,表示為255),所有低於該閾值的像素設為另一個值(通常是黑色,表示為0)。這樣就產生了一個二值圖像。
# 轉換為灰度圖像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 應用二元閾值
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)

# 顯示二值圖像
plt.imshow(binary_image, cmap='gray')
plt.axis('off')
plt.show()

https://ithelp.ithome.com.tw/upload/images/20240829/201689015MEvWwJ0hI.jpg

9. 小節

在今天的鐵人賽中,我們介紹了 OpenCV 的基本概念和操作,包括圖像讀取、顯示、保存、色彩空間轉換、圖像處理(如模糊、邊緣檢測、閾值處理)以及簡單的圖像編輯和批量處理技巧。你也可以看到光是一個套件就有這麼多的功能,這也是為甚麼Opencv會在電腦視覺領域中紅這麼久吧~


撰文者: RenHe Huang


上一篇
[AI 影像處理 30天] [Day 01] 歡迎來到AI影像處理的世界
下一篇
[AI 影像處理 30天] [Day 03] 電腦視覺進階應用:2D 平面圖像置入技術
系列文
AI 影像處理 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言