Novell Home

HowTo: Use a Webcam and PC as a Magic Mirror - Part 1

Novell Cool Solutions: Feature
By Stomfi

Digg This - Slashdot This

Posted: 27 Oct 2005
 

StomfiLearning to use Linux at Home and Work
Welcome to my ongoing series of HowTo articles designed to help Linux newbies get comfortable with Linux. Before trying any of these HowTos, take a few minutes to study the prerequisites so you can hit the ground running.
--Stomfi

This HowTo describes a system which can be used at home and in shops to retain several views of an object or person, so that comparisons can be made between them on a computer screen. The incentive for this system was that when trying on new spectacle frames, I could not see what they really looked like. I realised that because the computer can remember several views, that many other uses where one would like to pick the best of several choices, could be an advantage for all sorts of things in the home and in shops, so I decided to create such a system using the shell, Runtime Revolution, a camera, and some picture grabbing and saving software. I have called it the "magic mirror" and I would like you to do the same if you make one.

As the inventor of this system I state that any patents arising from the description and methods described in this two part article are to be assigned by any and all developers to the Patent Commons held at the Open Source Development Laboratories for the common good.

This is a summary of the patent description for the systems described in this article. A combination of the following mechanisms assembled in such a fashion as to achieve picture grabbing, viewing and printing for the purpose of selecting a wearable product.
  • Any camera device that can supply a digitally downloadable picture within approximately 10 seconds of a remote button press.
  • Any mirror or screen that can adequately display a suitable reflection of the user or users.
  • Software and electronic display system that can display a viewable selection of down loaded pictures from the camera device, and associated control procedures that can display and mirror a single large picture of one of the selection, and enable the any or all of the displayed pictures to be printed, saved or transferred by electronic means to facilitate viewing by third parties.
  • Software that can print, save and electronically transfer any or all of the displayed pictures.

The instance of the system described here I have named IKEAM, sort of a play on words, as it can be built from pre manufactured parts by the DIY enthusiast.

I started writing this how to back in December last year, but had to put it aside as finding Linux drivers for web cameras one could buy in retail stores in Australia was a non event. In less than one year the situation has changed quite dramatically. There are now drivers for all sorts of add on peripherals, from web cameras to wifi cards. We have to thank the Linux development community, and the chip manufacturers who are actively helping them, as well as the lobbying by distribution companies like SUSE, who want us to have a better desktop experience.

Because it is supposed to be more fun, we'll create this system bottom up, instead of top down, so the first thing we'll develop is the Runtime Revolution GUI interface. See www.runrev.com. I will use RunRev 2.2.1 for this development. I suggest you use the GNOME window manager when you log in, as I have found that there are a few interface issues with KDE 3.x.

Runtime Revolution recently sent me these links where you can get lots of examples about using their products, although not too much on Linux, so if you are a user and have some hints, send them a link.

http://support.runrev.com/useful_sites.php

Maybe revjournal would be a good one, SoSmart is good, as is Sons of Thunder. They have a new add on library which works on 2.2.1 and above, called arcade which is worth checking out if you like creating games and dynamic movement. I am going to play with it and make you a whiz bang how to in the near future.

You know the drill to start off a RunRev project. Create a folder in your home directory called IKEAM, create some sub folders called "bin", "bin/develop", "info", "pics", "tmp". "bin/develop" is where you will save the RunRev development file "IKEAM.rev". Start up RunRev and make a new stack. stretch the window to suit your preferred display size. I'd settle on 800x600 as the size of a large web cam picture is likely to be best at 640x480, and we need a bit of room for buttons, instructions and the like.

This is the picture layout. Either a large single picture is shown or up to 6 collected ones are tiled. Clicking the drop down menu allows the user to select one of 6 pictures to view this size, or up to 6 pictures at once. More than this is too hard to see and too hard to choose on from for the average person. The MIRROR button allows the user to horizontally flip the large picture so the magic mirror can show both what a mirror reflects or what others see when they are looking at you. This button only appears in the large picture mode.




These are pictures of some of my shell hacker guests from out of town after a long session at the screen.

The tiled pictures should be the same ratio as the large picture, which should be the same ratio as the one from your digital web camera.

Create the large image first and label it PIC1, create image PIC2 on the top left to be 1/6 of the area of image PIC1. Create the other five images by copying image PIC1 and relabelling them as image PIC3 to PIC7. Create the Picture Selector pull down menu to show 7 items which are "ALL" and "1" through to "6" , and the CLEAR and MIRROR buttons.

These are the scripts for the stack, card, and objects. You create the script by right clicking the object or a blank window area of the part you want, then choose Edit Card Script, or Edit Object Script from the pop up menu as shown here.


The property inspector allows you to modify the objects name and as in this application the Lock Position & Size parameter.

This is the stack script which set the card in the condition it needs to be at the start. Image 1 is the large picture which appears and disappears by using the Picture Selector menu after some pictures have been saved. All the gif pictures are the same here but it would be more cognitive for the use if the message mentioned the picture number associated with the button to press in this example. Of course you could use a single button and add one to each picture number as it was pressed in the grabbing and saving section, reverting back to 1 after 6 is reached in this layout. The file "grabpic.sh" contains the shell command to grab and save the pictures.

on openStack

   #Hide and lower Image 1

   set the invisible of image 1 to true

   set the layer of image 1 to bottom

   #Hide and show buttons

   set the invisible of button "MIRROR" to true

   set the invisible of button "CLEAR" to false

   #Load the instruction pictures

   set the filename of image "PIC1" to ($HOME & "/IKEAM/pics/file1.gif")

   set the filename of image "PIC2" to ($HOME & "/IKEAM/pics/file2.gif")

   set the filename of image "PIC3" to ($HOME & "/IKEAM/pics/file3.gif")

   set the filename of image "PIC4" to ($HOME & "/IKEAM/pics/file4.gif")

   set the filename of image "PIC5" to ($HOME & "/IKEAM/pics/file5.gif")

   set the filename of image "PIC6" to ($HOME & "/IKEAM/pics/file6.gif")

   set the filename of image "PIC7" to ($HOME & "/IKEAM/pics/file7.gif")

   #Delete the old jpegs

   put ("rm -f" && $HOME & "/IKEAM/tmp/*") into DUDEL

   replace return with empty in DUDEL

   put the shell of DUDEL into DUNDEL

   #Set up a global picture grab process

   global OGRAB

   put ($HOME & "/IKEAM/bin/grabpic.sh") into OGRAB

end openStack

This is the card script which responds to key presses. The "ikeam" field is for messages and debugging. It is useful for displaying the key numbers, and help with the time taken to grab a picture.

The time the system, including the camera and grabbing software, takes to save the picture after the button is pressed, is called latency. On my system it is about 4 to 5 seconds with a 640x480 jpeg which means I have to remain in place for that long after I press the button (Or I can dance round the room for 3 seconds, arriving back in time for the picture). Reducing the picture size can reduce latency as this reduces the time taken to scan in the picture.

Modern digital cameras have solved this problem, but you have to find one with a remote control and USB instant download cable. Or you could design and build a mechanical relay switch which will physically press the shutter button powered from your serial port or a 9 volt battery. The possibilities are there.

The three key numbers are: the numbers above the "qwerty" keys, the keypad with the numlock on and off.

The if statements set the PressedThis holder and the switch loop decides which action to take. There are some messages for KEY1 which can be copied into the other KEY actions. You can change these to suit. Notice that although it takes a few seconds to actually take the picture, when it does do it, it is reasonably fast so small movements don't matter.

