日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Python OpenCV GrabCut进行前景分割和提取

發布時間:2023/11/27 生活经验 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python OpenCV GrabCut进行前景分割和提取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python OpenCV GrabCut進行前景分割和提取

    • 1. 效果圖
    • 1.1 邊界框GrabCut效果圖
      • 1.2 Mask GrabCut效果圖
    • 2. GrabCut原理
      • 2.1 GrabCut是什么及步驟
      • 2.2 grabCut(img, mask, rect, bgdModel, fgdModel, iterCount)
      • 2.3 GrabCut與R-CNN對比
    • 3. 源代碼
      • 3.1 根據邊界框執行GrabCut
      • 3.2 根據Mask執行GrabCut
    • 參考

圖像掩模Mask是圖像處理的基本概念。這篇博客將介紹如何使用OpenCV和GrabCut算法執行前景分割和提取。Grabcut算法通過CV2.grabcut實現,可以通過以下任一方法初始化:

1)前景邊界框,屏蔽近似圖像中對象的像素的位置
2)使用近似前景掩碼;

雖然基于深度學習的圖像分割網絡(例如,掩碼R-CNN和U-NET)實際檢測和近似圖像中對象的掩碼,但也并不完美,可能帶有噪點;可以輔助使用Grabcut來清理這些細分網絡返回的“雜亂”掩碼!

1. 效果圖

1.1 邊界框GrabCut效果圖

輸入圖像 VS GrabCut Mask VS 最終效果圖

構建第一張輸入圖像可以使用Thresholding、Canny邊緣檢測,輪廓檢測,基于深度學習的分割以及cv2.inRange(hsv,low_color,high_color)顏色范圍

效果圖2:輸入圖像 VS GrabCut Mask VS 最終效果圖

1.2 Mask GrabCut效果圖

原圖與Mask疊加的粗糙效果圖:

確定背景 VS 可能背景 VS 確定前景 VS 可能前景效果圖:

原圖 VS GrabCut 蒙版圖 VS 疊加效果圖如下: 可以看到右側最終效果圖比原始圖還要干凈,去掉了一些雜質噪點;

2. GrabCut原理

2.1 GrabCut是什么及步驟

  • 在深度學習和語義/實例分割如Mask-RCNN,U-Net之前,GrabCut是從背景準確分割圖像前景的方法。
  • GrabCut 接受帶有(1)一個邊界框的輸入圖像,該邊界框指定了要分割的圖像中對象的位置;(2)一個與分割近似的蒙版

并迭代以下步驟:

  1. 通過高斯混合模型(GMM)估算前景和背景的顏色分布
  2. 在像素標簽上構建Markov隨機字段(即前景與背景)
  3. 應用圖割優化最終細分結果

2.2 grabCut(img, mask, rect, bgdModel, fgdModel, iterCount)

1. 入參

  • img: 輸入圖像,無符號8位int的 BRG三通道圖像;
  • mask:單通道無符號8位int,默認邊界框初始化(即cv2.GC_INIT_WITH_RECT); 否則GrabCut假設執行掩碼初始化(cv2.GC_INIT_WITH_MASK);
  • rect:包含要分割的區域的邊界框矩形。僅在設置模式是cv2.GC_INIT_WITH_RECT時使用此參數;
  • bgModel:當對背景建模時,GrabCut內部使用的臨時數組;
  • fgModel:對前景建模時,GrabCut使用的臨時數組;
  • iterCount:對前景和背景建模時,GrabCut將執行的迭代次數。迭代次數越多,GrabCut運行時間將越長,結果會更好;
  • mode:使用初始化GrabCut的模式類型,cv2.GC_INIT_WITH_RECT或cv2.GC_INIT_WITH_MASK;

2. 返回值:一個三元組

  • mask:應用GrabCut后的輸出蒙版
  • bgModel:用于背景建模的臨時數組
  • fgModel:用于前景建模的臨時數組

2.3 GrabCut與R-CNN對比

  • GrabCut是好的,但并不是完美的;和背景粘連色很相似的可能會丟失。
  • 雖然R-CNN和U-Net更快,但它們可能得出凌亂的Mask結果。可以使用grabcut來幫助清理Mask的部分污點。

3. 源代碼

3.1 根據邊界框執行GrabCut

# USAGE
# python grabcut_bbox.py --image images/06_output.jpgimport argparse
import os
import timeimport cv2
import imutils
# 導入必要的包
import numpy as np# 構建命令行參數及解析
# --images 輸入圖像
# --iter 要執行的grabcut迭代的數量,其中較小的值導致更快的總時間;更大的值導致較慢的運行,但更理想的分段結果;
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str,default=os.path.sep.join(["images", "06_output.jpg"]),help="path to input image that we'll apply GrabCut to")
ap.add_argument("-c", "--iter", type=int, default=10,help="# of GrabCut iterations (larger value => slower runtime)")
args = vars(ap.parse_args())# 從磁盤加載輸入圖像,然后為grabcut輸出的mask分配空間,將和輸入圖像擁有相同的空間維度
image = cv2.imread(args["image"])
width = image.shape[0]
image = imutils.resize(image, width=450)
cv2.imshow("Input", image)
cv2.waitKey(0)
mask = np.zeros(image.shape[:2], dtype="uint8")# 定義邊界框坐標,大致包括臉和脖子區域
rect = (81, 262, 171, 168)# 為倆個數組分配內存,GrabCut算法從背景中分割前景時會用到
fgModel = np.zeros((1, 65), dtype="float")
bgModel = np.zeros((1, 65), dtype="float")# 使用GrabCut應用邊界框分割方法
start = time.time()
(mask, bgModel, fgModel) = cv2.grabCut(image, mask, rect, bgModel,fgModel, iterCount=args["iter"], mode=cv2.GC_INIT_WITH_RECT)
end = time.time()
print("[INFO] applying GrabCut took {:.2f} seconds".format(end - start))# 輸出mask有4種可能的結果:標記每一個像素為1、確定背景;2、確定前景;3、可能背景;4、可能前景
# 0、 2、 1、 3
values = (("Definite Background", cv2.GC_BGD),("Probable Background", cv2.GC_PR_BGD),("Definite Foreground", cv2.GC_FGD),("Probable Foreground", cv2.GC_PR_FGD),
)# 遍歷可能的MaskGrab區域
for (name, value) in values:print(name, value)# 為當前值構建maskprint("[INFO] showing mask for '{}'".format(name))valueMask = (mask == value).astype("uint8") * 255# mask可視化cv2.imshow(name, valueMask)cv2.waitKey(0)# 設置所有確定背景和可能背景為0,設置所有確定前景和可能前景為1
outputMask = np.where((mask == cv2.GC_BGD) | (mask == cv2.GC_PR_BGD), 0, 1)# 縮放mask的像素值由[0,1] 到 [0,255]
outputMask = (outputMask * 255).astype("uint8")# 使用mask對圖像進行按位與得到最終輸出圖像
output = cv2.bitwise_and(image, image, mask=outputMask)
# output_or = cv2.bitwise_or(image, image, mask=outputMask)
# output_xor = cv2.bitwise_xor(image, image, mask=outputMask)
# output_not = cv2.bitwise_not(image, image, mask=outputMask)# 展示輸入圖像,GrabCut mask, 原始圖像的前景+ 通過Grabcut Mask得到的背景的迭加圖
cv2.imshow("Input", image)
cv2.imshow("GrabCut Mask", outputMask)
cv2.imshow("GrabCut Output", output)
# cv2.imshow("GrabCut Output not", output_not)
# cv2.imshow("GrabCut Output xor", output_xor)
# cv2.imshow("GrabCut Output or", output_or)
# cv2.imwrite("D:\\py-demo\\20210331\\grab_cut\\images\\06_.jpg", imutils.resize(output_not, width=width))
cv2.waitKey(0)

