首页 > 解决方案 > OpenCv圆函数可以用来画一个直径奇数的圆吗?

问题描述

我想将直径为 15 的圆绘制成 15 x 15 的矩阵。为此,我尝试了 OpenCv 圆函数和移位函数。

我不确定我是否以正确的方式使用该功能,或者我想做的事情是不可能的。

我取得的最好成绩是以下大小为 16 像素的不对称圆圈:

不对称圆

如何获得直径为 15 像素的对称圆?

我使用的代码:

    import cv2
    import numpy as np  

    circle_diameter = 15
    circular_mask = np.zeros((circle_diameter, circle_diameter, 1), dtype='uint8')
    #Draw circle with subpixel accuracy
    shift = 4
    factor = (1 << shift)
    cv2.circle(circular_mask, (int(round((circle_diameter/2) * factor)), int(round((circle_diameter/2) * factor))), int(round((circle_diameter/2) * factor)), (255), -1, shift=shift)

    circular_mask = cv2.resize(circular_mask,None,fx=5,fy=5)
    cv2.imshow("mask", circular_mask)

谢谢

标签: python-3.xopencv

解决方案


好的,给你。

我将用 C++ 语法编写,但对于 Python 应该是一样的。

似乎 cv::circle 中的像素坐标指的是像素中心。

    cv::Mat img = cv::Mat::zeros(15, 15, CV_8UC1);
    // in this code, shift must be >= 1 because of the later line (1<<(shift-1)) to add the .5 for an arbitrary shift size
    const int shift = 2;

    int radiusLow = 7;
    int radiusShift = (radiusLow << shift) + (1<<(shift-1)); // + .5

    //int x = (7 << shift) + (1<<(shift-1)); // wrong, because the pixel position seems to be the pixel center already. 7.5 would be the right ede of the pixel
    //int y = (7 << shift) + (1<<(shift-1)); // wrong, because the pixel position seems to be the pixel center already. 7.5 would be the right ede of the pixel

    int x = 7<<shift;
    int y = 7<<shift;

    cv::circle(img, cv::Point(x, y), radiusShift, cv::Scalar::all(255), -1, 8, shift);

    //cv::resize(img, img, cv::Size(), 50, 50); // for visualization

    cv::imshow("img", img);
    cv::waitKey(0);

但结果似乎有一些像素离散化问题,虽然看起来像蜜蜂居中并且半径为 7.5。结果已调整大小以进行可视化。

在此处输入图像描述

半径为 6.5 的相同代码(但更小的调整因子)给出了这个图像(在绘图过程中看起来像一些舍入片段)。

在此处输入图像描述

另一个测试,使用更多位来表示接近 7.5 半径的数字,但要小一些,以减少绘图中的舍入碎片:

    cv::Mat img = cv::Mat::zeros(17, 17, CV_8UC1); // 2 pixels bigger for visualization of possible artifacts

    const int shift = 5; // more bits for fraction
    int radiusLow = 7;
    int radiusShift = (radiusLow << shift) + (1<<(shift-1)) -1; // 7+ 2^-1 - 2^-5 

    // center of the 17x17 image
    int x = 8<<shift;
    int y = 8<<shift;

在此处输入图像描述


推荐阅读