I'm trying to apply a ripple effect to an image in python. I found Pillow's im.transform(im.size, Image.MESH,.... is it possible? Maybe I have to load the image with numpy and apply the algorithm. I also found this: http://www.pygame.org/project-Water+Ripples-1239-.html
another way manually but I don't know any algorithm. this is my start. it doesn't do anything...
#!/usr/bin/env python3
from PIL import Image
import sys
import numpy
import math
im = Image.open(sys.argv[1])
im.show()
matrix = numpy.asarray(im)
width = im.size[0]
height = im.size[1]
amplitude = ? # parameters
frequency = ?
matrix_dest = numpy.zeros((im.size[0],im.size[1],3))
for x in range(0, width):
for y in range(0, height):
pass # ç_ç
im2 = Image.fromarray(numpy.uint8(matrix_dest))
im2.show()
EDIT:
I'd really like to keep this structure (using pillow. I already use extensivly in my project and if I can I wouldn't add any other dependency) and not including scipi or matplotlib.. With the following code I have the distortion I wanted, but colors are screwed up. Maybe I have to apply the distortion to R,G,B planes and then compose the result in one image. Or palettize the image and then apply the original palette.
(Btw the image would be used as a texture to display moving water in a 3D environment.)
im = Image.open(sys.argv[1])
im.show()
m = numpy.asarray(im)
m2 = numpy.zeros((im.size[0],im.size[1],3))
width = im.size[0]
height = im.size[1]
A = m.shape[0] / 3.0
w = 1.0 / m.shape[1]
shift = lambda x: A * numpy.sin(2.0*numpy.pi*x * w)
for i in range(m.shape[0]):
print(int(shift(i)))
m2[:,i] = numpy.roll(m[:,i], int(shift(i)))
im2 = Image.fromarray(numpy.uint8(m2))
im2.show()
You could use np.roll
to rotate each row or column according to some sine function.
from scipy.misc import lena
import numpy as np
import matplotlib.pyplot as plt
img = lena()
A = img.shape[0] / 3.0
w = 2.0 / img.shape[1]
shift = lambda x: A * np.sin(2.0*np.pi*x * w)
for i in range(img.shape[0]):
img[:,i] = np.roll(img[:,i], int(shift(i)))
plt.imshow(img, cmap=plt.cm.gray)
plt.show()
Why don't you try something like:
# import scipy
# import numpy as np
for x in range(cols):
column = im[:,x]
y = np.floor(sin(x)*10)+10
kernel = np.zeros((20,1))
kernel[y] = 1
scipy.ndimage.filters.convolve(col,kernel,'nearest')
I threw this together just right now, so you'll need to tweak it a bit. The frequency of the sin is definitely too high, check here. But I think overall this should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With