【问题标题】:Asking for a faster method for extraction of data from Images寻求一种更快的从图像中提取数据的方法
【发布时间】:2020-07-24 07:27:06
【问题描述】:

目前我正在编写一个代码,我使用 Opencv/PIL 提取图像 RGB 值(两者都尝试过)。 然后我将它们通过一个函数来计算它们的平均值和中位数以及上下部分的平均值和中位数。 目前我的代码每秒大约需要 1 张图像,我需要为 10,000 多张图像执行此操作,这些图像存储在其类别的不同子文件夹中。 我使用 numpy 函数来表示平均值和中位数。

有没有更快的方法可以做到这一点?

编辑:图像大小不同,尺寸从 1x1 到 1000x100 不等,格式为 jpg、png 和 bmp

至于代码,我知道访问图像不会花费很长时间,但问题在于计算这些数组的均值和中值。
我会在它的外观下面添加一个代码 sn-p(如果它看起来很糟糕,我提前道歉) 最后,我还使用 xlwt 将所有这些平均值和中值写入 Excel 表,我希望这也不应该花很长时间。

我使用 os.walk 遍历目录,之后我使用
img = os.path.join(dirName,fname)
并从另一个文件中定义的函数中获取值
值 = rgbavg(img)

image = cv2.imread(image_path)
    img = np.array(image)
    img = img.transpose(2,0,1).reshape(3,-1)
    x, size = img.shape
    avg = np.mean(img, axis = 1)

    for i in range(0,3):
        upper = np.array([])
        lower = np.array([])
        for ele in img[i]:
            if ele > avg[i]:
                upper = np.append(upper,ele)
            else:
                lower = np.append(lower,ele)

        if upper.size != 0:
            mean = np.mean(upper)
            avg = np.append(avg,mean)
        else:
            avg = np.append(avg,0)
        if lower.size != 0:
            mean = np.mean(lower)
            avg = np.append(avg,mean)
        else:
            avg = np.append(avg,0)

【问题讨论】:

  • 尝试包含代码 sn-ps 显示您当前拥有的解决方案。它将帮助您描述问题的细微差别,并帮助人们为您提供更有用的答案。
  • 了解一些格式、像素尺寸和文件大小可能也很有用。如果这些是几百万像素的图像,那么花一秒钟的速度与您预期的一样快。如果它们是 100 像素的缩略图,则可以改进

标签: python image-processing data-mining


【解决方案1】:

有可能是您的程序花费大量时间等待读写操作和大量循环。

更新中的实际答案

您可以通过使用多个进程来缓解等待部分。我认为最简单的方法是使用池。这也可以通过您可用的内核数量来提高您的代码速度。

首先你要准备你的数据(收集所有文件/文件路径的列表)

然后您将其作为参数传递,以便 Pool 创建进程并保存结果

import multiprocessing
import time

files = ["img1.jpeg", "img2.jpeg", "img3.jpeg", "img4.jpeg"]

def process_image(path):
    # process image and return your data
    # time.sleep is only here to show that a different process is running as it executes faster than pool starts processes
    time.sleep(1)
    return [[0,0,0], [14,14,14], multiprocessing.current_process().name]

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(process_image, files)
        print(results)

更新:

在检查了原始代码后,我发现过滤需要很长时间(在这种情况下,将数组中的高于和低于平均值分开)。 Numpy 有一个更快的过滤器:

boolean_array = img_array |= value # 返回一个布尔数组

filtered = img_array[boolean_array] # 返回过滤后的列表

import multiprocessing
import numpy
import cv2


def process_image(xyz):
    img = numpy.random.randint(255, size=(1000,1000,3),dtype=numpy.uint8)
                      .transpose(2,0,1).reshape(3,-1)
    avg = numpy.mean(img, axis = 1)

    x, size = img.shape

    for i in range(0,3):
        upper = img[i][img[i] >= avg[i]]
        lower = img[i][img[i] < avg[i]]
        if upper.size != 0:
            # Why you are saving these idk but ok
            mean = numpy.mean(upper)
            avg = numpy.append(avg,mean)
        else:
            avg = numpy.append(avg,0)
        if lower.size != 0:
            mean = numpy.mean(lower)
            avg = numpy.append(avg,mean)
        else:
            avg = numpy.append(avg,0)
    
    return [avg, mean, multiprocessing.current_process().name]

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(process_image, range(0,12))
        print(results)

这是添加了多处理

【讨论】:

  • 您答案的第二部分很好(+1)。但是第一部分没有意义。如果处理受 I/O 限制,并且 CPU 大部分时间处于空闲状态,那么使用更多线程根本没有帮助,因为它不会使 I/O 带宽更大。
  • @CrisLuengo 我不知道为什么我认为读取图像可能需要一段时间,所以 cpu 在等待下一个图像加载时处于空闲状态。原来有很多循环。
猜你喜欢
  • 2012-01-03
  • 2016-10-20
  • 2016-06-09
  • 2019-12-31
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
相关资源
最近更新 更多