I'm revisiting an old IR tracking project, and want to use it in a blender game.
I would like to know if anyone could help optimize the parsing algorithm or tell me an easier way to track multiple points with code.
"im" is an instance of an image I captured via VideoCapture module that accesses the webcam. I use Image from PIL to find pixels. There is a filter on the webcam, so I only get IR light. All other pixel values are black or (0,0,0).
I've tried using psycho to speed things up a bit. I'm thinking threading could help the speed, but I'm new to threading; if that's even an option.
Any suggestions?
#Method to parse for two IR points.
#This method is really slow; even with psycho.
#Returns average of each point so we map the middle of the dot
#not just the first true value.
def xy(self,im,res):
imxy = []
x = 0
y = 0
p1x = p1y = p2x = p2y = 0
while x*y <= res: #Resolution of the cam. 640*480
if im.getpixel((x,y)) > (250,250,250): #RGB threshold
imxy.append((x,y))
x += 1
if x == 640:
x = 0
y += 1
if y == 480:
break
#Take the average
point1 = imxy[:len(imxy)/2] #slice to separate the two dots
point2 = imxy[len(imxy)/2:]
for i in points1:
p1x += i[0]
p1y += i[1]
for i in points2:
p2x += i[0]
p2y += i[1]
#return average
return (p1x/len(point1),p1y/len(point1)),(p2x/len(point2),p2y/len(point2))Could we get one 'im' as sample to do true test of the function?
Use attachment and zip the file if it is not accepted as it is (GIF?)
I've sped it up by looking at every 4th pixel
IE: x+=4 and y+=4
I will still like to know if there is a better way.
I will include a sample image of whats being scanned. It will be in jpg format.
I'm using windows; thought it would be good to mention. Also Python 2.6
To make a functional program I did this:
from time import clock
import Tkinter as tk
import Image
#Method to parse for two IR points.
#This method is really slow; even with psycho.
#Returns average of each point so we map the middle of the dot
#not just the first true value.
def xy(im,xres,yres):
imxy = []
x = 0
y = 0
p1x = p1y = p2x = p2y = 0
while x*y <= xres*yres: #Resolution of the cam.
if im.getpixel((x,y)) > (250,250,250): #RGB threshold
imxy.append((x,y))
x += 4
if x >= xres:
x = 0
y += 4
if y >= yres:
break
#Take the average
point1 = imxy[:len(imxy)/2] #slice to separate the two dots
point2 = imxy[len(imxy)/2:]
for i in point1:
p1x += i[0]
p1y += i[1]
for i in point2:
p2x += i[0]
p2y += i[1]
#return average
return (p1x/len(point1),p1y/len(point1)),(p2x/len(point2),p2y/len(point2))
root = tk.Tk()
image=Image.open('t.jpg')
t=clock()
ima1=xy(image,640,480)
print clock()-t,ima1
Timing in my computer:
0.161569696707 ((438, 128), (234, 144))
with psyco:
0.127528778099 ((438, 128), (234, 144))
I did this which stops at first found pixel of each spot, so is less accurate, also it assumes that spots are not over each other:
from time import clock
import Tkinter as tk
import Image
#Method to parse for two IR points.
def xy(im,xres,yres):
maxsize=128
notfound=True
hx=0
for x in range(0,xres,4):
for y in range(0,yres,4):
if im.getpixel((x,y)) > (250,250,250): #RGB threshold
if notfound:
hx=x+maxsize ## minimum sepation between in x direction
x1,y1=x,y
notfound=False
if x>hx:
## second spot found
return ((x1,y1),(x,y))
root = tk.Tk()
image=Image.open('t.jpg')
t=clock()
ima1=xy(image,640,480)
print clock()-t,ima1 Timing in my computer:
0.108073791501 ((232, 144), (436, 128)) with psyco:
0.0931864245316 ((232, 144), (436, 128))Version with separation in x or y direction:
from time import clock
import Tkinter as tk
import Image
try:
import psyco # python specialising compiler
psyco.full()
except:
print 'Install psyco for faster execution'
pass
#Method to parse for two IR points.
def xy(im,xres,yres):
maxsize=64
found=False
for x in range(0,xres,4):
for y in range(0,yres,4):
if im.getpixel((x,y)) > (250,250,250):
if not found:
x1,y1 = (x,y)
hx,hy = (x+maxsize,y+maxsize)
found=True
elif x>hx or y>hy:
return ((x1,y1),(x,y))
root = tk.Tk()
image=Image.open('t.jpg')
t=clock()
r=xy(image,640,480)
t=clock()-t
print r,t
"""Output
((232, 144), (436, 128)) 0.107791074005 ## no psyco:
((232, 144), (436, 128)) 0.0926679228785 ## psyco:
"""If everything else fails read the documentation, from PIL documents I found that this method with load is faster:
from time import clock
import Tkinter as tk
import Image
#Method to parse for two IR points.
def xy(im,xres,yres):
maxsize=64
notfound=True
hx=0
pix = im.load()
## print pix[232,144]
for x in range(0,xres,4):
for y in range(0,yres,4):
if pix[x,y] > (250,250,250): #RGB threshold
if notfound:
hx=x+maxsize ## minimum sepation between
x1,y1=x,y
notfound=False
if x>hx:
## second spot found
return ((x1,y1),(x,y))
root = tk.Tk()
image=Image.open('t.jpg')
t=clock()
ima1=xy(image,640,480)
t2=clock()-t
print t2,1/t2,'Hz',ima1
"""Output:
0.021093462996 47.4080524469 Hz ((232, 144), (436, 128))
""" from time import clock
import Image
try:
import psyco # python specialising compiler
psyco.full()
except:
print 'Install psyco for faster execution'
pass
#Method to parse for two IR points.
#This method is really slow; even with psycho.
#Returns average of each point so we map the middle of the dot
#not just the first true value.
def xy(im,xres,yres):
pix = im.load()
imxy = []
x = 0
y = 0
p1x = p1y = p2x = p2y = 0
while x*y <= xres*yres: #Resolution of the cam.
if pix[x,y] > (250,250,250): #RGB threshold
imxy.append((x,y))
x += 4
if x >= xres:
x = 0
y += 4
if y >= yres:
break
#Take the average
point1 = imxy[:len(imxy)/2] #slice to separate the two dots
point2 = imxy[len(imxy)/2:]
for i in point1:
p1x += i[0]
p1y += i[1]
for i in point2:
p2x += i[0]
p2y += i[1]
#return average
return (p1x/len(point1),p1y/len(point1)),(p2x/len(point2),p2y/len(point2))
image=Image.open('t.jpg')
t=clock()
ima1 = xy(image,640,480)
t2=clock()-t
print t2,1/t2,'Hz',ima1
""" Output:
0.0337917249259 29.593043924 Hz ((438, 128), (234, 144))
0.025817527088 38.7333766163 Hz ((438, 128), (234, 144)) ## psyco
"""