Điều khiển máy tính từ xa bằng ... tay không.

Hầu hết ai mà chẳng điều khiển máy tính bằng tay, tay cầm chuột, tay gõ phím, nhưng trong bài viết này sẽ giới thiệu cách điều khiển máy tính bằng tay nhưng không động đến chuột hay bàn phím. Đối với nhiều người thì điều này có lẽ cũng còn khá xa vời, trong tưởng tượng hay trong các bộ phim, 1 viễn cảnh của công nghệ tương lai hay mới chỉ xuất hiện trong các phòng thí nghiệm hay trong 1 số ít sản phẩm công nghệ hiện đại chưa đại chúng. Trong bài này tôi sẽ cho các bạn thấy điều này không phải là cái gì đó trong tưởng tượng hay trong phim ảnh mà bất kỳ ai cũng có thể tự thực hiện được.

Các công cụ cần thiết :
- Máy tính có Webcam.
- Microsoft Visual Studio (phiên bản 2008 chẳng hạn) :
Mã:
http://diendan.goonline.vn/showthread.php/528224-Visual-Studio-2008-Team-Suite-Full
- Thư viện về Computer Vision của Intel, ở đây dùng phiên bản OpenCV_1.1pre1a :
Mã:
http://www.mediafire.com/?bxw22fxzvy70q1m
- Bộ CSLD training do tôi đã chuẩn bị sẵn (nếu bạn nào quan tâm đến training và mở rộng khả năng học hỏi của máy tính có thể đặt câu hỏi tại đây) :
Mã:
http://www.mediafire.com/?skds3nbugbn3f
Chú ý : Để thuận tiện các bạn cài OpenCV vào ngay ổ C:

Tiến hành :

Mở Visual Studio và tạo 1 project Visual C++, Win32 Console Application mới. Đặt tên là diendan.go.vn_Control_Computer :

4db93ca1_56758242_1.png

Chọn như các hình sau :

4db93ca1_20f81961_2.png

4db93ca1_7579aa98_3.png


Sau khi tạo project, click chuột phải vào tên project và chọn Properties :

4db93ca2_5a7e3378_4.png

Chọn mục C/C++ và paste dòng sau vào khung Additional Include Directories :
Mã:
"C:\OpenCV\lib\cv.lib" "C:\OpenCV\lib\cxcore.lib" "C:\OpenCV\lib\highgui.lib"
4db93ca2_5b6ccc40_5.png

Trong mục Linker --> Input --> Additional Dependencies chọn như sau :

4db93ca2_1486e98d_6.png

Paste vào các dòng sau :
Mã:
"C:\OpenCV\lib\cv.lib"
"C:\OpenCV\lib\cxcore.lib"
"C:\OpenCV\lib\highgui.lib"
4db93ca2_383828af_7.png

Nhấn OK :

4db93ca3_31bf43ef_8.png

Click chuột phải vào Source Files --> Add --> New Item... :

4db93ca3_5abe2b0d_9.png

Chọn C++ File (.cpp), nhập vào tên main và nhấn Add :

4db93ca3_4df7cc17_10.png

Tiếp theo nháy đúp chuột vào main.cpp và paste toàn bộ đoạn code sau vào :
[spoil]
Mã:
#include "cv.h"
#include "highgui.h"
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
 
#ifdef _EiC
#define WIN32
#endif
 
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade1 = 0;
static CvHaarClassifierCascade* cascade2 = 0;
static CvHaarClassifierCascade* cascade3 = 0;
static CvHaarClassifierCascade* cascade4 = 0;
int use_nested_cascade = 0;
 
void detect_and_draw( IplImage* image);
 
const char* cascade1_name ="Next.xml";
const char* cascade2_name ="Previous.xml";
const char* cascade3_name ="Stop.xml";
const char* cascade4_name ="Play.xml";
 
double scale = 1;
 
int main( )
{
    CvCapture* capture = 0;
    IplImage *frame, *frame_copy = 0;
    IplImage *image = 0;
    const char* scale_opt = "--scale=";
    int scale_opt_len = (int)strlen(scale_opt);
    const char* cascade_opt = "--cascade=";
    int cascade_opt_len = (int)strlen(cascade_opt);
    const char* nested_cascade_opt = "--nested-cascade";
    int nested_cascade_opt_len = (int)strlen(nested_cascade_opt);
 
 
    cascade1 = (CvHaarClassifierCascade*)cvLoad( cascade1_name, 0, 0, 0 );
    cascade2 = (CvHaarClassifierCascade*)cvLoad( cascade2_name, 0, 0, 0 );
    cascade3 = (CvHaarClassifierCascade*)cvLoad( cascade3_name, 0, 0, 0 );
    cascade4 = (CvHaarClassifierCascade*)cvLoad( cascade4_name, 0, 0, 0 );
 
    storage = cvCreateMemStorage(0);
    capture = cvCaptureFromCAM(0);
    cvNamedWindow( "BACHKIM01", 1 );
    if( capture )
    {
        for(;;)
        {
            if( !cvGrabFrame( capture ))
                break;
            frame = cvRetrieveFrame( capture );
            if( !frame )
                break;
            if( !frame_copy )
                frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
                                            IPL_DEPTH_8U, frame->nChannels );
            if( frame->origin == IPL_ORIGIN_TL )
                cvCopy( frame, frame_copy, 0 );
            else
                cvFlip( frame, frame_copy, 0 );
 
            cvShowImage( "BACHKIM01", frame_copy );
 
            detect_and_draw( frame_copy );
 
            if( cvWaitKey( 10 ) >= 0 )
                goto _cleanup_;
        }
 
        cvWaitKey(0);
_cleanup_:
        cvReleaseImage( &frame_copy );
        cvReleaseCapture( &capture );
    }
 
    cvDestroyWindow("BACHKIM01");
 
    return 0;
}
void detect_and_draw( IplImage* img )
{
    static CvScalar colors[] = 
    {
        {{0,0,255}},
        {{0,128,255}},
        {{0,255,255}},
        {{0,255,0}},
        {{255,128,0}},
        {{255,255,0}},
        {{255,0,0}},
        {{255,0,255}}
    };
 
    IplImage *gray, *small_img;
 
    gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
    small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
                         cvRound (img->height/scale)), 8, 1 );
 
    cvCvtColor( img, gray, CV_BGR2GRAY );
    cvResize( gray, small_img, CV_INTER_LINEAR );
    cvEqualizeHist( small_img, small_img );
    c***earMemStorage( storage );
    double t = (double)cvGetTickCount();
    CvSeq* faces=0;
 
 
    int ind=0;
    if( cascade1 )
    {
        faces = cvHaarDetectObjects( small_img, cascade1, storage,
            1.2, 3, 0
            //|CV_HAAR_FIND_BIGGEST_OBJECT
            //|CV_HAAR_DO_ROUGH_SEARCH
            |CV_HAAR_DO_CANNY_PRUNING
            //|CV_HAAR_SCALE_IMAGE
            ,
            cvSize(90, 90) );
 
        if(faces->total>0)
        {
            printf( "Next\n");
            ind=1;
        }
        if(faces->total==0)
        {
 
            faces = cvHaarDetectObjects( small_img, cascade2, storage,
                1.2, 3, 0
                //|CV_HAAR_FIND_BIGGEST_OBJECT
                //|CV_HAAR_DO_ROUGH_SEARCH
                |CV_HAAR_DO_CANNY_PRUNING
                //|CV_HAAR_SCALE_IMAGE
                ,
                cvSize(90, 90));
            {
                printf( "Previous\n");
                ind=2;
            }
        }
 
        if(faces->total==0)
        {
            faces = cvHaarDetectObjects( small_img, cascade3, storage,
                1.2, 3, 0
                //|CV_HAAR_FIND_BIGGEST_OBJECT
                //|CV_HAAR_DO_ROUGH_SEARCH
                |CV_HAAR_DO_CANNY_PRUNING
                //|CV_HAAR_SCALE_IMAGE
                ,
                cvSize(90, 90) );
            if(faces->total>0)
            {
                printf( "Stop\n");
                ind=3;
            }
        }
        if(faces->total==0)
        {
            faces = cvHaarDetectObjects( small_img, cascade4, storage,
                1.2, 3, 0
                //|CV_HAAR_FIND_BIGGEST_OBJECT
                //|CV_HAAR_DO_ROUGH_SEARCH
                |CV_HAAR_DO_CANNY_PRUNING
                //|CV_HAAR_SCALE_IMAGE
                ,
                cvSize(90, 90) );
            if(faces->total>0)
            {
                printf( "Play\n");
                ind=4;
            }
        }
    }        
    t = (double)cvGetTickCount() - t;
    printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
    for( int i = 0; i < (faces ? faces->total : 0); i++ )
    {
        CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
        CvMat small_img_roi;
        CvSeq* nested_objects;
        CvPoint pt1,pt2;
        CvScalar color = colors[i%8];
        int radius;
        pt1.x=cvRound(r->x * scale);
        pt1.y=cvRound(r->y * scale);
        pt2.x=cvRound((r->x + r->width) * scale);
        pt2.y=cvRound((r->y + r->height) * scale);
        cvRectangle(img, pt1,pt2,CV_RGB(255, 0, 0), 3, 8, 0);
        CvFont font;
        cvInitFont(&font,CV_FONT_HERSHEY_PLAIN, 2.0,2.0, 0,2, CV_AA);
        switch(ind)
            {
        case 1: {cvPutText(img, "Right!", cvPoint(pt1.x +40,pt1.y+40), &font, CV_RGB(255,0,0));
                    keybd_event(0x27, 0, 0, 0); //gửi thông điệp phím right arrow bar được nhấn đến hđh
                    Sleep(1500);
                }
                    break;
 
        case 2: {cvPutText(img, "Left!", cvPoint(pt1.x+40,pt1.y+40), &font, CV_RGB(255,0,0));
                    keybd_event (0x25, 0, 0, 0); //gửi thông điệp phím left arrow bar được nhấn đến hđh
                    Sleep(1500);
                }
                    break;
 
        case 3: {cvPutText(img, "Stop!", cvPoint(pt1.x+40,pt1.y+40), &font, CV_RGB(255,0,0));
                    //Thêm bất kỳ thông điệp bàn phím nào vào đây
                    //Sleep(1500);
                }
                    break;
        case 4: {cvPutText(img, "Up!", cvPoint(pt1.x+40,pt1.y+40), &font, CV_RGB(255,0,0));
                    //Thêm bất kỳ thông điệp bàn phím nào vào đây
                    //Sleep(1500);
                }
                    break;
 
            }
        printf("%d - %d\n",r->width,r->height);
    }
    cvShowImage( "BACHKIM01", img );
    cvReleaseImage( &gray );
    cvReleaseImage( &small_img );
}
[/spoil]
Đến đây là đã xong rồi, giờ copy bộ CSLD training vào thư mục chứa project :
4db942bf_5f40636d_0.png
Nhấn F5 để chạy chương trình. Thử mở 1 file ppt bất kỳ rồi chạy slide show và điều khiển nó bằng tay xem, sẽ thật thú vị nếu buổi thuyết trình của bạn không hề động đến máy tính phải không.
Vài hình ảnh :

4db941ef_65f199fa_left.png

4db941f0_7833bdd8_right.png

4db941f0_7c8b83eb_stop.png

4db941f0_64bc0003_up.png

4db941f0_6899241d_ppt%20control.png

Điều khiển slide bằng tay

Bảng mã bàn phím :


VK_NUMPAD7 |0x67| VK_BACK |0x08
VK_NUMPAD8 |0x68| VK_TAB |0x09
VK_NUMPAD9 |0x69| VK_RETURN |0x0D
VK_MULTIPLY |0x6A| VK_SHIFT |0x10
VK_ADD |0x6B| VK_CONTROL |0x11
VK_SEPARATOR |0x6C| VK_MENU |0x12
VK_SUBTRACT |0x6D| VK_PAUSE |0x13
VK_DECIMAL |0x6E| VK_CAPITAL |0x14
VK_DIVIDE |0x6F| VK_ESCAPE |0x1B
VK_F1 |0x70| VK_SPACE |0x20
VK_F2 |0x71| VK_END |0x23
VK_F3 |0x72| VK_HOME |0x24
VK_F4 |0x73| VK_LEFT |0x25
VK_F5 |0x74| VK_UP |0x26
VK_F6 |0x75| VK_RIGHT |0x27
VK_F7 |0x76| VK_DOWN |0x28
VK_F8 |0x77| VK_PRINT |0x2A
VK_F9 |0x78| VK_SNAPSHOT |0x2C
VK_F10 |0x79| VK_INSERT |0x2D
VK_F11 |0x7A| VK_DELETE |0x2E
VK_F12 |0x7B| VK_LWIN |0x5B
VK_NUMLOCK |0x90| VK_RWIN |0x5C
VK_SCROLL |0x91| VK_NUMPAD0 |0x60
VK_LSHIFT |0xA0| VK_NUMPAD1 |0x61
VK_RSHIFT |0xA1| VK_NUMPAD2 |0x62
VK_LCONTROL |0xA2| VK_NUMPAD3 |0x63
VK_RCONTROL |0xA3| VK_NUMPAD4 |0x64
VK_LMENU |0xA4| VK_NUMPAD5 |0x65
VK_RMENU |0xA5| VK_NUMPAD6 |0x66
 
Ðề: Điều khiển máy tính từ xa bằng ... tay không.

hay nhỉ......... phát minh mới đây
 
Ðề: Điều khiển máy tính từ xa bằng ... tay không.

Bạn cho mình nick yahoo hay email để mình hỏi bạn một chút về việc huấn luyện file XML nha!
 
Ðề: Điều khiển máy tính từ xa bằng ... tay không.

xài sao nhỉ :D
chẳng hiểu gì cả :(
 

trandacthang

陳 得 勝
Ðề: Điều khiển máy tính từ xa bằng ... tay không.

xài sao nhỉ :D
chẳng hiểu gì cả :(
Nguyên lý hoạt động của phương pháp điều khiển này là: phần mềm kia nó sẽ thu hình các cử chỉ của bạn thông qua webcam rồi so sánh, đối chiếu hình ảnh đó với các hình ảnh của chính bạn đã được lưu trong cơ sở dữ liệu từ trước. Nếu thấy trùng khớp (một cách tương đối) thì nó sẽ thực hiện các lệnh tương ứng đã được gán cho cho các tấm ảnh từ trước.
 
Ðề: Điều khiển máy tính từ xa bằng ... tay không.

cái này mà la xa vời à? có bị gì không thế? CHừng nào màn hình trên không ấy lúc đó hả nói là xa vời nhưng mà cũng thanks nhiều
 
Ðề: Điều khiển máy tính từ xa bằng ... tay không.

Hay quá...Like kaka...Thanks!
 
Top