- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了一个脚本,使用均方根比较对大量图像(超过 4500 个文件)进行相互比较。首先,它将每个图像的大小调整为 800x600 并绘制直方图。之后,它构建一个组合数组并将它们平均分配给四个线程,计算每个组合的均方根。 RMS 低于 500 的图像将被移动到文件夹中,以便稍后手动整理。
#!/usr/bin/python3
import sys
import os
import math
import operator
import functools
import datetime
import threading
import queue
import itertools
from PIL import Image
def calc_rms(hist1, hist2):
return math.sqrt(
functools.reduce(operator.add, map(
lambda a, b: (a - b) ** 2, hist1, hist2
)) / len(hist1)
)
def make_histogram(imgs, path, qout):
for img in imgs:
try:
tmp = Image.open(os.path.join(path, img))
tmp = tmp.resize((800, 600), Image.ANTIALIAS)
qout.put([img, tmp.histogram()])
except Exception:
print('bad image: ' + img)
return
def compare_hist(pairs, path):
for pair in pairs:
rms = calc_rms(pair[0][1], pair[1][1])
if rms < 500:
folder = 'maybe duplicates'
if rms == 0:
folder = 'exact duplicates'
try:
os.rename(os.path.join(path, pair[0][0]), os.path.join(path, folder, pair[0][0]))
except Exception:
pass
try:
os.rename(os.path.join(path, pair[1][0]), os.path.join(path, folder, pair[1][0]))
except Exception:
pass
return
def get_time():
return datetime.datetime.now().strftime("%H:%M:%S")
def chunkify(lst, n):
return [lst[i::n] for i in range(n)]
def main(path):
starttime = get_time()
qout = queue.Queue()
images = []
for img in os.listdir(path):
if os.path.isfile(os.path.join(path, img)):
images.append(img)
imglen = len(images)
print('Resizing ' + str(imglen) + ' Images ' + starttime)
images = chunkify(images, 4)
threads = []
for x in range(4):
threads.append(threading.Thread(target=make_histogram, args=(images[x], path, qout)))
[x.start() for x in threads]
[x.join() for x in threads]
resizetime = get_time()
print('Done resizing ' + resizetime)
histlist = []
for i in qout.queue:
histlist.append(i)
if not os.path.exists(os.path.join(path, 'exact duplicates')):
os.makedirs(os.path.join(path, 'exact duplicates'))
if not os.path.exists(os.path.join(path, 'maybe duplicates')):
os.makedirs(os.path.join(path, 'maybe duplicates'))
combinations = []
for img1, img2 in itertools.combinations(histlist, 2):
combinations.append([img1, img2])
combicount = len(combinations)
print('Going through ' + str(combicount) + ' combinations of ' + str(imglen) + ' Images. Please stand by')
combinations = chunkify(combinations, 4)
threads = []
for x in range(4):
threads.append(threading.Thread(target=compare_hist, args=(combinations[x], path)))
[x.start() for x in threads]
[x.join() for x in threads]
print('\nstarted at ' + starttime)
print('resizing done at ' + resizetime)
print('went through ' + str(combicount) + ' combinations of ' + str(imglen) + ' Images')
print('all done at ' + get_time())
if __name__ == '__main__':
main(sys.argv[1]) # sys.argv[1] has to be a folder of images to compare
这可行,但比较会在 15 到 20 分钟内完成调整大小后运行数小时。起初我假设这是一个锁定队列,工作人员从中获取他们的组合,所以我用预定义的数组 block 替换它。这并没有减少执行时间。我还在不移动文件的情况下运行它,以排除可能的硬盘驱动器问题。
使用 cProfile 对此进行分析可提供以下输出。
Resizing 4566 Images 23:51:05
Done resizing 00:05:07
Going through 10421895 combinations of 4566 Images. Please stand by
started at 23:51:05
resizing done at 00:05:07
went through 10421895 combinations of 4566 Images
all done at 03:09:41
10584539 function calls (10584414 primitive calls) in 11918.945 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
16/1 0.001 0.000 11918.945 11918.945 {built-in method exec}
1 2.962 2.962 11918.945 11918.945 imcomp.py:3(<module>)
1 19.530 19.530 11915.876 11915.876 imcomp.py:60(main)
51 11892.690 233.190 11892.690 233.190 {method 'acquire' of '_thread.lock' objects}
8 0.000 0.000 11892.507 1486.563 threading.py:1028(join)
8 0.000 0.000 11892.507 1486.563 threading.py:1066(_wait_for_tstate_lock)
1 0.000 0.000 11051.467 11051.467 imcomp.py:105(<listcomp>)
1 0.000 0.000 841.040 841.040 imcomp.py:76(<listcomp>)
10431210 1.808 0.000 1.808 0.000 {method 'append' of 'list' objects}
4667 1.382 0.000 1.382 0.000 {built-in method stat}
可以在 here 中找到完整的分析器输出。
考虑到第四行,我猜测线程以某种方式锁定了。但为什么以及为什么不管图像数量多少都恰好是 51 次?
我在 Windows 7 64 位上运行它。
提前致谢。
最佳答案
一个主要问题是您使用线程来完成至少部分受 CPU 限制的工作。由于全局解释器锁,一次只能运行一个 CPython 线程,这意味着您无法利用多个 CPU 内核。这将使 CPU 绑定(bind)任务的多线程性能充其量与单核执行没有区别,甚至可能更糟,因为线程增加了额外的开销。这在 threading
documentation 中有说明。 :
CPython implementation detail: In CPython, due to the Global Interpreter Lock, only one thread can execute Python code at once (even though certain performance-oriented libraries might overcome this limitation). If you want your application to make better use of the computational resources of multi-core machines, you are advised to use
multiprocessing
. However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously.
要绕过 GIL 的限制,您应该按照文档中的说明进行操作,并使用 multiprocessing
库而不是 threading
库:
import multiprocessing
...
qout = multiprocessing.Queue()
for x in range(4):
threads.append(multiprocessing.Process(target=make_histogram, args=(images[x], path, qout)))
...
for x in range(4):
threads.append(multiprocessing.Process(target=compare_hist, args=(combinations[x], path)))
如您所见,multiprocessing
在大多数情况下是 threading
的直接替代品,因此进行更改应该不会太难。唯一的复杂情况是,如果您在进程之间传递的任何参数不可挑选,尽管我认为所有这些参数都适用于您的情况。在进程之间发送 Python 数据结构的 IPC 成本也会增加,但我怀疑真正并行计算的好处将超过额外的开销。
综上所述,由于依赖于对磁盘的读/写操作,您可能仍会受到 I/O 的限制。并行化不会使您的磁盘 I/O 更快,因此在那里可以做的事情不多。
关于python - 如何优化图像比较脚本的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25879558/
我正在尝试学习 Knockout 并尝试创建一个照片 uploader 。我已成功将一些图像存储在数组中。现在我想回帖。在我的 knockout 码(Javascript)中,我这样做: 我在 Jav
我正在使用 php 编写脚本。我的典型问题是如何在 mysql 中添加一个有很多替代文本和图像的问题。想象一下有机化学中具有苯结构的描述。 最有效的方法是什么?据我所知,如果我有一个图像,我可以在数据
我在两个图像之间有一个按钮,我想将按钮居中到图像高度。有人可以帮帮我吗? Entrar
下面的代码示例可以在这里查看 - http://dev.touch-akl.com/celebtrations/ 我一直在尝试做的是在 Canvas 上绘制 2 个图像(发光,然后耀斑。这些图像的链接
请检查此https://jsfiddle.net/rhbwpn19/4/ 图像预览对于第一篇帖子工作正常,但对于其他帖子则不然。 我应该在这里改变什么? function readURL(input)
我对 Canvas 有疑问。我可以用单个图像绘制 Canvas ,但我不能用单独的图像绘制每个 Canvas 。- 如果数据只有一个图像,它工作正常,但数据有多个图像,它不工作你能帮帮我吗? va
我的问题很简单。如何获取 UIImage 的扩展类型?我只能将图像作为 UIImage 而不是它的名称。图像可以是静态的,也可以从手机图库甚至文件路径中获取。如果有人可以为此提供一点帮助,将不胜感激。
我有一个包含 67 个独立路径的 SVG 图像。 是否有任何库/教程可以为每个路径创建单独的光栅图像(例如 PNG),并可能根据路径 ID 命名它们? 最佳答案 谢谢大家。我最终使用了两个答案的组合。
我想将鼠标悬停在一张图片(音乐专辑)上,然后播放一张唱片,所以我希望它向右移动并旋转一点,当它悬停时我希望它恢复正常动画片。它已经可以向右移动,但我无法让它随之旋转。我喜欢让它尽可能简单,因为我不是编
Retina iOS 设备不显示@2X 图像,它显示 1X 图像。 我正在使用 Xcode 4.2.1 Build 4D502,该应用程序的目标是 iOS 5。 我创建了一个测试应用(主/细节)并添加
我正在尝试从头开始以 Angular 实现图像 slider ,并尝试复制 w3school基于图像 slider 。 下面我尝试用 Angular 实现,谁能指导我如何使用 Angular 实现?
我正在尝试获取图像的图像数据,其中 w= 图像宽度,h = 图像高度 for (int i = x; i imageData[pos]>0) //Taking data (here is the pr
我的网页最初通过在 javascript 中动态创建图像填充了大约 1000 个缩略图。由于权限问题,我迁移到 suPHP。现在不用标准 标签本身 我正在通过这个 php 脚本进行检索 $file
我正在尝试将 python opencv 图像转换为 QPixmap。 我按照指示显示Page Link我的代码附在下面 img = cv2.imread('test.png')[:,:,::1]/2
我试图在这个 Repository 中找出语义分割数据集的 NYU-v2 . 我很难理解图像标签是如何存储的。 例如,给定以下图像: 对应的标签图片为: 现在,如果我在 OpenCV 中打开标签图像,
import java.util.Random; class svg{ public static void main(String[] args){ String f="\"
我有一张 8x8 的图片。 (位图 - 可以更改) 我想做的是能够绘制一个形状,给定一个 Path 和 Paint 对象到我的 SurfaceView 上。 目前我所能做的就是用纯色填充形状。我怎样才
要在页面上显示图像,你需要使用源属性(src)。src 指 source 。源属性的值是图像的 URL 地址。 定义图像的语法是: 在浏览器无法载入图像时,替换文本属性告诉读者她们失去的信息。此
**MMEditing是基于PyTorch的图像&视频编辑开源工具箱,支持图像和视频超分辨率(super-resolution)、图像修复(inpainting)、图像抠图(matting)、
我正在尝试通过资源文件将图像插入到我的程序中,如下所示: green.png other files 当我尝试使用 QImage 或 QPixm
我是一名优秀的程序员,十分优秀!