我有从分割模型获得的二进制掩模,我只想得到其轮廓的四个角,其中包括具有最小面积的大多数点,如下图所示:
角不一定形成矩形,并且掩模有噪声:
我尝试过轮廓检测、近似和
minAreaRect
,但矩形在很多情况下比形状更宽,并且没有最小化到我想要的极限:
#!/usr/bin/env python3
import os
from os import path as osp
import cv2
import numpy as np
path = "seg_masks"
im_list = os.listdir(path)
def lcc(binary_image:np.ndarray)->np.ndarray:
# Find connected components
print(binary_image.shape, binary_image.dtype)
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_image, connectivity=8)
# Find the label (index) of the largest connected component
largest_component_label = np.argmax(stats[1:, cv2.CC_STAT_AREA]) + 1 # Skip background label (0)
largest_component_mask = (labels == largest_component_label).astype(np.uint8)
largest_component_mask = largest_component_mask.astype(np.uint8)
return largest_component_mask
for img_name in im_list:
bgr_img_mask = cv2.imread(osp.join(path, img_name), 0)
cv2.imwrite(osp.join(path, "white", img_name), bgr_img_mask)
lcc_mask = lcc(bgr_img_mask)
# Erosion to clean the mask contour a bit
cl_ker = 5
kernel = np.ones((cl_ker, cl_ker), np.uint8)
erosion = cv2.erode(lcc_mask,kernel,iterations = 3)
contours, _ = cv2.findContours(
lcc_mask, mode=cv2.RETR_TREE,
method=cv2.CHAIN_APPROX_NONE
)
if(len(contours)):
max_cnt = max(contours, key=cv2.contourArea)
epsilon = 0.008 * cv2.arcLength(max_cnt, True)
approx = cv2.approxPolyDP(max_cnt, epsilon, True)
approx = np.squeeze(np.array(approx, dtype=int), axis=1)
rect = cv2.minAreaRect(approx)
box = cv2.boxPoints(rect)
box = np.int0(box)
bgr_img_mask = cv2.drawContours(bgr_img_mask, [box], 0, 200, 2)
cv2.drawContours(bgr_img_mask, [approx], -1, 128, 2)
bgr_img_mask = cv2.putText(bgr_img_mask, f"{round(epsilon,2)}", (50, 50) ,
cv2.FONT_HERSHEY_SIMPLEX , 1, 255, 2, cv2.LINE_AA)
win_name = "img"
cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)
cv2.imshow(win_name, bgr_img_mask)
cv2.waitKey(0)
输出:
您能指导我如何做到这一点吗?谢谢。