'Problem in image processing code using pillow?
I have tried to create a filter which transforms a picture.
Example: The first pixel takes the color from next one, and the last one takes the color from first one.
I used python 3.6.8 and the pillow library.
Here is my code:
from PIL import Image
from time import sleep
import random
size1=1024
size2=1024
img_1 = Image.new( 'RGB', (size1,size2), "black") # create a new black image
pixels = img_1.load() # create the pixel map
img_1.show()
for i in range(img_1.size[0]): # for every col:
for j in range(img_1.size[1]): # For every row
pixels[i,j] = (random.randint(0,255), random.randint(0,255), random.randint(0,255)) # set the colour accordingly
img_1.show()
img_2=img_1
pixels2 = img_2.load()
for j in range(img_2.size[0]):
for i in range(img_2.size[1]):
if i<size1+1:
pixels2[i,j] = pixels[i+1,j]
else:
pixels2[255,j] = pixels[0,j]
img_2.show()
And here is the error I get:
Traceback (most recent call last):
File "C:\Users\spyrosamvra\Desktop\Image procesing\image_prosec.py", line 23, in <module>
pixels2[i,j] = pixels[i+1,j]
IndexError: image index out of range
How can I fix this issue to properly transform the image as described above?
Solution 1:[1]
The bound check is wrong. You should check against size1-1
, not size1+1
. You furthermore hardcoded 255
as column in the else
case, but size1
is 1024
, so it makes more sense to just use i
insteat:
pixels2 = img_2.load()
for j in range(img_2.size[0]):
for i in range(img_2.size[1]):
if i < size1-1:
pixels2[i,j] = pixels[i+1,j]
else:
pixels2[i,j] = pixels[0,j]
img_2.show()
You can simplify this further by using a modulo expression:
pixels2 = img_2.load()
for j in range(img_2.size[0]):
for i in range(img_2.size[1]):
pixels2[i,j] = pixels[(i+1)%size1,j]
img_2.show()
The above will however still not work, since here you will first assign a value to a pixel that you will later use for a second copy operation. You can solve this by storing the first pixel in a variable, and then later set that variable, like:
pixels2 = img_2.load()
for j in range(img_2.size[0]):
first = pixels2[0,j]
for i in range(img_2.size[1]-1):
pixels2[i,j] = pixels[i+1,j]
pixels2[-1,j] = first
img_2.show()
For advanced image processing, it might however make more sense to use a library like opencv-python
[PyPi].
Solution 2:[2]
There are better ways to roll an image than use for
loops.
You can convert to a Numpy array and use Numpy's roll()
documentation like this (untested):
from PIL import Image
import numpy as np
# Load image and make Numpy version
im = Image.open('start.png')
numpyIm = np.array(im)
# Roll image
rolled = np.roll(numpyIm,1,1). # change first 1 to alter distance, change second 1 to alter direction
# Convert Numpy image back to PIL Image
pilIm = Image.fromarray(rolled)
Or you can use PIL's example from here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Willem Van Onsem |
Solution 2 | Mark Setchell |