鱼C论坛

 找回密码
 立即注册
查看: 2298|回复: 6

如何提取图片中的椭圆中心

[复制链接]
发表于 2022-3-3 21:25:39 | 显示全部楼层 |阅读模式
60鱼币
本帖最后由 King丨小义 于 2022-3-4 08:29 编辑

求助关于数字图像处理的一个问题

如图所示,图片中有若干椭圆,如何提取出椭圆的中心坐标(不需要知道椭圆的长半轴参数)
test.jpg

目前我的想法是先通过梯度算子将边缘提取出来,对于只有一个椭圆的图像,我可以通过对边缘的所有像素点求平均值来提取椭圆中心坐标。
但是对于一张图中有多个椭圆的情况,提取过程中就需要告诉程序如何分辨多个椭圆。

求问各位大佬有什么好的想法?对于提取这张图片的椭圆的中心坐标?

最好使用Python + OpenCV(别的语言也可以)

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-3-7 19:08:52 | 显示全部楼层
本帖最后由 King丨小义 于 2022-3-7 19:09 编辑

我已经有一个思路了。具体算法如下:
1. 对图像使用Canny边缘检测(其实不检测也可以,个人感觉检测之后算法效率会高,虽然没有比较过)
2. 寻找第一个边缘点,给该点上一种颜色
3. 然后从该点出发,寻找其八领域内的下一个没有上过色的边缘点
4. 重复2-3步(没错,我要开始递归了)
5. 到此为止,理论上已经给不同的椭圆上不同的色了,接下来就可以根据颜色区分不同椭圆,然后对边缘求平均值得到中心点坐标

该算法默认椭圆不相交不粘连(基本够我用了)

代码如下,图片在本帖提问处。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np


def addEllipseColor(x, y):
    canny_img[x, y] = colorIndex
    points.remove((x, y))  # 减小外层循环次数
    # 检查八领域,如果有未着色的边界点(当然可以写循环)
    if(canny_img[x-1, y-1] == 255):
        addEllipseColor(x-1, y-1)
    if(canny_img[x, y-1] == 255):
        addEllipseColor(x, y-1)
    if(canny_img[x+1, y-1] == 255):
        addEllipseColor(x+1, y-1)
    if(canny_img[x, y-1] == 255):
        addEllipseColor(x, y-1)
    if(canny_img[x, y+1] == 255):
        addEllipseColor(x, y+1)
    if(canny_img[x+1, y-1] == 255):
        addEllipseColor(x+1, y-1)
    if(canny_img[x+1, y] == 255):
        addEllipseColor(x+1, y)
    if(canny_img[x+1, y+1] == 255):
        addEllipseColor(x+1, y+1)


if __name__ == "__main__":
    img = cv.imread("./test.jpg")
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    x, y = gray.shape
    colorIndex = 0
    colorStep = 80   # 颜色增量(当然可以调成最低1,这里调80只是为了下面可以观察颜色赋值情况)
    canny_img = cv.Canny(gray, 0, 100)
    # cv.imshow("img", canny_img)
    # cv.waitKey(0)
    lt = np.where(canny_img == 255)
    points = list(zip(lt[0], lt[1]))
    for point in points:
        colorIndex += colorStep  # 换个颜色,继续给下个椭圆着色
        addEllipseColor(point[0], point[1])
        # 运行到这里,理论上已经给一个椭圆完整的着色了

    # cv.imshow("canny_img", canny_img)
    # cv.waitKey(0)
    # 例如 colorIndex = 240 代表检测到了3个椭圆
    while colorIndex != 0:
        border = np.where(canny_img == colorIndex)
        y, x = int(border[0].mean()), int(border[1].mean())
        print("(%d, %d)" % (x, y))
        cv.circle(img, (x, y), 5, [0, 0, 255], -1)  # 在图上画点
        colorIndex -= colorStep
    cv.imshow("img", img)
    cv.waitKey(0)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-3 22:44:04 | 显示全部楼层
可不可以这样啊,边缘知道了,就可以求出斜率,找到斜率为0的位置,和斜率不存在的位置,四个点交点就是中点

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
King丨小义 + 5 + 5 + 3 感谢提供思路

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-3-4 08:12:33 | 显示全部楼层
本帖最后由 King丨小义 于 2022-3-4 08:17 编辑
Python初学者8号 发表于 2022-3-3 22:44
可不可以这样啊,边缘知道了,就可以求出斜率,找到斜率为0的位置,和斜率不存在的位置,四个点交点就是中 ...


感觉不能识别多个椭圆哎,而且算法复杂度还不如求所有边缘点的均值。
并且椭圆不是正放的,有一点倾斜度,这个算法有点问题吧。(虽然结果是对的,因为根据对称性,只要找出一对对称的点,就可以求出中点)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-4 13:41:55 | 显示全部楼层
King丨小义 发表于 2022-3-4 08:12
感觉不能识别多个椭圆哎,而且算法复杂度还不如求所有边缘点的均值。
并且椭圆不是正放的,有一点倾斜 ...

我也来提供一个思路,
1.用数组找宽度最长行,
2用数组找高度最长列,
3.计算他们交叉点?

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
King丨小义 + 5 + 5 + 3 感谢提供思路

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-3-4 14:06:41 | 显示全部楼层
z5560636 发表于 2022-3-4 13:41
我也来提供一个思路,
1.用数组找宽度最长行,
2用数组找高度最长列,

没听懂哎,感觉和楼上那位求斜率为0和斜率不存在的差不多哎
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-5 00:21:00 | 显示全部楼层
King丨小义 发表于 2022-3-4 08:12
感觉不能识别多个椭圆哎,而且算法复杂度还不如求所有边缘点的均值。
并且椭圆不是正放的,有一点倾斜 ...

我草,倾斜度,这个,有点复杂了。我也琢磨琢磨
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-6 12:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表