python中的快速寻峰和质心

2023-11-27

我正在尝试用 python 开发一种快速算法,用于查找图像中的峰值,然后找到这些峰值的质心。我使用 scipy.ndimage.label 和 ndimage.find_objects 编写了以下代码来定位对象。这似乎是代码中的瓶颈,在 500x500 图像中定位 20 个对象大约需要 7 毫秒。我想将其放大到更大的 (2000x2000) 图像,但时间会增加到几乎 100 毫秒。所以,我想知道是否有更快的选择。

这是我到目前为止的代码,它可以工作,但速度很慢。首先,我使用一些高斯峰值模拟我的数据。这部分很慢,但实际上我将使用真实数据,所以我不太关心加快这部分的速度。我希望能够很快找到峰值。

import time
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage
import matplotlib.patches 

plt.figure(figsize=(10,10))
ax1 = plt.subplot(221)
ax2 = plt.subplot(222)
ax3 = plt.subplot(223)
ax4 = plt.subplot(224)

size        = 500 #width and height of image in pixels
peak_height = 100 # define the height of the peaks
num_peaks   = 20
noise_level = 50
threshold   = 60

np.random.seed(3)

#set up a simple, blank image (Z)
x = np.linspace(0,size,size)
y = np.linspace(0,size,size)

X,Y = np.meshgrid(x,y)
Z = X*0

#now add some peaks
def gaussian(X,Y,xo,yo,amp=100,sigmax=4,sigmay=4):
    return amp*np.exp(-(X-xo)**2/(2*sigmax**2) - (Y-yo)**2/(2*sigmay**2))

for xo,yo in size*np.random.rand(num_peaks,2):
    widthx = 5 + np.random.randn(1)
    widthy = 5 + np.random.randn(1)
    Z += gaussian(X,Y,xo,yo,amp=peak_height,sigmax=widthx,sigmay=widthy)

#of course, add some noise:
Z = Z + scipy.ndimage.gaussian_filter(0.5*noise_level*np.random.rand(size,size),sigma=5)    
Z = Z + scipy.ndimage.gaussian_filter(0.5*noise_level*np.random.rand(size,size),sigma=1)    

t = time.time() #Start timing the peak-finding algorithm

#Set everything below the threshold to zero:
Z_thresh = np.copy(Z)
Z_thresh[Z_thresh<threshold] = 0
print 'Time after thresholding: %.5f seconds'%(time.time()-t)

#now find the objects
labeled_image, number_of_objects = scipy.ndimage.label(Z_thresh)
print 'Time after labeling: %.5f seconds'%(time.time()-t)

peak_slices = scipy.ndimage.find_objects(labeled_image)
print 'Time after finding objects: %.5f seconds'%(time.time()-t)

def centroid(data):
    h,w = np.shape(data)   
    x = np.arange(0,w)
    y = np.arange(0,h)

    X,Y = np.meshgrid(x,y)

    cx = np.sum(X*data)/np.sum(data)
    cy = np.sum(Y*data)/np.sum(data)

    return cx,cy

centroids = []

for peak_slice in peak_slices:
    dy,dx  = peak_slice
    x,y = dx.start, dy.start
    cx,cy = centroid(Z_thresh[peak_slice])
    centroids.append((x+cx,y+cy))

print 'Total time: %.5f seconds\n'%(time.time()-t)

###########################################
#Now make the plots:
for ax in (ax1,ax2,ax3,ax4): ax.clear()
ax1.set_title('Original image')
ax1.imshow(Z,origin='lower')

ax2.set_title('Thresholded image')
ax2.imshow(Z_thresh,origin='lower')

ax3.set_title('Labeled image')
ax3.imshow(labeled_image,origin='lower') #display the color-coded regions

for peak_slice in peak_slices:  #Draw some rectangles around the objects
    dy,dx  = peak_slice
    xy     = (dx.start, dy.start)
    width  = (dx.stop - dx.start + 1)
    height = (dy.stop - dy.start + 1)
    rect = matplotlib.patches.Rectangle(xy,width,height,fc='none',ec='red')
    ax3.add_patch(rect,)

ax4.set_title('Centroids on original image')
ax4.imshow(Z,origin='lower')

for x,y in centroids:
    ax4.plot(x,y,'kx',ms=10)

ax4.set_xlim(0,size)
ax4.set_ylim(0,size)

plt.tight_layout
plt.show()

The results for size=500: enter image description here

编辑:如果峰值数量很大(~100)并且图像尺寸很小,那么瓶颈实际上是质心部分。所以,也许这部分的速度也需要优化。


当然,您寻找峰值的方法(简单阈值处理)对阈值的选择非常敏感:将阈值设置得太低,您将“检测到”不是峰值的东西;将其设置得太高,您将错过有效的峰值。

有更强大的替代方案,可以检测图像强度中的所有局部最大值,无论其强度值如何。我的首选方法是使用小型(5x5 或 7x7)结构元素进行扩张,然后找到原始图像及其扩张版本具有相同值的像素。这是有效的,因为根据定义, dilation(x, y, E, img) = { E 内以像素 (x,y) 为中心的最大 img },因此 dilation(x, y, E, img) = img(x , y) 只要 (x,y) 是 E 尺度上的局部最大值的位置。

通过快速实现形态学算子(例如 OpenCV 中的算子),该算法在空间和时间上的图像大小都是线性的(一个额外的图像大小的缓冲区用于扩张图像,并且对两者都进行一次传递)。在紧要关头,它也可以在线实现,无需额外的缓冲区和一点额外的复杂性,而且仍然是线性时间。

为了在存在椒盐或类似噪声(可能会引入许多虚假最大值)的情况下进一步增强其鲁棒性,您可以使用不同大小的结构元素(例如 5x5 和 7x7)应用该方法两次,然后仅保留稳定的最大值,其中稳定性可以通过最大值的位置不变或位置变化不超过一个像素等来定义。此外,当您有理由相信附近的最大值是由噪声引起时,您可能希望抑制它们。一种有效的方法是首先检测上面的所有局部最大值,按高度降序对它们进行排序,然后沿着排序列表向下查找,如果它们在图像中的值没有改变,则保留它们,如果保留,则设置为将 (2d+1) x (2d+1) 邻域中的所有像素归零,其中 d 是您愿意容忍的附近最大值之间的最小距离。

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

python中的快速寻峰和质心 的相关文章

  • 将一维数组转换为下三角矩阵

    我想将一维数组转换为较低的零对角矩阵 同时保留所有数字 我知道numpy tril函数 但它用零替换了一些元素 我需要扩展矩阵以包含所有原始数字 例如 10 20 40 46 33 14 12 46 52 30 59 18 11 22 30
  • 在Python中以交互方式执行多行语句

    我是 Python 世界的新手 这是我用 Python 编写的第一个程序 我来自 R 世界 所以这对我来说有点不直观 当我执行时 In 15 import math import random random random math sqrt
  • 对于相同的查询,MySQL Workbench 比 Python 快得多

    MySQL Workbench 中的以下查询需要 0 156 秒才能完成 SELECT date time minute price id FROM minute prices WHERE contract id 673 AND TIMES
  • 如何在Python代码中查找列号

    简短问题 当按上述方式调用函数时 我可以找到行号here https stackoverflow com questions 3056048 filename and line number of python script 同样 如何找到
  • NumPy 和 SciPy - .todense() 和 .toarray() 之间的区别

    我想知道使用是否有什么区别 优点 缺点 toarray vs todense 在稀疏 NumPy 数组上 例如 import scipy as sp import numpy as np sparse m sp sparse bsr mat
  • Django 模型字段默认基于另一个模型字段

    我使用 Django Admin 构建一个管理站点 有两张表 一张是ModelA其中有数据 另一个是ModelB里面什么也没有 如果一个模型字段b b in ModelB为None 可以显示在网页上 值为ModelA的场a b 我不知道该怎
  • 如何使用 PyMongo 在重复键错误后继续插入

    如果我需要在 MongoDB 中插入尚不存在的文档 db stock update one document set document upsert True 将完成这项工作 如果我错了 请随时纠正我 但是 如果我有一个文档列表并想将它们全
  • 返回上个月的日期时间对象

    如果 timedelta 在它的构造函数中有一个月份参数就好了 那么最简单的方法是什么 EDIT 正如下面指出的那样 我并没有认真考虑这一点 我真正想要的是上个月的任何一天 因为最终我只会获取年份和月份 因此 给定一个日期时间对象 返回的最
  • Pandas groupby apply 执行缓慢

    我正在开发一个涉及大量数据的程序 我正在使用 python pandas 模块来查找数据中的错误 这通常工作得非常快 然而 我当前编写的这段代码似乎比应有的速度慢得多 我正在寻找一种方法来加快速度 为了让你们正确测试它 我上传了一段相当大的
  • 如何使用 Celery 多工作人员启用自动缩放?

    命令celery worker A proj autoscale 10 1 loglevel info启动具有自动缩放功能的工作人员 当创建多个工人时 me mypc projects x celery multi start mywork
  • Pandas:将 pytz.FixedOffset 应用于系列

    我有一个带有timestamp列看起来像这样 0 2020 01 26 05 00 00 08 00 1 2020 01 26 06 00 00 08 00 Name timestamp dtype datetime64 ns pytz F
  • 将列表中的 None 替换为最左边的非 none 值

    Given a None 1 2 3 None 4 None None I d like a None 1 2 3 3 4 4 4 目前我已经用以下方法强制它 def replaceNoneWithLeftmost val last Non
  • 计算 pyspark df 列中子字符串列表的出现次数

    我想计算子字符串列表的出现次数 并根据 pyspark df 中包含长字符串的列创建一个列 Input ID History 1 USA UK IND DEN MAL SWE AUS 2 USA UK PAK NOR 3 NOR NZE 4
  • 在python中读取PASCAL VOC注释

    我在 xml 文件中有注释 例如这个 它遵循 PASCAL VOC 约定
  • 在 scipy 中创建新的发行版

    我试图根据我拥有的一些数据创建一个分布 然后从该分布中随机抽取 这是我所拥有的 from scipy import stats import numpy def getDistribution data kernel stats gauss
  • Python 导入非常慢 - Anaconda python 2.7

    我的 python import 语句变得非常慢 我使用 Anaconda 包在本地运行 python 2 7 导入模块后 我编写的代码运行得非常快 似乎只是导入需要很长时间 例如 我使用以下代码运行了一个 tester py 文件 imp
  • 如何使用 os.chdir 转到减去最后一步的路径?

    例如 一个方法传递了一个路径作为参数 这个路径可能是 C a b c d 如果我想使用 os chdir 更改为 C a b 怎么办 c 没有最后一个文件夹 os chdir 可以接受 命令吗 os chdir 可以采取 作为论点 是的 然
  • 沿轴 0 重复 scipy csr 稀疏矩阵

    我想重复 scipy csr 稀疏矩阵的行 但是当我尝试调用 numpy 的重复方法时 它只是将稀疏矩阵视为对象 并且只会将其作为 ndarray 中的对象重复 我浏览了文档 但找不到任何实用程序来重复 scipy csr 稀疏矩阵的行 我
  • Java/Python 中的快速 IPC/Socket 通信

    我的应用程序中需要两个进程 Java 和 Python 进行通信 我注意到套接字通信占用了 93 的运行时间 为什么通讯这么慢 我应该寻找套接字通信的替代方案还是可以使其更快 更新 我发现了一个简单的修复方法 由于某些未知原因 缓冲输出流似
  • 在python中对列表列表执行行总和和列总和

    我想用python计算矩阵的行和和列和 但是 由于信息安全要求 我无法使用任何外部库 因此 为了创建矩阵 我使用了列表列表 如下所示 matrix 0 for x in range 5 for y in range 5 for pos in

随机推荐

  • 访问相邻组件/字段的最佳方式

    我正在寻找一种访问组件 字段的方法 这些组件 字段要么与访问的项目位于同一项目数组中 要么甚至仅位于同一父项目数组中 最后一个只是一个选项 在 ExtJS3 中 这很容易 只需定义一个ref在所有者容器中 但我没有在 ExtJS4 中找到类
  • R 根据行中的值在列中重复

    我有一个如下所示的数据框 Name School Weight Days Antoine Bach 0 03 5 Antoine Ken 0 02 7 Barbara Franklin 0 04 3 我想获得如下输出 Name School
  • Python sys.path - 附加 PYTHONPATH

    开始之前 我已经尝试完成它有一段时间了 但我没有运气 我正在尝试创建自己的 python 包 我将在项目中的单独文件中导入其中的模块 我尝试通过 sys 将项目的目录添加到 pythonpath 但 mod wsgi 仍然无法识别它 imp
  • 使用本地通知 ios 打开 url

    我已经搜索了一段时间试图找到答案 但似乎找不到 我想做的是让我的应用程序在后台运行时发送本地通知 并且当用户打开通知时 会将他们带到网站 我已全部设置完毕 但它一直打开应用程序而不是访问网站 我的问题是 这可能吗 如果是这样 您能看看我下面
  • 从源代码构建 Python3.7.3 缺少“_ctypes”

    我正在尝试从源代码构建Python 3 7 3ensurepip但我收到此错误 ModuleNotFoundError No module named ctypes 网上所有的答案都这么说libffi dev是需要的 但我已经安装了它 但它
  • Mobile Safari - 当最后一次触摸被删除时,“touchend”事件没有触发?

    我试图捕获的 手势 是当但仅当元素 其他或相同 已经触摸时的点击 因此 触摸 1 按下按钮 同时触摸 2 点击所选选项 触摸 1 释放并按下按钮 我遇到的问题是最后一点 当我释放最后一个手指时 touchend 事件没有被触发 那么我没有办
  • Android手机可以使用windows DirectX库吗?

    我有一些使用 Windows 中的 Direct X 库绘制游戏屏幕的函数 因此 我尝试使用 ndk 来使用 Android 手机中的功能 但我有一些问题 使用Java的Android手机可以识别Direct X功能吗 如果可以的话 我必须
  • git add --interactive“您编辑的块不适用”

    我正在尝试使用git add interactive有选择地向我的索引添加一些更改 但我不断收到 您编辑的大块不适用 再次编辑 消息 即使我选择 e 选项 我也会收到此消息 并立即保存 关闭我的编辑器 换句话说 如果根本不编辑该块 该补丁就
  • Rabbitmq Consumer_Timeout 行为未按预期工作?

    我很难证明consumer timeout设置正在按预期工作 我可能做错了或者误解了consumer timeout行为 我所有的测试代码都可以在这里找到 https github com Rafarel rabbitmq tests 基本
  • instance_eval 的块参数 - 已记录?目的?

    刚刚意识到instance eval yields self作为关联块的参数 1 9 2 版本中的错误除外 http www ruby forum com topic 189422 1 9 3p194 003 gt class C end
  • 如何从 LINQ to XML 中的 XElement 读取特定元素值

    我有一个XElement其中有这样的内容
  • HTML:如何创建“另存为”按钮?

    在浏览器中 当您想要保存当前正在查看的 HTML 页面时 通常会转到 文件 菜单并单击 另存为 我可以在 HTML 页面底部添加一个具有相同功能的小按钮吗 因此 我希望我的用户能够单击按钮将页面保存到磁盘上 而不是转到 文件 菜单 gt 另
  • EF Core 2.0 Identity - 添加导航属性

    在 EF Core 2 0 中 默认情况下不包含 Identity 导航属性 因此在升级后 我添加了它们 因此 对于用户和角色之间的多对多关系以及角色和 RoleClaim 之间的一对多关系 我添加了以下导航属性 public class
  • 如何扩展Spring注解@Transactional

    我必须在我的网络应用程序中使用 3 个不同的事务管理器 所以我根据以下内容编写了自己的注释弹簧参考 第 10 5 6 3 节自定义快捷方式注释 一个注释 用于使用一个特定的事务管理器 如下所示 import java lang annota
  • 使用 PHP 删除文件夹中的所有文件?

    例如 我有一个名为 Temp 的文件夹 我想使用 PHP 删除或刷新该文件夹中的所有文件 我可以这样做吗 files glob path to temp get all file names foreach files as file it
  • Numpy 融合乘法和加法以避免浪费内存

    是否可以将两个 ndarray A 和 B 相乘并将结果添加到 C 而无需为 A 乘以 B 创建一个大型中间数组 Numpy 对于 C A 乘 B 的情况有 out 关键字参数 numpy multiply A B out C C A 乘以
  • SQL Server SORT 顺序与 ASCII 代码顺序不对应

    我正在使用 SQL Server 2012 并且我有一个数据库SQL Latin1 General CP1 CI AS整理 create table testtable c nvarchar 1 null insert into testt
  • 通过 USB 安装应用程序 [安装被用户取消]

    我可以通过 USB 将应用程序安装到我的 Android 设备上 但是 当 Android 上显示允许 拒绝安装弹出窗口时 我错误地单击了 拒绝 并选中了 记住我的选择 现在 每次尝试通过 USB ADB 安装应用程序都失败并出现错误com
  • UrlHelper.GenerateUrl 的 ASP.NET MVC 公共替代方案

    我想在我的页面中嵌入一个指向控制器操作的链接 以便我可以从 javascript 使用它 就像是 var pollAction Mycontroller CheckStatus 现在我很高兴对其进行硬编码 但如果有一种可以用来创建 URL
  • python中的快速寻峰和质心

    我正在尝试用 python 开发一种快速算法 用于查找图像中的峰值 然后找到这些峰值的质心 我使用 scipy ndimage label 和 ndimage find objects 编写了以下代码来定位对象 这似乎是代码中的瓶颈 在 5