King丨小义 发表于 2022-3-3 21:25:39

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

本帖最后由 King丨小义 于 2022-3-4 08:29 编辑

求助关于数字图像处理的一个问题{:5_92:}

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


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

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

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

King丨小义 发表于 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 = colorIndex
    points.remove((x, y))# 减小外层循环次数
    # 检查八领域,如果有未着色的边界点(当然可以写循环)
    if(canny_img == 255):
      addEllipseColor(x-1, y-1)
    if(canny_img == 255):
      addEllipseColor(x, y-1)
    if(canny_img == 255):
      addEllipseColor(x+1, y-1)
    if(canny_img == 255):
      addEllipseColor(x, y-1)
    if(canny_img == 255):
      addEllipseColor(x, y+1)
    if(canny_img == 255):
      addEllipseColor(x+1, y-1)
    if(canny_img == 255):
      addEllipseColor(x+1, y)
    if(canny_img == 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, lt))
    for point in points:
      colorIndex += colorStep# 换个颜色,继续给下个椭圆着色
      addEllipseColor(point, point)
      # 运行到这里,理论上已经给一个椭圆完整的着色了

    # 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.mean()), int(border.mean())
      print("(%d, %d)" % (x, y))
      cv.circle(img, (x, y), 5, , -1)# 在图上画点
      colorIndex -= colorStep
    cv.imshow("img", img)
    cv.waitKey(0)

Python初学者8号 发表于 2022-3-3 22:44:04

可不可以这样啊,边缘知道了,就可以求出斜率,找到斜率为0的位置,和斜率不存在的位置,四个点交点就是中点

King丨小义 发表于 2022-3-4 08:12:33

本帖最后由 King丨小义 于 2022-3-4 08:17 编辑

Python初学者8号 发表于 2022-3-3 22:44
可不可以这样啊,边缘知道了,就可以求出斜率,找到斜率为0的位置,和斜率不存在的位置,四个点交点就是中 ...

感觉不能识别多个椭圆哎,而且算法复杂度还不如求所有边缘点的均值。
并且椭圆不是正放的,有一点倾斜度,这个算法有点问题吧。(虽然结果是对的,因为根据对称性,只要找出一对对称的点,就可以求出中点)

z5560636 发表于 2022-3-4 13:41:55

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

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

King丨小义 发表于 2022-3-4 14:06:41

z5560636 发表于 2022-3-4 13:41
我也来提供一个思路,
1.用数组找宽度最长行,
2用数组找高度最长列,


没听懂哎,感觉和楼上那位求斜率为0和斜率不存在的差不多哎

Python初学者8号 发表于 2022-3-5 00:21:00

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

我草,倾斜度,这个,有点复杂了。我也琢磨琢磨{:10_266:}
页: [1]
查看完整版本: 如何提取图片中的椭圆中心