Click here to Skip to main content
Click here to Skip to main content

Computer Vision: Virtual Buttons

By , 2 Mar 2010
 

Introduction

Wouldn't it be great if you could control your computer with your hands? In this article, I will show you a small application I created to control the Windows Media Player with my hand motion and an ordinary web-cam. You can see the picture above; this application creates three "hot-spots" in the web-cam view, and you can assume that these hot-spots are virtual buttons, and they get activated when you make a click movement in them. I've programmed each of the hot-spots to control a particular button in Windows Media Player; the one at the top (blue) is for play/pause, and the other two are for next/previous songs. Check out this video to see my application in action.

Creating click-able virtual buttons

The criteria for clicking of a "hot-spot" is the increase in motion to a certain threshold; when it crosses its limit, then a click event is raised for a particular "hot-spot", which could be programmed to do further actions (like controlling the Media Player). Basically, I process each frame of my web-cam to check for motion levels in each of "hot-spots", and whenever it sees a motion is continuously increasing its threshold value in 10 to 20 frames, then it raises an event. Pretty simple!

To detect motion, I used a fairly simple algorithm of subtracting two images. Every image is made of three layers: red, blue, and green. Thus, each of the pixels in an image holds three values corresponding to its RGB. But, what about gray-scale images? Do they have three layers too? Well, yes, but the value of R, G, and B are the same for a particular pixel in a gray-scaled image. Imagine that there is an image of 2X2 pixels:

{1R 2G 3B, 4R 5G 6B} 
{7R 8G 9B, 2R 3G 4B}

The above 2X2 matrix is for a bitmap image where each pixel consists of RGB. Now, to make a gray-scale of the above image, we will take the average of the RGB values of each pixel and assign this average value to the RGB of the pixel. So, our gray-scaled image would be:

{(1+2+3)/3R (1+2+3)/3G (1+2+3)/3B, (4+5+5)/3R (4+5+5)/3G (4+5+5)/3B}
{(7+8+9)/3R (7+8+9)/3G (7+8+9)/3B, (2+3+4)/3R (2+3+4)/3G (2+3+4)/3B}

We can see that the gray-scaled images have the same RGB value for each pixel. So, I preferred to convert the web-cam images to gray-scale and then simply subtract it from the previous images using matrix algebra.

public ImageMatrix(Bitmap image)//constructor
{
    this.width = image.Width;
    this.height = image.Height;

    byte[,] function = new byte[width, height];
    //define bounds of function

    //unsafe bitmap to iterate through the image
    unSafeBitmap usb = new unSafeBitmap(image);
    usb.LockImage();

    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            /* Reading average (gray scale) 
               value for each of the pixel
             * and storing it in function*/
            this.function[i, j] = usb.GetAverage(i, j);
        }
    }
}

The above code snippet shows that it is easy to get a matrix of form byte[,] from a bitmap image. Once you have two of such matrices from consecutive web-cam frames, you could subtract them to find the matrix that shows the motion in each of the pixels. Further, you can make an image from this byte[,] using the code snippet shown below:

public Bitmap ToImage()//to convert imagematrix to 
{
    Bitmap image = new Bitmap(width, height);

    unSafeBitmap usb = new unSafeBitmap(image);
    //making object for unsafe bitmapping
    usb.LockImage();
    
    //making a grayscale image according to function array
    for(int i=0;i<width;i++)
    {
        for(int j=0;j<height;j++)
        {
            //writign each pixel on image bitmap.
            byte Value = function[i, j];
            Color c = Color.FromArgb(Value, Value, Value);
            //gray scale image

            usb.SetPixel(i, j, c);
        }
    }

    //unlock image before returning 
    usb.UnlockImage();

    return image;
}

Once you get the motion levels in each of the "hot-spots", add code to raise an event if it increases beyond a certain value, and that's it!

Fast image processing

Even in my earlier articles, I've used a class for faster image processing in C#. If you are not aware of it, then you should check my previous article, "Computer Vision - Decoding a Morse Code Flashing LED".

Using the program

The program was designed and tested on my web-cam; you can make it work perfectly fine on your computer by adjusting a few settings. You can see the settings in the screenshot below:

In the sample program I've provided with this article, there are three buttons:

  • Top: Play/Pause
  • Left: Previous song
  • Right: Next song

You can also easily modify the code to control whatever you wish, or you could even add more virtual buttons! If you have questions about the program's functioning, then leave your comments here.

You can visit my blog for more information about this program.

Have fun!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Shivamkalra
Canada Canada
Member
I'm an engineering student at UOIT, Canada. Visit my blog http://shivam-kalra.blogspot.com.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHi. Great work here!memberthree_xtreme26 Feb '13 - 0:25 
Hi. Great work here! Awesome.
 
Anyhow, do you have any experience in integrating this codes/apps in Adobe Flash.
I tried to make one but failed.
Can you help to enlighten me? =)
 
Thanks.
QuestionOnly one at a timemember0706029F18 Dec '12 - 21:55 
Hi Shivamkalra,
 
Can you enlighten me how to activate the button only once at a time? When the hand was over two buttons, I only want the top button to be execute, instead of two buttons.
 
Thanks in advance.
 
