用openvc 统制鼠标 来移动和打开文件
这一阵做了冷板凳。蛋有淡淡的忧伤。开始吓唬闹ing....................
需求:
有时候坐在离鼠标比较远的地方(比如推到沙发上)看网页,看电影要用鼠标去控制,还得蹭过去。写个用握拳挥动来控制鼠标移动,用掌来打开文件的程序。
打算到时候可以移到自家android电视上去。
困难:
之前也没有写过c 语言程序(还读书的时候考级用过),开始看opencv 更是雾水,还好 “凡是不决问狗狗”。顺便蛋伤下:狗狗提供的不只是口粮,还有思想。
下面是代码 ,另外,我想写一个基于图片中实物分类的程序,作用是可以从网上自动down 图片,然后按照要的分类 比如 鲜花 或者 狗狗 来自动保存和分类。 爬虫 存储 ,分类和展示 用 jsoup ,mongo gridfs, spring mvc 和 js 已完成。准备训练大量的不同事务的分级文件。有兴趣多交流。
下面是代码
大概步骤
1、抓视频,帧 处理
2、看有没有 手掌 (双击) 和拳头移动(鼠标移动),有的化就处理。
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
using namespace cv;
void mousemove(int fd, int x, int y);
void mousedoubleclick(int fd);
void fist(Mat frame);
void palm(Mat frame);
void *thread1(void *);
struct mypoint {
int x1;
int y1;
};
mypoint p;
int fd_mouse;
// 这两个链接分类的文件我是从 qq 手势 里扣出来的,正准备自己训练几个不同手势的文件
String palmfile = "data/mycascade/palm.dat";
String fistfile = "data/mycascade/fist.dat";
int xarray = 0;
int yarray = 0;
int movex = 0;
int movey = 0;
int palmcount = 0;
int fistcount = 0;
bool waitfist = false;
bool waitpalm = false;
bool isfirst = true;
pthread_t pid1;
float lv = 1;
CascadeClassifier palm_cascade;
CascadeClassifier fist_cascade;
//string window_name = "Capture - Face detection";
int objectDetectionxx(int argc, char** argv)
{
CvCapture* capture;
Mat frame;
if (!palm_cascade.load(palmfile)) {
printf("--(!)Error loading\n");
return -1;
};
if (!fist_cascade.load(fistfile)) {
printf("--(!)Error loading\n");
return -1;
};
//打开鼠标文件 不同机器可能不一样 我的
fd_mouse = open("/dev/input/event3", O_RDWR);
if (fd_mouse <= 0) {
printf("error open mouse/n please chmod +wr /dev/input/e*");
}
capture = cvCaptureFromCAM(-1);
Mat frame_gray;
if (capture) {
while (true) {
frame = cvQueryFrame(capture);
if (!frame.empty()) {
cvtColor(frame, frame_gray, CV_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
//再 双击有有各线程设置waitfist这个值, 这个线程主要是睡 防止双击频繁
if (!waitfist) {
palm(frame_gray);
}
if (!waitpalm) {
fist(frame_gray);
}
// imshow(window_name, frame_gray);
} else {
printf(" --(!) No captured frame -- Break!");
break;
}
waitKey(10);
// int c = waitKey(50);
// if ((char) c == 'c') {
// break;
// }
}
}
return 0;
}
//测试视频中是否有 手掌出现, 手掌一出现 鼠标停止移动,双击
void palm(Mat frame) {
std::vector<Rect> palmrect;
palm_cascade.detectMultiScale(frame, palmrect, 1.1, 2,
0 | CV_HAAR_SCALE_IMAGE, Size(70, 70));
if (palmrect.size() > 0) {
fistcount++;
if (fistcount == 3) {
if (pthread_create(&pid1, NULL, thread1, NULL) != 0) {
printf("create thread1 failed/n");
}
mousedoubleclick(fd_mouse);
}
} else {
fistcount = 0;
}
}
//检测是否有拳头出现 出想的坐标
void fist(Mat frame) {
std::vector<Rect> fistrect;
//-- Detect faces
fist_cascade.detectMultiScale(frame, fistrect, 1.1, 2,
0 | CV_HAAR_SCALE_IMAGE, Size(80, 80));
if (fistrect.size() > 0) {
palmcount = 0;
p.x1 = fistrect[0].x + fistrect[0].width * 0.5;
p.y1 = fistrect[0].y + fistrect[0].width * 0.5;
// Point center(fistrect[0].x + fistrect[0].width * 0.5,
// fistrect[0].y + fistrect[0].height * 0.5);
// ellipse(frame, center,
// Size(fistrect[0].width * 0.5, fistrect[0].height * 0.5), 0, 0,
// 360, Scalar(255, 0, 0), 2, 8, 0);
if ((xarray - p.x1) * (xarray - p.x1) > 25
&& (p.y1 - yarray) * (p.y1 - yarray) > 25) {
if (xarray != 0) {
mousemove(fd_mouse, lv * (xarray - p.x1), lv * (p.y1 - yarray));
cout << "palm:" << "movex:=" << lv * (xarray - p.x1) << "nx:="
<< p.x1 << "ox:=" << xarray << endl;
cout << "palm:" << "movey:=" << lv * (p.y1 - yarray) << "ny:="
<< p.y1 << "oy:=" << yarray << endl;
xarray = p.x1;
yarray = p.y1;
} else {
xarray = p.x1;
yarray = p.y1;
}
}
} else {
palmcount++;
if (palmcount > 5) {
palmcount = 0;
xarray = 0;
yarray = 0;
}
}
}
//鼠标移动
void mousemove(int fd, int x, int y) {
struct input_event event;
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_REL;
event.code = REL_X;
event.value = x;
write(fd, &event, sizeof(event));
event.type = EV_REL;
event.code = REL_Y;
event.value = y;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(event));
}
//鼠标左键双击
void mousedoubleclick(int fd) {
struct input_event event;
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = 1;
write(fd, &event, sizeof(event));
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = 0;
write(fd, &event, sizeof(event));
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = 1;
write(fd, &event, sizeof(event));
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = 0;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(event));
}
//当鼠标双击后会触发这个线程 ,这个线程的左右是 防止重复的双击
void *thread1(void *) {
cout << "fist:" << "waitfist begin! double click" << endl;
waitfist = true;
waitpalm = true;
usleep(100 * 1000);
waitpalm = false;
usleep(200 * 1000);
cout << "fist:waitfist end!" << endl;
waitfist = false;
}