付費限定

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

更新於 發佈於 閱讀時間約 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會員
217內容數
本業是影像辨識軟體開發,閒暇時間進修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
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
使用 LBP(Local Binary Patterns) 進行紋理分析和瑕疵檢測 Local Binary Patterns(LBP) 是一種用來描述圖像紋理的特徵提取技術。LBP 對於檢測表面紋理的異常具有很好的效果,尤其在檢測紋理一致的材料表面(例如紡織品、紙張、金屬)時,LBP 非常有用。
Thumbnail
前言 讀了許多理論,是時候實際動手做做看了,以下是我的模型訓練初體驗,有點糟就是了XD。 正文 def conv(filters, kernel_size, strides=1): return Conv2D(filters, kernel_size,
Thumbnail
接續上一邊,分割了螺絲與螺母的圖像,但分割後的結果,因為螺絲過於接近的關係,沒有切割乾淨,會有其他螺絲的頭或者身體,這樣會影響到後續量測。 [OpenCV應用][Python]擷取出螺絲或螺母的影像 本文主要是,如何去除掉不要的背景雜物。 下層為原先分割的圖,上層為去除背景雜物的圖。
Thumbnail
此篇為上一篇文章的延伸,先辦別是螺絲還是螺母才擷取出影像。 [OpenCV應用][Python]利用findContours辨識螺絲還是螺母 因為可能會需要另外處理螺絲與螺母才可以準確地去做量測,所以第一步就是先分割出這兩種的圖像。
Thumbnail
比特幣區塊鏈為了滿足各種不同的需求與技術,目前衍生出四種不同型態的地址形式,主要是針對安全性、靈活性與新版本兼容性的改革。
Thumbnail
先上成果圖,如果是螺母的話就標註 is circle來區分。 簡單的用圖表加文字說明AOI辨識 在此文章的範例中: 影像前處理:色彩空間轉換(灰階) -> 二值化閥值處理 演算法:尋找輪廓 數值判斷:長,寬,面積,周長 圖片來源 程式碼 import cv2 import nu
Thumbnail
網格擴散可以就像剪紙一樣,把紙上想要的部分剪下來。 通過模型的一個點,找到周圍相鄰的點;其他點又能找到周圍相鄰的點,就像水波一樣擴散出去。 許多3D的算法,如裁切、干涉深度偵測等都會用到。
Thumbnail
本文在介紹如何用Python繪製各點大小不同的散布圖及用箭頭標註特殊點
Thumbnail
[OpenCV應用][Python]找出圖像中的四個方位的邊緣點求出寬高 呈上篇應用Numpy找到的座標點,那我們如何捨棄掉差異過大的座標點呢? 可能圖像物件邊緣不佳,採樣就會差異過大,造成計算出的寬高是不準確的。 遇到這種狀況,就可以使用下方的程式範例來篩選座標點。 為求方便,此範例跟圖
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
使用 LBP(Local Binary Patterns) 進行紋理分析和瑕疵檢測 Local Binary Patterns(LBP) 是一種用來描述圖像紋理的特徵提取技術。LBP 對於檢測表面紋理的異常具有很好的效果,尤其在檢測紋理一致的材料表面(例如紡織品、紙張、金屬)時,LBP 非常有用。
Thumbnail
前言 讀了許多理論,是時候實際動手做做看了,以下是我的模型訓練初體驗,有點糟就是了XD。 正文 def conv(filters, kernel_size, strides=1): return Conv2D(filters, kernel_size,
Thumbnail
接續上一邊,分割了螺絲與螺母的圖像,但分割後的結果,因為螺絲過於接近的關係,沒有切割乾淨,會有其他螺絲的頭或者身體,這樣會影響到後續量測。 [OpenCV應用][Python]擷取出螺絲或螺母的影像 本文主要是,如何去除掉不要的背景雜物。 下層為原先分割的圖,上層為去除背景雜物的圖。
Thumbnail
此篇為上一篇文章的延伸,先辦別是螺絲還是螺母才擷取出影像。 [OpenCV應用][Python]利用findContours辨識螺絲還是螺母 因為可能會需要另外處理螺絲與螺母才可以準確地去做量測,所以第一步就是先分割出這兩種的圖像。
Thumbnail
比特幣區塊鏈為了滿足各種不同的需求與技術,目前衍生出四種不同型態的地址形式,主要是針對安全性、靈活性與新版本兼容性的改革。
Thumbnail
先上成果圖,如果是螺母的話就標註 is circle來區分。 簡單的用圖表加文字說明AOI辨識 在此文章的範例中: 影像前處理:色彩空間轉換(灰階) -> 二值化閥值處理 演算法:尋找輪廓 數值判斷:長,寬,面積,周長 圖片來源 程式碼 import cv2 import nu
Thumbnail
網格擴散可以就像剪紙一樣,把紙上想要的部分剪下來。 通過模型的一個點,找到周圍相鄰的點;其他點又能找到周圍相鄰的點,就像水波一樣擴散出去。 許多3D的算法,如裁切、干涉深度偵測等都會用到。
Thumbnail
本文在介紹如何用Python繪製各點大小不同的散布圖及用箭頭標註特殊點
Thumbnail
[OpenCV應用][Python]找出圖像中的四個方位的邊緣點求出寬高 呈上篇應用Numpy找到的座標點,那我們如何捨棄掉差異過大的座標點呢? 可能圖像物件邊緣不佳,採樣就會差異過大,造成計算出的寬高是不準確的。 遇到這種狀況,就可以使用下方的程式範例來篩選座標點。 為求方便,此範例跟圖