Sa
Question(Interaction with Computer using Webcam)memberalshabi12 Jun '12 - 6:01 
please helpe me Cry | :((
The aim of our project is to develop a real-time system capable of understanding commands given by Hand gestures. The user must be able to communicate with computer, all basic commands required by a human-computer interface.
Our system will provide following functions:
1. Mouse movement on screen according to the hand movement.
2. Gesture recognition to do mouse events Right click, left click, double clicks of mouse and key press which are up, down, left, right.
3. Sign Language Recognition for some numbers and Characters.
Another goal is that the user not only can communicate from a distance, but need have no physical contact with the computer. However standard desktop computers are now quick enough to make this project a viable proposition. This interface is simple enough to be run using an ordinary webcam and requires little training.
GeneralMy vote of 5membermarekbar2186 Dec '11 - 12:14 
That's great solution, I'm gonna for spend some time to implement your solution in my app - so simple idea...
GeneralSource of projectmembersaavedranet23 Mar '11 - 9:20 
Hi
 
you created a program that could control cursor by using a webcam and laser pen.
 
my question is...can I download source code?
 

please, can you help me. i will be very thankful to you...
Questionreading error & adding a new button??membermaanvandr26 Jan '11 - 12:32 
Hi,
 
Nice article, I've got a problem about motion reading in the source code. The reading show in the form is always zero, although the motion triggering is ok. How to get the reading. But in your executable file it is perfect. and I can't add new button give some Idea?
 
Thanks
QuestionMotion reading error??memberGeorge_micom14 Oct '10 - 23:51 
Hi,
 
Nice article, simple and good algorithm for motion detection.
I've got a problem about motion reading in the source code. The reading show in the form is always zero, although the motion triggering is ok. To get the reading, I need to break at the motionevent and break at the camera_FrameEvent. But in your executable file it is perfect. Do you have any ideas?
 
Thanks
GeneralHimemberangel_100359 Apr '10 - 5:19 
First I appreciate for your response
But I need to write code in C# , and I have not permission to use opencv or forghe , ...
I need code to combination in my total program
Frown | :(
Regards,
Angel
GeneralRe: HimemberShivamkalra9 Apr '10 - 9:23 
Well, opencv is an open source library, it has a C# variant named emgucv.When you download that library you will get source code with it, and you could always copy the code and modify it according to your need. If you are thinking of writing your own library, then it's gonna be very difficult.
GeneralHi Shivam kalramemberangel_100358 Apr '10 - 7:12 
Dear Shivam
 
I need a image processing application for detecting circle and triangle on a input image
 
i wish you can help me in this case .
 
sincerely yours ,
angel
GeneralRe: Hi Shivam kalramemberShivamkalra8 Apr '10 - 13:49 
You could use opencv, it has a in-build function for circle and line detection using hough tranform.
GeneralRe: Hi Shivam kalramemberKhaniya6 Oct '10 - 0:04 
hey
can you show me your image
 
thanks
Life's Like a mirror. Smile at it & it smiles back at you.- P Pilgrim
So Smile Please

Generalversion of windows media playermembersaavedranet11 Mar '10 - 5:33 
which version of windows media player needs to work???,because I do not work...
GeneralRe: version of windows media playermembershivam_kalra11 Mar '10 - 13:16 
It will work with any windows media player, actually it sends a "short key" like cntrl+p or cntrl+m to windows media player..just make sure WMP window is in focus and is opened not minimized...thats it!!
GeneralRe: version of windows media playermembersaavedranet12 Mar '10 - 8:55 
Thanks you... but I do not work... :(
GeneralRe: version of windows media playermemberAdrabi Abderrahim26 Sep '10 - 20:24 
try to change in file "WMP_Contol" window title & after try to fight webcam to detect you Big Grin | :-D .
GeneralHelp.. Regarding COLOR recognition.membershirishyc4 Mar '10 - 6:17 
Hi.. Nice Article,
I wnt 2 know how to recognition paricular Color pattern.
for eg. Only RED From WebCam. Plz Help Me Out
 
Thanx Smile | :)
GeneralRe: Help.. Regarding COLOR recognition.memberPaulo Zemek4 Mar '10 - 7:14 
This is easy.
If you look at the code, it generates a grayscale value using the GetAverage which, in turns, sums (R + G + B) and divides by three.
 
You can simple get Color.R instead of using the average.
But, note that doing so you will be "ignoring" other elements. So, White (255, 255 and 255) will be registered the same way as full red (255, 0, 0).
 
If you want the nearest to full red, you can use something like:
int redLevel = color.R - color.G - color.B;
 
In this case, (255, 0, 0) which is full red will result in 255.
(255, 255, 255), which is white, will return -255.
 
Yellow (255, 255, 0) will return zero. So, you will only be considering the colors that are really similar to red (instead of colors composed of red).
GeneralRe: Help.. Regarding COLOR recognition.membershirishyc4 Mar '10 - 7:17 
Thanx..
I will try n let u kwn.
GeneralMinor error... [modified]memberPaulo Zemek3 Mar '10 - 8:10 
When I looked at the code here, I thought you are creating a local variable:
 
  byte[,] function = new byte[width, height];
 
But seeing the real code, you are using the class variable (without the preceding byte[,].
 
Also, even not causing a bug you are not calling UnlockImage in ImageMatrix constructor. This will keep the bitmap pinned in memory (is bad for GC).
modified on Wednesday, March 3, 2010 2:30 PM

GeneralRe: Minor error...membershivam_kalra3 Mar '10 - 8:57 
umm, ya..this is not a local variable, it's a member variable of the class named "ImageMatrix", I made this mistake during writing this article..
GeneralRe: Minor error...membershivam_kalra3 Mar '10 - 20:22 
I got the modified code, I appreciate it..Thanks! Smile | :)
GeneralRe: Minor error...memberPaulo Zemek4 Mar '10 - 2:21 
I will be very happy if you could use my library in your next article.
GeneralWowmemberOption Greek3 Mar '10 - 6:51 
That's so cool and possibilities are endless (like may be asking user to dance for a tune instead of entering password Laugh | :laugh: )
GeneralRe: Wowmembershivam_kalra3 Mar '10 - 9:02 
Laugh | :laugh:

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 3 Mar 2010
Article Copyright 2010 by Shivamkalra
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid