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

Edited 6 Years Ago by Tech B: n/a

Attachments

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
"""

Edited 6 Years Ago by pyTony: n/a

This question has already been answered. Start a new discussion instead.