首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在OpenCV Python中更快地调整图像大小

在OpenCV Python中更快地调整图像大小
EN

Stack Overflow用户
提问于 2018-11-04 05:35:17
回答 2查看 6.4K关注 0票数 6

我在一个文件夹(5M+)中有很多图像文件。这些图像大小不一。我想调整这些图像到128x128的大小。

我在一个循环中使用下面的函数来使用OpenCV调整Python中的大小

代码语言:javascript
运行
复制
def read_image(img_path):
    # print(img_path)
    img = cv2.imread(img_path)
    img = cv2.resize(img, (128, 128))
    return img

for file in tqdm(glob.glob('train-images//*.jpg')):
    img = read_image(file)
    img = cv2.imwrite(file, img)

但它需要超过7个小时才能完成。我想知道是否有任何方法来加快这一进程。

我能否实现并行处理来高效地使用dask或其他什么。?如果是的话,怎么可能呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-04 10:16:08

如果你绝对想用Python来做这件事,那么请不要理会我的答案。如果你对简单而快速地完成工作感兴趣,请读下去.

我建议GNU并行,如果您有很多事情要并行做,而且随着CPU变得“胖”,有更多的核心,而不是更高的时钟速率(GHz),那么就更好了。

最简单的是,您可以在Linux、macOS和Windows中的命令行中使用ImageMagick来调整一组图像的大小:

代码语言:javascript
运行
复制
magick mogrify -resize 128x128\! *.jpg

如果您有数百张图像,您最好并行运行它,如下所示:

代码语言:javascript
运行
复制
parallel magick mogrify -resize 128x128\! ::: *.jpg

如果您有数以百万计的图像,*.jpg的扩展将使您的shell命令缓冲区溢出,因此您可以使用以下内容在stdin上输入图像名称,而不是将它们作为参数传递:

代码语言:javascript
运行
复制
find -iname \*.jpg -print0 | parallel -0 -X --eta magick mogrify -resize 128x128\!

这里有两个“技巧”:

  • 我使用find ... -print0parallel -0来空终止文件名,这样它们中的空格就没有问题,
  • 我使用parallel -X,这意味着,与其为每个映像启动一个全新的mogrify进程,GNU并行计算出了mogrify可以接受多少文件名,并给出了很多批文件。

我向你推荐这两种工具。

虽然上述答案的ImageMagick方面在Windows上工作,但我不使用Windows,也不确定是否在那里使用GNU并行。我认为它可能运行在git-bash和/或Cygwin下-你可以尝试问一个单独的问题-他们是免费的!

关于ImageMagick部分,我认为您可以使用以下命令获得文件中所有JPEG文件名的列表:

代码语言:javascript
运行
复制
DIR /S /B *.JPG > filenames.txt

然后,您可能可以像这样处理它们(而不是并行的):

代码语言:javascript
运行
复制
magick mogrify -resize 128x128\! @filenames.txt

如果您了解如何在Windows上运行GNU并行,您可能可以使用如下所示并行处理它们:

代码语言:javascript
运行
复制
parallel --eta -a filenames.txt magick mogrify -resize 128x128\!
票数 11
EN

Stack Overflow用户

发布于 2018-11-04 06:08:49

如果这些图像存储在一个磁性硬盘上,你很可能会发现你受到读/写速度的限制(很多小的读和写在旋转磁盘上是非常慢的)。

否则,您总是可以将问题抛到处理池中,以利用多个核:

代码语言:javascript
运行
复制
from multiprocessing.dummy import Pool
from multiprocessing.sharedctypes import Value
from ctypes import c_int
import time, cv2, os

wdir = r'C:\folder full of large images'
os.chdir(wdir)

def read_imagecv2(img_path, counter):
    # print(img_path)
    img = cv2.imread(img_path)
    img = cv2.resize(img, (128, 128))
    cv2.imwrite('resized_'+img_path, img) #write the image in the child process (I didn't want to overwrite my images)
    with counter.get_lock(): #processing pools give no way to check up on progress, so we make our own
        counter.value += 1

if __name__ == '__main__':
    # start 4 worker processes
    with Pool(processes=4) as pool: #this should be the same as your processor cores (or less)
        counter = Value(c_int, 0) #using sharedctypes with mp.dummy isn't needed anymore, but we already wrote the code once...
        chunksize = 4 #making this larger might improve speed (less important the longer a single function call takes)
        result = pool.starmap_async(read_imagecv2, #function to send to the worker pool
                                    ((file, counter) for file in os.listdir(os.getcwd()) if file.endswith('.jpg')),  #generator to fill in function args
                                    chunksize) #how many jobs to submit to each worker at once
        while not result.ready(): #print out progress to indicate program is still working.
            #with counter.get_lock(): #you could lock here but you're not modifying the value, so nothing bad will happen if a write occurs simultaneously
            #just don't `time.sleep()` while you're holding the lock
            print("\rcompleted {} images   ".format(counter.value), end='')
            time.sleep(.5)
        print('\nCompleted all images')

由于多少为人所知问题,cv2不能很好地处理多进程,所以我们可以使用线程代替进程,将multiprocessing.Pool替换为multiprocessing.dummy.Pool。无论如何,许多openCV函数都会释放GIL,所以我们仍然应该看到一次使用多个核的计算好处。此外,这还减少了一些开销,因为线程没有进程那么重。经过一些调查后,我还没有找到一个图像库,它可以很好地处理进程。当尝试选择要发送到子进程的函数(如何将工作项发送到子进程以进行计算)时,它们似乎都失败了。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53138062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档