SHARE
TWEET

OpenCV connection to Blender25

a guest Sep 18th, 2010 1,154 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. # OpenCV and Blender - Test1 Sept 19, 2010
  3. # by HartsAntler - bhartsho@yahoo.com
  4. # License: GNU GPL3
  5. # Tested with Ubuntu Lucid and Blender2.54
  6.  
  7. '''
  8. Hacking - Ram Drive Workaround:
  9.         mkdir /tmp/ramdrive
  10.         sudo mount -t ramfs /dev/ram10 /tmp/ramdrive/
  11.         sudo chmod 777 /tmp/ramdrive
  12.  
  13.  
  14. Getting Blender Connected:
  15.         0. sudo apt-get install python-opencv python-pygame python3
  16.  
  17.         1. download posix_ipc from http://semanchuk.com/philip/posix_ipc
  18.         2. cd posix_ipc-0.8.1/
  19.         3. sudo python setup.py install
  20.         4. sudo python3 setup.py install
  21.         5. set the path to blender25 below `PATH2BLENDER`
  22.  
  23.         (blender will not respect local py3 installations? this step should be optional)
  24.         6. cp -Rv /usr/local/lib/python3.1/dist-packages/posix_ipc.so /<change me>/blender25/2.53/python/lib/python3.1/site-packages/.
  25.  
  26. #6 will fail if your local python is Python 3.1.2 [GCC 4.4.3] and Blender is compiled with Python 3.1.1 [GCC 4.3.3]
  27. ImportError: /home/brett/pyppet2/blender25/2.53/python/lib/python3.1/site-packages/posix_ipc.so: undefined symbol: PyUnicodeUCS4_FromString
  28.  
  29. '''
  30. PATH2BLENDER = 'blender25/blender'
  31.  
  32. Size640x480_RGBA = 1228800
  33. import os, sys, time
  34.  
  35. SHARED_MEMORY = '/mysharedmem'          # '/tmp/something' is invlid is tmp sharedmemory has not been created
  36. SEMAPHORE_NAME = '/mysemaphore'
  37.  
  38. PY_MAJOR_VERSION = sys.version_info[0]
  39. if PY_MAJOR_VERSION > 2: NULL_CHAR = 0
  40. else: NULL_CHAR = '\0'
  41.  
  42.  
  43. import multiprocessing, ctypes
  44. from multiprocessing import sharedctypes
  45.  
  46. posix_ipc = None
  47. try: import posix_ipc
  48. except: print( 'posix_ipc not installed' )
  49.  
  50. import mmap
  51.  
  52.  
  53. def shm_write(mapfile, s):
  54.         """Writes the string s to the mapfile"""
  55.         mapfile.seek(0)
  56.         #s += '\0'      # I append a trailing NULL in case I'm communicating with a C program.
  57.         if PY_MAJOR_VERSION > 2: s = s.encode()
  58.         mapfile.write(s)
  59.  
  60. def shm_read_slowly(mapfile):
  61.         """Reads a string from the mapfile and returns that string"""
  62.         mapfile.seek(0)
  63.         s = [ ]
  64.         c = mapfile.read_byte()
  65.         while c != NULL_CHAR:
  66.                 s.append(c)
  67.                 c = mapfile.read_byte()
  68.         if PY_MAJOR_VERSION > 2: s = [chr(c) for c in s]
  69.         s = ''.join(s)  
  70.         return s
  71.  
  72. def shm_read(mapfile):
  73.         """Reads a string from the mapfile and returns that string"""
  74.         mapfile.seek(0)
  75.         return mapfile.read(Size640x480_RGBA)
  76.  
  77. '''
  78. if 0:           # ctypes can not load libc
  79.         import ctypes.util
  80.         libc = ctypes.util.find_library('libc')
  81.         print libc
  82.         libc = ctypes.CDLL('/usr/lib/libc.a')
  83.         print libc
  84.         raise
  85. '''
  86.  
  87. class BlenderConnection(object):
  88.         def __init__(self):
  89.                 if posix_ipc:
  90.                         print( 'trying to open sharedmemory')
  91.                         self.shm = memory = posix_ipc.SharedMemory(SHARED_MEMORY)
  92.                         # MMap the shared memory
  93.                         self.mapfile = mmap.mmap(memory.fd, memory.size, mmap.MAP_PRIVATE)              # MAP_PRIVATE=copy-on-write
  94.                         #os.close(memory.fd)            # also valid
  95.                         memory.close_fd()
  96.                         print( 'sharedmem', self.mapfile)
  97.                         self.semaphore = posix_ipc.Semaphore(SEMAPHORE_NAME)
  98.  
  99.                 self.bimage = im = bpy.data.images.new('_opencv_')
  100.                 im.source = 'FILE'
  101.                 im.filepath = '/tmp/ramdrive/dump.png'
  102.                 tex = bpy.data.textures[0]
  103.                 tex.type = 'IMAGE'              # invalidates object, get again
  104.                 self.btexture = tex = bpy.data.textures[0]
  105.                 tex.image = im
  106.                 self.bmat = mat = bpy.data.materials[0]
  107.                 mat.use_transparency=True
  108.                 mat.alpha = .0
  109.                 mat.emit = 1.0
  110.                 mat.specular_intensity = .0
  111.  
  112.                 ts = mat.texture_slots[0]
  113.                 ts.use_map_alpha=True
  114.  
  115.                 scn = bpy.data.scenes[0]
  116.                 scn.game_settings.material_mode = 'GLSL'
  117.  
  118.                 self.setup_blender_loop()
  119.  
  120.         def setup_blender_loop(self):           # hacks like this should not have to be pulled anymore!?
  121.                 bpy.ops.screen.animation_play('EXEC_DEFAULT')
  122.                 for area in bpy.context.window.screen.areas:
  123.                         print(area.type)
  124.                         if area.type == 'VIEW_3D':
  125.                                 #print('viewportshade', area.viewport_shade)
  126.                                 for reg in area.regions:
  127.                                         print( '\tregion: ', reg.type )
  128.                                         if reg.type == 'WINDOW':
  129.                                                 print( 'adding callback' )
  130.                                                 reg.callback_add(self.loop, (area,reg), 'POST_PIXEL')
  131.  
  132.         def loop( self, area, reg ):
  133.                 if posix_ipc:
  134.                         self.semaphore.acquire()
  135.                         data = shm_read( self.mapfile )
  136.                         self.semaphore.release()
  137.                         print( len(data) )
  138.                 if self.bimage.bindcode:
  139.                         #self.bimage.gl_free()
  140.                         self.bimage.reload()
  141.  
  142. if '--blender' in sys.argv:
  143.         import bpy
  144.         bc = BlenderConnection()
  145.  
  146. else:
  147.         import pygame
  148.         #import Image, ImageDraw, ImageChops
  149.         import gtk, glib, cairo, pango, gobject
  150.  
  151.         import opencv as cv
  152.         from opencv import highgui
  153.         cv.cvSetNumThreads(3)           # 4 threads might be wasteful
  154.         print( 'opencv threads', cv.cvGetNumThreads() )
  155.  
  156.         _colorspaces = '''
  157.         CV_BGR2GRAY
  158.         CV_BGR2HLS
  159.         CV_BGR2HSV
  160.         CV_BGR2Lab
  161.         CV_BGR2Luv
  162.         CV_BGR2RGB
  163.         CV_BGR2XYZ
  164.         CV_BGR2YCrCb
  165.         '''
  166.         ColorSpaces = {}
  167.         ColorSpacesByValue = {}
  168.         for name in _colorspaces.splitlines():
  169.                 name = name.strip()
  170.                 if name:
  171.                         value = getattr(cv,name)
  172.                         ColorSpacesByValue[ value ] = name
  173.                         ColorSpaces[ name ] = value
  174.  
  175. BG_RED = 0.98
  176. BG_GREEN = 0.98
  177. BG_BLUE = 0.99
  178. BG_ALPHA = 0.0
  179. BG_COLOR = (BG_RED,BG_GREEN,BG_BLUE,BG_ALPHA)
  180.  
  181. def transparent_window( win, color=BG_COLOR, decorate=False ):
  182.         win.set_decorated( decorate )
  183.         # Tell GTK+ that we want to draw the windows background ourself.
  184.         # If we don't do this then GTK+ will clear the window to the
  185.         # opaque theme default color, which isn't what we want.
  186.         win.set_app_paintable(True)
  187.         make_transparent( win, color )
  188.  
  189.  
  190. def expose_transparent(widget, event):
  191.         cr = widget.window.cairo_create()
  192.         r,g,b,a = widget._trans_color_hack
  193.         cr.set_source_rgba(r, g, b, a) # Transparent
  194.         # Draw the background
  195.         cr.set_operator(cairo.OPERATOR_SOURCE)
  196.         cr.paint()
  197.         return False
  198.  
  199. def make_transparent(widget, color=BG_COLOR ):
  200.         widget._trans_color_hack = color
  201.         # The X server sends us an expose event when the window becomes
  202.         # visible on screen. It means we need to draw the contents.  On a
  203.         # composited desktop expose is normally only sent when the window
  204.         # is put on the screen. On a non-composited desktop it can be
  205.         # sent whenever the window is uncovered by another.
  206.         #
  207.         # The screen-changed event means the display to which we are
  208.         # drawing changed. GTK+ supports migration of running
  209.         # applications between X servers, which might not support the
  210.         # same features, so we need to check each time.
  211.         widget.connect('expose-event', expose_transparent)
  212.         #win.connect('screen-changed', self.screen_changed)
  213.         # To check if the display supports alpha channels, get the colormap
  214.         screen = widget.get_screen()
  215.         colormap = screen.get_rgba_colormap()
  216.         # Now we have a colormap appropriate for the screen, use it
  217.         widget.set_colormap(colormap)
  218.         return False
  219.  
  220.  
  221. '''
  222. useful utils:
  223. cv.Ipl2NumPy
  224. cv.Ipl2PIL
  225. cv.NumPy2Ipl
  226. cv.NumPy2PIL
  227. cv.PIL2Ipl
  228. cv.PIL2NumPy
  229.  
  230. notes:
  231. CV_ADAPTIVE_THRESH_GAUSSIAN_C
  232. CV_ADAPTIVE_THRESH_MEAN_C
  233. CV_CALIB_CB_ADAPTIVE_THRESH
  234. CV_THRESH_BINARY
  235. CV_THRESH_BINARY_INV
  236. #something else? CV_THRESH_MASK         # adaptive only?
  237. #CV_THRESH_OTSU
  238. CV_THRESH_TOZERO
  239. CV_THRESH_TOZERO_INV
  240. CV_THRESH_TRUNC
  241. cvAdaptiveThreshold
  242. cvThreshHist
  243. cvThreshold
  244.  
  245. cvAdaptiveThreshold(*args)
  246.    cvAdaptiveThreshold(CvArr src, CvArr dst, double max_value, int adaptive_method = 0,
  247.        int threshold_type = 0, int block_size = 3,
  248.        double param1 = 5)
  249.  
  250. cvThreshold(*args)
  251.    cvThreshold(CvArr src, CvArr dst, double threshold, double max_value,
  252.        int threshold_type) -> double
  253.  
  254.  
  255. '''
  256.  
  257.  
  258.  
  259. def pygame_to_pil_img(pg_img):
  260.         imgstr = pygame.image.tostring(pg_img, 'RGB')
  261.         return Image.fromstring('RGB', pg_img.get_size(), imgstr)
  262.  
  263. def pil_to_pygame_img(pil_img):
  264.         imgstr = pil_img.tostring()
  265.         return pygame.image.fromstring(imgstr, pil_img.size, 'RGB')
  266.  
  267. class Trackable(object):
  268.         def __init__(self, haar):
  269.                 self.haar = haar
  270.                 self._cv_storage = cv.cvCreateMemStorage(0)
  271.                 self.score = .0
  272.                 self.rects = []
  273.                 self.color = None
  274.                 self.grayscale = None
  275.  
  276.         #               cv.cvSetImageROI( grayscale, cv.cvRect(fx, fy, fw, fh) )
  277.         #               cv.cvClearMemStorage(storage)   # this invalidates the f.x, f.* attributes
  278.         def detector( self, grayscale, scale=1 ):
  279.                 self.grayscale = grayscale
  280.                 storage = self._cv_storage
  281.                 cv.cvClearMemStorage(storage)
  282.                 # equalize histogram
  283.                 cv.cvEqualizeHist(grayscale, grayscale)
  284.  
  285.                 _rects = cv.cvHaarDetectObjects(grayscale, self.haar, storage, 1.2, 2, cv.CV_HAAR_DO_CANNY_PRUNING, cv.cvSize(25, 25))
  286.                 rects = []
  287.                 if _rects:
  288.                         for r in _rects:
  289.                                 rects.append( pygame.rect.Rect(r.x*scale, r.y*scale, r.width*scale, r.height*scale) )
  290.                 return rects
  291.  
  292. _cfg_ubytes =  'active alpha blur athresh_block_size thresh_min thresh_max'.split()
  293. _cfg_ubytes += 'sobel_xorder sobel_yorder sobel_aperture'.split()
  294. _cfg_ubytes += 'split_red split_green split_blue'.split()
  295. FXtypes = 'FXsplit FXstencil FXblur FXsobel FXathresh FXthresh FXdetect'.split()
  296. _cfg_ubytes += FXtypes
  297. class LayerConfig( ctypes.Structure ):
  298.         _fields_ = [ ('colorspace',ctypes.c_int) ]
  299.         for tag in _cfg_ubytes: _fields_.append( (tag, ctypes.c_ubyte) )
  300.         #for tag in _cfg_ints: _fields_.append( (tag, ctypes.c_int) )
  301.         del tag
  302.  
  303. class UI(object):
  304.         def __init__(self, active, layers, rawimage):
  305.                 self.active = active            # shared
  306.                 self.layers = layers            # shared
  307.                 self.rawimage = rawimage
  308.  
  309.                 ## gtk ##
  310.                 self.window = win = gtk.Window()
  311.                 win.set_size_request( 900, 480 )
  312.                 win.set_title( 'Harts OpenCV Blender Demo' )
  313.                 win.connect('destroy', lambda w: gtk.main_quit() )
  314.                 transparent_window( win, decorate=True )
  315.                 root = gtk.HBox(); root.set_border_width( 3 )
  316.                 win.add( root )
  317.  
  318.                 #####################################
  319.                 eb = gtk.EventBox()
  320.                 root.pack_start( eb, expand=False )
  321.                 self._drawing_area = da = gtk.DrawingArea()
  322.                 da.set_size_request( 640,480 )
  323.                 da.connect('realize', self.realize)
  324.                 eb.add( da )
  325.                 make_transparent(da)
  326.  
  327.                 ##################
  328.                 eb = gtk.EventBox()
  329.                 root.pack_start( eb, expand=True )
  330.                 split = gtk.VBox(); eb.add( split )
  331.                 make_transparent(split)
  332.  
  333.                 header = gtk.HBox(); split.pack_start( header, expand=False )
  334.                 b = gtk.Button('open blender')
  335.                 b.connect('clicked', lambda b: os.system('%s -P %s --blender &'%(PATH2BLENDER, sys.argv[0])) )
  336.                 header.pack_start( b, expand=False )
  337.  
  338.                 b = gtk.ToggleButton('[-]'); b.set_active(True)
  339.                 b.connect('toggled', lambda b: win.set_decorated( b.get_active() ) )
  340.                 header.pack_start( b, expand=False )
  341.                
  342.  
  343.                 #ex = gtk.Expander( 'settings' ); ex.set_expanded(False)
  344.                 #split.pack_start( ex, expand=False )
  345.                 #ex = gtk.Expander( 'adjust layers' ); ex.set_expanded(True)
  346.                 #split.pack_start( ex, expand=True)
  347.  
  348.                 note = gtk.Notebook()
  349.                 note.set_tab_pos( gtk.POS_RIGHT )
  350.                 #ex.add( note )
  351.                 split.pack_start( note )
  352.                 for layer in layers:
  353.                                 cspace = ColorSpacesByValue[ layer.colorspace ]
  354.                                 tag = cspace.split('2')[-1]
  355.                                 page = gtk.HBox()
  356.                                 h = gtk.HBox()
  357.                                 b = gtk.CheckButton()
  358.                                 b.connect('toggled', lambda b,lay: setattr(lay,'active',bool(b.get_active())), layer)
  359.                                 h.pack_start( b, expand=False )
  360.                                 h.pack_start( gtk.Label(tag) )
  361.                                 note.append_page( page, h )
  362.                                 h.show_all()
  363.                                 b.set_active( bool(layer.active) )
  364.  
  365.                                 col1, col2 = gtk.VBox(), gtk.VBox()
  366.                                 page.pack_start( col1, expand=False )
  367.                                 page.pack_start( col2, expand=True )
  368.  
  369.                                 fxgroups = {}
  370.                                 for name in FXtypes:
  371.                                         bx = gtk.VBox()
  372.                                         fxgroups[ name.split('FX')[-1] ] = bx
  373.                                         frame = gtk.Frame(); frame.add( bx )
  374.                                         val = getattr( layer, name )
  375.                                         b = gtk.CheckButton( name )
  376.                                         b.set_active( bool(val) )
  377.                                         b.connect('toggled', lambda b,lay,nam: setattr(lay,nam,bool(b.get_active())), layer, name)
  378.                                         frame.set_label_widget( b )
  379.                                         col2.pack_end( frame )
  380.  
  381.                                 for name in dir(layer):
  382.                                         if not name.startswith('_') and name not in ['colorspace','active']+FXtypes:
  383.                                                 val = getattr( layer, name )
  384.                                                 bx = None
  385.                                                 for fx in fxgroups:
  386.                                                         if name.startswith(fx):
  387.                                                                 bx = fxgroups[fx]
  388.                                                                 break
  389.                                                 if not bx:
  390.                                                         adjust = gtk.Adjustment(
  391.                                                                 value=val,
  392.                                                                 lower=0, upper=255,
  393.                                                                 step_incr=1 )
  394.                                                         adjust.connect("value_changed", lambda a,lay,nam: setattr(lay,nam,int(a.value)), layer,name)
  395.                                                         scale = gtk.HScale( adjust ); scale.set_value_pos(gtk.POS_RIGHT)
  396.                                                         scale.set_digits(0)
  397.                                                         frame = gtk.Frame( name )
  398.                                                         frame.add( scale )
  399.                                                         col2.pack_start( frame )
  400.                                                 else:
  401.                                                         if fx=='split':
  402.                                                                 b = gtk.CheckButton( name )
  403.                                                                 b.set_active( bool(getattr(layer,name)) )
  404.                                                                 b.connect('toggled', lambda b,lay,nam: setattr(lay,nam,bool(b.get_active())), layer, name)
  405.                                                                 bx.pack_start( b )
  406.                                                         else:
  407.                                                                 upper = 255
  408.                                                                 lower = 0
  409.                                                                 step = 1
  410.                                                                 if name.startswith('sobel'):
  411.                                                                         upper = 31; lower = 1; step=2
  412.                                                                 adjust = gtk.Adjustment(
  413.                                                                         value=val,
  414.                                                                         lower=lower, upper=upper,
  415.                                                                         step_incr=step )
  416.                                                                 adjust.connect("value_changed", lambda a,lay,nam: setattr(lay,nam,int(a.value)), layer,name)
  417.                                                                 scale = gtk.HScale( adjust ); scale.set_value_pos(gtk.POS_RIGHT)
  418.                                                                 scale.set_digits(0)
  419.                                                                 row = gtk.HBox()
  420.                                                                 row.pack_start( gtk.Label( name.split(fx)[-1].replace('_',' ') ), expand=False )
  421.                                                                 row.pack_start( scale )
  422.                                                                 bx.pack_start( row )
  423.  
  424.                 win.show_all()
  425.  
  426.         def realize( self, da ):
  427.                 wid = da.window.xid
  428.                 os.environ['SDL_WINDOWID'] = str(wid)           # child fork respects environ
  429.                 self.subprocess = p = multiprocessing.Process(target=subprocess, args=(self.active,self.layers,self.rawimage))
  430.                 p.start()
  431.                 #p.join()
  432.                 time.sleep(1)
  433.                 print( 'trying to open sharedmemory')
  434.                 #self.shm = memory = posix_ipc.SharedMemory(SHARED_MEMORY)
  435.                 # MMap the shared memory
  436.                 #self.mapfile = mmap.mmap(memory.fd, memory.size, mmap.MAP_PRIVATE)
  437.                 #os.close(memory.fd)            # also valid
  438.                 #memory.close_fd()
  439.                 #print( 'sharedmem', self.mapfile)
  440.                 #self.semaphore = posix_ipc.Semaphore(SEMAPHORE_NAME)
  441.                 #glib.timeout_add( 300, self.check_shm )
  442.  
  443.         def check_shm( self ):
  444.                 self.semaphore.acquire()
  445.                 data = shm_read( self.mapfile )
  446.                 self.semaphore.release()
  447.                 #print len(data)
  448.                 #print self.rawimage[0]         # ctypes is slightly faster or slower than posix_ipc?
  449.                 return True
  450.  
  451. class Camera(object):
  452.         try:    ## opencv haar detect is multithreaded! ##
  453.                 DO_HAAR = True
  454.                 FaceCascade = cv.cvLoadHaarClassifierCascade('haarcascades/haarcascade_frontalface_alt.xml', cv.cvSize(1,1))
  455.                 EyesCascade = cv.cvLoadHaarClassifierCascade('haarcascades/haarcascade_eye.xml', cv.cvSize(1,1))
  456.         except:
  457.                 print( 'download opencv latest source code, and copy the haarcascades folder to here')
  458.                 DO_HAAR = False
  459.  
  460.         def exit(self):
  461.                 self.mapfile.close()
  462.                 # I could call memory.unlink() here but in order to demonstrate
  463.                 # unlinking at the module level I'll do it that way.
  464.                 posix_ipc.unlink_shared_memory( SHARED_MEMORY )
  465.                 print( 'subprocess clean exit')
  466.  
  467.         def __init__(self, layers, rawimage):
  468.                 self.layers = layers
  469.                 self.rawimage = rawimage
  470.                 self.shm = memory = posix_ipc.SharedMemory(SHARED_MEMORY, posix_ipc.O_CREAT, size=Size640x480_RGBA)
  471.                 self.mapfile = mmap.mmap(memory.fd, memory.size, mmap.ACCESS_WRITE)#, mmap.MAP_PRIVATE)
  472.                 memory.close_fd()
  473.                 print( 'sharedmemory created', self.mapfile)
  474.                 self.semaphore = posix_ipc.Semaphore(SEMAPHORE_NAME, posix_ipc.O_CREAT)
  475.  
  476.  
  477.                 pygame.display.init()
  478.                 SSBACKEND = pygame.transform.get_smoothscale_backend()
  479.                 if SSBACKEND == 'GENERIC':
  480.                         try: pygame.transform.set_smoothscale_backend( 'SSE' ); SSBACKEND = 'SSE'
  481.                         except: print( 'SSE backend not available')
  482.                 print( 'smooth scale backend', SSBACKEND)
  483.  
  484.  
  485.                 self.prevfaces = None
  486.                 self.active = True
  487.                 self.index = 0
  488.                 for arg in sys.argv:
  489.                         if arg.startswith('camera='): self.index = int(arg.split('=')[-1]); break
  490.                 self.camera_pointer = highgui.cvCreateCameraCapture(self.index)         # this is the old swig bindings ubuntu lucid works fine
  491.  
  492.                 # HIGHGUI ERROR: V4L: setting property #16 is not supported
  493.                 #highgui.cvSetCaptureProperty( self.camera_pointer, highgui.CV_CAP_PROP_CONVERT_RGB, True )
  494.                 ## default color space is BGR - linux ##
  495.                 self.resize_capture( 640, 480 )
  496.                 self.resize_output( 640, 480 )
  497.  
  498.                 if self.DO_HAAR:
  499.                         self.track_face = Trackable( self.FaceCascade )
  500.  
  501.         def resize_capture( self, x,y ):
  502.                 self.cwidth = x
  503.                 self.cheight = y
  504.                 highgui.cvSetCaptureProperty( self.camera_pointer, highgui.CV_CAP_PROP_FRAME_WIDTH, self.cwidth )
  505.                 highgui.cvSetCaptureProperty( self.camera_pointer, highgui.CV_CAP_PROP_FRAME_HEIGHT, self.cheight )
  506.                 highgui.cvSetCaptureProperty( self.camera_pointer, highgui.CV_CAP_PROP_FPS, 30 )
  507.  
  508.                 self._rgb8 = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 3)
  509.                 self._rgb32 = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_32F, 3)
  510.                 self._gray8 = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 1)
  511.                 self._gray32 = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_32F, 1)
  512.  
  513.                 self._R = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 1)
  514.                 self._G = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 1)
  515.                 self._B = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 1)
  516.                 self._A = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 1)
  517.  
  518.  
  519.         def resize_output( self, x, y ):
  520.                 self.owidth = x
  521.                 self.oheight = y
  522.                 pygame.display.set_mode((x,y), 0, 32 )          # size, flags, depth
  523.                 self.screen = pygame.display.get_surface()
  524.  
  525.         def loop(self):
  526.                 self.semaphore.release()
  527.                 ## BGR - linux
  528.                 _frame = highgui.cvQueryFrame(self.camera_pointer)              # grabFrame returns 1?
  529.                 if not _frame: print( 'lost connection to webcam?')
  530.  
  531.                 self.screen.fill( (0,0,0,0) )
  532.                 surf = self.screen.copy()
  533.                 surf.fill( (0,0,255) )
  534.                 surf.set_alpha(255)
  535.                 stencil = []
  536.  
  537.                 ## pre allocated ##
  538.                 _rgb8 = self._rgb8
  539.                 _rgb32 = self._rgb32
  540.                 _gray8 = self._gray8
  541.                 _gray32 = self._gray32
  542.  
  543.                 for layer in self.layers:
  544.                         if layer.active:
  545.                                 a = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 3)
  546.                                 cv.cvCvtColor(_frame, a, layer.colorspace)
  547.                                 #print 'colorspaced converted'
  548.                                 ## FX
  549.                                 if layer.FXsplit:
  550.                                         _a = cv.cvCreateImage((self.cwidth,self.cheight), cv.IPL_DEPTH_8U, 4)
  551.                                         cv.cvCvtColor(a, _a, cv.CV_RGB2RGBA)
  552.                                         cv.cvSplit( _a, self._R, self._G, self._B, self._A )
  553.                                         if layer.split_red: a = self._R
  554.                                         elif layer.split_green: a = self._G
  555.                                         elif layer.split_blue: a = self._B
  556.  
  557.                                 if layer.FXblur:                        # blur before threshing
  558.                                         blur = layer.blur
  559.                                         if blur < 1: blur = 1
  560.                                         cv.cvSmooth( a, a, cv.CV_BLUR, blur )
  561.                                 if layer.FXsobel and layer.sobel_aperture % 2 and layer.sobel_aperture < 32:
  562.                                         if layer.sobel_xorder < layer.sobel_aperture and layer.sobel_yorder < layer.sobel_aperture:
  563.                                                 if a.nChannels == 1:
  564.                                                         cv.cvSobel( a, _gray32, layer.sobel_xorder, layer.sobel_yorder, layer.sobel_aperture )  #xorder, yorder, aperture
  565.                                                         cv.cvConvert( _gray32, a )#; cv.cvCvtColor(_sobel8, _sobel, cv.CV_GRAY2RGB)
  566.                                                 else:
  567.                                                         cv.cvSobel( a, _rgb32, layer.sobel_xorder, layer.sobel_yorder, layer.sobel_aperture )   #xorder, yorder, aperture
  568.                                                         cv.cvConvert( _rgb32, a )#; cv.cvCvtColor(_sobel8, _sobel, cv.CV_GRAY2RGB)
  569.                                 if layer.FXthresh:
  570.                                         cv.cvThreshold( a, a, layer.thresh_min, layer.thresh_max, cv.CV_THRESH_BINARY )
  571.                                 if layer.FXathresh:
  572.                                         blocksize = layer.athresh_block_size
  573.                                         if blocksize <= 2: blocksize = 3
  574.                                         if blocksize % 2 != 1: blocksize += 1
  575.                                         if a.nChannels == 1:
  576.                                                 cv.cvAdaptiveThreshold(a, a, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, blocksize )
  577.                                         else:
  578.                                                 cv.cvCvtColor(a, _gray8, cv.CV_RGB2GRAY)
  579.                                                 cv.cvAdaptiveThreshold(_gray8, _gray8, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, blocksize )
  580.                                                 cv.cvCvtColor(_gray8, a, cv.CV_GRAY2RGB)
  581.  
  582.                                 if a.nChannels == 1:
  583.                                                 cv.cvCvtColor(a, _rgb8, cv.CV_GRAY2RGB)
  584.                                                 a = _rgb8
  585.                                 ## pygame
  586.                                 b = pygame.image.frombuffer(a.imageData, (self.cwidth,self.cheight), 'RGB')
  587.                                 b.set_alpha( layer.alpha )
  588.                                 if layer.FXstencil: stencil.append( b )
  589.                                 surf.blit(b, (0,0))
  590.  
  591.                 self.screen.lock()
  592.                 array = pygame.surfarray.pixels_alpha(self.screen)
  593.                 if stencil:
  594.                         stencil = pygame.transform.average_surfaces( stencil )
  595.                         alpha = pygame.surfarray.pixels3d( stencil )
  596.                         array[:] = alpha[:,:,0]
  597.                         del alpha
  598.                 else: array[:] = 255                    # values higher than 256 are additive!
  599.                 del array
  600.                 self.screen.unlock()
  601.                 self.screen.blit( surf, (0,0) )
  602.                 #data = pygame.image.tostring(self.screen, 'RGBA')
  603.                 pygame.display.flip()
  604.                 #self.rawimage.value = data
  605.                 #self.semaphore.acquire()               # waiting for Blender to update to python 3.1.2 and support directly setting a RGBA buffer
  606.                 #shm_write( self.mapfile, data )
  607.                 #self.semaphore.release()
  608.  
  609.                 # this is an ugly hack #
  610.                 #tmp = pygame.transform.scale( self.screen, (320,240) )
  611.                 os.system('mv /tmp/ramdrive/_dump.png /tmp/ramdrive/dump.png')          # atomic
  612.                 pygame.image.save(self.screen, '/tmp/ramdrive/_dump.png')
  613.  
  614.                 return self.active
  615.  
  616.  
  617.  
  618. def subprocess( active, layers, rawimage ):
  619.         cam = Camera( layers, rawimage )
  620.         while active.value: cam.loop()
  621.         cam.exit()
  622.  
  623.  
  624. if __name__ == '__main__' and '--blender' not in sys.argv:
  625.         #CV_BGR2HLS
  626.         #CV_BGR2Luv
  627.         #CV_BGR2XYZ
  628.         _default_spaces = [
  629.                 (cv.CV_BGR2RGB,),
  630.                 (cv.CV_BGR2HSV,),
  631.                 (cv.CV_BGR2Lab,),
  632.                 (cv.CV_BGR2YCrCb,),
  633.         ]
  634.         active = sharedctypes.Value('i', 1, lock=False)
  635.         rawimage = sharedctypes.Array( ctypes.c_char, Size640x480_RGBA, lock=True )
  636.         layers = sharedctypes.Array( LayerConfig, _default_spaces, lock=True )
  637.         for layer in layers:
  638.                 layer.alpha = 32
  639.                 layer.thresh_min = 32
  640.                 layer.thresh_max = 200
  641.                 layer.blur = 2
  642.                 layer.athresh_block_size = 3
  643.                 layer.sobel_xorder = 1
  644.                 layer.sobel_yorder = 1
  645.                 layer.sobel_aperture = 5
  646.         layers[0].active = 1
  647.         layers[0].alpha = 128
  648.  
  649.         gui = UI( active, layers, rawimage )
  650.         gtk.main()
  651.         gui.active.value = 0
  652.         print( 'waiting for child to exit')
  653.         time.sleep(1)
  654.         gui.subprocess.join()
  655.         print( 'main process exit')
RAW Paste Data
Pastebin PRO Summer Special!
Get 60% OFF on Pastebin PRO accounts!
Top