Мне нужно разделить маску таким образом, чтобы в случае несоответствия внутри маски она была разделена. Например, если я рисую маску кошки, я хочу, чтобы широкая часть (тело) была одной маской, а узкая часть (хвост) — другой.
Сейчас у меня есть сплошная маска, включающая в себя как тело кошки, так и ее хвост. Я хочу разделить это на две отдельные маски. Как я могу добиться этого с помощью Python?
оригинальная маска
желаемая маска
Я рассмотрел использование методов, описанных в этом, в которых основное внимание уделяется разбиению многоугольников и разделению контуров на несколько треугольников. Однако этот подход не соответствует моим потребностям, поскольку я хочу разделить маску по размеру и форме, а не создавать несколько треугольных разделов.
🤔 А знаете ли вы, что...
С Python можно создавать ботов для социальных сетей и мессенджеров.
Вы можете использовать Дефекты выпуклости, чтобы определить точки, между которыми нужно «разрезать».
Это делается так здесь например.
import cv2
import matplotlib.pyplot as plt
import numpy as np
def split_mask(mask):
_, thresh = cv2.threshold(mask , 120,255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, 2, 1)
for contour in contours:
if cv2.contourArea(contour) > 20:
hull = cv2.convexHull(contour, returnPoints = False)
defects = cv2.convexityDefects(contour, hull)
if defects is None:
continue
# Gather all defect points to filter them.
dd = [e[0][3]/256 for e in defects]
points = []
for i in range(len(dd)):
_,_,f,_ = defects[i,0]
if dd[i] > 1.0 and dd[i]/np.max(dd) > 0.2:
points.append(f)
# If there is defect points, erase the mask closest points.
if len(points) >= 2:
for i, f1 in enumerate(points):
p1 = tuple(contour[f1][0])
nearest = min((tuple(contour[f2][0]) for j, f2 in enumerate(points) if i != j),
key=lambda p2: (p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
cv2.line(thresh, p1, nearest, 0, 20)
return thresh
if __name__= = "__main__":
mask = cv2.imread("<path-to-your-image>", cv2.IMREAD_GRAYSCALE)
mask_splitted = split_mask(mask)
plt.imshow(mask_splitted)
plt.show()
Это даст следующее на вашем изображении: