0

I want to open an image with PIL and map every pixel to a new color(trough a more complicated function that in essence takes rgb values as a tuple an returns a new tuple of rgb values), let's say I want every pixel mapped to a random RGB color(the argument is there only to make it compatible with map):

import random


def rand_rgb(*_) -> tuple:
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)

What I would like to do is to use some for of(preferably) high level parallelism such as multiprocessing:

import multiprocessing


def row_rand_rgb(pixelrow: list) -> list:
    return list(map(rand_rgb, pixelrow)


with PIL.Image.open(imgname) as im:
    width, height = im.size
    pixelaccess = im.load()

    pixelaccess = multiprocessing.Pool().map(row_rand_rgb, pixelaccess)

    im.save()

If pixelaccess was a "normal" Python matrix, meaning a list of lists, then something of this sort would have worked, and each row of pixels in the image would have been processed separately, however this does not exactly work since from what I could see, a pixel access object is not a list of lists.

How should I go about parallelizing this?

Rares Dima
  • 1,575
  • 1
  • 15
  • 38

1 Answers1

2

You can always use numpy:

%matplotlib inline 
import matplotlib.pyplot as plt
import numpy as np

with PIL.Image.open(imgname) as im:
    width, height = im.size
    npim = np.array(im.getdata()).reshape(width, height, 3)

    pixelaccess = multiprocessing.Pool().map(row_rand_rgb, npim)

    new_im = np.array(pixelaccess, dtype=np.float32).reshape(width, height, 3)

plt.imshow(new_im)

This is what I got for a 1050x700 input image:

enter image description here

havanagrawal
  • 1,039
  • 6
  • 12