TradesmanS60 PyS60 example app

                              
Here’s a an app I wrote a while ago that I thought I’d share.

The original idea was a mobile application for tradesmen to work with. The main (and currently only) feature allows you to use the phone’s camera to work out the angle on something.

There’s no fancy computer vision unfortunately, you take a photo and are presented with the image and a cursor. move the cursor around the image until you have clicked on one side of the “angle”, then the pivot, then the other side. Using matrix operations it will then tell you the angle of your selection.

I wrote this to run on the Nokia 6630, but it should be easily portable to any other S60 phone. Check out the video of the app in action:

And here’s the code:

#Title: TradesMan

#Author: Mike Terzza

#Summary: An application to measure angles from images taken by a phone's camera

#Version: 1.3.2

#Date: 26/01/08

#

#Import all nessecary modules

import e32, camera, appuifw, key_codes, graphics, math

#

#Define variables for image use

#

#The current mode of the program

mode = None

#Cursor coordinates

x = 80

y = 60

#Variables for angle coordinates

dotax = 1

dotay = 1

dotbx = 1

dotby = 1

dotcx = 1

dotcy = 1

#The main image variable

imgFile = None

def handle_redraw(rect):

"""Callback function to redraw the screen if necessary"""

if imgFile:

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

def handle_event(event):

"""Handles Keypress events and calls the necessary functions"""

ev = event['keycode']

if mode != None:

if event['type'] == appuifw.EEventKeyDown:

pass

elif ev == key_codes.EKeySelect:

select()

if ev == key_codes.EKeyUpArrow:

up()

elif ev == key_codes.EKeyRightArrow:

right()

elif ev == key_codes.EKeyDownArrow:

down()

elif ev == key_codes.EKeyLeftArrow:

left()

else:

pass

def up():

"""Code for when the 'up' button is pressed"""

global y

if imgFile != None:

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

y -= 5

drawDot()

else:

pass

def down():

"""Code for when the 'down' button is pressed"""

global y

if imgFile != None:

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

y += 5

drawDot()

else:

pass

def left():

"""Code for when the 'left' button is pressed"""

global x

if imgFile != None:

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

x -= 5

drawDot()

else:

pass

def right():

"""Code for when the 'right' button is pressed"""

global x

if imgFile != None:

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

x += 5

drawDot()

else:

pass

def select():

"""Code for when the 'select' button is pressed"""

global dotax, dotay, dotbx, dotby, dotcx, dotcy, mode, imgFile

if mode == 0:

shoot()

dotStart()

elif mode == 1:

dotax = x

dotay = y

mode = 2

elif mode == 2:

dotbx = x

dotby = y

mode = 3

imgFile.line((dotax, dotay, dotbx, dotby)\

, outline = (0, 255, 0), width = 2)

elif mode == 3:

dotcx = x

dotcy = y

imgFile.line((dotax, dotay, dotbx, dotby), outline = (0, 255, 0)\

, width = 2)

imgFile.line((dotbx, dotby, dotcx, dotcy), outline = (0, 255, 0)\

, width = 2)

appuifw.query(u'The angle is:  %.0f Degrees' % angleCalc(), "query")

mode = 4

loadImg()

elif mode == 4:

quit()

def angleCalc():

"""Takes the co-ordinates from the points and returns the angle"""

ax = dotax - dotbx

ay = dotby - dotay

bx = dotcx - dotbx

by = dotby - dotcy

aLen = math.sqrt((ax**2 + ay**2))

bLen = math.sqrt((bx**2 + by**2))

dotProd = (ax * bx + ay * by)

angle = degrees(math.acos((dotProd / (aLen * bLen))))

return angle

def degrees(angle):

"""Converts radians to Degrees"""

return (180 * angle) / math.pi

def viewfinder(img):

"""CallBack Function for camera.start_finder() that takes the stream of

images and displays them on the canvas """

canvas.blit(img, target = (0, 0, w, 0.75 * w), scale = 1)

def shoot():

"""Take photo and saves it to disk, then calls the loadImg() function to

display it to the canvas"""

global imgFile, mode

mode = 1

photo = camera.take_photo(size = (160, 120))

photo.save('e:\\Images\\photo.jpg')

loadImg()

def startFinder():

"""Starts camera viewfinder"""

camera.start_finder(viewfinder, size = (160, 120))

def loadImg():

"""Takes saved image file and blits it to the screen and

if necessary, adds lines of the angle"""

global imgFile

imgFile = graphics.Image.open('e:\\Images\\photo.jpg')

camera.stop_finder()

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

if mode > 2:

imgFile.line((dotax, dotay, dotbx, dotby), outline = (0, 0, 255)\

, width = 2)

if mode > 3:

imgFile.line((dotbx, dotby, dotcx, dotcy), outline = (0, 0, 255)\

, width = 2)

def drawDot():

"""Draws the dot (cursor) on screen and when necessary, adds the

interactive angle lines to the screen"""

loadImg()

imgFile.point((x, y), outline = (255, 0, 0), width = 5)

if mode == 2:

imgFile.line((dotax, dotay, x, y), outline = (0, 255, 0), width = 2)

if mode == 3:

imgFile.line((dotbx, dotby, x, y), outline = (0, 255, 0), width = 2)

def dotStart():

"""Stops the camera and viewfinder and starts the dot drawing"""

camera.stop_finder()

drawDot()

def splashScreen():

"""Introductory Splash Screen, welcoming you to the application"""

imgFile = graphics.Image.new((w, h))

imgFile.clear((61, 89, 171))

imgFile.ellipse((23, 37, 153, 107), outline = (0, 0, 255)\

, fill = (0, 0, 128), width = 5)

imgFile.text((62, 75), u'TradesMan', fill = (202, 255, 255))

imgFile.text((55, 140), u'By Mike Terzza', fill = (202, 255, 255))

canvas.blit(imgFile, target = (0, 0, w, 0.75 * w), scale = 1)

e32.ao_sleep(2)

def quit():

"""Quits the application"""

app_lock.signal()

#######################
#

#Set user interface options

#

appuifw.app.screen = "normal"

canvas = appuifw.Canvas(redraw_callback = handle_redraw\

, event_callback = handle_event)

appuifw.app.body = canvas

appuifw.app.title = u"TradesMan"

appuifw.app.exit_key_handler = quit

#Find out canvas size

w, h = canvas.size

#

#Show SplashScreen then start Camera Viewfinder

#

splashScreen()

mode = 0

startFinder()

#

#App_lock - App waits for commands and doesn't just exit sequentially

#

app_lock = e32.Ao_lock()

app_lock.wait()

I aim to add more features and compile it to a sis / sisx file eventually, but for now I thought I’d just upload it as an example of a working S60 script for you to play with.

As requested, Download the source here:

TradesMan.tar.gz

TradesMan.zip

Tags: , ,

2 Responses to “TradesmanS60 PyS60 example app”

  1. Taavit says:

    Make a download link, so somebody does not lost how to get that on the phone ;)
    Very userful

    Cheers
    Alba/Taavit

  2. Dear friend,

    Use Nokia’s Computer Vision technology for Python, it can help you make a code that will give the measure directly be moving the camera on the angle diagram.

    Download Link ‘Nokia’s Computer Vision technology for Python’:

    http://research.nokia.com/files/PyNcvLib-1.0_0.zip

    This makes the phone recognize and process the inputs from camera.
    So no need to mark the lines manually by pressing the keys.

    Search more on Google or goto http://research.nokia.com/ to know more!!!

    Great work!!!

    Raavi
    …Using same mobile & same language to code different…

Leave a Reply