使用Python,OpenCV对图像进行亚像素点检测,并拟合椭圆进行绘制

2023-11-13

这篇博客将介绍如何使用Python,OpenCV对图像进行亚像素检测,并对亚像素点进行椭圆拟合绘制。

1. 效果图

原始图上绘制拟合椭圆 VS 原始图上绘制拟合椭圆及亚像素点绘制随机半径及颜色的圆 VS 灰度图上绘制亚像素点效果图如下:
在这里插入图片描述
我喜欢的颖宝效果图2如下:
在这里插入图片描述
圆的随机半径放大一点效果图如下:
在这里插入图片描述

2. 源码

需要注意,绘制圆需要圆心都是int值

# 计算图像的亚像素点并绘制(matplotlib以及cv2),并对亚像素点进行3种椭圆方式拟合绘制
# python zernick_detection.py

import time

import cv2
import imutils
import matplotlib.pyplot as plt
import numpy as np

g_N = 7

M00 = np.array([0, 0.0287, 0.0686, 0.0807, 0.0686, 0.0287, 0,
                0.0287, 0.0815, 0.0816, 0.0816, 0.0816, 0.0815, 0.0287,
                0.0686, 0.0816, 0.0816, 0.0816, 0.0816, 0.0816, 0.0686,
                0.0807, 0.0816, 0.0816, 0.0816, 0.0816, 0.0816, 0.0807,
                0.0686, 0.0816, 0.0816, 0.0816, 0.0816, 0.0816, 0.0686,
                0.0287, 0.0815, 0.0816, 0.0816, 0.0816, 0.0815, 0.0287,
                0, 0.0287, 0.0686, 0.0807, 0.0686, 0.0287, 0]).reshape((7, 7))

M11R = np.array([0, -0.015, -0.019, 0, 0.019, 0.015, 0,
                 -0.0224, -0.0466, -0.0233, 0, 0.0233, 0.0466, 0.0224,
                 -0.0573, -0.0466, -0.0233, 0, 0.0233, 0.0466, 0.0573,
                 -0.069, -0.0466, -0.0233, 0, 0.0233, 0.0466, 0.069,
                 -0.0573, -0.0466, -0.0233, 0, 0.0233, 0.0466, 0.0573,
                 -0.0224, -0.0466, -0.0233, 0, 0.0233, 0.0466, 0.0224,
                 0, -0.015, -0.019, 0, 0.019, 0.015, 0]).reshape((7, 7))

M11I = np.array([0, -0.0224, -0.0573, -0.069, -0.0573, -0.0224, 0,
                 -0.015, -0.0466, -0.0466, -0.0466, -0.0466, -0.0466, -0.015,
                 -0.019, -0.0233, -0.0233, -0.0233, -0.0233, -0.0233, -0.019,
                 0, 0, 0, 0, 0, 0, 0,
                 0.019, 0.0233, 0.0233, 0.0233, 0.0233, 0.0233, 0.019,
                 0.015, 0.0466, 0.0466, 0.0466, 0.0466, 0.0466, 0.015,
                 0, 0.0224, 0.0573, 0.069, 0.0573, 0.0224, 0]).reshape((7, 7))

M20 = np.array([0, 0.0225, 0.0394, 0.0396, 0.0394, 0.0225, 0,
                0.0225, 0.0271, -0.0128, -0.0261, -0.0128, 0.0271, 0.0225,
                0.0394, -0.0128, -0.0528, -0.0661, -0.0528, -0.0128, 0.0394,
                0.0396, -0.0261, -0.0661, -0.0794, -0.0661, -0.0261, 0.0396,
                0.0394, -0.0128, -0.0528, -0.0661, -0.0528, -0.0128, 0.0394,
                0.0225, 0.0271, -0.0128, -0.0261, -0.0128, 0.0271, 0.0225,
                0, 0.0225, 0.0394, 0.0396, 0.0394, 0.0225, 0]).reshape((7, 7))

M31R = np.array([0, -0.0103, -0.0073, 0, 0.0073, 0.0103, 0,
                 -0.0153, -0.0018, 0.0162, 0, -0.0162, 0.0018, 0.0153,
                 -0.0223, 0.0324, 0.0333, 0, -0.0333, -0.0324, 0.0223,
                 -0.0190, 0.0438, 0.0390, 0, -0.0390, -0.0438, 0.0190,
                 -0.0223, 0.0324, 0.0333, 0, -0.0333, -0.0324, 0.0223,
                 -0.0153, -0.0018, 0.0162, 0, -0.0162, 0.0018, 0.0153,
                 0, -0.0103, -0.0073, 0, 0.0073, 0.0103, 0]).reshape(7, 7)

M31I = np.array([0, -0.0153, -0.0223, -0.019, -0.0223, -0.0153, 0,
                 -0.0103, -0.0018, 0.0324, 0.0438, 0.0324, -0.0018, -0.0103,
                 -0.0073, 0.0162, 0.0333, 0.039, 0.0333, 0.0162, -0.0073,
                 0, 0, 0, 0, 0, 0, 0,
                 0.0073, -0.0162, -0.0333, -0.039, -0.0333, -0.0162, 0.0073,
                 0.0103, 0.0018, -0.0324, -0.0438, -0.0324, 0.0018, 0.0103,
                 0, 0.0153, 0.0223, 0.0190, 0.0223, 0.0153, 0]).reshape(7, 7)

M40 = np.array([0, 0.013, 0.0056, -0.0018, 0.0056, 0.013, 0,
                0.0130, -0.0186, -0.0323, -0.0239, -0.0323, -0.0186, 0.0130,
                0.0056, -0.0323, 0.0125, 0.0406, 0.0125, -0.0323, 0.0056,
                -0.0018, -0.0239, 0.0406, 0.0751, 0.0406, -0.0239, -0.0018,
                0.0056, -0.0323, 0.0125, 0.0406, 0.0125, -0.0323, 0.0056,
                0.0130, -0.0186, -0.0323, -0.0239, -0.0323, -0.0186, 0.0130,
                0, 0.013, 0.0056, -0.0018, 0.0056, 0.013, 0]).reshape(7, 7)


def zernike_detection(path):
    img = cv2.imread(path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blur_img = cv2.medianBlur(img, 13)
    c_img = cv2.adaptiveThreshold(blur_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 7, 4)
    ZerImgM00 = cv2.filter2D(c_img, cv2.CV_64F, M00)
    ZerImgM11R = cv2.filter2D(c_img, cv2.CV_64F, M11R)
    ZerImgM11I = cv2.filter2D(c_img, cv2.CV_64F, M11I)
    ZerImgM20 = cv2.filter2D(c_img, cv2.CV_64F, M20)
    ZerImgM31R = cv2.filter2D(c_img, cv2.CV_64F, M31R)
    ZerImgM31I = cv2.filter2D(c_img, cv2.CV_64F, M31I)
    ZerImgM40 = cv2.filter2D(c_img, cv2.CV_64F, M40)

    point_temporary_x = []
    point_temporary_y = []
    scatter_arr = cv2.findNonZero(ZerImgM00).reshape(-1, 2)
    for idx in scatter_arr:
        j, i = idx
        theta_temporary = np.arctan2(ZerImgM31I[i][j], ZerImgM31R[i][j])
        rotated_z11 = np.sin(theta_temporary) * ZerImgM11I[i][j] + np.cos(theta_temporary) * ZerImgM11R[i][j]
        rotated_z31 = np.sin(theta_temporary) * ZerImgM31I[i][j] + np.cos(theta_temporary) * ZerImgM31R[i][j]
        l_method1 = np.sqrt((5 * ZerImgM40[i][j] + 3 * ZerImgM20[i][j]) / (8 * ZerImgM20[i][j]))

        l_method2 = np.sqrt((5 * rotated_z31 + rotated_z11) / (6 * rotated_z11))

        l = (l_method1 + l_method2) / 2

        k = 3 * rotated_z11 / (2 * (1 - l_method2 ** 2) ** 1.5)

        # h = (ZerImgM00[i][j] - k * np.pi / 2 + k * np.arcsin(l_method2) + k * l_method2 * (1 - l_method2 ** 2) ** 0.5)
        # / np.pi
        k_value = 20.0
        l_value = 2 ** 0.5 / g_N

        absl = np.abs(l_method2 - l_method1)

        if k >= k_value and absl <= l_value:
            y = i + g_N * l * np.sin(theta_temporary) / 2
            x = j + g_N * l * np.cos(theta_temporary) / 2
            point_temporary_x.append(x)
            point_temporary_y.append(y)
        else:
            continue

    return point_temporary_x, point_temporary_y


image = cv2.imread('ml2.jpg')
path = 'ym_600.jpg'
cv2.imwrite(path, imutils.resize(image, height=600))

time1 = time.time()
point_temporary_x, point_temporary_y = zernike_detection(path)
time2 = time.time()
print(time2 - time1)

# gray : 进行检测的图像
gray = cv2.imread(path, 0)
plt.imshow(gray, cmap="gray")
# point检测出的亚像素点
point = np.array([point_temporary_x, point_temporary_y])
# s:调整显示点的大小
plt.scatter(point[0, :], point[1, :], s=10, marker="*")
plt.show()


def cv_fit_ellipse(points, flag=0):
    # cv2.fitEllipse only can estimate int numpy 2D array data
    p = np.array(points)
    p = np.array(p).astype(int)
    center0, axes0, angle0 = cv2.fitEllipse(p)
    center1, axes1, angle1 = cv2.fitEllipseAMS(p)
    center2, axes2, angle2 = cv2.fitEllipseDirect(p)
    print(type(center0))
    print("fitEllipse:       " + str(np.array(center0)))
    print("fitEllipseAMS:    " + str(np.array(center1)))
    print("fitEllipseDirect: " + str(np.array(center2)))
    box = tuple([tuple(np.array(center0)), tuple(np.array(axes0)), angle0])
    if flag == 0:
        box = tuple([tuple(np.array(center0)), tuple(np.array(axes0)), angle0])
    elif flag == 1:
        box = tuple([tuple(np.array(center1)), tuple(np.array(axes1)), angle1])
    else:
        box = tuple([tuple(np.array(center0)), tuple(np.array(axes0)), angle0])
    return box


points = np.array(list(zip(point_temporary_x, point_temporary_y)))
print(type(points), points[0], points.shape)
box1 = cv_fit_ellipse(points, flag=1)

image = cv2.imread(path)

cv2.ellipse(img=image, box=box1, color=(255, 0, 255), thickness=1)
cv2.imshow("image", image)
for i in points:
    # 亚像素点绘制随机颜色半径圆
    radius = np.random.randint(1, high=10)
    color = np.random.randint(0, high=256, size=(3,)).tolist()
    # print('radius: ', radius, type(radius))
    # print('color: ', color, type(color))
    cv2.circle(image, (int(i[0]), int(i[1])), radius, color, -1)

cv2.imshow("image1", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

参考

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Python,OpenCV对图像进行亚像素点检测,并拟合椭圆进行绘制 的相关文章

  • Vimeo API:获取下载所有视频文件的链接列表

    再会 我正在尝试从 Vimeo 帐户获取所有视频文件的列表 直接下载的链接 有没有办法在 1 GET 请求中做到这一点 好的 如果是API限制的话 就100倍 我有硬编码脚本 我在其中发出 12 个 GET 请求 1100 多个视频 根据文
  • 为什么 Mypy 在 __init__ 中分配已在类主体中进行类型提示的属性时不给出键入错误?

    这是我的示例 python 文件 class Person name str age int def init self name age self name name self age age p Person 5 5 但当我跑步时myp
  • Flask-SocketIO redis 订阅

    我在用着https github com miguelgrinberg Flask SocketIO https github com miguelgrinberg Flask SocketIO实现 WebSocket 服务器 我需要从另一
  • 在函数内的 for 循环上使用 tqdm 来检查进度

    我正在使用 for 循环迭代目录树内的一大组文件 这样做时 我想通过控制台中的进度条来监视进度 因此 我决定使用 tqdm 来实现此目的 目前 我的代码如下所示 for dirPath subdirList fileList in tqdm
  • GUI 测试工具 PyUseCase 与 Dogtail 相比如何?

    GUI测试工具如何Py用例 http pypi python org pypi PyUseCase重命名为故事文本 http pypi python org pypi StoryText 相比于Dogtail http en wikiped
  • App Engine 上的 Django 与 webapp2 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Python Requests 库重定向新 url

    我一直在浏览 Python 请求文档 但看不到我想要实现的任何功能 在我的脚本中我设置allow redirects True 我想知道该页面是否已重定向到其他内容 新的 URL 是什么 例如 如果起始 URL 为 www google c
  • 将整数系列转换为交替(双元)二进制系列

    我不知道如何最好地表达这个问题 因为在这里谷歌搜索和搜索总是让我找到更复杂的东西 我很确定这是基本的东西 但对于我的生活来说 我找不到一个好的方法来做到这一点下列 给定一个整数序列 比如说 for x in range 0 36 我想将这些
  • 列表推导式和 for 循环中的 Lambda 表达式[重复]

    这个问题在这里已经有答案了 我想要一个 lambda 列表 作为一些繁重计算的缓存 并注意到这一点 gt gt gt j for j in lambda i for i in range 10 9 9 9 9 9 9 9 9 9 9 Alt
  • 了解 Python 2.7 中的缩进错误

    在编写 python 代码时 我往往会遇到很多缩进错误 有时 当我删除并重写该行时 错误就会消失 有人可以为菜鸟提供 python 中 IndentationErrors 的高级解释吗 以下是我在玩 CheckIO 时收到的最近 inden
  • 无法通过 Android 应用程序访问我的笔记本电脑的本地主机

    因此 我在发布此内容之前做了一项研究 我发现的解决方案不起作用 更准确地说 连接到我的笔记本电脑的 IPv4192 168 XXX XXX 没用 连接到10 0 2 2 加上端口 不起作用 我需要测试使用 Django Rest 框架构建的
  • Pandas 字典键到列[重复]

    这个问题在这里已经有答案了 我有一个像这样的数据框 index column1 e1 u c680 5 u c681 1 u c682 2 u c57 e2 u c680 6 u c681 2 u c682 1 u c57 e3 u c68
  • 在 django 中导入设置时出现奇怪的错误

    我有很多项目在 ubuntu 中使用 python2 7 和 virtualenv virtualenvwrapper 工作 在我的工作中 一些开发人员使用 macosx 和 windows 通常我像往常一样创建项目 django admi
  • 获取多个同名请求参数

    我的问题是给定的代码 from flask import Flask request app Flask name app route def hello return str request values get param None a
  • 如何将两列 pandas Dataframe 移动并堆叠为一列?

    我有一个下面提到的数据框 ETHNIC SEX USUBJID 0 HISPANIC OR LATINO F 16 1 HISPANIC OR LATINO M 8 2 HISPANIC OR LATINO Total 24 3 NOT H
  • SQLAlchemy 与 count、group_by 和 order_by 使用 ORM

    我有几个函数需要使用 count group by 和 order by 进行一对多连接 我使用 sqlalchemy select 函数生成一个查询 该查询将返回一组 id 然后我对其进行迭代以对各个记录执行 ORM 选择 我想知道是否有
  • py2exe ImportError:没有名为 的模块

    我已经实现了一个名为 myUtils 的包 它由文件夹 myUtils 文件 组成 init py 和许多名称为 myUtils 的 py 文件 该包包含在 myOtherProject py 中 当我从 Eclipse 运行它们时可以找到
  • Chrome 驱动程序和 Chromium 二进制文件无法在 aws lambda 上运行

    我陷入了一个问题 我需要在 AWS lambda 上做一些抓取工作 所以我按照下面提到的博客及其代码库作为起点 这非常有帮助 并且在运行时环境 Python 3 6 的 AWS lambda 上对我来说工作得很好 https manivan
  • PyObjC + Python 3.0 问题

    默认情况下 Cocoa Python 应用程序使用默认的 Python 运行时版本 2 5 如何配置我的 Xcode 项目以便它使用较新的 Python 3 0 运行时 我尝试用新版本替换项目中包含的Python framework 但它不
  • 超过两个点的Python相对导入

    是否可以使用路径中包含两个以上点的模块引用 就像这个例子一样 Project structure sound init py codecs init py echo init py nix init py way1 py way2 py w

随机推荐