Итак (для нетерпеливых видео результата в самом низу), идея сделать что-то вроде планшета для рисования из веб-камеры и старой мыши родилась (как у всех ненормальных) ночью:
lorimage:320x240
Идея заключалась в том, что бы написать программу (используя opencv как основу), отслеживающую веб-камерой объект опр. цвета, и переводящую его координаты, в координаты курсора мыши.
На утро, принялся создавать свое «инновационное» устройство. Раскурочил старую мышь, отпаял правую кнопку:
lorimage:320x240
Припаял кнопку к длинным проводам, и замотал ее на простую шариковую ручку, к концу пришкварил небольшую пластиковую крышку розового цвета, которую собственно и будет отслеживать программа:
lorimage:320x240
Устройство готово, дело оставалось за малым — написать программу:
// wsight
#include "iostream"
#include "time.h"
#include "string"
#include "X.h"
#include "Xlib.h"
#include "Xutil.h"
#include "opencv2/opencv.hpp"
using namespace std;
IplImage* imgTracking;
int lastX = -1;
int lastY = -1;
bool shows = false;
string intToString(int N) {
ostringstream ss("");
ss << N;
return ss.str();
}
string floatToString(float N) {
ostringstream ss("");
ss << N;
return ss.str();
}
IplImage* getThresholdedImage(IplImage* imgHSV) {
IplImage* imgThresh = cvCreateImage(cvGetSize(imgHSV), IPL_DEPTH_8U, 1);
cvInRangeS(imgHSV, cvScalar(130, 100, 100), cvScalar(179, 256, 256), imgThresh);
return imgThresh;
}
void trackObject(IplImage* imgThresh) {
CvMoments *moments = (CvMoments*) malloc(sizeof(CvMoments));
cvMoments(imgThresh, moments, 1);
double moment10 = cvGetSpatialMoment(moments, 1, 0);
double moment01 = cvGetSpatialMoment(moments, 0, 1);
double area = cvGetCentralMoment(moments, 0, 0);
if (area > /*250*/100) {
int posX = moment10 / area;
int posY = moment01 / area;
shows = true;
lastX = posX;
lastY = posY;
}
else {
shows = false;
}
free(moments);
}
void setCaptureMouse() {
CvCapture* capture = 0;
capture = cvCaptureFromCAM(0);
int w = 320;
int h = 240;
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, w);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, h);
IplImage* frame = 0;
frame = cvQueryFrame(capture);
imgTracking = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvZero(imgTracking);
cvNamedWindow("Video");
cvSetWindowProperty("Video", w, h);
cvResizeWindow("Video", w, h);
cvNamedWindow("Ball");
cvSetWindowProperty("Ball", w, h);
cvResizeWindow("Ball", w, h);
cout << "Works capture mouse\n";
Display *dpy;
Window root_window;
dpy = XOpenDisplay(0);
root_window = XRootWindow(dpy, 0);
XSelectInput(dpy, root_window, KeyReleaseMask);
while (true) {
frame = cvQueryFrame(capture);
frame = cvCloneImage(frame);
IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvCvtColor(frame, imgHSV, CV_BGR2HSV);
IplImage* imgThresh = getThresholdedImage(imgHSV);
cvFlip(imgThresh, imgThresh, 1);
cvFlip(frame, frame, 1);
trackObject(imgThresh);
cvAdd(frame, imgTracking, frame);
if (shows) {
cvLine(frame, cv::Point(lastX + 8, lastY),cv::Point(lastX + 20, lastY), cv::Scalar(0, 256, 0), 2,2);
cvLine(frame, cv::Point(lastX - 8, lastY),cv::Point(lastX - 20, lastY), cv::Scalar(0, 256, 0), 2,2);
cvLine(frame, cv::Point(lastX, lastY + 8),cv::Point(lastX, lastY + 20), cv::Scalar(0, 256, 0), 2,2);
cvLine(frame, cv::Point(lastX, lastY - 8),cv::Point(lastX, lastY - 20), cv::Scalar(0, 256, 0), 2,2);
cvLine(frame, cv::Point(lastX + 20, lastY),cv::Point(lastX + 80, lastY), cv::Scalar(256, 256, 256), 1,1);
cvLine(frame, cv::Point(lastX - 20, lastY),cv::Point(lastX - 80, lastY), cv::Scalar(256, 256, 256), 1,1);
cvLine(frame, cv::Point(lastX, lastY + 20),cv::Point(lastX, lastY + 80), cv::Scalar(256, 256, 256), 1,1);
cvLine(frame, cv::Point(lastX, lastY - 20),cv::Point(lastX, lastY - 80), cv::Scalar(256, 256, 256), 1,1);
XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, lastX*2.0f, lastY*2.0f);
XFlush(dpy);
}
else {
cvLine(frame, cv::Point(lastX + 8, lastY),cv::Point(lastX + 20, lastY), cv::Scalar(0, 0, 256), 2,2);
cvLine(frame, cv::Point(lastX - 8, lastY),cv::Point(lastX - 20, lastY), cv::Scalar(0, 0, 256), 2,2);
cvLine(frame, cv::Point(lastX, lastY + 8),cv::Point(lastX, lastY + 20), cv::Scalar(0, 0, 256), 2,2);
cvLine(frame, cv::Point(lastX, lastY - 8),cv::Point(lastX, lastY - 20), cv::Scalar(0, 0, 256), 2,2);
cvLine(frame, cv::Point(lastX + 20, lastY),cv::Point(lastX + 80, lastY), cv::Scalar(256, 256, 256), 1,1);
cvLine(frame, cv::Point(lastX - 20, lastY),cv::Point(lastX - 80, lastY), cv::Scalar(256, 256, 256), 1,1);
cvLine(frame, cv::Point(lastX, lastY + 20),cv::Point(lastX, lastY + 80), cv::Scalar(256, 256, 256), 1,1);
cvLine(frame, cv::Point(lastX, lastY - 20),cv::Point(lastX, lastY - 80), cv::Scalar(256, 256, 256), 1,1);
}
cvShowImage("Video", frame);
cvShowImage("Ball", imgThresh);
cvReleaseImage(&imgHSV);
cvReleaseImage(&imgThresh);
cvReleaseImage(&frame);
int c = cvWaitKey(10);
if ((char) c == 27) break;
}
cvDestroyAllWindows();
cvReleaseImage(&imgTracking);
cvReleaseCapture(&capture);
}
int main (void) {
setCaptureMouse();
return 0;
}
В результате получилось довольно забавно:
Видео процесса рисования «инновационным» устройством :D
lorimage:320x240