Just tried writing a quine in python, I'm ashamed that it took me too much time to find a solution, so the hide the shame I covered my quine in an ascii art -
OMG T2 starts tomorrow, I'm probably gonna fail in Random Processes this time. But before I start preparing, I had to try out the tempting Camera Module of PyGame. PyGame has pretty cool stuff under pygame.transform and pygame.mask, which makes the task of thresholding very easy. I came up with an interactive Tux based on the "Capturing a Live Stream" code in the Camera Module Introduction.
My program tries to detect red colored objects, finds the centroid of such points and draws a ghost (find in your /usr/share/icons/oxygen/32x32/apps/) and makes Tux (/usr/share/icons/oxygen/128x128/apps/tux.png) run away from it.
Here's how the code looks like -
# -*- coding: utf-8 -*-
# An interactive Tux, interact with it using any red colored object # # based on PyGame camera module intro by Nirav Patel # http://www.pygame.org/docs/tut/camera/CameraIntro.html # -- Abhishek Mishra (ideamonk # gmail.com)
import os import pygame import pygame.camera from pygame.localsimport*
class Capture(object): ''' A Capture class to get location of a desired blob '''
def__init__(self, ccolor=(248, 111, 115), threshold=(60, 10, 10)): self.size = (640,480) # create a display surface. standard pygame stuff self.display = pygame.display.set_mode(self.size, 0) # initialize camera module pygame.camera.init() # this is the same as what we saw before self.clist = pygame.camera.list_cameras() ifnotself.clist: raiseValueError("Sorry, no cameras detected.") self.cam = pygame.camera.Camera(self.clist[0], self.size) self.cam.start()
# create a surface to capture to. for performance purposes # bit depth is the same as that of the display surface. self.snapshot = pygame.surface.Surface(self.size, 0, self.display) # target color to detect -- default is red self.ccolor = ccolor # by default we give more priority to shades of red self.threshold = threshold
def get_blob_location(self): self.snapshot =self.cam.get_image(self.snapshot) # threshold against the color we got before mask = pygame.mask.from_threshold(self.snapshot, self.ccolor, self.threshold) # keep only the largest blob of that color connected = mask.connected_component() # these numbers are purely experimental and specific to your room and object # print mask.count() # use this to estimate # make sure the blob is big enough that it isn't just noise if mask.count() >7: # find the center of the blob return mask.centroid() return (None,None)
class Ghost(): ''' Ghost class, to have a rect for collision detection ''' def__init__(self): self.image = pygame.image.load (os.path.join ("./","gv.png")) self.rect =self.image.get_rect()
while going: events = pygame.event.get() for e in events: if e.type== QUIT or (e.type== KEYDOWN and e.key == K_ESCAPE): # close the camera safely self.cam.stop() going =False
new_coord =self.get_blob_location() if new_coord != (None,None): # delta = sum( [(x-y)**2 for (x,y) in zip(new_coord,old_coord)]) # for less fuzziness # if delta>200: old_coord = new_coord self.ghost.set_rect(old_coord)
Failed attempts at tracking a colored object in OpenCV
Recently, I purchased a webcam for fun. Basically wanted to have some augumented reality fun while sitting at home, trying to make something interactive, so that I can stand back and maybe control a car with something like a Star Wars projection torch. For now, an Old Spice empty deo can would do, its totally red. Time to get some tools of trade in my bag of tricks. So this lazy pythonista looks out for something pythonic and dead easy. A little common sense from past experience (SpaceLock) tells that OpenCV is the way to go. A backing from intel makes it look more shinier. But surprisingly, he finds these many options - PyOpenCV, ctypes-opencv, swig based default bindings, and completely newly written bindings in OpenCV 2.0. Wow, now you're in a mess where every blog, every other newbie tutorial speaks about their own python bindings for opencv. A big mess out there with some folks on stackoverflow - "Since the new bindings are incomplete and the old ones are painful to use", what the hell!
Tried out the face detection code (had to be modified to work with opencv2.0 bindings) with haar-like features. Worked well with my face though it couldn't detect when I was looking down. I think one needs a bigger data file with all angles of human face covered to make detection more accurate. So much for 1MB of haar data.
Here is a better formatted code if you have trouble indenting that one -
if faces: #print 'face detected!' for i in faces: if i[1] >10: cv.Circle(self.frame, ((2*i[0][0]+i[0][2])/2,(2*i[0][1]+i[0][3])/2), (i[0][2]+i[0][3])/4, (128, 255, 128), 2, 8, 0)
def run(self): # check if capture device is OK ifnotself.capture: print"Error opening capture device" sys.exit(1)
if k ==0x1b: # ESC print'ESC pressed. Exiting ...' break
sys.exit(1)
if__name__=="__main__": print"Press ESC to exit ..." face_detect = FaceDetect() face_detect.run()
After some thinking I tried writing a colored object detector. I haven't yet gone into things like filters and thresholding techniques, which I guess are faster than my kiddish approach. Simply put what I am doing is -
Grab the image
Look for points with distance from target color in range of a particular tolerance
Count the number of these points
If this count is > a particular density then show a circle at the mean location of these points
Tune up the constants for your lightening conditions and target color.
Don't crib much as again this is "kid's" approach to object tracking :P
Here is how the failed attempt looks like -
# -*- coding: utf-8 -*- # A simple capture and draw code import sys import cv
class ColorFinder(): ''' Finds out red objects on webcam '''
# -- Recognition settings # Maximum rgb space distance to consider close self.tolerance = tolerance # how many pixels indicate an object self.density = density # currently two shades of red, one bright, other dark self.colors = colors # step is opposite of accuracy, you have to tweak density and tolerance accordinly self.step = step
# -- detection vars # mean positions self.mean_pos = [0,0]
def setupCV(self): ''' sets up opencv to capture from webcam ''' cv.NamedWindow (self.windowName, 1) self.capture = cv.CaptureFromCAM(self.device) cv.SetCaptureProperty(self.capture, cv.CV_CAP_PROP_FRAME_WIDTH, self.capture_size[0]) cv.SetCaptureProperty(self.capture, cv.CV_CAP_PROP_FRAME_HEIGHT, self.capture_size[1])
def distance2(self,source, dest): ''' finds square euclidean distance in RGB space ''' returnsum ([ (x-y)**2for (x,y) inzip(source[:3][::-1],dest[:3]) ]) # ^^ we just need rgb
def find_by_steps(self): ''' finds colored object by calculating mean position of such colors ''' mean_pos = [0,0] # reset the mean pix_count =0# to find density
x,y = (0,0) for x inxrange(0, self.capture_size[0], self.step): for y inxrange(0, self.capture_size[1], self.step): source = cv.Get2D(self.frame,y,x) for color inself.colors: if ( self.distance2(source,color) <self.tolerance ): pix_count +=1 mean_pos[0]+=x mean_pos[1]+=y break #print pix_count # just use this to tweak you if pix_count>self.density: # now we have a good bulk under detection, update mean self.mean_pos = [t/pix_count for t in mean_pos]
def run(self): ''' runs a loop to do color detection ''' self.frame = cv.QueryFrame(self.capture) whileTrue: self.frame = cv.QueryFrame(self.capture)
k = cv.WaitKey(10) if k ==1048603: # ESC print'ESC pressed. Exiting ...' return
if__name__=='__main__': cf = ColorFinder(colors=[(172, 0, 16)], density=8, tolerance=300, step=3) # find me these shades of red cf.setupCV() cf.run()
Afterthoughts -
OpenCV is good, given the support and backing it is supposed to have. But it isn't straightforward enough for someone without understanding of filters, etc to try it out.
There is webcam support in PyGame, which I'm tempted to try out. A good introduction by Nirav Patel. Besides his blog is full of inspration for anyone else to try out.
Documentation of current OpenCV binding is insufficient, besides presense of just one example for new bindings and 10+ examples for old SWIG based binding leaves newcomers in dilemma. So does the presence of many other bindings, tools, etc
My current approach is very slow, hence I'm leaving 3 pixels gap, besides this method is also very sensitive to lightening conditions around your place, better tweak it before you try out.
A better approach would be a divide and conquer kind of approach of finding the region (maybe an experienced person would disagree, but I'm speaking from a novice's point of view)
Or even better would be filtering out only reddish components and thresholding them to a black & white image. Afterwards finding white portions is not tough.
T2 starts from Wednesday, I better get back to my books for a while.
"a 'spec' is close to useless. I have _never_ seen a spec that was both big enough to be useful _and_ accurate. And I have seen _lots_ of total crap work that was based on specs. It's _the_ single worst way to write software, because it by definition means that the software was written to match theory, not reality."
Remember way back when your were that kid whose only tools of trade in teh bag o' tricks were pencil and crayons and stuff like that, ah the small bricks of water colors, the cheap blue color box or color bricks where you'd brush the watery brush and ... blah ends here. So, yes, better than even copy pasting, not caring about copyrights, etc why not trace the stuff you like as in the old school days :). After all there's no harm/copyright violation in getting inspired from an artform. So for lenny.in (crap this is 3rd day in making and its not yet out)... I needed some logos, some cool graphics for gmail, twitter and Lenny itself. Here's how I got it done -
1. Load original image/photo into ArtRage or MyPaint (on linux) 2. Start drawing... draw ... draw... draw some more 3. Resize into iconic/useful proportion, and smile.
Lol I might just have mislead you... but hey this obviously sounds like a safer practice than outright copy pasting media content from here and there.
Anyways so this is what I could get out of it (zoom to see brush strokes) -
Two times in my life I've come across something like this -
>>> d = {'data' : u'\u2013'} >>> urllib.urlencode(d) Traceback (most recent call last): File "", line 1, in File "/usr/lib/python2.6/urllib.py", line 1268, in urlencode v = quote_plus(str(v)) UnicodeEncodeError: 'ascii' codec can't encode character u'\u2013' in position 0: ordinal not in range(128)
And now that I've a generic solution this this issue (thanks to Jarret Hardie and Grego), I would like to pin it here so that I know where to look for it in future.
# gets rid of ascii codec shite def sanitize_codec(fooDict,charset): return dict([(k, v.encode(charset)) for k, v in fooDict.items()])
weird_data = sanitize_codec(weird_data,'utf-8')
Pretty useful when you've to pass on some chunk of an rss feed to some other webapplication, say from gmail feed to twitter rest api.
Ah! more than a year ago I wrote this yet to be finished 2d sidescrolling game with very crappy collision detection and pretty poorly programmed, blah blah called NinCompoop - The Unfinished Quest.
I felt like porting it to linux today. The good news is that allegro is already in the Ubuntu repository, so all I needed to do was a sudo apt-get install liballegro4.2.-dev
Porting again, was dead simple, just change the windows styles slashes to linux style slashes - \\ to /
... just another guy flying in winds of information overload. keeping a tap on programming, web-design, security and open-source ...
He can also be hired for some work - madetokill.com