3.2 根據Mask執行GrabCut

Mask可以通過:在照片編輯軟件如如Photoshop,Gimp中手動創建,也可應用基本圖像處理操作,例如閾值,邊緣檢測,輪廓濾波等,或者利用基于深度學習的分割網絡(例如,掩碼R-CNN和U-NET)。

# USAGE
# python grabcut_mask.py --image images/thl.jpg --mask images/thl_mask2.jpg# 導入必要的包
import numpy as np
import argparse
import time
import cv2
import os
import imutils# 構建命令行參數及解析
# --image 輸入圖像
# --mask 輸入Mask
# --iter 迭代次數,非必選,默認10
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str,default=os.path.sep.join(["images", "thl.jpg"]),help="path to input image that we'll apply GrabCut to")
ap.add_argument("-mask", "--mask", type=str,default=os.path.sep.join(["images", "thl_mask2.jpg"]),help="path to input mask")
ap.add_argument("-c", "--iter", type=int, default=10,help="# of GrabCut iterations (larger value => slower runtime)")
args = vars(ap.parse_args())# 從磁盤加載輸入圖像及Mask
image = cv2.imread(args["image"])
image = imutils.resize(image, width=400)
mask = cv2.imread(args["mask"], cv2.IMREAD_GRAYSCALE)
print(image.shape, mask.shape)# 應用按位與看直接合并得到的最粗糙的結果
roughOutput = cv2.bitwise_and(image, image, mask=mask)# 展示粗糙的,近似輸出結果
cv2.imshow("Rough Output", roughOutput)
cv2.waitKey(0)# Mask中任意大于0的像素將被認為是可能的前景,為0的認為是確定的背景
mask[mask > 0] = cv2.GC_PR_FGD
mask[mask == 0] = cv2.GC_BGD# 為Grabcut的前景和背景模型分配內存
fgModel = np.zeros((1, 65), dtype="float")
bgModel = np.zeros((1, 65), dtype="float")# 使用近似掩模分段在圖像上執行Grabcut算法
start = time.time()
(mask, bgModel, fgModel) = cv2.grabCut(image, mask, None, bgModel,fgModel, iterCount=args["iter"], mode=cv2.GC_INIT_WITH_MASK)
end = time.time()
print("[INFO] applying GrabCut took {:.2f} seconds".format(end - start))# 輸出Mask有4種可能的值:1、確定背景 2、確定前景 3、可能背景 4、可能前景
values = (("Definite Background", cv2.GC_BGD),("Probable Background", cv2.GC_PR_BGD),("Definite Foreground", cv2.GC_FGD),("Probable Foreground", cv2.GC_PR_FGD),
)# 遍歷GrabCut可能的結果值
for (name, value) in values:# 為當前值構建maskprint("[INFO] showing mask for '{}'".format(name))valueMask = (mask == value).astype("uint8") * 255# 可視化maskcv2.imshow(name, valueMask)cv2.waitKey(0)# 設置所有確定背景、可能背景像素值為0,設置確定前景、可能前景像素值為1,然后縮放像素值[0,1]到[0, 255]
# 相當于刪除了背景,提取到了前景
outputMask = np.where((mask == cv2.GC_BGD) | (mask == cv2.GC_PR_BGD), 0, 1)
outputMask = (outputMask * 255).astype("uint8")# 使用mask應用按位與得到最終輸出結果圖
output = cv2.bitwise_and(image, image, mask=outputMask)# 展示輸出圖像,GrabCut前景Mask,GrabCut結果圖
cv2.imshow("Input", image)
cv2.imshow("GrabCut Mask", outputMask)
cv2.imshow("GrabCut Output", output)
cv2.waitKey(0)

參考

  • https://www.pyimagesearch.com/2020/07/27/opencv-grabcut-foreground-segmentation-and-extraction/

總結

以上是生活随笔為你收集整理的Python OpenCV GrabCut进行前景分割和提取的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。