[OpenCV][Python]使用GrabCut 來去背

更新於 2024/10/02閱讀時間約 12 分鐘

iPhone也有去背的功能,那麼OpenCV能不能做到這件事呢?,答案是可以的

  • 如果圖像背景簡單且與前景有明顯的顏色區分,可以使用 色彩空間轉換閥值分割
  • 如果背景較為複雜一點點,但你可以提供一個大致的前景位置,則可以使用 GrabCut

結果圖

但在背景相當複雜的情況下,結果就不太好,若要好又要設很多條件才能完美切割。

raw-image


GrabCut 是一種強大的前景提取演算法,特別適合處理具有複雜背景的圖像分割問題。它基於圖割(Graph Cut)的技術進行迭代優化,能夠在給定前景物體的大致區域後,自動分割出前景。

原文連結


GrabCut 演算法的核心原理

GrabCut 演算法基於 最大流最小割 的圖論技術。圖像中的每個像素被視為圖中的一個節點,而前景和背景被視為兩個特殊的節點:源點(Source)匯點(Sink)。演算法通過最大化像素到這兩個特殊點的連接來進行優化。這意味著,演算法會嘗試尋找一個切割線,將圖像中的節點劃分為前景和背景。

  • 數學模型:GrabCut 將前景和背景的像素顏色分布建模為 高斯混合模型(GMM)。在每次迭代中,算法會根據當前的分割結果不斷更新 GMM,並進一步優化分割。

cv2.grabCut 函數的語法:

cv2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode)

各個參數說明:

  1. img
    • 類型:np.ndarray(輸入圖像)
    • 說明:這是需要進行分割的原始圖像。它應該是一個彩色圖像(通常是 BGR 格式)。演算法將根據這個圖像來計算前景和背景的分割。
    • 用途:分割目標圖像。
  2. mask
    • 類型:np.ndarray(遮罩)
    • 說明:這是一個與圖像大小相同的單通道遮罩圖像,表示哪些像素是前景、背景或不確定的區域。它通常在初始執行時全為 0。
    • 當使用 cv2.GC_INIT_WITH_RECT 模式時,矩形內的像素會被初始化為可能的前景,矩形外的像素會被初始化為背景。
    • 遮罩的值可以為以下幾個:
      cv2.GC_BGD(0):確定的背景像素。
      cv2.GC_FGD(1):確定的前景像素。
      cv2.GC_PR_BGD(2):可能的背景像素。
      cv2.GC_PR_FGD(3):可能的前景像素。
    • 用途:分割過程中會不斷更新這個遮罩,將像素標識為前景或背景
  3. rect
    • 類型:tuple(矩形邊界,格式為 (x, y, w, h))
    • 說明:用來定義包含前景物體的大致區域。矩形內的像素被初始化為前景,矩形外的像素被初始化為背景。該矩形不需要完全精確包圍前景,但要盡量包含整個前景,避免太多背景。此參數僅在 cv2.GC_INIT_WITH_RECT 模式下使用。
    • 用途:指定初始前景和背景區域。
  4. bgdModel(背景模型):
    • 類型:np.ndarray,大小為 (1, 65),浮點數類型。
    • 說明:這是背景模型,它是由 GrabCut 演算法內部計算並用來描述背景顏色分布的數據結構。該陣列在運行之前需要初始化為全 0。演算法在運行過程中會更新此模型。
    • 用途:演算法內部用來表示背景的顏色統計模型,外部不需要干預。
  5. fgdModel(前景模型):
    • 類型:np.ndarray,大小為 (1, 65),浮點數類型。
    • 說明:這是前景模型,它是由 GrabCut 演算法內部計算並用來描述前景顏色分布的數據結構。該陣列在運行之前需要初始化為全 0。演算法在運行過程中會更新此模型。
    • 用途:演算法內部用來表示前景的顏色統計模型,外部不需要干預。
  6. iterCount
    • 類型:整數
    • 說明:表示演算法應該進行的迭代次數。演算法是一個迭代優化過程,每次迭代會優化分割結果。通常 5-10 次迭代已經能夠產生滿意的結果。如果結果不理想,增加迭代次數可能會改善結果。
    • 用途:控制演算法的收斂過程。
  7. mode
    • 類型:int,表示初始化模式。
    • 說明:這個參數指定了 GrabCut 的初始化方式,有兩種模式:cv2.GC_INIT_WITH_RECT:使用矩形來初始化前景和背景。這是最常用的模式,矩形內的像素被初始化為前景,矩形外的像素被初始化為背景。cv2.GC_INIT_WITH_MASK:使用遮罩來初始化前景和背景。如果遮罩已經部分標定了前景和背景區域,可以使用這種模式進行更精確的初始化。
    • 用途:指定 GrabCut 的初始化方法,是使用矩形還是掩膜進行初始分割。

使用矩形來初始化前景和背景

範例

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

# 顯示圖像的函數
def show_image(image, title="Image"):
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title(title)
plt.axis('off') # 不顯示座標軸
plt.show()

# 讀取圖像
image_path = 'your_image_path.png' # 替換成你的圖像路徑
img = cv2.imread(image_path)

# 初始化掩膜
mask = np.zeros(img.shape[:2], np.uint8)

# 背景和前景模型(由 GrabCut 需要)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)

# 定義一個矩形來包含前景物體
rect = (350, 200, 300, 300) # 根據圖像大小進行調整 x,y,w,h
# 在原圖上畫出矩形框
img_with_rect = img.copy()
cv2.rectangle(img_with_rect, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (0, 255, 0), 2)

# 顯示畫出矩形框的圖像
show_image(img_with_rect, "Image with Rectangle")
# 執行 GrabCut 算法
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 10, cv2.GC_INIT_WITH_RECT)

# 修改掩膜以提取前景
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
grabcut_result = img * mask2[:, :, np.newaxis]

# 顯示原圖和 GrabCut 結果
show_image(img, "Original Image")
show_image(grabcut_result, "GrabCut Foreground Extraction")

原圖

raw-image

矩形位置

框選想保留的物件位置

raw-image

GrabCut 結果

raw-image

使用遮罩來初始化前景和背景

先標示前景與背景的區域,設定一個矩形範圍。

範例

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

# 顯示圖像的函數
def show_image(image, title="Image"):
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title(title)
plt.axis('off') # 不顯示座標軸
plt.show()

# 讀取圖像
image_path = 'your_image_path.png' # 替換成你的圖像路徑
img = cv2.imread(image_path)

# 初始化掩膜
mask = np.zeros(img.shape[:2], np.uint8)

# 背景和前景模型(由 GrabCut 需要)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)

# 定義一個矩形來包含前景物體
rect = (350, 200, 300, 300) # 根據圖像大小進行調整 x,y,w,h

# 手動調整掩膜來改善前景檢測
mask[200:500, 350:650] = cv2.GC_FGD # 標記這部分是確定的前景
mask[800:1000, 40:300] = cv2.GC_BGD # 標記這部分是確定的背景

# 再次執行 GrabCut
cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)

# 修改掩膜以提取前景
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
grabcut_result = img * mask2[:, :, np.newaxis]

# 顯示原圖和 GrabCut 結果
show_image(img, "Original Image")
show_image(grabcut_result, "GrabCut Foreground Extraction")
raw-image

遮罩的進階用法

設定符合顏色範圍的部分,設定為前景,以下範例設定為紅色的部分,就可只截取氣球的部分了

# 初始化掩膜
mask = np.zeros(img.shape[:2], np.uint8)
# 將圖像轉換為 RGB 色彩空間
RGB_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 定義顏色範圍
lower_color = np.array([150, 0, 0]) # 低閥值
upper_color = np.array([255, 70, 70]) # 高閥值

# 創建遮罩,篩選出符合顏色範圍的部分
mask_red = cv2.inRange(RGB_img, lower_color, upper_color)

# 初始化 GrabCut 所需的掩膜
mask_grabcut = np.zeros(img.shape[:2], np.uint8)

