|
|
(30 intermediate revisions by the same user not shown) |
Line 5: |
Line 5: |
| Here is my first drawing in class with coding. | | Here is my first drawing in class with coding. |
| my sheep robot. . . funny one | | my sheep robot. . . funny one |
| [[File:Sheep.png |100px|]] | | [[File:Sheep.png |200px|]] |
|
| |
|
|
| |
|
Line 29: |
Line 29: |
| ----Cloud Code---- | | ----Cloud Code---- |
| <pre style="font-size:smaller" > | | <pre style="font-size:smaller" > |
| | <source lang="python"> |
| #cloud | | #cloud |
| width = 400 | | width = 400 |
Line 83: |
Line 84: |
|
| |
|
| </pre> | | </pre> |
| | </source> |
|
| |
|
|
| |
|
Line 92: |
Line 94: |
| ======Kaleidoscope Bot=======''' | | ======Kaleidoscope Bot=======''' |
|
| |
|
| | '''STEP 1: Still Kaleido''' |
|
| |
|
| My midtern project is making a image processing bot which make a kaleidoscope style image out of an image. | | My midtern project is making a image processing bot which make a kaleidoscope style image out of an image. |
Line 106: |
Line 109: |
| [[File:Screen Shot 2558-06-17 at 12.03.18 AM.png]] | | [[File:Screen Shot 2558-06-17 at 12.03.18 AM.png]] |
|
| |
|
| As can be seen here,in this step, the final resault take only small part of the source image. | | As can be seen here,in this step, the final result take only small part of the source image. |
|
| |
|
| It is quite difficult to trance back what the sorce image look like. | | It is quite difficult to trace back what the source image look like but it is the preparation for the next step. |
|
| |
|
|
| |
|
| code for the image processing | | code for the image processing |
| ============================= | | ============================= |
| <pre style="font-size:normal" > | | |
| | <source lang="python"> |
|
| |
|
| from PIL import Image, ImageDraw,ImageFilter | | from PIL import Image, ImageDraw,ImageFilter |
Line 219: |
Line 223: |
|
| |
|
|
| |
|
| </pre> | | </source> |
|
| |
|
|
| |
|
| I also made the gif version of Kaleidoscope by make 35 different images each turning 10 degree of the source image.
| | '''FINAL BOT''' |
|
| |
|
| Source image : illustration from Oliver Jeffers
| | '''STEP 2 : moving Kaleido''' |
| [[File:JEFFERS>JPG]]
| |
|
| |
|
| This is the code of Gif Version
| | The next step is to make the bot gives more feeling of Kaleidoscope. The nice part of Kaleidoscope is whhen one rotate it around and see the abtract patterns moving. |
|
| |
|
| [[Media:jeffers.gif |Example result .GIF]]
| | I try to make it the similar feeling here with the bot that each still image is so abstact but when one finish watching the whole loop of rotation then you will have clue about what is the source image. |
|
| |
|
| ======Kaleidoscope 360 GIF ========
| | [[File:kaleidochart2.jpg]] |
| <pre style="font-size:normal" >
| |
|
| |
|
| from PIL import Image, ImageDraw,ImageFilter
| | In the code, I made the variable 'n' and 'a' to be able to adjust the the result GIF file. |
| import PIL.ImageOps as im
| | n is the number of the rotation time |
| import numpy as np
| | a is the degree of the rotation |
| import moviepy.editor as mpy
| |
|
| |
|
| | so they will affect how smooth the animated GIF going to be. |
|
| |
|
|
| |
|
| def onepic():
| | '''STEP 3 Making the bot works online''' |
| global output
| |
| #creat mask base the same size with source image
| |
| mask = Image.new('RGBA', base.size, (255,255,255,0))
| |
| x, y = base.size
| |
| print("base size: %sx%s"%(x,y))
| |
|
| |
|
| # one variable to vary the size of triangle
| | The @kaleidogif twiiter account is created to be the page for the bot. |
| var = y/28
| | ( Before that I just did trial and errors with my own account) |
| | |
| # Define triangle mask position (triangle with 20 degree)
| |
| (originx,originy) = (int(0.4*x),int(y))
| |
| trih = int(12*var) #fix formular for triangle height
| |
| triw = int(4.2*var) #fix formular for triangle width
| |
| polygonpos = [(originx,originy),
| |
| (originx+triw,originy),
| |
| (originx+triw/2,originy-trih)]
| |
| print(trih,triw)
| |
| | |
| | |
| # Create mask
| |
| draw = ImageDraw.Draw(mask,'RGBA')
| |
| draw.polygon(polygonpos,(0,0,0,255))
| |
| del draw
| |
| mask.save("mask.png")
| |
|
| |
|
| # Get the Alpha band from the template
| | Link : [KaleidoGIF twitter|https://twitter.com/kaleidogif] |
| tmplt = Image.open('mask.png')
| |
| A = tmplt.split()[3]
| |
|
| |
|
|
| |
|
| #make one piece of triangle on transparent bg
| | [[File:Botscreen1.PNG|900px]] |
| [R,G,B]=base.split()
| |
| tri = Image.merge('RGBA', (R, G, B, A))
| |
|
| |
|
| #crop it to the exact size of triangle!! to create primary pattern
| | This is the example result. |
| #box (left, top , right, buttom)
| |
| box =(originx,(originy-trih),(originx+triw),originy)
| |
| pattern_plain=tri.crop(box)
| |
| pattern_plain.save('pattern_plain.png')
| |
| print('....pattern created....')
| |
|
| |
|
| | [[File:Botexample1.png|210 px]] |
| | [[File:Kaleidogif1.gif]] |
|
| |
|
| # add style to pattern
| | more examples of the final result !! |
| pattern = pattern_plain
| | [[File:Botexamplegif2.gif]] |
| #pattern= pattern_plain.filter(ImageFilter.EDGE_ENHANCE)
| | [[File:Kaleidoexample3.gif.gif|320 px]] |
| pattern.save('pattern_tri.png')
| | [[File:Kaleidoexample2.gif|320 px]] |
| print('....stylized pattern....')
| |
|
| |
|
|
| |
|
| #make square canvas for the output (wide = double size of height of primary pattern)
| | '''FINISHING STEP''' |
| canvas =Image.new('RGBA',(2*trih,2*trih), (255,255,255,0))
| |
| canvas.save('tmpcanvas.png')
| |
| pcanvas=Image.new('RGBA',(2*trih,2*trih), (255,255,255,0))
| |
|
| |
|
| | Last step . . . for the summaery event , I improved a bit the quality of the |
| | GIF by editing the code to be able to make best quality it can and also the final GIF is not larger that the twitter status update limit. |
|
| |
|
| | So I added lines of code to get the size of the final GIF and resize it if it exceed the limit. |
|
| |
|
|
| |
|
| #put pattern on the canvas
| | '''The complete code of the final version can be found here in the GitHub link'''. [https://github.com/AaeApasri/KaleidoGIFBot] |
| #make sure to put the tip of the triangle at the center of the canvas
| | feel free to download and develop it further if you are interested. ;) |
| #because when we rotate the center of the object is the pivot point
| |
| #note: paste command require the coordinate of top left corner
| |
| #so point to paste the pattern is . . .
| |
| ccenterx = int(trih-triw/2)
| |
| canvas.paste(pattern_plain,(ccenterx,trih))
| |
| | |
| | |
| # start rotate the pattern around every 40 degree
| |
| | |
| for i in range (0,360,40):
| |
| tmpcanvas = canvas
| |
| tmppat = canvas.rotate(i)
| |
| canvas= Image.alpha_composite(tmpcanvas,tmppat)
| |
| | |
| # now we get half of the things
| |
| half = canvas
| |
| print('half already')
| |
| #mirror the half and put in the space to create simple kaleidoscpoe effect
| |
| mirror = im.mirror(half)
| |
| half2= mirror.rotate(20)
| |
| print('mirrored')
| |
| | |
| #merge 2 half
| |
| output=Image.alpha_composite(half,half2)
| |
| output.save("output.png")
| |
| | |
| | |
| #def makegif():
| |
| #clip = mpy.ImageSequenceClip(outfilename, fps=3)
| |
| #clip.write_gif("%s.gif"%filename)
| |
| | |
| def makekaleido(image) :
| |
| global base, filename, source, imgfile, n, outfilename
| |
| #IN CASE Working on filename in the laptop
| |
| #put image path
| |
| imgfile = "tweetimg.jpg"
| |
| filename = imgfile[:-4]
| |
| print(filename)
| |
|
| |
| #load Image
| |
| source = Image.open(imgfile)
| |
|
| |
| #source = image.copy()
| |
| x, y = source.size
| |
| | |
| if x > 1000:
| |
| newy = int(1000*y/x)
| |
| source =source.resize((1000,newy), Image.ANTIALIAS)
| |
| print('resize to %sx%s'%source.size)
| |
| | |
| #creat mask base the same size with source image
| |
| mask = Image.new('RGBA', source.size, (255,255,255,0))
| |
| print("mask size:%sx%s"%source.size)
| |
|
| |
| | |
| #rotate source n times for a degree
| |
| n= 10
| |
| outfilename=[]
| |
| for a in range(n+n-2):
| |
| outfilename.insert(a,'0')
| |
| a= 10
| |
| base = source
| |
| for i in range(n):
| |
| base = source.rotate(31+i*a)
| |
| onepic()
| |
| output.save('%s%s.png'%(filename,i))
| |
| outfilename[i] = filename+str(i)+'.png'
| |
| if i!=0:
| |
| outfilename[2*n-2-i] = filename+str(i)+'.png'
| |
|
| |
| clip = mpy.ImageSequenceClip(outfilename, fps=3)
| |
| clip.write_gif("%s.gif"%filename)
| |
| image2 = Image.open('tweetimg3.png')
| |
| | |
| return image2,clip
| |
| | |
|
| |
| | |
| if __name__ == '__main__':
| |
| | |
| makekaleido(image)
| |
| </pre>
| |