OpenCV 查詢輪廓

GoCodingInMyWay發表於2021-06-07

本文將結合例項程式碼,介紹 OpenCV 如何查詢輪廓、獲取邊界框。

OpenCV 提供了 findContours 函式查詢輪廓,需要以二值化影像作為輸入、並指定些選項呼叫即可。

我們以下圖作為示例:

二值化影像

程式碼工程 data/ 提供了小狗和紅球的二值化掩膜影像:

其使用預訓練好的例項分割模型來生成的,指令碼可見 detectron2_seg_threshold.py。模型檢出結果,如下:

模型用的 Mask R-CNN 已有預測邊框。但其他模型會有隻出預測掩膜的,此時想要邊框就可以使用 OpenCV 來提取。

本文程式碼也提供了根據色域來獲取紅球掩膜的辦法:

import cv2 as cv
import numpy as np

# 讀取影像
img = cv.imread(args.image, cv.IMREAD_COLOR)

# HSV 閾值,獲取掩膜
def _threshold_hsv(image, lower, upper):
  hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
  mask = cv.inRange(hsv, lower, upper)
  result = cv.bitwise_and(image, image, mask=mask)
  return result, mask

_, thres = _threshold_hsv(img, np.array([0,110,190]), np.array([7,255,255]))

# 清除小點(可選)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (1, 1))
thres = cv.morphologyEx(thres, cv.MORPH_OPEN, kernel)

查詢輪廓

# 查詢輪廓
#  cv.RETR_EXTERNAL: 只查詢外部輪廓
contours, hierarchy = cv.findContours(
  threshold, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# 近似輪廓,減點(可選)
contours_poly = [cv.approxPolyDP(c, 3, True) for c in contours]

# 繪製輪廓
h, w = threshold.shape[:2]
drawing = np.zeros((h, w, 3), dtype=np.uint8)
for i in range(len(contours)):
  cv.drawContours(drawing, contours_poly, i, (0, 255, 0), 1, cv.LINE_8, hierarchy)

獲取邊界框

boundingRect 獲取邊界框,並繪製:

for contour in contours_poly:
  rect = cv.boundingRect(contour)
  cv.rectangle(drawing,
                (int(rect[0]), int(rect[1])),
                (int(rect[0]+rect[2]), int(rect[1]+rect[3])),
                (0, 255, 0), 2, cv.LINE_8)

minEnclosingCircle 獲取邊界圈,並繪製:

for contour in contours_poly:
  center, radius = cv.minEnclosingCircle(contour)
  cv.circle(drawing, (int(center[0]), int(center[1])), int(radius),
            (0, 255, 0), 2, cv.LINE_8)

參考

GoCoding 個人實踐的經驗分享,可關注公眾號!

相關文章