#!BPY """ Registration info for Blender menus: Name: 'Image Based Motion Blur...' Blender: 236 Group: 'Animation' Tip: 'Blurs the selected obj. in prerendered image sequences.' """ __author__ = "Arben (Ben) Omari" __url__ = ("blender", "elysiun", "Author's site, http://www.omariben.too.it") __version__ = "0.4" __bpydoc__ = """\ What this does? Render an image sequence(or single by setting Sta: End: the same)) and save it. Then select the object which moves and add it to the list.(to be blurred) Execute the script.In the "renderMB" will be saved a new sequence with the object blurred in the motion direction. Requires PIL (Python Image Library) Notes:
Check author's site or the elYsiun forum for a new beta version of the script. """ # MotionBlur.py version 0.4 # Copyright (C) 2005 Arben OMARI -- omariarben@everyday.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # Grab the latest version here :www.omariben.too.it import Blender from Blender import Object,NMesh,Scene from Blender.Mathutils import * import PIL.Image as Image import PIL.ImageDraw as ImageDraw import PIL.ImageFilter as Filter import math from Blender import Draw, BGL, Window from Blender.BGL import * EVENT_String = 1 EVENT_String_0 = 2 EVENT_String_1 = 3 EVENT_String_2 = 4 EVENT_String_3 = 5 EVENT_String_4 = 6 EVENT_Button = 7 EVENT_Button_0 = 8 EVENT_Button_1 = 9 EVENT_Button_2 = 10 EVENT_Button_3 = 15 EVENT_Button_4 = 14 EVENT_Menu = 16 EVENT_Menu_1 = 17 EVENT_Toggle = 11 EVENT_Toggle_0 = 12 EVENT_Number_4 = 13 Object_Text = Draw.Create("") Object_Text_0 = Draw.Create("") Object_Text_1 = Draw.Create("") Object_Text_2 = Draw.Create("") Object_Text_3 = Draw.Create("") Object_Text_4 = Draw.Create("") Object_Text_5 = Draw.Create("") Object_Text_6 = Draw.Create("") Object_Text_7 = Draw.Create("") Object_Text_8 = Draw.Create("") a = Blender.Get('filename') b = Blender.sys.dirname(a) r = Blender.sys.join(b, "render") mb = Blender.sys.join(b, "renderMB") Object_String = Draw.Create(r) Object_String_0 = Draw.Create(mb) Object_String_1 = Draw.Create(1) Object_String_2 = Draw.Create(1) Object_String_4 = Draw.Create("") Object_Menu = Draw.Create(1) Object_Menu_1 = Draw.Create(1) Object_Toggle = Draw.Create(1) Object_Toggle_0 = Draw.Create(0) Object_Number_4 = Draw.Create(1.0) Object_Button_0 = Draw.Create(0) Object_Button_1 = Draw.Create(0) Object_Button_2 = Draw.Create(0) Object_Button_3 = Draw.Create(0) Object_Button_4 = Draw.Create(0) global list_obj list_obj = [] obj = Object.GetSelected()[0] mesh = obj.getData() if type(mesh) == Blender.Types.NMeshType : list_obj.append(obj) Object_String_3 = Draw.Create(list_obj[0].name + ",") else: Object_String_4.val = " Must select a mesh object." Object_String_3 = Draw.Create("") def draw(): global EVENT_String, EVENT_String_0, EVENT_String_1, EVENT_String_2, EVENT_String_3 global EVENT_Toggle_0, EVENT_Button_0, EVENT_Toggle, EVENT_Button_1, EVENT_Button_2, EVENT_Button_3, EVENT_Button_4 global EVENT_Menu global Object_String, Object_String_0, Object_String_1, Object_String_2, Object_String_3, Object_String_4 global Object_Button, Object_Button_0, Object_Button_1, Object_Button_2, Object_Button_3, Object_Button_4 global Object_Menu, Object_Menu_1, Object_Number_4, Object_Toggle, Object_Toggle_0 BGL.glClearColor(0.500000, 0.500000, 0.500000, 0.0) BGL.glClear(GL_COLOR_BUFFER_BIT) #TITLE############################################################## BGL.glColor3f(0.700000, 0.400000, 0.400000) BGL.glRasterPos2i(15, 476) Object_Text = Draw.Text("Motion Blur Image Based Script 0.2") BGL.glColor3f(0.700000, 0.400000, 0.400000) BGL.glRasterPos2i(17, 476) Object_Text = Draw.Text("Motion Blur Image Based Script 0.2") BGL.glColor3f(0.300000, 0.100000, 0.100000) BGL.glRasterPos2i(19, 476) Object_Text = Draw.Text("Motion Blur Image Based Script 0.2") #END TITLE############################################################ Object_String = Draw.String("", EVENT_String, 8, 450, 200, 20,Object_String.val, 1024, "") BGL.glRasterPos2i(16, 440) Object_Text_1 = Draw.Text("the path of the prerendered file","small") Object_Button_3 = Draw.Button("Open", EVENT_Button_3, 208, 450, 90, 20, "") Object_String_0 = Draw.String("", EVENT_String_0, 8, 410, 200, 20,Object_String_0.val, 1024, "") BGL.glRasterPos2i(16, 400) Object_Text_2 = Draw.Text("the path of the blurred image","small") Object_Button_3 = Draw.Button("Open", EVENT_Button_4, 208, 410, 90, 20, "") BGL.glRasterPos2i(16, 360) Object_Text_1 = Draw.Text("list of objects","small") Object_String_3 = Draw.String("", EVENT_String_3, 8, 370, 200, 20,Object_String_3.val, 1024, "") Object_Button_0 = Draw.Button("Add Object", EVENT_Button_0, 208, 370, 90, 20, "") Object_Menu = Draw.Menu("EXTENSION%t|JPEG%x1|PNG%x2|BMP%x3|TIFF%x4", EVENT_Menu, 8, 330, 60, 20, Object_Menu.val, "the extension of the output file") BGL.glRasterPos2i(8, 320) Object_Text_3 = Draw.Text("filout extension","small") Object_Menu_1 = Draw.Menu("EXTENSION%t|JPEG%x1|PNG%x2|BMP%x3|TGA%x4", EVENT_Menu_1, 100, 330, 60, 20, Object_Menu_1.val, "the extension of the prerendered file") BGL.glRasterPos2i(100, 320) Object_Text_3 = Draw.Text("filein extension","small") Object_Number_4 = Draw.Number("", EVENT_Number_4, 195, 330, 60, 20, Object_Number_4.val, 0.0, 10.0, "multiply ammount of blur with factor") BGL.glRasterPos2i(195, 320) Object_Text_3 = Draw.Text("Factor of Blur","small") Object_Toggle = Draw.Toggle("Auto", EVENT_Toggle, 8, 290, 60, 20, Object_Toggle.val, "Automatic Blur") BGL.glRasterPos2i(8, 280) Object_Text_4 = Draw.Text("Automatic Blur(based on the movement)","small") Object_Toggle_0 = Draw.Toggle("Manual", EVENT_Toggle_0, 8, 245, 60, 20, Object_Toggle_0.val, "") BGL.glRasterPos2i(8, 235) Object_Text_5 = Draw.Text("Manual Blur","small") Object_String_1 = Draw.Number("", EVENT_String_1, 104, 245, 60, 20,Object_String_1.val, 1,1024, "Ammount of blur(in pixels) ") BGL.glRasterPos2i(104, 235) Object_Text_6 = Draw.Text("ammount of blur","small") Object_String_2 = Draw.Number("", EVENT_String_2, 208, 245, 60, 20,Object_String_2.val,1,1024, "Nr. of frames to check the movement") BGL.glRasterPos2i(208, 235) Object_Text_7 = Draw.Text("frame difference","small") Object_String_4 = Draw.String("", EVENT_String_4, 8, 90, 300, 20,Object_String_4.val, 1024, "") BGL.glRasterPos2i(8, 80) Object_Text_7 = Draw.Text("error messages","small") Object_Button_1 = Draw.Button("BLUR", EVENT_Button_1, 16, 32, 85, 30, "") Object_Button_2 = Draw.Button("EXIT", EVENT_Button_2, 176, 32, 85, 30, "") BGL.glRasterPos2i(16, 8) Object_Text_8 = Draw.Text("by Ben Omari (omariarben@everyday.com)") def event(event, value): if event == Draw.ESCKEY and not value: Draw.Exit() def b_event(event): global EVENT_String, EVENT_String_0, EVENT_String_1, EVENT_String_2, EVENT_String_3 global EVENT_Toggle_0, EVENT_Button_0, EVENT_Toggle, EVENT_Button_1, EVENT_Button_2 global EVENT_Menu global Object_String, Object_String_0, Object_String_1, Object_String_2, Object_String_3 global Object_Button, Object_Button_0, Object_Button_1, Object_Button_2, Object_Toggle, Object_Toggle_0 global Object_Menu, Object_Menu_1 if event == 0: pass elif event == EVENT_String: pass elif event == EVENT_String_0: pass elif event == EVENT_Menu: #***Place your code for Object Menu here***# pass elif event == EVENT_Toggle: if Object_Toggle.val == 0: Object_Toggle_0.val == 1 Object_Toggle_0 = Draw.Create(1) if Object_Toggle.val == 1: Object_Toggle_0.val == 0 Object_Toggle_0 = Draw.Create(0) elif event == EVENT_Toggle_0: if Object_Toggle_0.val == 0: Object_Toggle.val == 1 Object_Toggle = Draw.Create(1) if Object_Toggle_0.val == 1: Object_Toggle.val == 0 Object_Toggle = Draw.Create(0) elif event == EVENT_Button_3: file =Blender.Window.FileSelector(render, "Select Image") elif event == EVENT_Button_4: fileMB =Blender.Window.FileSelector(renderMB, "Select Image") elif event == EVENT_Button_1: MotionBlur() elif event == EVENT_Button_0: obj = Object.GetSelected()[0] mesh = obj.getData() if type(mesh) == Blender.Types.NMeshType : if obj in list_obj: Object_String_4.val = "Just added" else: list_obj.append(obj) Object_String_3.val = Object_String_3.val + obj.name +"," Object_String_4.val = "" else: Object_String_4.val = "Must select a mesh object." elif event == EVENT_Button_2:Draw.Exit() Draw.Draw() Draw.Register(draw, event, b_event) ########## MAIN ######################################## render_path = Object_String.val renderMB_path = Object_String_0.val def render(file): global render_path render_path = Blender.sys.dirname(file) Object_String.val = render_path def renderMB(fileMB): global renderMB_path renderMB_path = Blender.sys.dirname(fileMB) Object_String_0.val = renderMB_path def Blur(p_list,img,an_list,kernel): source = img.split() R,G,B = 0,1,2 size = img.size w = size[0] h = size[1] if w != width or h != height: print "ERROR MESSAGE!!!!--Different image dimmension (" +str(w),str(h)+") from Blender settings ("+str(width),str(height)+")" for x,y in p_list: ########Red Channel pix_r = 0 cR = 0 nR = -1 for j in an_list: nR += 1 try: pix_r +=kernel[nR]*source[R].getpixel((x+j[0],y+j[1])) cR += kernel[nR] except: pass if cR > 0: pix_Red = pix_r / cR source[R].putpixel((x,y), pix_Red) #######Green channel pix_g = 0 cG = 0 nG = -1 for j in an_list: nG += 1 try: pix_g += kernel[nG]*source[G].getpixel((x+j[0],y+j[1])) cG += kernel[nG] except: pass if cG > 0: pix_G = pix_g / cG source[G].putpixel((x,y), pix_G) ########Blue Channel pix_b = 0 cB = 0 nB = -1 for j in an_list: nB += 1 try: pix_b += kernel[nB]*source[B].getpixel((x+j[0],y+j[1])) cB += kernel[nB] except: pass if cB > 0: pix_B = pix_b / cB source[B].putpixel((x,y), pix_B) ##########Alpha Channel try : pix_a = 0 cA = 0 nA = -1 for j in an_list: nA += 1 try: pix_a += kernel[nA]*source[3].getpixel((x+j[0],y+j[1])) cA += kernel[nA] except: pass if cA > 0: pix_A = pix_a / cA source[3].putpixel((x,y), pix_A) except: pass img_new = Image.merge(img.mode, source) return img_new def projOnscreen(wld_vec,mat): pr_vec = VecMultMat(wld_vec, mat) px = int(width/2 - ((width/2)/math.tan(fovx))*pr_vec[0]/(pr_vec[2])) py = int(height/2 + ((height/2)/math.tan(fovy))*pr_vec[1]/(pr_vec[2])) return px,py def getAngle(frame): Blender.Set('curframe', frame-pix) mat_f = camera.getMatrix() mat_f.invert() l_f1 = obj.getLocation() l_f1v = Vector([l_f1[0], l_f1[1], l_f1[2], 1]) px1,py1 = projOnscreen(l_f1v ,mat_f) Blender.Set('curframe', frame) l_f2 = obj.getLocation() matx = camera.getMatrix() matx.invert() l_f2v = Vector([l_f2[0], l_f2[1], l_f2[2], 1]) px2,py2 = projOnscreen(l_f2v, matx) try : angle = math.atan((py2 - py1)/(px2 - px1)) except: angle = 0 k = int(math.sqrt(((py2 - py1)*(py2 - py1))+((px2 - px1)*(px2 - px1)))) return angle,k def getAngleVec(angle): an_list = [] for m in range(-bl,bl): n = int(m * math.tan(angle)) an_list.append([m,n]) return an_list def getKernel(an_list): ker = [] kel = [] l = len(an_list)/2 for i in range(0, l): if i < l : ker.append(i) for i in range(0, l): if i < l : kel.append(i) kel.reverse() kernel = ker+kel return kernel def getBuff(fr,obj): mesh = obj.getData() for frame in (fr-1,fr+1): Blender.Set('curframe', frame) mat = camera.getMatrix() mat.invert() for face in mesh.faces: vx = [] for n in range(len(face.v)): vec = Vector([face.v[n].co[0], face.v[n].co[1], face.v[n].co[2], 1]) wld_vec = VecMultMat(vec, obj.getMatrix()) px,py = projOnscreen(wld_vec,mat) vx.append((px,py)) drw.polygon(vx,(100)) Blender.Set('curframe', fr) mat = camera.getMatrix() mat.invert() for face in mesh.faces: vx = [] for n in range(len(face.v)): vec = Vector([face.v[n].co[0], face.v[n].co[1], face.v[n].co[2], 1]) wld_vec = VecMultMat(vec, obj.getMatrix()) px,py = projOnscreen(wld_vec,mat) vx.append((px,py)) drw.polygon(vx,(0)) def getScPart(img): global bu_img sc_part = [] buf_img = img.filter(Filter.BLUR) bu_img = buf_img.filter(Filter.BLUR) for l in range(0, height): for i in range(0,width): poi = bu_img.getpixel((i,l)) if poi != 255 : sc_part.append([i,l]) return sc_part ###### MAIN ################### def MotionBlur(): global camera,width,height,fovx,fovy,pix,bl global list_obj,buff_img,drw AUTO_Blur = Object_Toggle.val MAN_Blur = Object_Toggle_0.val if Object_Menu.val == 1 : ext_out = ".jpg" elif Object_Menu.val == 2 : ext_out = ".png" elif Object_Menu.val == 3 : ext_out = ".bmp" elif Object_Menu.val == 4 : ext_out = ".tiff" if Object_Menu_1.val == 1 : ext_in = ".jpg" elif Object_Menu_1.val == 2 : ext_in = ".png" elif Object_Menu_1.val == 3 : ext_in = ".bmp" elif Object_Menu_1.val == 4 : ext_in = ".tga" sta = Blender.Get('staframe') end = Blender.Get('endframe') scene = Blender.Scene.GetCurrent() context = scene.getRenderingContext() width = context.imageSizeX() height = context.imageSizeY() camera = scene.getCurrentCamera() cam_name = camera.name cam = camera.getData() lens = cam.getLens() factor = lens / 32.0 pr = float(height) / float(width) fovx = math.atan(.5/factor) fovy = math.atan(.5*pr/factor) for fr in range(sta, end+1): Blender.Set('curframe', fr) buff_img = Image.new("L",(width,height),(255)) drw = ImageDraw.Draw(buff_img) for obj in list_obj: old_time = Blender.sys.time() pix = 1 ang,k = getAngle(fr) if AUTO_Blur : bl = int(k * Object_Number_4.val) elif MAN_Blur: pix = Object_String_2.val blu = Object_String_1.val bl = int(blu * Object_Number_4.val) angle_vec = getAngleVec(ang) angle_ker = getKernel(angle_vec) getBuff(fr, obj) sc_part = getScPart(buff_img) filename = str(fr) file =filename.zfill(4) filein = file + ext_in fileout = file + ext_out input_file = Blender.sys.join(render_path, filein) try: img = Image.open(input_file) if bl > 0 : img_new = Blur(sc_part,img,angle_vec,angle_ker) else : img_new = img Object_String_4.val = "" except IOError: Object_String_4.val = "" Object_String_4.val = 'no file named "' + filein + '"' break ##### time ellapsed ######### new_time = Blender.sys.time()-old_time min = str(int(new_time/60)) min = min.zfill(2) sec = str(int(math.fmod(new_time,60))) sec = sec.zfill(2) print "..frame", fr, "blurred in 00 :",min,".",sec output_file = Blender.sys.join(renderMB_path, fileout) img_new.save(output_file) print "...finished"