目录
- 环境配置
-
- pip install opencv-python opencv-contrib-python
- pip install pyclipper
- pip install numpy
- import cv2
- import numpy as np
- import pyclipper
-
-
- def equidistant_zoom_contour(contour, margin):
- """
- 等"距离"缩放多边形轮廓点
- :param contour: 一个图形的轮廓格式[[[x1, x2]],...],shape是(-1, 1, 2)
- :param margin: 轮廓外扩的像素距离,margin正数是外扩,负数是缩小
- :return: 外扩后的轮廓点
- """
- pco = pyclipper.PyclipperOffset()
- # 参数限制,默认成2,这里设置大一些,主要是用于多边形的尖角是否用圆角代替
- pco.MiterLimit = 10 # 2是圆角,10是尖角
- contour = contour[:, 0, :]
- pco.AddPath(contour, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON)
- solution = pco.Execute(margin)
- solution = np.array(solution).reshape(-1, 1, 2).astype(int)
- return solution
-
-
- if __name__ == '__main__':
- poly = np.array([[[200, 200]], [[200, 300]], [[400, 350]], [[350, 200]], [[300, 200]], [[200, 100]]])
- contour1 = equidistant_zoom_contour(poly, 20) # 等距离
- img = np.zeros((500, 500, 3))
- cv2.polylines(img, [contour1], True, (0, 255, 0), 3)
- cv2.polylines(img, [poly], True, (0, 0, 255), 3)
-
- cv2.namedWindow("img", cv2.WINDOW_NORMAL), cv2.imshow("img", img), cv2.waitKey()
参数MiterLimit=10是尖角(左图),默认值是2,圆角(右图)

第一版clipper: Download Clipper
最新版clipper2: https://github.com/AngusJohnson/Clipper2
官方介绍:https://angusj.com/clipper2/Docs/Overview.htm
(1)这里使用旧版clipper,下载后解压

(2)vs2019配置clipper环境,只需要添加包含目录即可。

(3) 添加现有clipper头文件和源码 clipper.cpp和clipper.hpp

- #include
- #include
- #include
-
- using namespace ClipperLib;
-
- std::vector
equidistant_zoom_contour(const std::vector>& contours, double margin) { - ClipperOffset co;
- co.MiterLimit = 10; // 默认2圆角,10尖角
- co.AddPaths(contours, jtMiter, etClosedPolygon);
- Paths solution;
- co.Execute(solution, margin);
-
- std::vector
result; - for (const auto& path : solution) {
- result.insert(result.end(), path.begin(), path.end());
- }
-
- return result;
- }
-
- int main() {
- Paths poly = {
- {{200, 200}, {200, 300}, {400, 350}, {350, 200}, {300, 200}, {200, 100}}
- };
-
- double margin = 20.0;
-
- std::vector
contour1 = equidistant_zoom_contour(poly, margin); -
- cv::Mat img = cv::Mat::zeros(500, 500, CV_8UC3);
- std::vector
> contours_cv(1); - for (const auto& point : contour1) {
- contours_cv[0].emplace_back(point.X, point.Y);
- }
-
- cv::polylines(img, contours_cv, true, cv::Scalar(0, 255, 0), 3);
-
- contours_cv.clear();
- for (const auto& path : poly) {
- std::vector
contour_cv; - for (const auto& point : path) {
- contour_cv.emplace_back(point.X, point.Y);
- }
- contours_cv.push_back(contour_cv);
- }
-
- cv::polylines(img, contours_cv, true, cv::Scalar(0, 0, 255), 3);
-
- cv::namedWindow("img", cv::WINDOW_NORMAL);
- cv::imshow("img", img);
- cv::waitKey(0);
-
- return 0;
- }
MiterLimit默认2圆角(左图),10尖角 (右图)


待续。。。