如果想要跟著一起練習歡迎使用這個連結進入Kaggle練習 (按下網頁右上方的Copy & Edit)
打開命令行或終端。
運行以下命令安裝OpenCV:
pip install opencv-python
這將安裝OpenCV的主要模塊。
如果你需要額外的模塊(如contrib模塊),可以運行:
opencv-contrib-python:這是擴展版本,除了包含核心功能外,還包括了許多額外的模塊和算法。這些附加功能可能包括高級的特徵檢測器、跟踪算法、深度學習模塊等。當然這篇只會針對一些基礎的功能去進行介紹,如果有興趣更進階的內容歡迎在下方留言鼓勵我們會再進行整理~
pip install opencv-contrib-python
安裝完成後,可以通過運行以下命令來驗證安裝:
import cv2
print(cv2.__version__)
如果安裝成功,這將打印出OpenCV的版本號。
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筆記就可以看到這隻可愛的狗狗~
# 保存圖像
cv2.imwrite('path/to/save/image.jpg', image)
如果你有跟著我們的kaggle Notebook一起實作你就可以看到在右邊的框框中Output有張image.jpg的輸出!
這邊要來講一點點數學啦~圖像在計算機中通常以向量的形式存儲,每個像素包含一個或多個通道,每個通道代表圖像的一種顏色成分(例如,紅色、綠色和藍色)。通道數是指圖像中每個像素的數據組成。以下是一些常見的通道數:
# 將圖像從 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()
透過上方的程式可以產生下方的這張圖。
大家應該都有一點印象RGB的表示法,(255, 255, 255)表示白色,而(0, 0, 0)表示黑色。這裡使用的是加色法,也就是說將紅色、綠色和藍色光加在一起會變成白色。假如圖片的尺寸是100x100,那麼每個顏色通道(如red_channel)也會是一個100x100的矩陣,矩陣中的每個數值代表該通道在該像素位置上的強度。
接著我們來看看這張圖的大小吧~
height, width, channels = image.shape
print(f'圖像高度: {height} 像素')
print(f'圖像寬度: {width} 像素')
print(f'圖像通道數: {channels}')
可以看到這張圖片為一張500X375的圖片因此我們前面說的red_channel大小當然也是500X375。看到這邊應該對於圖片在電腦中的屬性有個基本的認識了吧~那我們就不等人了繼續往下吧!!
width = 750
height = 1000
resized_image = cv2.resize(image, (width, height))
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()
如果我們用上方的向量進行裁切就可以獲得狗狗的大臉🤣(好像有點恐怖
# 旋轉圖像
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')
# 調整亮度和對比度
adjusted_image = cv2.convertScaleAbs(image, alpha=1.2, beta=90) # alpha: 對比度, beta: 亮度
# 使用 matplotlib 顯示圖像
plt.imshow(cropped_image)
plt.axis('off') # 不顯示坐標軸
plt.show()
這邊直接用一張圖來看看大部分會使用到的功能吧~
# 定義要展示的繪圖功能及其參數
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()
# 將 BGR 轉換為 RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 顯示 RGB 圖像
plt.imshow(image_rgb)
plt.axis('off')
plt.show()
# 將彩色圖像轉換為灰度圖像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 顯示灰度圖像
plt.imshow(gray_image, cmap='gray')
plt.axis('off')
plt.show()
# 將 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()
這邊看完或許你還會有點霧颯颯,為什麼要做圖像平滑?最主要在於許多圖像處理算法(如邊緣檢測)對噪聲很敏感,預先進行平滑可以提高這些算法的準確性和穩定性,並且在進行特徵提取或模式識別之前,平滑處理可以突出重要特徵。又或著更平易近人的例子像是在醫學影像如X光片或MRI掃描中,平滑可以幫助醫生更好地分析圖像。
# 均值模糊
#這裡的(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()
使用上方的程式,你可以更全面地理解和比較不同的圖像平滑技術。也可以嘗試調整核心大小或其他參數,觀察它們如何影響結果。例如,可以將cv2.blur(noisy_image, (5, 5))中的(5, 5)改為(3, 3)或(7, 7),看看均值模糊的效果如何變化。
# 轉換為灰度圖像
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()
# 轉換為灰度圖像
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()
在今天的鐵人賽中,我們介紹了 OpenCV 的基本概念和操作,包括圖像讀取、顯示、保存、色彩空間轉換、圖像處理(如模糊、邊緣檢測、閾值處理)以及簡單的圖像編輯和批量處理技巧。你也可以看到光是一個套件就有這麼多的功能,這也是為甚麼Opencv會在電腦視覺領域中紅這麼久吧~