簡體   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