Я сделал проект, который преобразовал все пиксели, близкие к белому, в прозрачные пиксели, используя модуль PIL
(библиотека изображений Python).Я не уверен, как реализовать ваш алгоритм для «относительно того, как далеко от выбранного цвета они», но мой код выглядит так:
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)) # transparent pixel
else:
newData.append(item) # unedited pixel
planeIm.putdata(newData)
planeIm.save('output.png', "PNG")
Это проходит через изображение 1920 X 1080 для меня в1.605 секунд, так что, может быть, если вы внедрите свою логику в это, вы увидите повышение скорости, которое вы хотите?
Это может быть даже быстрее, если инициализировать 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 # we already have (255, 255, 255, 0) there
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:
# print("Items in queue: {}".format(q.qsize()))
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%моего процессора, и он работает на холостом ходу уже на 1-2% ...