🦀【影像處理新手必看】二值圖像型態與像素值的陷阱:端點偵測踩雷全紀錄

更新於 發佈於 閱讀時間約 8 分鐘

在 Python 影像處理(OpenCV、skimage)專案中,二值圖像的像素值與資料型態常常讓人踩雷!

本文以「骨架端點偵測」為例,帶你認識這個常見問題、如何避免,以及正確的寫法。


1️⃣ 問題背景

我們常會用**骨架化(skeletonization)**來分析物件形狀,並想找出骨架的端點(endpoints)。端點偵測常見兩種方法:

找到的結果是一致的

差別在效率

raw-image
raw-image


  • filter2D 卷積法(適合 0/1 二值圖)
  • for-loop 8鄰域法(適合 0/255 二值圖)

7x5「數字 1」骨架(端點明顯版)

0/1 格式(for filter2d)

0 0 0 0 0
0 0 1 0 0端點 (1,2)
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0

0/255 格式(for loop)

  0   0   0   0   0
0 0 255 0 0端點 (1,2)
0 0 255 0 0
0 0 255 0 0
0 0 255 0 0
0 0 255 0 0
0 0 0 0 0

端點位置

  • (1,2) (第二列第三行)
  • (5,2) (第六列第三行)

這兩個點就是骨架的端點,因為它們只連接一個骨架點。


視覺化標註

0 0 0 0 0
0 0 x 0 0端點 (1,2)
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 x 0 0端點 (5,2)
0 0 0 0 0

但如果圖像型態搞錯,就會發生「偵測不到端點」的慘劇!


2️⃣ 常見踩雷情境

範例一:filter2D 只適用 0/1 圖像

def find_skeleton_endpoints_filter2d(skeleton: np.ndarray) -> np.ndarray:
kernel = np.array([[1,1,1], [1,10,1], [1,1,1]], dtype=np.uint8)
filtered = cv2.filter2D(skeleton, -1, kernel)
endpoints = (filtered == 11).astype(np.uint8)
return endpoints

錯誤用法:

skeleton = skeletonize(binary > 0).astype(np.uint8) * 255  # 這時像素值是 0/255
endpoints = find_skeleton_endpoints_filter2d(skeleton) # ❌ 找不到端點

正確用法:

skeleton = skeletonize(binary > 0).astype(np.uint8)        # 這時像素值是 0/1
endpoints = find_skeleton_endpoints_filter2d(skeleton) # ✅ 正常偵測

範例二:for-loop 8鄰域法適用 0/255

def find_skeleton_endpoints_loop(skeleton: np.ndarray) -> list:
h, w = skeleton.shape
endpoints = []
for y in range(1, h - 1):
for x in range(1, w - 1):
if skeleton[y, x] == 255:
neighbors = skeleton[y - 1:y + 2, x - 1:x + 2]
num_neighbors = np.sum(neighbors == 255) - 1
if num_neighbors == 1:
endpoints.append((y, x))
return endpoints

這裡預設骨架點是 255,如果你傳進去的是 0/1 圖像,會找不到端點!


3️⃣ 解決方法與最佳實踐

✅ 1. 明確轉換像素值

  • filter2D 方法前,請轉成 0/1:
    skeleton_01 = (skeleton > 0).astype(np.uint8)
  • for-loop 方法前,請轉成 0/255:
    skeleton_255 = (skeleton > 0).astype(np.uint8) * 255

✅ 2. 明確註記每個函式的輸入格式

  • 在每個函式 docstring 註明「輸入需為 0/1 或 0/255」。
  • 在主流程中,統一管理資料型態與像素值

✅ 3. 善用 assert 檢查

  • 在函式開頭加上 assert,避免型態錯誤:
    assert np.max(skeleton) in (1, 255), "骨架像素值應為 1 或 255"

4️⃣ 完整範例:兩種端點偵測都正確

# 取得骨架
skeleton_01 = skeletonize(binary_block > 0).astype(np.uint8) # 0/1
skeleton_255 = skeleton_01 * 255 # 0/255

# filter2D 法
endpoints_mask = find_skeleton_endpoints_filter2d(skeleton_01)

# for-loop 法
endpoints_loop = find_skeleton_endpoints_loop(skeleton_255)

5️⃣ 實戰小結

  • filter2D 法:只適用 0/1 圖像
  • for-loop 法:只適用 0/255 圖像
  • 型態不一致會導致偵測失敗!
  • 養成習慣:每次處理二值圖像都明確轉型、註明型態

6️⃣ 常見問答

Q:為什麼 OpenCV 有時會自動把 0/1 轉成 0/255?

A:OpenCV 的大多數函式預設處理 8-bit 圖像(0~255),但 skimage 等科學套件常用 0/1。兩者混用時,務必手動轉型。

Q:有沒有一個「萬用端點偵測」?

A:建議根據資料型態選擇方法,或在函式內自動轉型。


7️⃣ 結語

資料型態與像素值的混用,是影像處理最常見的 bug 來源之一。

每次處理二值圖像,請務必檢查型態與像素值!

這樣就能避免「端點偵測不到」這種隱藏 bug,讓你的程式更穩定、易維護!


留言
avatar-img
留言分享你的想法!
avatar-img
螃蟹_crab的沙龍
150會員
294內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。 興趣是攝影,踏青,探索未知領域。 人生就是不斷的挑戰及自我認清,希望老了躺在床上不會後悔自己什麼都沒做。
螃蟹_crab的沙龍的其他內容
2025/02/15
在電腦視覺應用中,輪廓(Contour)常用來描述物體的邊界。 當圖像中有雜訊或物體邊緣過於複雜時,我們可以利用輪廓逼近技術,將輪廓簡化成較少點數的多邊形,這不僅有助於後續的形狀分析,也能提高處理速度。 本文將介紹如何使用 OpenCV 中的 cv2.arcLength 與 cv2.approx
Thumbnail
2025/02/15
在電腦視覺應用中,輪廓(Contour)常用來描述物體的邊界。 當圖像中有雜訊或物體邊緣過於複雜時,我們可以利用輪廓逼近技術,將輪廓簡化成較少點數的多邊形,這不僅有助於後續的形狀分析,也能提高處理速度。 本文將介紹如何使用 OpenCV 中的 cv2.arcLength 與 cv2.approx
Thumbnail
2024/12/02
中值濾波器(Adaptive Median Filter)是一種針對噪聲去除的圖像處理技術,主要應用於處理含有椒鹽雜訊的圖像,但在椒鹽雜訊過大時就會面臨,若為了處理掉雜訊,使用的處理窗口(kernel)就要大一點,會造成圖像的邊緣模糊掉。 後面為解決這個問題,就發展了自適應中值濾波器,其概念源自於
Thumbnail
2024/12/02
中值濾波器(Adaptive Median Filter)是一種針對噪聲去除的圖像處理技術,主要應用於處理含有椒鹽雜訊的圖像,但在椒鹽雜訊過大時就會面臨,若為了處理掉雜訊,使用的處理窗口(kernel)就要大一點,會造成圖像的邊緣模糊掉。 後面為解決這個問題,就發展了自適應中值濾波器,其概念源自於
Thumbnail
2024/10/03
在影像處理中,形態學操作是非常重要的一種技術,能夠幫助我們去除噪點、強化特徵、修復物體的形狀等。形態學操作的核心是「結構元素」(kernel),不同形狀的結構元素會產生不同的處理效果。本文將介紹如何使用不同形狀的結構元素來進行圖像處理,並結合實際程式範例和測試圖片來說明其效果。
Thumbnail
2024/10/03
在影像處理中,形態學操作是非常重要的一種技術,能夠幫助我們去除噪點、強化特徵、修復物體的形狀等。形態學操作的核心是「結構元素」(kernel),不同形狀的結構元素會產生不同的處理效果。本文將介紹如何使用不同形狀的結構元素來進行圖像處理,並結合實際程式範例和測試圖片來說明其效果。
Thumbnail
看更多
你可能也想看
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
本文將說明如何去辨識出圖片文字​位置及高寬。
Thumbnail
本文將說明如何去辨識出圖片文字​位置及高寬。
Thumbnail
在影像處理中,有時候我們只想特別關注某個感興趣的區域時,就是ROI的概念,擷取此範圍的圖像來做處理。 設定超過圖像邊界時就會報錯,本文主要介紹如何擷取影像的同時,避免設定錯誤造成程式崩潰的狀況。 擷取圖像示意圖 ROI程式範例 import cv2 import numpy as np
Thumbnail
在影像處理中,有時候我們只想特別關注某個感興趣的區域時,就是ROI的概念,擷取此範圍的圖像來做處理。 設定超過圖像邊界時就會報錯,本文主要介紹如何擷取影像的同時,避免設定錯誤造成程式崩潰的狀況。 擷取圖像示意圖 ROI程式範例 import cv2 import numpy as np
Thumbnail
在影像辨識中,若遇到物件與背景難以分辨的狀況下,先做一下色彩分析,知道了色彩強度階層上的像素數,有助於了解後續需要做什麼處理,比較好分割出辨識物。 若想辨識的物件與背景的RGB值過於接近,也比較好說明此狀況,為什麼較難分割出物件。 成果呈現 第一張圖:左邊為原圖,右邊為分析結果的圖,用其他顏
Thumbnail
在影像辨識中,若遇到物件與背景難以分辨的狀況下,先做一下色彩分析,知道了色彩強度階層上的像素數,有助於了解後續需要做什麼處理,比較好分割出辨識物。 若想辨識的物件與背景的RGB值過於接近,也比較好說明此狀況,為什麼較難分割出物件。 成果呈現 第一張圖:左邊為原圖,右邊為分析結果的圖,用其他顏
Thumbnail
接續上一邊,分割了螺絲與螺母的圖像,但分割後的結果,因為螺絲過於接近的關係,沒有切割乾淨,會有其他螺絲的頭或者身體,這樣會影響到後續量測。 [OpenCV應用][Python]擷取出螺絲或螺母的影像 本文主要是,如何去除掉不要的背景雜物。 下層為原先分割的圖,上層為去除背景雜物的圖。
Thumbnail
接續上一邊,分割了螺絲與螺母的圖像,但分割後的結果,因為螺絲過於接近的關係,沒有切割乾淨,會有其他螺絲的頭或者身體,這樣會影響到後續量測。 [OpenCV應用][Python]擷取出螺絲或螺母的影像 本文主要是,如何去除掉不要的背景雜物。 下層為原先分割的圖,上層為去除背景雜物的圖。
Thumbnail
此篇為上一篇文章的延伸,先辦別是螺絲還是螺母才擷取出影像。 [OpenCV應用][Python]利用findContours辨識螺絲還是螺母 因為可能會需要另外處理螺絲與螺母才可以準確地去做量測,所以第一步就是先分割出這兩種的圖像。
Thumbnail
此篇為上一篇文章的延伸,先辦別是螺絲還是螺母才擷取出影像。 [OpenCV應用][Python]利用findContours辨識螺絲還是螺母 因為可能會需要另外處理螺絲與螺母才可以準確地去做量測,所以第一步就是先分割出這兩種的圖像。
Thumbnail
[OpenCV應用][Python]找出圖像中的四個方位的邊緣點求出寬高 呈上篇應用Numpy找到的座標點,那我們如何捨棄掉差異過大的座標點呢? 可能圖像物件邊緣不佳,採樣就會差異過大,造成計算出的寬高是不準確的。 遇到這種狀況,就可以使用下方的程式範例來篩選座標點。 為求方便,此範例跟圖
Thumbnail
[OpenCV應用][Python]找出圖像中的四個方位的邊緣點求出寬高 呈上篇應用Numpy找到的座標點,那我們如何捨棄掉差異過大的座標點呢? 可能圖像物件邊緣不佳,採樣就會差異過大,造成計算出的寬高是不準確的。 遇到這種狀況,就可以使用下方的程式範例來篩選座標點。 為求方便,此範例跟圖
Thumbnail
觀看本文將可以學習到如何利用Numpy求得物件的邊緣點,及算出物件的寬跟高。 有詳細的程式邏輯說明,及各函式用法說明。 綠點及紅點則是採樣到的邊界點,比較粗的點是偵測到的最大值 完整程式碼 import cv2 import numpy as np import matplotl
Thumbnail
觀看本文將可以學習到如何利用Numpy求得物件的邊緣點,及算出物件的寬跟高。 有詳細的程式邏輯說明,及各函式用法說明。 綠點及紅點則是採樣到的邊界點,比較粗的點是偵測到的最大值 完整程式碼 import cv2 import numpy as np import matplotl
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News