付費限定

[OpenCV應用][Python]應用watershed分割圖像(硬幣分割)

更新於 2024/03/15閱讀時間約 16 分鐘

本文參考OpenCV官方Image Segmentation with Watershed Algorithm來實作分割相黏的硬幣

相較於官方範例,多新增取出分割後的物件的中心點來標註,大部分在分割圖像後我們都想知道分割後物件的位置(x,y)。

結果圖

二值化 -> 像素到背景的距離圖 -> 前景圖 ->分割背景圖

標記圖 -> 分割後的圖 -> 套用到原圖並畫出中心

分割結果圖

分割結果圖

OpenCV 實作了一種基於標記的分水嶺演算法物件賦予不同的標籤用一種顏色(或強度)標記我們確定是前景或物體的區域,用另一種顏色標記我們確定是背景或非物體的區域最後標記我們不確定的區域,用0 標記它。然後應用分水嶺演算法。將使用我們給出的標籤進行更新,並且物件的邊界的值為-1。

標記圖像的數值對應於不同的標籤,常見的標籤值為正整數,但有一些特殊值:

正整數: 表示已知的區域,其中每個數字代表一個不同的標籤。

例如,1 表示前景,2 表示背景,0表示不確定的區域。

-1: 在分水嶺演算法後,標記圖像的邊界值會被設為-1。這樣可以用來標示物體的邊界。

程式範例

import numpy as np
import cv2
from matplotlib import pyplot as plt
import copy
img = cv2.imread('coins.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# noise removal 噪聲去除
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
sure_bg = cv2.dilate(opening,kernel,iterations=3)
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
_, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)

# Finding unknown region 找到未知區域
sure_fg = np.uint8(sure_fg) #
unknown = cv2.subtract(sure_bg,sure_fg)

# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers + 1
# Now, mark the region of unknown with zero。
markers[unknown==255] = 0

#watershed
markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]

# 在 'markers' 陣列中找到唯一的標籤
unique_labels = np.unique(markers)

# 排除標籤 -1(表示watershed邊界)
unique_labels = unique_labels[unique_labels != -1]

# 將 'img' 轉換為 RGB 以便視覺化
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 逐一處理每個標籤,找到其中心
for label in unique_labels:
mask = (markers == label) # 建立當前標籤的遮罩
ys, xs = np.where(mask) # 找到當前標籤所有像素的座標

# 計算中心座標
centroid = (np.mean(xs), np.mean(ys)) # (mean x, mean y)

# 將中心座標轉換為整數
center_coordinates = (int(centroid[0]), int(centroid[1])) # (x, y)

# 在中心繪製一個圓
cv2.circle(img_rgb, center_coordinates, radius=5, color=(255, 0, 0), thickness=-1) # -1 fills the circle

# Display the result
plt.imshow(img_rgb)
plt.title('Centroids Marked')
plt.axis('off')
plt.show()
程式結果圖

程式結果圖



程 式 解 析

將會拆解程式範例,並輸出圖片,直觀的了解每個步驟輸出的圖

載入圖片

使用 Otsu 的二值化。

import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('coins.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
#因用ipynb呈現,需plt與opencv默認RGB不同需轉換
gray = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
gray = cv2.cvtColor(thresh, cv2.COLOR_BGR2RGB)
plt.imshow(gray)
plt.axis('off')
plt.show()
raw-image

前處理步驟

主要用於確定前景背景區域,同時找到未知區域(物體邊界)。

  1. 通過對二值化圖像 thresh 執行兩次開運算,清除圖像中的小斑點或小區域
  2. 膨脹操作(Dilation),通過對 opening 圖像進行三次膨脹操作,確定背景區域
  3. 距離變換(Distance Transform)和二值化操作,將這些距離轉換為二進制圖像,形成確定的前景區域
  4. 背景區域減去前景區域。未知區域是分水嶺演算法中需要進一步處理的區域
import copy
# noise removal 去除雜訊
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
#通過對二值化圖像 thresh 執行兩次開運算,清除圖像中的小斑點或小區域。

# sure background area 確定背景區域
sure_bg = cv2.dilate(opening,kernel,iterations=3)
#通過對 opening 圖像進行三次膨脹操作,進一步確定背景區域。

# Finding sure foreground area 找到確定的前景區域:
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
#使用 distanceTransform 函數計算二值化圖像 opening 中每個像素到最近的零像素的距離。
_, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# 通過 threshold 函數將這些距離轉換為二進制圖像,形成確定的前景區域

# Finding unknown region 找到未知區域
sure_fg = np.uint8(sure_fg) # 將確定的前景區域(二進制圖像)轉換為 8 位的無符號整數型別 uint8
unknown = cv2.subtract(sure_bg,sure_fg) #通過 subtract 函數找到未知區域,即背景區域減去前景區域。

#因用ipynb呈現,需plt與opencv默認RGB不同需轉換
unknown_show = cv2.cvtColor(unknown, cv2.COLOR_GRAY2BGR)
unknown_show = cv2.cvtColor(unknown_show, cv2.COLOR_BGR2RGB)
sure_fg_Show = cv2.cvtColor(sure_fg, cv2.COLOR_GRAY2BGR)
sure_fg_Show = cv2.cvtColor(sure_fg_Show, cv2.COLOR_BGR2RGB)
plt.subplot(1, 3, 1), plt.imshow(dist_transform), plt.title('dist_transform'), plt.axis('off')
plt.subplot(1, 3, 2), plt.imshow(sure_fg_Show), plt.title('sure_fg'), plt.axis('off')
plt.subplot(1, 3, 3), plt.imshow(unknown_show), plt.title('unknown'), plt.axis('off')
plt.show()

左圖:像素到背景的距離圖

中間的圖:找到的前景圖

右圖:物體邊界圖

raw-image

建立標記

以行動支持創作者!付費即可解鎖
本篇內容共 6493 字、0 則留言,僅發佈於[Python][OpenCV]學習心得筆記你目前無法檢視以下內容,可能因為尚未登入,或沒有該房間的查看權限。
avatar-img
128會員
209內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
本文介紹OpenCV中的SimpleBlobDetector用於檢測斑點或圓,以及其與霍夫轉換找圓方法的差異。透過程式範例和解析,講解檢測到的關鍵點和設定參數,並整理SimpleBlobDetector與霍夫轉換的不同。最後,探討不同的應用場景和參數調整。
大部分在求物件的寬度及高度,都會想到用OpenCV的findContours函式來做,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度 [OpenCV應用][Python]利用findContours找出物件邊界框求出寬度及高度 本文將用不同的方法,利用Numpy
本文將利用OpenCV的findContours函式,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度。 一般來說,我們在進行輪廓檢測時,會先進行圖像二值化,將對象轉換為白色,背景為黑色。這樣,在找到輪廓後,輪廓的點就會以白色表示,背景為黑色。 結果圖 從圖中綠色框
利用OPENCV,實現SIFT應用,尋找圖片中物件的旋轉角度 本文介紹主要提出SIFT提取關鍵角點的座標,由此算出物件的旋轉角度 程式功能介紹 : 導入待檢測圖及樣本圖,則會依照樣本圖中的物件為基準
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉
本文介紹OpenCV中的SimpleBlobDetector用於檢測斑點或圓,以及其與霍夫轉換找圓方法的差異。透過程式範例和解析,講解檢測到的關鍵點和設定參數,並整理SimpleBlobDetector與霍夫轉換的不同。最後,探討不同的應用場景和參數調整。
大部分在求物件的寬度及高度,都會想到用OpenCV的findContours函式來做,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度 [OpenCV應用][Python]利用findContours找出物件邊界框求出寬度及高度 本文將用不同的方法,利用Numpy
本文將利用OpenCV的findContours函式,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度。 一般來說,我們在進行輪廓檢測時,會先進行圖像二值化,將對象轉換為白色,背景為黑色。這樣,在找到輪廓後,輪廓的點就會以白色表示,背景為黑色。 結果圖 從圖中綠色框
利用OPENCV,實現SIFT應用,尋找圖片中物件的旋轉角度 本文介紹主要提出SIFT提取關鍵角點的座標,由此算出物件的旋轉角度 程式功能介紹 : 導入待檢測圖及樣本圖,則會依照樣本圖中的物件為基準
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
在樹莓派安裝OpenCV的紀錄。板子是樹莓派3B(沒有+),系統raspbian bullseye 32bit灌到USB隨身碟。
Thumbnail
#安裝 OpenCV 相關套件 pip install opencv-python pip install opencv-contrib-python pip install matplotlib
Haar Cascade classifier OpenCV 官方 Github:https://github.com/opencv/opencv/tree/4.x/data 人臉特徵模型:haarcascade_frontalface_default.xml 資料來源: https://steam
Thumbnail
OpenCV 讀取圖片 原碼:https://reurl.cc/3354ZL 成果: OpenCV 本身有提供讀取圖檔的函數可用,讀取圖檔,只要呼叫 cv2.imread 即可將圖片讀取進來,以 cv2.imread 讀進來的資料,會儲存成一個 NumPy 的陣列。 將圖片讀取進來之後,可使用 c
opencv is use BGR color matplotlib is use RGB color 顯示圖片 opencv matplotlib
Thumbnail
初稿 作者: Stan Ht. Wu (stanwu 吳信典) 想像一下,如果整台電腦裝瀏覽器就好了?這樣多輕鬆啊!人生就是要斷捨離,什麼都不裝,就用瀏覽器就好了,您看連寫方格子的文章也是直接用瀏覽器耶!! 用瀏覽器基本上是最符合懶人原則,為什麼呢?因為從頭到尾根本不需要切換應用程式,存檔案放在雲端
Thumbnail
OpenCart 官方的 3.0.3.7 版於上周釋出,除了修正許多 3.0.x 版累積的小問題,也更新了 twig 套件解決了 PHP 7.4 的相容問題,所以 OpenCart 台灣電商技術團隊,也以 OpenCart 3.0.3.7 版為基礎,加上了在地優化及實用模組,推出台灣優化版。
Thumbnail
綠界科技雖然為 OpenCart 電商系統推出了可直接安裝使用的金流擴充模組,但其設計的模組架構,並不算完全符合 OpenCart 金流模組的架構規則,包含後臺編輯不同付款方式時的設定,無法獨立分開設定,前台的金流選擇,更是被設計成兩段式的模式,非常不符合台灣消費者慣用的習性。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
在樹莓派安裝OpenCV的紀錄。板子是樹莓派3B(沒有+),系統raspbian bullseye 32bit灌到USB隨身碟。
Thumbnail
#安裝 OpenCV 相關套件 pip install opencv-python pip install opencv-contrib-python pip install matplotlib
Haar Cascade classifier OpenCV 官方 Github:https://github.com/opencv/opencv/tree/4.x/data 人臉特徵模型:haarcascade_frontalface_default.xml 資料來源: https://steam
Thumbnail
OpenCV 讀取圖片 原碼:https://reurl.cc/3354ZL 成果: OpenCV 本身有提供讀取圖檔的函數可用,讀取圖檔,只要呼叫 cv2.imread 即可將圖片讀取進來,以 cv2.imread 讀進來的資料,會儲存成一個 NumPy 的陣列。 將圖片讀取進來之後,可使用 c
opencv is use BGR color matplotlib is use RGB color 顯示圖片 opencv matplotlib
Thumbnail
初稿 作者: Stan Ht. Wu (stanwu 吳信典) 想像一下,如果整台電腦裝瀏覽器就好了?這樣多輕鬆啊!人生就是要斷捨離,什麼都不裝,就用瀏覽器就好了,您看連寫方格子的文章也是直接用瀏覽器耶!! 用瀏覽器基本上是最符合懶人原則,為什麼呢?因為從頭到尾根本不需要切換應用程式,存檔案放在雲端
Thumbnail
OpenCart 官方的 3.0.3.7 版於上周釋出,除了修正許多 3.0.x 版累積的小問題,也更新了 twig 套件解決了 PHP 7.4 的相容問題,所以 OpenCart 台灣電商技術團隊,也以 OpenCart 3.0.3.7 版為基礎,加上了在地優化及實用模組,推出台灣優化版。
Thumbnail
綠界科技雖然為 OpenCart 電商系統推出了可直接安裝使用的金流擴充模組,但其設計的模組架構,並不算完全符合 OpenCart 金流模組的架構規則,包含後臺編輯不同付款方式時的設定,無法獨立分開設定,前台的金流選擇,更是被設計成兩段式的模式,非常不符合台灣消費者慣用的習性。