# 使用篩選出的顏色區域更新掩膜,將篩選出的部分設為"可能前景"(cv2.GC_PR_FGD
mask_grabcut[mask_red > 0] = cv2.GC_PR_FGD
raw-image













avatar-img
128會員
209內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
以下是如何使用 Tesseract OCR 來辨識圖像中的文字的教學。 涵蓋了安裝 Tesseract、基本使用方法,以及如何在 Python 中進行整合。 1. 安裝 Tesseract 首先,需要安裝 Tesseract OCR 工具。這裡提供針對 Windows、macOS 和 Linu
本文主要介紹使用cv2.findContours找到圖像中最大物件的輪廓,再用cv2.minAreaRect取得該輪廓的最小矩形與旋轉角度,並將這些資訊印上圖像中的右上角。
在OpenCV中可以利用 cv2.findContours 判斷物件的形狀,可以通過計算輪廓的某些特徵來實現的。 本文主要利用cv2.arcLength與cv2.approxPolyDP來判斷三角形,正方形,矩形。檢查是否為圓形,則用通過輪廓面積和邊界框面積的比率來判斷。
先前文章有使用連通域分析來印出物件的位置及高寬面積及達成物件定位等功能。 [OpenCV應用][Python]利用連通域分析達成物件定位 [OpenCV基礎][Python]connectedComponent連通域分析 [OpenCV][Python]印出圖像中OCR面積及位置 這次我們將
本文主要使用pyzbar 與pylibdmtx來讀取條碼,並用靜態方法將這兩個套件的讀碼功能包裝起來,因應不同需求,調用相對應的方法來讀取QR code,一維條碼,Data Matrix。最後再將讀到的條碼資料與框選條碼位子於原圖上。
這次我們使用影像差分處理,用來檢測圖像中的瑕疵。 首先定義瑕疵樣態,以下原圖為例,較淡的可能是錫油的反光,較亮的部分可能是瑕疵或者是刮痕造成,那我們的目的就是檢測出這些瑕疵或者是刮痕。
以下是如何使用 Tesseract OCR 來辨識圖像中的文字的教學。 涵蓋了安裝 Tesseract、基本使用方法,以及如何在 Python 中進行整合。 1. 安裝 Tesseract 首先,需要安裝 Tesseract OCR 工具。這裡提供針對 Windows、macOS 和 Linu
本文主要介紹使用cv2.findContours找到圖像中最大物件的輪廓,再用cv2.minAreaRect取得該輪廓的最小矩形與旋轉角度,並將這些資訊印上圖像中的右上角。
在OpenCV中可以利用 cv2.findContours 判斷物件的形狀,可以通過計算輪廓的某些特徵來實現的。 本文主要利用cv2.arcLength與cv2.approxPolyDP來判斷三角形,正方形,矩形。檢查是否為圓形,則用通過輪廓面積和邊界框面積的比率來判斷。
先前文章有使用連通域分析來印出物件的位置及高寬面積及達成物件定位等功能。 [OpenCV應用][Python]利用連通域分析達成物件定位 [OpenCV基礎][Python]connectedComponent連通域分析 [OpenCV][Python]印出圖像中OCR面積及位置 這次我們將
本文主要使用pyzbar 與pylibdmtx來讀取條碼,並用靜態方法將這兩個套件的讀碼功能包裝起來,因應不同需求,調用相對應的方法來讀取QR code,一維條碼,Data Matrix。最後再將讀到的條碼資料與框選條碼位子於原圖上。
這次我們使用影像差分處理,用來檢測圖像中的瑕疵。 首先定義瑕疵樣態,以下原圖為例,較淡的可能是錫油的反光,較亮的部分可能是瑕疵或者是刮痕造成,那我們的目的就是檢測出這些瑕疵或者是刮痕。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
呈上篇文章,針對單排的圖像文字增加間隔,但如果文字是雙排呢 [OpenCV][Python]OCR分割及增加間隔[單排文字]
Thumbnail
在文字辨識中,適當的增加一文字彼此間的間隔是有幫助於辨識的,原因在大多數OCR引擎在處理字符時會依賴空白區域來區分不同的字符。如果字符之間的間隔過小,OCR引擎可能會將相鄰的字符誤認為一個單一的字符或難以正確切割字符。增加間隔可以幫助OCR引擎更準確地識別和切割每個字符。 本文說明如何增加OCR間
Thumbnail
在影像處理中,有時候我們只想特別關注某個感興趣的區域時,就是ROI的概念,擷取此範圍的圖像來做處理。 設定超過圖像邊界時就會報錯,本文主要介紹如何擷取影像的同時,避免設定錯誤造成程式崩潰的狀況。 擷取圖像示意圖 ROI程式範例 import cv2 import numpy as np
Thumbnail
在某些特殊情況下,需要將圖片進行黑白反轉,例如Tesseract(OCR辨識引擎)就有建議黑底白字的狀況下辨識率較高。 本文將使用 NumPy 進行影像黑白反轉,並顯示反轉前後的影像。
Thumbnail
在影像辨識中,若遇到物件與背景難以分辨的狀況下,先做一下色彩分析,知道了色彩強度階層上的像素數,有助於了解後續需要做什麼處理,比較好分割出辨識物。 若想辨識的物件與背景的RGB值過於接近,也比較好說明此狀況,為什麼較難分割出物件。 成果呈現 第一張圖:左邊為原圖,右邊為分析結果的圖,用其他顏
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和影像處理庫,它提供了豐富的功能和工具,可用於開發各種視覺應用程式。 OpenCV最初是用C++編寫的,但它也提供了Python、Java等多種程式語言的接口,方便不同語言的開發者使用。
Thumbnail
本文將利用OpenCV的findContours函式,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度。 一般來說,我們在進行輪廓檢測時,會先進行圖像二值化,將對象轉換為白色,背景為黑色。這樣,在找到輪廓後,輪廓的點就會以白色表示,背景為黑色。 結果圖 從圖中綠色框
Thumbnail
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
呈上篇文章,針對單排的圖像文字增加間隔,但如果文字是雙排呢 [OpenCV][Python]OCR分割及增加間隔[單排文字]
Thumbnail
在文字辨識中,適當的增加一文字彼此間的間隔是有幫助於辨識的,原因在大多數OCR引擎在處理字符時會依賴空白區域來區分不同的字符。如果字符之間的間隔過小,OCR引擎可能會將相鄰的字符誤認為一個單一的字符或難以正確切割字符。增加間隔可以幫助OCR引擎更準確地識別和切割每個字符。 本文說明如何增加OCR間
Thumbnail
在影像處理中,有時候我們只想特別關注某個感興趣的區域時,就是ROI的概念,擷取此範圍的圖像來做處理。 設定超過圖像邊界時就會報錯,本文主要介紹如何擷取影像的同時,避免設定錯誤造成程式崩潰的狀況。 擷取圖像示意圖 ROI程式範例 import cv2 import numpy as np
Thumbnail
在某些特殊情況下,需要將圖片進行黑白反轉,例如Tesseract(OCR辨識引擎)就有建議黑底白字的狀況下辨識率較高。 本文將使用 NumPy 進行影像黑白反轉,並顯示反轉前後的影像。
Thumbnail
在影像辨識中,若遇到物件與背景難以分辨的狀況下,先做一下色彩分析,知道了色彩強度階層上的像素數,有助於了解後續需要做什麼處理,比較好分割出辨識物。 若想辨識的物件與背景的RGB值過於接近,也比較好說明此狀況,為什麼較難分割出物件。 成果呈現 第一張圖:左邊為原圖,右邊為分析結果的圖,用其他顏
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和影像處理庫,它提供了豐富的功能和工具,可用於開發各種視覺應用程式。 OpenCV最初是用C++編寫的,但它也提供了Python、Java等多種程式語言的接口,方便不同語言的開發者使用。
Thumbnail
本文將利用OpenCV的findContours函式,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度。 一般來說,我們在進行輪廓檢測時,會先進行圖像二值化,將對象轉換為白色,背景為黑色。這樣,在找到輪廓後,輪廓的點就會以白色表示,背景為黑色。 結果圖 從圖中綠色框
Thumbnail
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