在中间分割相交的多边形

Koo*_*rra 1 python geometry opencv polygon shapes

我正在处理一些生物成像样本,并尝试创建细胞形状的数字模型。为了简单起见,我想通过将它们建模为多边形来概括它们的形状。

我正在努力将两个重叠的多边形分割成在其交叉点处不共享重叠区域的多边形。相反,该区域分为两个形状。下面最能说明我的意图。

我使用 Python 和 OpenCV 包工作,但很乐意实现任何可以解决此问题的替代包。(numpythonic 方式是最好的 - 如果可能的话!)

在此输入图像描述

Mic*_*del 5

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import cv2


threshold = 200
thickness = 16
linewidth = 2
white = 255
black = 0


def fun(image):
    res = np.full(image.shape, white).astype(np.uint8)
    # determine contours
    grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(grayscale, threshold, white, cv2.THRESH_BINARY)[1]
    contours = cv2.findContours(thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)[0]
    # create intersection and union
    intersection, union = sorted(contours, key=len)[::len(contours) - 2]
    outline = np.full(res.shape, white).astype(np.uint8)
    cv2.drawContours(outline, [union], -1, black, thickness, cv2.LINE_AA)
    inline = np.full(res.shape, white).astype(np.uint8)
    cv2.drawContours(inline, [intersection], -1, black, thickness, cv2.LINE_AA)
    # determine points for line
    points = np.logical_and(outline == 0, inline == 0).astype(np.uint8)[:,:,0] * white
    a, b = cv2.findContours(points, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)[0]
    a = np.mean(a.squeeze(), axis=0).astype(int)
    b = np.mean(b.squeeze(), axis=0).astype(int)
    # draw outline of union
    cv2.drawContours(res, [union], -1, black, linewidth, cv2.LINE_AA)
    # draw connecting line
    cv2.line(res, a, b, black, linewidth)
    return res

for img in ['img1.jpg', 'img2.jpg']:
    orig = np.asarray(Image.open(img))
    res = fun(orig)
    fig, ax = plt.subplots(1, 2)
    for i, img in enumerate([orig, res]):
        ax[i].imshow(img, cmap='gray');
        ax[i].axes.get_xaxis().set_visible(False)
        ax[i].axes.get_yaxis().set_visible(False)
    plt.show();
Run Code Online (Sandbox Code Playgroud)

图像1 图像2

该方法的工作原理如下:

  1. 首先将图像转换为灰度并使用阈值对图像进行二值化,然后确定contours。接下来,通过增加大小对轮廓进行排序,这确保交集的轮廓(要删除的部分)排在第一位,并集的轮廓(要保留的部分)排在倒数第二位(最后是图像边界的轮廓)。
  2. 创建两个新的白色图像,outline在一个图像上用黑色绘制联合轮廓,在另一个图像上用黑色绘制相交轮廓inline,然后将两个图像的黑色部分相交以获得标记新线端点的补丁。然后计算端点a并将b新线作为其各自补丁的平均值。
  3. 在一个新的、最初为白色的黑色图像上绘制一条连接两点的直线a以及b联合的轮廓,从而得到所需的输出图像。

备注:这种方法不适用于第三种情况(因为它假设形状是凸的,或者更确切地说,只有一个交点),但我的猜测是,对其进行调整以适用于这种情况应该是可行的。