on rawKeyDown ThisKey

   #Return number of key for debugging

   put ThisKey into field "ikeam"

   global OGRAB

   #set all number key possibilities

   #set PressedKey to something else

   put "KEY0" into PressedKey

   if ThisKey = "49" or ThisKey = "65457" or ThisKey = "65436"

   then

      put "KEY1" into PressedThis

   end if

   if ThisKey = "50" or ThisKey = "65458" or ThisKey = "65433"

   then

      put "KEY2" into PressedThis

   end if

   if ThisKey = "51" or ThisKey = "65459" or ThisKey = "65435"

   then

      put "KEY3" into PressedThis

   end if

   if ThisKey = "52" or ThisKey = "65460" or ThisKey = "65430"

   then

      put "KEY4" into PressedThis

   end if

   if ThisKey = "53" or ThisKey = "65461" or ThisKey = "65437"

   then

      put "KEY5" into PressedThis

   end if

   if ThisKey = "54" or ThisKey = "65462" or ThisKey = "65432"

   then

      put "KEY6" into PressedThis

   end if

   if ThisKey = "45" or ThisKey = "65453"

   then

      #The minus key was pressed

      put "MMCLEAR" into PressedThis

   end if

   #Make sure the small pictures are on top

   set the invisible of image "PIC1" to true

   set the layer of image "PIC1" to bottom

   #Do the grab and display

   #Return activity message for debug timing

   switch PressedThis

      case "KEY1"

         put (OGRAB && "2") into PGRAB

         put "Grabbing Picture" into field "ikeam"

         put the shell of PGRAB into DUNGRAB

         set the invisible of image "PIC2" to false

         set the filename of image "PIC2" to empty

         set the filename of image "PIC2" to ($HOME & "/IKEAM/tmp/file2.jpg")

         put "Picture Displayed" into field "ikeam"

         break

      case "KEY2"

         put (OGRAB && "3") into PGRAB

         put the shell of PGRAB into DUNGRAB

         set the invisible of image "PIC3" to false

         set the filename of image "PIC3" to empty

         set the filename of image "PIC3" to ($HOME & "/IKEAM/tmp/file3.jpg")

         break

      case "KEY3"

         put (OGRAB && "4") into PGRAB

         put the shell of PGRAB into DUNGRAB

         set the invisible of image "PIC4" to false

         set the filename of image "PIC4" to empty

         set the filename of image "PIC4" to ($HOME & "/IKEAM/tmp/file4.jpg")

         break

      case "KEY4"

         put (OGRAB && "5") into PGRAB

         put the shell of PGRAB into DUNGRAB

         set the invisible of image "PIC5" to false

         set the filename of image "PIC5" to empty

         set the filename of image "PIC5" to ($HOME & "/IKEAM/tmp/file5.jpg")

         break

      case "KEY5"

         put (OGRAB && "6") into PGRAB

         put the shell of PGRAB into DUNGRAB

         set the invisible of image "PIC6" to false

         set the filename of image "PIC6" to empty

         set the filename of image "PIC6" to ($HOME & "/IKEAM/tmp/file6.jpg")

         break

      case "KEY6"

         put (OGRAB && "7") into PGRAB

         put the shell of PGRAB into DUNGRAB

         set the invisible of image "PIC7" to false

         set the filename of image "PIC7" to empty

         set the filename of image "PIC7" to ($HOME & "/IKEAM/tmp/file7.jpg")

         break

      case "MMCLEAR"

         put "Clearing saved Pictures" into field "ikeam"

         #Load the instruction pictures

         set the filename of image "PIC1" to ($HOME & "/IKEAM/pics/file1.gif")

         set the filename of image "PIC2" to ($HOME & "/IKEAM/pics/file2.gif")

         set the filename of image "PIC3" to ($HOME & "/IKEAM/pics/file3.gif")

         set the filename of image "PIC4" to ($HOME & "/IKEAM/pics/file4.gif")

         set the filename of image "PIC5" to ($HOME & "/IKEAM/pics/file5.gif")

         set the filename of image "PIC6" to ($HOME & "/IKEAM/pics/file6.gif")

         set the filename of image "PIC7" to ($HOME & "/IKEAM/pics/file7.gif")

         #Delete the old jpegs

         put ("rm -f" && $HOME & "/IKEAM/tmp/*") into DODEL

         replace return with empty in DODEL

         put the shell of DUDEL into DUNDEL

         break

   end switch

end rawKeyDown

The global OGRAB contains the line which executes "grabpic.sh" which I'll explain in part 2 of this article.

This next script controls what happens when a menu item is selected from the Picture Select drop down menu.

Mostly it is changing the invisible state of objects and whether the large picture is at the top or bottom of the layers. The global PPAGE is used to tell the PRINT button what to display.

on menuPick thisItem

   global PPAGE

   switch thisItem

      case "ALL"

         put "S" into PPAGE

         set the invisible of image "PIC1" to true

         set the invisible of button "MIRROR" to true

         set the invisible of button "CLEAR" to false

         set the layer of image "PIC1" to bottom

         break

      case "1"

put "L" into PPAGE

         put the filename of image "PIC2" into PicFile

         set the invisible of image "PIC1" to true

         set the layer of image "PIC1" to top

         set the filename of image "PIC1" to PicFile

         set the invisible of image "PIC1" to false

         set the invisible of button "MIRROR" to false

         set the invisible of button "CLEAR" to true

         break

      case "2"

         put "L" into PPAGE

         put the filename of image "PIC3" into PicFile

         set the invisible of image "PIC1" to true

         set the layer of image "PIC1" to top

         set the filename of image "PIC1" to PicFile

         set the invisible of image "PIC1" to false

         set the invisible of button "MIRROR" to false

         set the invisible of button "CLEAR" to true

         break

      case "3"

         put "L" into PPAGE

         put the filename of image "PIC4" into PicFile

         set the invisible of image "PIC1" to true

         set the layer of image "PIC1" to top

         set the filename of image "PIC1" to PicFile

         set the invisible of image "PIC1" to false

         set the invisible of button "MIRROR" to false

         set the invisible of button "CLEAR" to true

         break

      case "4"

         put "L" into PPAGE

         put the filename of image "PIC5" into PicFile

         set the invisible of image "PIC1" to true

         set the layer of image "PIC1" to top

         set the filename of image "PIC1" to PicFile

         set the invisible of image "PIC1" to false

         set the invisible of button "MIRROR" to false

         set the invisible of button "CLEAR" to true

         break

      case "5"

         put "L" into PPAGE

         put the filename of image "PIC6" into PicFile

         set the invisible of image "PIC1" to true

         set the layer of image "PIC1" to top

         set the filename of image "PIC1" to PicFile

         set the invisible of image "PIC1" to false

         set the invisible of button "MIRROR" to false

         set the invisible of button "CLEAR" to true

         break

      case "6"

         put "L" into PPAGE

         put the filename of image "PIC7" into PicFile

         set the invisible of image "PIC1" to true

         set the layer of image "PIC1" to top

         set the filename of image "PIC1" to PicFile

         set the invisible of image "PIC1" to false

         set the invisible of button "MIRROR" to false

         set the invisible of button "CLEAR" to true

         break

   end switch

end menuPick

Each case ends in a "break" otherwise the next lot of statements might be performed.

The drop down menu, the buttons, and the images are all found in the objects menu in the RunRev main bar.

This is the CLEAR button script. This bit of script appears three times in various places you will notice.

on mouseUp

   #Hide and lower Image 1

   set the invisible of image "PIC1" to true

   set the layer of image "PIC1" to bottom

   #Hide and show buttons

   set the invisible of button "MIRROR" to true

   set the invisible of button "CLEAR" to false

   #Load the instruction pictures

   set the filename of image "PIC1" to ($HOME & "/IKEAM/pics/file1.gif")

   set the filename of image "PIC2" to ($HOME & "/IKEAM/pics/file2.gif")

   set the filename of image "PIC3" to ($HOME & "/IKEAM/pics/file3.gif")

   set the filename of image "PIC4" to ($HOME & "/IKEAM/pics/file4.gif")

   set the filename of image "PIC5" to ($HOME & "/IKEAM/pics/file5.gif")

   set the filename of image "PIC6" to ($HOME & "/IKEAM/pics/file6.gif")

   set the filename of image "PIC7" to ($HOME & "/IKEAM/pics/file7.gif")

   #Delete the old jpegs

   put ("rm -f" && $HOME & "/IKEAM/tmp/*") into DODEL

   replace return with empty in DODEL

   put the shell of DUDEL into DUNDEL

end mouseUp

This is the PRINT button script which launches the Linux "gthumb" application. I chose this one as it will automagically set up the print layout for several images on one page. You will have to set it to print 8 to a page to get all six.

on mouseUp

   #Print current displayed picture/s

   put "Using Gthumb to print pictures" into field "ikeam"

   global PPAGE

   if PPAGE = "L"

   then

      #Print single large jpeg picture

      put the filename of image "PIC1" into PPIC

      launch PPIC with "gthumb"

   else

      #print requested current jpeg pictures 2 to 6 in tmp folder if any are there

      put ("ls" && $HOME & "/IKEAM/tmp") into DOTSUM

      replace return with empty in DUSUM

      put the shell of DUSUM into GOTSUM

      if GOTSUM <> ""

      then

         put ("gthumb" && $HOME & "/IKEAM/tmp/*") into PPICS

         replace return with empty in PPICS

         put "Click Catalog in Gthumb, Select all Pics, Click File - Print" into field "ikeam"

         put the shell of PPICS into DUNPRINT

      else

         put "No pictures to Print" into field "ikeam"

      end if

   end if

end mouseUp

This is the MIRROR button script:

on mouseUp

   flip image "PIC1" horizontal

   #Using this function turns on the paint tool, so reset to browse tool

   choose browse tool

end mouseUp

Nice and simple really.

This is a picture of the card elements showing you the names of everything. I have also put in tooltips on the buttons to aid the user. The keyboard could be used with the rawKeyDown function to perform more activities, but in a shop situation where expenses need to be monitored, it maybe better to have an assistant in control of mouse activity for printing, and the two other functions I haven't implemented on this example which are saving on a floppy, pen drive or CD and electronically transferring via email or FTP.


When you have it all finished the layout could look something like this:


Use the property settings to lock the size and position of all your fields especially the images otherwise the small one will resize to the actual size when you grab them.


I think that it is wonderful that Linux and RunRev has made such simple easy to apply tools that a non programmer like me can use to put an idea into practice in such a short time and get such a professional result.

Three cheers to all involved.

This is the end of part one of this HowTo. In the next part we shall look at web cameras and their software. How the camera will work and what practical requirements must be met to make sure the system is usable.


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell