将图像中的椭圆转换为圆(将椭圆扭曲为圆形,就像多边形扭曲为矩形)

2024-09-29 22:05:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个椭圆的图像,如果一个图像有椭圆,我用findConteurs()找到它,然后我想把这个椭圆转换成一个圆。在

参见示例

enter image description here

enter image description here

我想把他们都变成这样

enter image description here

首先,我应用了canny edge检测。然后呢在此图像上应用findCountour()。在

我用findcontours()找到了椭圆,得到了所有的轮廓,得到了所需的椭圆轮廓,然后我用fitellipse()来获得椭圆的中心、旋转角度和长轴和短轴。在

然后我试着用旋转的角度旋转图像,然后缩放图像的高度和宽度w.r.t短轴和长轴(即使长轴和短轴的长度相同),但是我没有得到正确的圆形物体图像。会有一些向左旋转/它仍然像一个椭圆,将接近圆左右。在

     _, contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    for c in contours:
        if len(c) >= 5:
            a = cv2.fitEllipse(c)
            (x, y), (MA, ma), angle = a
            area = (math.pi * MA * ma)/4
            if abs(x-image.shape[0]/2) <= 2 and abs(y-image.shape[1]/2) <= 2 and (area - cv2.contourArea(c)) < 50:
                screenCount = c
                width, height = MA, ma
                centerX, centerY = x, y
                ellipseAngle = angle
                print(width, height, centerX, centerY, ellipseAngle)
                # cv2.drawContours(img, c, -1, (0, 255, 0), 4)
                cv2.ellipse(img, a, (0, 0, 255), 2, 8)
                cv2.imshow("ellipse", img)
                break

    img = image.copy()
    if ellipseAngle < 90:
        rotatedImg = imutils.rotate(img, ellipseAngle)
    else:
        rotatedImg = imutils.rotate(img, -(ellipseAngle - 90))

然后我按长轴和短轴缩放

在应用findcontour()之后,我得到了这两个轮廓作为文章的第一张图片

enter image description hereenter image description here

从这些曲线上看任何轮廓都很好,对吗?我根据代码使用countour的第一条轮廓,fitellipse()给了我这个椭圆

enter image description here

编辑-如果有更好的方法来解决这个问题,这将是有帮助的。在


Tags: 图像imageimgifcv2轮廓角度椭圆
1条回答
网友
1楼 · 发布于 2024-09-29 22:05:51

在代码中我可以看到几个问题:

  1. 你使用的是边缘检测算法,并得到结果的轮廓。这在原则上是可以的,但这会导致图像有两个轮廓:一个用于边缘检测结果的内边缘,另一个用于外部边缘。只需对图像进行阈值处理并获得一条单一的边缘就比较容易了。不过,如果图像变得更复杂,边缘检测可能是相关的。实际上,您获得的两个轮廓中的任何一个都应该是有用的。

  2. if abs(x-image.shape[0]/2) <= 2 and abs(y-image.shape[1]/2) <= 2 and (area - cv2.contourArea(c)) < 50非常限制,它没有为我的第二个图像触发。

  3. 如果角度为负,旋转-(ellipseAngle - 90)是奇怪的。你应该以同样的方式旋转所有的椭圆。

下面的代码为问题中显示的两个椭圆图像生成一个圆形输出。我认为用这种方法确定的椭圆参数不是很精确,但是看起来它们对于这个应用来说已经足够好了。在

import cv2
import numpy as np

img = cv2.imread('im1.png',0)
_, thresh = cv2.threshold(img, 128, 255, type=cv2.THRESH_BINARY_INV)
_, contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
params = cv2.fitEllipse(contours[0])
angle = params[2]
scale = params[1]
scale = scale[0]/scale[1]

M = cv2.getRotationMatrix2D((img.shape[0]/2, img.shape[1]/2), angle, 1)
# Let's add the scaling too:
M[:,0:2] = np.array([[1,0],[0,scale]]) @ M[:,0:2]
M[1,2] = M[1,2] * scale # This moves the ellipse so it doesn't end up outside the image (it's not correct to keep the ellipse in the middle of the image)

out = cv2.warpAffine(img, M, img.shape, borderValue=255)
cv2.imshow('out',out)
cv2.waitKey()

使用PyDIP(我是一个作者)你可以在理想情况下得到一个更精确的测量,在理想情况下,不设阈值,并使用椭圆边缘周围的灰色值来获得更精确的拟合。我们计算图像的二阶中心矩,并由此导出椭圆参数。这里重要的是背景正好为0,并且前景(椭圆像素)的强度是均匀的,除了在边缘,中间的灰色值添加了关于边缘的亚像素位置的信息。在

^{pr2}$

相关问题 更多 >

    热门问题