Home > Mobile >  How to create a NumPy image array with the RGB value of each point using python?
How to create a NumPy image array with the RGB value of each point using python?

Time:10-31

I am trying to make something split an Image into two and merge the two images back. I tried to use NumPy to minus a random value from each point on the image and store the value to make it a new image. Then I got a 'photo can not open this file because the formating is currently unsupported, or the file is corrupted.' on the second image. So how can I create an image with these values?

import numpy
import random
from PIL import Image
a = Image.new('RGB', [1280, 720], (255, 255, 255))
a = numpy.array(a)
value = []
for x in a:
    for y in range(0, len(x)):
        temp = [random.randrange(0, 255), random.randrange(
            0, 255), random.randrange(0, 255)]
        b = numpy.array(temp)
        x[y] = x[y]-b
        value.append(temp)
a = Image.fromarray(a)
a.show()
#print(value)
#print(len(value))  # 1280*720=921600
c = numpy.array(value)
d = Image.fromarray(c)
d.show()

CodePudding user response:

b = a.copy()
for position, color_value in numpy.ndenumerate(a):
    b[position] = abs(color_value - random.randrange(0, 255))

d = Image.fromarray(b)
d.show()

CodePudding user response:

When processing images with Python, you should try and use vectorised Numpy operations because they are much faster, and less prone to errors. If you start using Python lists and for loops, you have probably gone wrong already IMHO.

I am not certain, but I think you want to generate a random image and subtract it from an input image so you need both parts to recreate the whole, so I think you want code more like this:

import numpy as np
from PIL import Image

# Open paddington and ensure he is 3-channel RGB rather than palette
im = Image.open('paddington.png').convert('RGB')

# Make Numpy array from him
na = np.array(im)

# Make another Numpy array (i.e. image) same size as Paddington and full of random numbers
rand = np.random.randint(0,256, na.shape, dtype=np.uint8)

# See how that looks
Image.fromarray(rand).show()

# Subtract random image from Paddington - this vectorised Numpy, fast and easy to get right
split = na - rand

# See how that looks
Image.fromarray(split).show()

# Recreate original by adding random image back to split - vectorised Numpy again
joined = split   rand

# See how that looks
Image.fromarray(joined).show()

enter image description here

enter image description here


If you prefer to persist with lists and for loops, there are a few issues in your code:

  • you keep recycling a, so initially it is PIL Image, then it's a Numpy array, then a PIL Image so it is hard to refer back to anything you calculated earlier

  • rather than c = numpy.array(value) which gives you an array of np.int64, you should use c = numpy.array(value, dtype=np.uint8) to get an unsigned 8-bit array, because PIL will not like 192-bits/pixel

  • the shape of the Numpy array you create from the list will be wrong and need reshaping with d = Image.fromarray(c.reshape(720,1280,3))

  • rather than calling random.randrange() three times for every pixel and converting the result to a Numpy array, you could call np.random.randint(0,256,(3),dtype=np.uint8) to get all three values as a Numpy array in one call

  • you are probably going to have problems with overflows and underflows since you lose the underlying type of values in lists

  • Related