簡體   English   中英

在 python 中使用 Clipper lib 生成多邊形偏移

[英]Producing polygon offsets using Clipper lib in python

我想使用 Clipper lib ( http://www.angusj.com/delphi/clipper.php ) 在閉合多邊形中產生偏移。

因為,我使用的是 python 2.7,所以我使用 pyclipper ( https://pypi.python.org/pypi/pyclipper ) 來做同樣的事情。

不幸的是,我無法從 C++ 中剪刀的多邊形偏移示例中理解:

 #include "clipper.hpp"  
    ...
    using namespace ClipperLib;

    int main()
    {
      Path subj;
      Paths solution;
      subj << 
        IntPoint(348,257) << IntPoint(364,148) << IntPoint(362,148) << 
        IntPoint(326,241) << IntPoint(295,219) << IntPoint(258,88) << 
        IntPoint(440,129) << IntPoint(370,196) << IntPoint(372,275);
      ClipperOffset co;
      co.AddPath(subj, jtRound, etClosedPolygon);
      co.Execute(solution, -7.0);

      //draw solution ...
      DrawPolygons(solution, 0x4000FF00, 0xFF009900);
    }

在 python 中實現相同。

我只看到了 pyclipper 的一個示例(裁剪,而不是偏移):

import pyclipper

subj = (
    ((180, 200), (260, 200), (260, 150), (180, 150)),
    ((215, 160), (230, 190), (200, 190))
)
clip = ((190, 210), (240, 210), (240, 130), (190, 130))

pc = pyclipper.Pyclipper()
pc.AddPath(clip, pyclipper.PT_CLIP, True)
pc.AddPaths(subj, pyclipper.PT_SUBJ, True)

solution = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD )  

不幸的是,我不是一個有經驗的程序員,無法繼續前進。

請在這方面幫助我。

提前致謝。

在 pyclipper 中相同的是:

subj = ((348, 257), (364, 148), (362, 148), (326, 241), (295, 219), (258, 88), (440, 129), (370, 196), (372, 275))

pco = pyclipper.PyclipperOffset()
pco.AddPath(subj, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
pco.Execute(-7.0)

""" Result (2 polygons, see image below):
[[[365, 260], [356, 254], [363, 202]], [[425, 133], [365, 191], [371, 149], [370, 145], [368, 142], [364, 141], [362, 141], [358, 142], [355, 145], [322, 230], [301, 215], [268, 98]]]
"""

我們嘗試使 pyclipper 方法和函數的命名盡可能接近 Python 包裝器的原始名稱。 此外,它應該與模仿基礎庫一起使用的方式。 唯一的大區別在於Execute函數的使用方式,如pyclipper - How to use 中所述

您可以檢查測試以更好地掌握用法。

抵消

以下是使用 Python 的演示,

它會顯示圖像,讓您更好地了解正在發生的事情。

from typing import List, Tuple
import pyclipper
import numpy as np
import cv2
from grid_extractor import show_img  # pip install grid_extractor  # Don't worry. It's a simple library. I am lazy, so I don't want to write a lot of things that is not what I cared, so I use a library that I publish to PyPI instead of it.

from matplotlib.colors import LinearSegmentedColormap
import matplotlib._cm
import matplotlib.pyplot


def main():
    point_list = (
        (348, 257), (364, 148), (362, 148), (326, 241),
        (295, 219), (258, 88), (440, 129), (370, 196),
        (372, 275)
    )
    img = init_canvas(max([x for x, y in point_list]), max([y for x, y in point_list]))
    # Show original data on the image
    draw_point_list(img, point_list, bgr_color=(0, 255, 255), size=5)
    draw_line(img, point_list, (255, 255, 0), thickness=3)
    # show_img(img)

    # Show the result after `pco.Execute`
    pco = pyclipper.PyclipperOffset()
    pco.AddPath(point_list, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
    contours_list: List[List[Tuple[int, int]]] = pco.Execute(-7.0)  # - shrink the outline

    dot_thickness = 3
    line_thickness = 2
    bgr_color_list = get_color_list('gist_rainbow', num_colors=len(contours_list))
    for contours, color in zip(contours_list, bgr_color_list):
        color = np.array(list(color)) * 255
        print(f'number of points found: {len(contours)}')

        draw_point_list(img, contours, color, dot_thickness)
        draw_line(img, contours, color, line_thickness)
    show_img(img)


if __name__ == '__main__':
    main()

結果圖像

在此處輸入圖片說明

額外代碼

不想一下子把代碼寫的太長(可能會導致用戶不願意看),所以我決定把不重要的代碼放在這里。 如果你想跑,只要把它放在一起跑,就完成了。

def get_color_list(cmap_name: str, num_colors: int, ft='bgr') -> List[Tuple[float, float, float]]:
    """
    ::

        bgr_list = get_color_list(cmap_name='gist_rainbow', num_colors=120)
        rgb_list = get_color_list(cmap_name='gist_rainbow', num_colors=120, ft='rgb')

        for color in bgr_list:
            color = np.array(list(color)) * 255
    """
    assert cmap_name in matplotlib._cm.datad, KeyError(cmap_name)
    cm: LinearSegmentedColormap = matplotlib.pyplot.get_cmap(cmap_name)
    color_list = [(int(b * 255) / 255, int(g * 255) / 255, int(r * 255) / 255) if ft == 'bgr' else
                  (int(r * 255) / 255, int(g * 255) / 255, int(b * 255) / 255)
                  for r, g, b, a in
                  [cm.__call__(1. * i / num_colors) for i in range(num_colors)]
                  ]
    return color_list  # some kind of stuff like that `[(1, 0, 0), (0, 1, 0) ...]`


def init_canvas(max_x: int, max_y: int) -> np.ndarray:
    img = np.ones((int(max_y * 1.2), int(max_x * 1.2), 3),  # 1.2 is margin
                  dtype=np.uint8) * 255  # fill the background with white color
    return img


def draw_point_list(img, point_list, bgr_color: Tuple[int, int, int], size):
    for x, y in point_list:
        img[int(y - size):int(y + size), int(x - size): int(x + size)] = bgr_color


def draw_line(img, point_list, bgr_color: Tuple[int, int, int], thickness, close_flag=True):
    """
    draw a line which cross every points.
    """
    begin_point = point_list[0]
    for i, (x, y) in enumerate(point_list):
        if i == 0:
            continue
        end_point = (x, y)
        cv2.line(img, tuple(begin_point), end_point, bgr_color, thickness)
        begin_point = end_point
    if close_flag:
        cv2.line(img, tuple(begin_point), tuple(point_list[0]), bgr_color, thickness)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM