我曾经完成了一个项目,使用PIL
(Python图像库)模块将接近白色的所有像素转换为透明像素。我不确定如何实现您提到的“相对于所选颜色距离”的算法,但我的代码如下:
Original Answer翻译成:“最初的回答”
from PIL import Image
planeIm = Image.open('InputImage.png')
planeIm = planeIm.convert('RGBA')
datas = planeIm.getdata()
newData = []
for item in datas:
if item[0] > 240 and item[1] > 240 and item[2] > 240:
newData.append((255, 255, 255, 0))
else:
newData.append(item)
planeIm.putdata(newData)
planeIm.save('output.png', "PNG")
这对我来说在1.605秒内通过了一张1920 X 1080的图片,所以也许如果你把你的逻辑实现到这里,你会看到你想要的速度提升?如果每次都初始化
newData
而不是使用
.append()
,速度可能会更快!类似这样的操作:
planeIm = Image.open('EGGW spider.png')
planeIm = planeIm.convert('RGBA')
datas = planeIm.getdata()
newData = [(255, 255, 255, 0)] * len(datas)
for i in range(len(datas)):
if datas[i][0] > 240 and datas[i][1] > 240 and datas[i][2] > 240:
pass
else:
newData[i] = datas[i]
planeIm.putdata(newData)
planeIm.save('output.png', "PNG")
多线程
一个使用多线程计算不同图像的示例如下:
虽然对我来说,这种第二种方法运行时间为2.067秒...
最初的回答:
from PIL import Image
from threading import Thread
from queue import Queue
import time
start = time.time()
q = Queue()
planeIm = Image.open('InputImage.png')
planeIm = planeIm.convert('RGBA')
datas = planeIm.getdata()
new_data = [0] * len(datas)
print('putting image into queue')
for count, item in enumerate(datas):
q.put((count, item))
def worker_function():
while True:
index, pixel = q.get()
if pixel[0] > 240 and pixel[1] > 240 and pixel[2] > 240:
out_pixel = (0, 0, 0, 0)
else:
out_pixel = pixel
new_data[index] = out_pixel
q.task_done()
print('starting workers')
worker_count = 100
for i in range(worker_count):
t = Thread(target=worker_function)
t.daemon = True
t.start()
print('main thread waiting')
q.join()
print('Queue has been joined')
planeIm.putdata(new_data)
planeIm.save('output.png', "PNG")
end = time.time()
elapsed = end - start
print('{:3.3} seconds elapsed'.format(elapsed))
现在对我来说需要58.1秒!速度差得可怕!我会把这归因于:
- 必须两次迭代每个像素,一次将其放入队列中,一次处理并将其写入
new_data
列表。
- 创建线程所需的开销。每个新线程都需要几毫秒的时间来创建,因此创建大量线程(在本例中为100个)可能会累积。
- 使用了简单的算法来修改像素,当需要对每个输入执行大量计算时,线程会发挥作用(更像您的情况)
- 线程不利用多个核心,您需要使用多进程才能获得该功能->我的任务管理器显示我只使用了10%的CPU,而它已经处于1-2%的空闲状态...
最初的回答: