函數
cv2.distanceTransform()
用于計算圖像中每一個非零點像素與其最近的零點像素之間的距離(Distance Transform, DT算法),輸出的是保存每一個非零點與最近零點的距離信息;圖像上越亮的點,代表了離零點的距離越遠。
distanceTransformWithLabels 可以返回距離圖和標簽圖。
distance, labels = cv.distanceTransformWithLabels(opn, cv.DIST_L1, 3, labelType=cv.DIST_LABEL_CCOMP)
cv2.distanceTransform(src, # 二通道二值圖,uint8 格式distanceType, # 距離類型maskSize[, # 距離變換掩碼的大小dst[, dstType]] # 要生成的標簽數組的類型) -> dst
參數
src:這是輸入的8位單通道(通常是二值化的)源圖像。每個像素值要么是0(背景),要么是255(前景),函數會計算每個前景像素到最近背景像素的距離。
dst:這是輸出圖像,包含計算出的距離信息。它是一個8位或32位浮點型的單通道圖像,與src圖像具有相同的尺寸。每個像素值表示該像素到最近的背景像素的距離。
labels:這是輸出的二維標簽數組(離散的Voronoi圖)。它具有CV_32SC1(32位整數)類型,并且與src圖像具有相同的尺寸。每個像素值代表了最近的背景像素或背景像素組成的連通組件的標簽。
distanceType:這指定了距離類型,它定義了計算距離的方式,具體包括:
- DIST_L1:城市街區距離,也稱為曼哈頓距離。
- DIST_L2:歐幾里得距離。
- DIST_C:棋盤距離,也稱為無限范數距離。
maskSize:這是距離變換所使用的掩模大小。它定義了計算距離時考慮的鄰域大小。DIST_MASK_PRECISE在此變體中不受支持。對于DIST_L1或DIST_C距離類型,參數被強制為3,因為3×3的掩模可以給出與5×5或任何更大窗口相同的距離結果。
labelType:這定義了要構建的標簽數組的類型,具體包括:
- DIST_LABEL_CCOMP:每個連通組件的背景像素都被賦予一個唯一的標簽。
- DIST_LABEL_PIXEL:每個背景像素都被賦予一個唯一的標簽。
通常,為了快速、粗略的距離估算DIST_L2,使用3×3掩模。為了更精確的距離估算DIST_L2,使用5×5掩模或精確算法。需要注意的是,無論是精確算法還是近似算法,它們的時間復雜度都是與像素數量線性的。
distanceTransformWithLabels
import cv2 as cv# 假設 opn 是經過預處理(如形態學開運算)的二值圖像
distance, labels = cv.distanceTransformWithLabels(opn, distanceType=cv.DIST_L1,maskSize=3,labelType=cv.DIST_LABEL_CCOMP
)
經典應用
提取硬幣前景
path = "..." # 補充圖片路徑
img = cv.imread(path, cv.IMREAD_GRAYSCALE)
_ret, img2 = cv.threshold(img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
kernel = np.ones((3, 3), np.uint8)
opn = cv.morphologyEx(img2, cv.MORPH_OPEN, kernel)
distance = cv.distanceTransform(opn, cv.DIST_L2, 3)
_ret, result = cv.threshold(distance, 0.05 * distance.max(), 255, cv.THRESH_BINARY)plt.subplot(221), plt.imshow(img, cmap='gray'), plt.title('org'), plt.axis('off')
plt.subplot(222), plt.imshow(opn, cmap='gray'), plt.title('opn'), plt.axis('off')
plt.subplot(223), plt.imshow(distance, cmap='gray'), plt.title('distance'), plt.axis('off')
plt.subplot(224), plt.imshow(result, cmap='gray'), plt.title('result'), plt.axis('off')
效果類似于下圖: