繁体   English   中英

更有效地过滤多个列表和嵌套的 for 循环

[英]More efficient filtering of multiple lists and nested for loops

我试图在 3 个重叠图像中找到对象的位置。 本质上,我在 3 个不同的光谱中拍摄图像并将它们叠加起来以提取浓度数据。 我对其进行了圆形分析,然后比较每个项目以查看它是否足够接近以重叠。 下面的算法正在运行,但是比较次数使该算法每次运行大约 2 分钟,我需要每次运行大约 1-5 秒,因为我必须在最终产品中进行数百次比较。

我正在尝试更复杂的算法,但我想我会问,因为可能有一个更简单的方法,我想多了。

我的列表平均有 100-500 项。

我认为这可能会有所帮助,但我不知道如何在其中进行所有比较或如何更快(我可能只是愚蠢)。

“更好”的算法:

  1. 将图像分成多个重叠的扇区,并在每个区域中进行相同的比较,然后过滤掉重叠部分。 我之前做过类似的事情,但最终的过滤器非常复杂。

  2. 将所有 3 个列表排序为一个“对角线”排序的列表,并将每个项目与远离其位置的一两个进行比较。 目前,我的排序算法很慢,无法使用,我无法解决“本地化”问题。

  3. (目前是先行者)我将 3 张图像混合在一起,覆盖我之前的检测算法,获取特征的平均颜色,然后运行聚类算法将其分离。

  circles_array = [[circles_blue, len(circles_blue)], [circles_green, len(circles_green)], [circles_grey, len(circles_grey)]]
  circles_array = sorted(circles_array, key=lambda x: x[1], reverse=True)

  shortest = circles_array[2][0]
  middle = circles_array[1][0]
  longest = circles_array[0][0]
  
  # CLASSIFYwhe
  perfect_drops = 0
  perfect_list = []

  print("Running sort, please wait...")
  for s in shortest:
    for m in middle:
      for l in longest:
        if s[1] < m[1]+50 and s[1] > m[1]-50:
          if s[1] < l[1]+50 and s[1] > l[1]-50:
            if s[0] < m[0]+50 and s[0] > m[0]-50:
              if s[0] < l[0]+50 and s[0] > l[0]-50: 
                perfect_drops += 1
                perfect_list.append([s,m,l])

示例输入

在此处输入图像描述

在此处输入图像描述 在此处输入图像描述

本质上,您的程序通过迭代每个组合来比较三个数字列表。 如果列表有n 个元素,则您正在进行n 3次比较。 这是非常低效的。 您可以改为 map 将绿色变为灰色,然后将蓝色变为灰色,从而仅进行 2 n 2比较。 尽管如此,没有必要进行这种循环,因为图像为您提供了空间索引。 您可以在灰色图像中找到每个圆圈的位置,然后查看绿色和蓝色图像中的这些位置,看看这些像素是否足够亮以将它们视为“开启”。

稍微重叠的圆圈和图像之间的轻微位移使这有点困难。 如果位移比本例中的情况更糟,则可能需要先进行图像配准。

这就是我使用DIPlib实现它的方式:

import diplib as dip
import numpy as np

gray = dip.ImageRead('kv8A9.jpg')
blue = dip.ImageRead('KZmTq.jpg')
blue = blue(2)
green = dip.ImageRead('nqIwo.jpg')
green = green(1)

blue = blue > 90    # some threshold, tweak as necessary
green = green > 75  # idem

s = dip.Watershed(gray, connectivity=2, maxDepth=20, flags={'labels','high first'})

msr = dip.MeasurementTool.Measure(s, features=['Size'])
msr_blue = dip.MeasurementTool.Measure(s, dip.Convert(blue, 'UINT8'), features=['Mean'])
msr_green = dip.MeasurementTool.Measure(s, dip.Convert(green, 'UINT8'), features=['Mean'])

isblue = np.array(msr_blue['Mean']) > 0.67    # sufficient overlap = 67%
isgreen = np.array(msr_green['Mean']) > 0.67
islarge = np.array(msr['Size']) > 4000        # sufficiently large to be a circle

value = np.ones(isblue.shape)
value[isblue] = 3            # maps to blue in the "labels" color map of DIPlib
value[isgreen] = 2           # maps to green
value[isblue & isgreen] = 5  # maps to cyan=green+blue
value[~islarge] = 0
value = value.squeeze()
index = msr.Objects()
out =  dip.LookupTable(s, value, index, interpolation='nearest', mode='values', lowerValue=0, upperValue=0)

彩色显示

当然你不需要做最后一段,那只是为了创建显示。 isblue & isgreen为您提供绿色和蓝色都具有足够亮度的区域。 您应该只计算那些islargeTrue的区域,因为其他区域太小而不能被视为一个圆圈。

您将不得不适当调整阈值。

此代码在几分之一秒内运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM