Esempio n. 1
0
static DWORD WINAPI ThreadFunc( LPVOID obj )
#endif
{
	TuioServer *tuioServer = static_cast<TuioServer*>(obj);
	while ((tuioServer->isConnected()) && (tuioServer->periodicMessagesEnabled())) {
		tuioServer->sendFullMessages();
#ifndef WIN32
        //usleep(USEC_SECOND*tuioServer->getUpdateInterval());
#else
		Sleep(MSEC_SECOND*tuioServer->getUpdateInterval());
#endif
	}	
	return 0;
};
Esempio n. 2
0
int main(int argc, char* argv[])
{
/*	if (( argc != 1) && ( argc != 3)) {
        	std::cout << "usage: SimpleSimulator [host] [port]\n";
        	return 0;
	}*/

#ifndef __MACOSX__
	glutInit(&argc,argv);
#endif

	TuioServer *server;
	if( argc == 3 ) {
		server = new TuioServer(argv[1],atoi(argv[2]));
	} else server = new TuioServer(); // default is UDP port 3333 on localhost
		
	// add an additional TUIO/TCP sender
	OscSender *tcp_sender;
	if( argc == 2 ) {
		tcp_sender = new TcpSender(atoi(argv[1]));
	} else tcp_sender = new TcpSender(3333);
	server->addOscSender(tcp_sender);
	
#ifndef WIN32
	// add an additional TUIO/DEV sender
	OscSender *dev_sender = new DevSender();
	server->addOscSender(dev_sender);
#endif

#ifndef LINUX
	// add an additional TUIO/FLC sender
	OscSender *flash_sender = new FlashSender();
	server->addOscSender(flash_sender);
#endif

	SimpleSimulator *app = new SimpleSimulator(server);
	app->run();
	
	delete app;
	delete server;
#ifndef LINUX
	delete flash_sender;
#endif
#ifndef WIN32
	delete dev_sender;
#endif
	delete tcp_sender;
	return 0;
}
Esempio n. 3
0
int main(int argc, char* argv[])
{
/*	if (( argc != 1) && ( argc != 3)) {
        	std::cout << "usage: SimpleSimulator [host] [port]\n";
        	return 0;
	}*/

#ifndef __MACOSX__
	glutInit(&argc,argv);
#else
    if ((argc>1) && ((std::string(argv[1]).find("-NSDocumentRevisionsDebugMode")==0 ) || (std::string(argv[1]).find("-psn_")==0))) argc = 1;
#endif

	TuioServer *server;
	if( argc == 3 ) {
		server = new TuioServer(argv[1],atoi(argv[2]));
	} else server = new TuioServer(); // default is UDP port 3333 on localhost

	// add an additional TUIO/TCP sender
	OscSender *tcp_sender;
	if( argc == 2 ) {
		tcp_sender = new TcpSender(atoi(argv[1]));
	} else if ( argc == 3 ) {
		tcp_sender = new TcpSender(argv[1],atoi(argv[2]));
	} else tcp_sender = new TcpSender(3333);
	server->addOscSender(tcp_sender);

	
	// add an additional TUIO/WS sender
	OscSender *ws_sender = new WebSockSender(8080);
	server->addOscSender(ws_sender);
	
	// add an additional TUIO/FLC sender
	OscSender *flash_sender = new FlashSender();
	server->addOscSender(flash_sender);

	SimpleSimulator *app = new SimpleSimulator(server);
	app->run();

	delete app;
	delete server;
#ifndef LINUX
	delete flash_sender;
#endif
	delete tcp_sender;
	delete ws_sender;
	return 0;
}
Esempio n. 4
0
void main() {
	using namespace std;
	using namespace cv;
	using namespace TUIO;

	cv::Mat depthFrameRaw(480, 640, CV_16UC1);
	cv::Mat x(480, 640, CV_32FC1);
	cv::Mat y(480, 640, CV_32FC1);
	cv::Mat z(480, 640, CV_32FC1);

	Mat1f debugFrame(480, 640);

	CLNUICamera cam = CreateNUICamera();

	const float rMin = 25;

	stringstream buffer;

	unsigned short* depthFrameRawData = (unsigned short*) depthFrameRaw.data;
	int key;

	bool tuio3dMode = false;
	TuioServer* tuio = new TuioServer(tuio3dMode);
	TuioTime time;

	bool debug = true;

	float zMin = 0.0f;
	float zMax = 0.75f;

	if ( StartNUICamera(cam) ) {
		cout << "cam started" << endl;
		while ( (key = cvWaitKey(1)) != 27) {
			if ( GetNUICameraDepthFrameRAW(cam, (PUSHORT)depthFrameRaw.data) ) {
				unproject(depthFrameRawData, (float*)x.data, (float*)y.data, (float*)z.data);
				debugFrame = z * 0.1; 

				if (key == 32) {
					debug = !debug;
				}

				std::vector<cv::Point2i> fingerTips;

				if (debug) {					
					fingerTips = detectFingertips(z, 0, 0.75, debugFrame);
				} else {
					// find fingertips
					fingerTips = detectFingertips(z);

					// draw fingetips
					for(vector<Point2i>::iterator it = fingerTips.begin(); it != fingerTips.end(); it++) {
						circle(debugFrame, (*it), 10, Scalar(1.0f), -1);
					}					
				}

				// send fingertip positions via TUIO
				time = TuioTime::getSessionTime();
				tuio->initFrame(time);
				for(vector<Point2i>::iterator it = fingerTips.begin(); it != fingerTips.end(); it++) {
					// pixel coordinates
					int u = (int)(*it).x;
					int v = (int)(*it).y;

					float pX = 1.0f - u / 640.0f;
					float pY = v / 480.0f;
					float pZ = (z.at<float>(v,u) - zMin) / (zMax - zMin);

					TUIO::TuioCursor* cursor = tuio->getClosestTuioCursor(pX,pY,pZ);
					if (cursor == NULL || cursor->getDistance(pX,pY,pZ) > 0.05) {
						tuio->addTuioCursor(pX,pY,pZ);						
					} else if(cursor->getTuioTime() != time) {
						tuio->updateTuioCursor(cursor, pX, pY, pZ);
					}
				}				
				tuio->stopUntouchedMovingCursors();				
				tuio->removeUntouchedStoppedCursors();
				tuio->commitFrame();

				cout << tuio->getTuioCursors().size() << endl;
				
				// draw our debugframe
				imshow("debugFrame", debugFrame);
			}
		}
	} else {
		cout << "could not start cam" << endl;
	}

	StopNUICamera(cam);
}
Esempio n. 5
0
int main(int argc, char* argv[]) {
	
	application_settings config;
	sprintf(config.file,"none");
	
	const char *app_name = "reacTIVision";
	const char *version_no = "1.6";
	
	bool headless = false;
	
	std::cout << app_name << " " << version_no << " (" << __DATE__ << ")" << std::endl << std::endl;
	
	if (argc>1) {
		if (strcmp( argv[1], "-h" ) == 0 ) {
			printUsage(app_name);
			return 0;
		} else if( strcmp( argv[1], "-c" ) == 0 ) {
			if (argc==3) sprintf(config.file,"%s",argv[2]);
			else {
				printUsage(app_name);
				return 0;
			}
		} else if( strcmp( argv[1], "-n" ) == 0 ) {
			headless = true;
		} else if( strcmp( argv[1], "-l" ) == 0 ) {
			CameraTool::listDevices();
			return 0;
		} else if ( (std::string(argv[1]).find("-NSDocumentRevisionsDebugMode")==0 ) || (std::string(argv[1]).find("-psn_")==0) ){
			// ignore mac specific arguments
		} else {
			printUsage(app_name);
		}
	}
	
#ifndef WIN32
	signal(SIGINT,terminate);
	signal(SIGHUP,terminate);
	signal(SIGQUIT,terminate);
	signal(SIGTERM,terminate);
#endif
	
	readSettings(&config);
	config.headless = headless;
	
	engine = new VisionEngine(app_name,&config);
	
	if (!headless) {
		UserInterface *uiface = new SDLinterface(app_name,config.fullscreen);
		switch (config.display_mode) {
			case 0: uiface->setDisplayMode(NO_DISPLAY); break;
			case 1: uiface->setDisplayMode(SOURCE_DISPLAY); break;
			case 2: uiface->setDisplayMode(DEST_DISPLAY); break;
		}
		engine->setInterface(uiface);
	}
	
	TuioServer *server = NULL;
	FrameProcessor *fiducialfinder	= NULL;
	FrameProcessor *thresholder	= NULL;
	FrameProcessor *calibrator	= NULL;
	
	for (int i=0;i<config.tuio_count;i++) {
		OscSender *sender = NULL;
		try { switch (config.tuio_type[i]) {
			case TUIO_UDP: sender = new UdpSender(config.tuio_host[i].c_str(),config.tuio_port[i]); break;
			case TUIO_TCP_CLIENT: sender = new TcpSender(config.tuio_host[i].c_str(),config.tuio_port[i]); break;
			case TUIO_TCP_HOST: sender = new TcpSender(config.tuio_port[i]); break;
			case TUIO_WEB: sender = new WebSockSender(config.tuio_port[i]); break;
			case TUIO_FLASH: sender = new FlashSender(); break;
			default: continue;
		} } catch (std::exception e) {}
		
		if (sender) {
			if(i==0) server = new TuioServer(sender);
			else server->addOscSender(sender);
			pv_sleep(1);
		}
	}
	server->setSourceName("rtv");
	server->setInversion(config.invert_x, config.invert_y, config.invert_a);
	
	thresholder = new FrameThresholder(config.gradient_gate, config.tile_size, config.thread_count);
	if (config.background) thresholder->toggleFlag(KEY_SPACE,false);
	engine->addFrameProcessor(thresholder);
	
	fiducialfinder = new FidtrackFinder(server, &config);
	engine->addFrameProcessor(fiducialfinder);
	
	calibrator = new CalibrationEngine(config.grid_config);
	engine->addFrameProcessor(calibrator);
	
	engine->start();
	
	engine->removeFrameProcessor(calibrator);
	delete calibrator;
	
	config.finger_size = ((FidtrackFinder*)fiducialfinder)->getFingerSize();
	config.finger_sensitivity = ((FidtrackFinder*)fiducialfinder)->getFingerSensitivity();
	config.max_blob_size = ((FidtrackFinder*)fiducialfinder)->getBlobSize();
	config.object_blobs = ((FidtrackFinder*)fiducialfinder)->getFiducialBlob();
	config.cursor_blobs = ((FidtrackFinder*)fiducialfinder)->getFingerBlob();
	config.yamaarashi = ((FidtrackFinder*)fiducialfinder)->getYamaarashi();

	engine->removeFrameProcessor(fiducialfinder);
	delete fiducialfinder;
	
	config.gradient_gate = ((FrameThresholder*)thresholder)->getGradientGate();
	config.tile_size = ((FrameThresholder*)thresholder)->getTileSize();
	config.background = ((FrameThresholder*)thresholder)->getEqualizerState();
	engine->removeFrameProcessor(thresholder);
	delete thresholder;
	
	config.invert_x = server->getInvertXpos();
	config.invert_y = server->getInvertYpos();
	config.invert_a = server->getInvertAngle();
	
	delete engine;
	delete server;
	
	writeSettings(&config);
	return 0;
}
Esempio n. 6
0
int main() {

	const unsigned int nBackgroundTrain = 30;
	const unsigned short touchDepthMin = 10;
	const unsigned short touchDepthMax = 20;
	const unsigned int touchMinArea = 50;

	const bool localClientMode = true; 					// connect to a local client

	const double debugFrameMaxDepth = 4000; // maximal distance (in millimeters) for 8 bit debug depth frame quantization
	const char* windowName = "Debug";
	const Scalar debugColor0(0,0,128);
	const Scalar debugColor1(255,0,0);
	const Scalar debugColor2(255,255,255);

	int xMin = 110;
	int xMax = 560;
	int yMin = 120;
	int yMax = 320;

	Mat1s depth(480, 640); // 16 bit depth (in millimeters)
	Mat1b depth8(480, 640); // 8 bit depth
	Mat3b rgb(480, 640); // 8 bit depth

	Mat3b debug(480, 640); // debug visualization

	Mat1s foreground(640, 480);
	Mat1b foreground8(640, 480);

	Mat1b touch(640, 480); // touch mask

	Mat1s background(480, 640);
	vector<Mat1s> buffer(nBackgroundTrain);

	CHECK_RC(initOpenNI("niConfig.xml"), "initOpenNI");

	// TUIO server object
	TuioServer* tuio;
	if (localClientMode) {
		tuio = new TuioServer();
	} else {
		tuio = new TuioServer("192.168.0.1",3333,false);
	}
	TuioTime time;

	// create some sliders
	namedWindow(windowName);
	createTrackbar("xMin", windowName, &xMin, 640);
	createTrackbar("xMax", windowName, &xMax, 640);
	createTrackbar("yMin", windowName, &yMin, 480);
	createTrackbar("yMax", windowName, &yMax, 480);

	// create background model (average depth)
	for (unsigned int i=0; i<nBackgroundTrain; i++) {
		CHECK_RC(xnContext.WaitAndUpdateAll(), "xnContext.WaitAndUpdateAll()");
		depth.data = (uchar*) xnDepthGenerator.GetDepthMap();
		buffer[i] = depth;
	}
	average(buffer, background);

	while ( waitKey(1) != 27 ) {
		// read available data
		xnContext.WaitAndUpdateAll();

		// update 16 bit depth matrix
		depth.data = (uchar*) xnDepthGenerator.GetDepthMap();
		//xnImgeGenertor.GetGrayscale8ImageMap()



		// update rgb image
		//rgb.data = (uchar*) xnImgeGenertor.GetRGB24ImageMap(); // segmentation fault here
		//cvtColor(rgb, rgb, CV_RGB2BGR);

		// extract foreground by simple subtraction of very basic background model
		foreground = background - depth;

		// find touch mask by thresholding (points that are close to background = touch points)
		touch = (foreground > touchDepthMin) & (foreground < touchDepthMax);

		// extract ROI
		Rect roi(xMin, yMin, xMax - xMin, yMax - yMin);
		Mat touchRoi = touch(roi);

		// find touch points
		vector< vector<Point2i> > contours;
		vector<Point2f> touchPoints;
		findContours(touchRoi, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, Point2i(xMin, yMin));
		for (unsigned int i=0; i<contours.size(); i++) {
			Mat contourMat(contours[i]);
			// find touch points by area thresholding
			if ( contourArea(contourMat) > touchMinArea ) {
				Scalar center = mean(contourMat);
				Point2i touchPoint(center[0], center[1]);
				touchPoints.push_back(touchPoint);
			}
		}

		// send TUIO cursors
		time = TuioTime::getSessionTime();
		tuio->initFrame(time);

		for (unsigned int i=0; i<touchPoints.size(); i++) { // touch points
			float cursorX = (touchPoints[i].x - xMin) / (xMax - xMin);
			float cursorY = 1 - (touchPoints[i].y - yMin)/(yMax - yMin);
			TuioCursor* cursor = tuio->getClosestTuioCursor(cursorX,cursorY);
			// TODO improve tracking (don't move cursors away, that might be closer to another touch point)
			if (cursor == NULL || cursor->getTuioTime() == time) {
				tuio->addTuioCursor(cursorX,cursorY);
			} else {
				tuio->updateTuioCursor(cursor, cursorX, cursorY);
			}
		}

		tuio->stopUntouchedMovingCursors();
		tuio->removeUntouchedStoppedCursors();
		tuio->commitFrame();

		// draw debug frame
		depth.convertTo(depth8, CV_8U, 255 / debugFrameMaxDepth); // render depth to debug frame
		cvtColor(depth8, debug, CV_GRAY2BGR);
		debug.setTo(debugColor0, touch);  // touch mask
		rectangle(debug, roi, debugColor1, 2); // surface boundaries
		for (unsigned int i=0; i<touchPoints.size(); i++) { // touch points
			circle(debug, touchPoints[i], 5, debugColor2, CV_FILLED);
		}

		// render debug frame (with sliders)
		imshow(windowName, debug);
		//imshow("image", rgb);
	}

	return 0;
}
Esempio n. 7
0
int main() {

    const unsigned int nBackgroundTrain = 30;
    const unsigned short touchDepthMin = 10;
    const unsigned short touchDepthMax = 20;
    const unsigned int touchMinArea = 50;

    const bool localClientMode = true; // connect to a local client

    const double debugFrameMaxDepth = 4000; // maximal distance (in millimeters) for 8 bit debug depth frame quantization
    const char* windowName = "Debug";
    const char* colorWindowName = "image";
    const Scalar debugColor0(0, 0, 128);
    const Scalar debugColor1(255, 0, 0);
    const Scalar debugColor2(255, 255, 255);
    const Scalar debugColor3(0, 255, 255);
    const Scalar debugColor4(255, 0, 255);

    int xMin = 50;
    int xMax = 550;
    int yMin = 50;
    int yMax = 300;

    Mat1s depth(480, 640); // 16 bit depth (in millimeters)
    Mat1b depth8(480, 640); // 8 bit depth
    Mat3b rgb(480, 640); // 8 bit depth

    Mat3b debug(480, 640); // debug visualization

    Mat1s foreground(640, 480);
    Mat1b foreground8(640, 480);

    Mat1b touch(640, 480); // touch mask

    Mat1s background(480, 640);
    vector<Mat1s> buffer(nBackgroundTrain);

    IplImage * image = cvCreateImage(cvSize(640, 480), 8, 3);
    IplImage * convertedImage = cvCreateImage(cvSize(640, 480), 8, 3);

    initOpenNI("niConfig.xml");

    // TUIO server object
    TuioServer* tuio;
    if (localClientMode) {
        tuio = new TuioServer();
    } else {
        tuio = new TuioServer("192.168.0.2", 3333, false);
    }
    TuioTime time;

    namedWindow(colorWindowName);
    createTrackbar("xMin", colorWindowName, &xMin, 640);
    createTrackbar("xMax", colorWindowName, &xMax, 640);
    createTrackbar("yMin", colorWindowName, &yMin, 480);
    createTrackbar("yMax", colorWindowName, &yMax, 480);
    // create some sliders
    namedWindow(windowName);
    createTrackbar("xMin", windowName, &xMin, 640);
    createTrackbar("xMax", windowName, &xMax, 640);
    createTrackbar("yMin", windowName, &yMin, 480);
    createTrackbar("yMax", windowName, &yMax, 480);

    Keyboard * piano = new Keyboard();
    (*piano).initKeyMap();

    system("qjackctl &");
    sleep(4);
    JackByTheNotes * notesJack = new JackByTheNotes();
    notesJack->connect();
    sleep(2);
    system("sudo jack_connect Piano:Rubinstein system:playback_1 &");

    map<double, timeval> keys;

    // create background model (average depth)
    for (unsigned int i = 0; i < nBackgroundTrain; i++) {
        xnContext.WaitAndUpdateAll();
        depth.data = (uchar*) xnDepthGenerator.GetDepthMap();
        buffer[i] = depth;
    }
    average(buffer, background);

    while (waitKey(1) != 27) {
        // read available data
        xnContext.WaitAndUpdateAll();

        // update 16 bit depth matrix
        depth.data = (uchar*) xnDepthGenerator.GetDepthMap();
        //xnImgeGenertor.GetGrayscale8ImageMap()

        XnRGB24Pixel* xnRgb =
            const_cast<XnRGB24Pixel*>(xnImgeGenertor.GetRGB24ImageMap());
        //		IplImage * image = cvCreateImage(cvSize(640, 480), 8, 3);
        //		IplImage * convertedImage = cvCreateImage(cvSize(640, 480), 8, 3);
        cvSetData		(image, xnRgb, 640 * 3);
        cvConvertImage(image, convertedImage, CV_CVTIMG_SWAP_RB);
        bool color = true;
        rgb = convertedImage;
        //		cvtColor(rgb,rgb,CV_RGB2BGR);
        // update rgb image
        //		rgb.data = (uchar*) xnImgeGenertor.GetRGB24ImageMap(); // segmentation fault here
        //		cvCvtColor(rgb, rgb, CV_BGR2RGB);

        // extract foreground by simple subtraction of very basic background model
        foreground = background - depth;

        // find touch mask by thresholding (points that are close to background = touch points)
        touch = (foreground > touchDepthMin) & (foreground < touchDepthMax);

        // extract ROI
        Rect roi(xMin, yMin, xMax - xMin, yMax - yMin);
        Mat touchRoi = touch(roi);

        // find touch points
        vector<vector<Point2i> > contours;
        vector<Point2f> touchPoints;
        findContours(touchRoi, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE,
                     Point2i(xMin, yMin));
        for (unsigned int i = 0; i < contours.size(); i++) {
            Mat contourMat(contours[i]);
            // find touch points by area thresholding
            if (contourArea(contourMat) > touchMinArea) {
                Scalar center = mean(contourMat);
                Point2i touchPoint(center[0], center[1]);
                touchPoints.push_back(touchPoint);
            }
        }

        // send TUIO cursors
        time = TuioTime::getSessionTime();
        tuio->initFrame(time);

        for (unsigned int i = 0; i < touchPoints.size(); i++) { // touch points
            float cursorX = (touchPoints[i].x - xMin) / (xMax - xMin);
            float cursorY = 1 - (touchPoints[i].y - yMin) / (yMax - yMin);
            TuioCursor* cursor = tuio->getClosestTuioCursor(cursorX, cursorY);
            // TODO improve tracking (don't move cursors away, that might be closer to another touch point)
            if (cursor == NULL || cursor->getTuioTime() == time) {
                tuio->addTuioCursor(cursorX, cursorY);
            } else {
                tuio->updateTuioCursor(cursor, cursorX, cursorY);
            }
        }

        tuio->stopUntouchedMovingCursors();
        tuio->removeUntouchedStoppedCursors();
        tuio->commitFrame();

        // draw debug frame
        depth.convertTo(depth8, CV_8U, 255 / debugFrameMaxDepth); // render depth to debug frame
        cvtColor(depth8, debug, CV_GRAY2BGR);
        debug.setTo(debugColor0, touch); // touch mask
        rectangle(debug, roi, debugColor1, 2); // surface boundaries
        if (color)
            rectangle(rgb, roi, debugColor1, 2); // surface boundaries

        // draw 10 white keys within the roi
        int stride = (xMax - xMin) / 10;
        for (int keys = 1; keys < 10; keys++) {
            Point lower(xMin + keys * stride, yMax);
            if (keys == 3 || keys == 7) {
                Point upper(xMin + keys * stride, yMin);
                line(debug, upper, lower, debugColor3, 2, 0);
                if (color)
                    line(rgb, upper, lower, debugColor3, 2, 0);
                continue;
            } else {
                Point upper(xMin + keys * stride, (yMin + yMax) / 2);
                line(debug, upper, lower, debugColor3, 2, 0);
                if (color)
                    line(rgb, upper, lower, debugColor3, 2, 0);
            }
            Point blkUpper(xMin + keys * stride - stride / 3, yMin);
            Point blkLower(xMin + keys * stride + stride / 3,
                           (yMin + yMax) / 2);
            rectangle(debug, blkUpper, blkLower, debugColor4, 2);
            if (color)
                rectangle(rgb, blkUpper, blkLower, debugColor4, 2);
        }

        for (unsigned int i = 0; i < touchPoints.size(); i++) { // touch points
            circle(debug, touchPoints[i], 5, debugColor2, CV_FILLED);
            if (color)
                circle(rgb, touchPoints[i], 5, debugColor2, CV_FILLED);
            double frequency = piano->keyFrequency(touchPoints[i].y - 50,
                                                   touchPoints[i].x - 50);

            cout << frequency << " " << touchPoints[i].y - 50 << " "
                 << touchPoints[i].x - 50 << endl;

            if (keys.find(frequency) == keys.end()) {
                Note * note = new Note(frequency, 2, 4000);
                notesJack->playNote(*note);
                timeval now;
                gettimeofday(&now, NULL);
                keys[frequency] = now;
            } else {
                timeval now;
                gettimeofday(&now, NULL);
                if ((now.tv_sec - keys[frequency].tv_sec) * 1000
                        + (now.tv_usec - keys[frequency].tv_usec) / 1000
                        > 1000) {
                    Note * note = new Note(frequency, 2, 4000);
                    notesJack->playNote(*note);
                    keys[frequency] = now;
                }
            }
        }
        // render debug frame (with sliders)
//		IplImage grayScale = debug;
//		cvFlip(&grayScale, NULL, 1);
//		Mat gray(&grayScale);
//		imshow(windowName, gray);
//
//		IplImage colorful = rgb;
//		cvFlip(&colorful, NULL, 1);
//		Mat real(&colorful);
//		imshow("image", real);
        imshow(windowName, debug);
        imshow("image", rgb);
        //		cvShowImage("image", image);
    }

    return 0;
}
int main() {

	const unsigned int nBackgroundTrain = 30;	// サンプリング回数
	int touchDepthMin = 10;	// タッチ判定の最小値(defautl:10)
	int touchDepthMax = 20;	// タッチ判定の最大値(default:20)
	int touchMinArea = 50;		// このエリアよりも輪郭が大きいなら、タッチ箇所とみなす

	const bool localClientMode = false; 		// connect to a local client

	const double debugFrameMaxDepth = 4000;		// maximal distance (in millimeters) for 8 bit debug depth frame quantization. 4000mm === 4m
	const char* windowName = "TouchReader";			// ウィンドウ名
	const Scalar debugColor0(0, 0, 128);		// タッチ近似領域の色:Scalr(Blue, Green, Red) === (0x800000) === red
	const Scalar debugColor1(255, 0, 0);		// ROIを囲む枠線の色
	const Scalar debugColor2(255, 255, 255);	// タッチの色

	const int xMin = 0;
	const int xMax = 640;
	const int yMin = 00;
	const int yMax = 480;

	Mat1s depth(480, 640);		// 16 bit depth (in millimeters) <Mat1s === short>
	Mat1b depth8(480, 640);		// 8 bit depth <Mat1b === uchar>
	//Mat3b rgb(480, 640);		// 8 bit depth <Mat3b === Vec3b<r,g,b>>

	Mat3b debug(480, 640);		// debug visualization

	Mat1s foreground(640, 480);
	Mat1b foreground8(640, 480);

	Mat1b touch(640, 480); // touch mask

	Mat1s background(480, 640);
	vector<Mat1s> buffer(nBackgroundTrain);

	if (initKinnect() != 0) {
		printf("initKinnect Error\n");
		return -1;
	}

	// TUIO server object
	TuioServer* tuio;
	if (localClientMode) {
		printf("connect \"LOCAL\" TuioServer\n");
		tuio = new TuioServer();
	} else {
		printf("connect TuioServer 150.43.77.24:3333\n");
		tuio = new TuioServer("150.43.74.5", 3333, false);			// 安東さん
		//tuio = new TuioServer("150.43.77.24", 3333, false);		// 龍さん
	}
	TuioTime time;

	// create some sliders
	namedWindow(windowName);
/*
	createTrackbar("xMin", windowName, &xMin, 640);
	createTrackbar("xMax", windowName, &xMax, 640);
	createTrackbar("yMin", windowName, &yMin, 480);
	createTrackbar("yMax", windowName, &yMax, 480);
//*/
	createTrackbar("touchDepthMin", windowName, &touchDepthMin, 100);
	createTrackbar("touchDepthMax", windowName, &touchDepthMax, 100);
	createTrackbar("touchMinArea", windowName, &touchMinArea, 100);

	// create background model (average depth)
	for (unsigned int i=0; i<nBackgroundTrain; i++) {
		updateKinnect();
		depth.data = getKinnectDepthMap();
		buffer[i] = depth;
	}
	average(buffer, background);

	while ( waitKey(1) != 27 ) {
		// データ読み取り
		updateKinnect();

		// update 16 bit depth matrix
		depth.data = getKinnectDepthMap();
		//xnImgeGenertor.GetGrayscale8ImageMap()

		// update rgb image
		//rgb.data = (uchar*) xnImgeGenertor.GetRGB24ImageMap(); // segmentation fault here
		//cvtColor(rgb, rgb, CV_RGB2BGR);

		// extract foreground by simple subtraction of very basic background model
		foreground = background - depth;

		// タッチマスク
		// find touch mask by thresholding (points that are close to background = touch points)
		touch = (foreground > touchDepthMin) & (foreground < touchDepthMax);

		// extract ROI
		Rect roi(xMin, yMin, xMax - xMin, yMax - yMin);
		Mat touchRoi = touch(roi);

		// タッチ位置を探す
		vector< vector<Point2i> > contours;
		vector<Point2f> touchPoints;//タッチ位置
		findContours(touchRoi, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, Point2i(xMin, yMin));//輪郭を探しだす by OpenCV
		for (unsigned int i=0; i<contours.size(); i++) {
			Mat contourMat(contours[i]);
			// find touch points by area thresholding
			if ( contourArea(contourMat) > touchMinArea ) {	// 小さすぎる点はタッチと見なさない
				Scalar center = mean(contourMat);
				Point2i touchPoint(center[0], center[1]);
				touchPoints.push_back(touchPoint);
			}
		}

		// send TUIO cursors
		time = TuioTime::getSessionTime();
		tuio->initFrame(time);

		for (unsigned int i = 0; i < touchPoints.size(); i++) { // touch points
				//float cursorX2 = (touchPoints[i].x - xMin) / (xMax - xMin);
				float cursorX = 1- (touchPoints[i].x - xMin) / (xMax - xMin);
				//float cursorY2 = 1 - (touchPoints[i].y - yMin)/(yMax - yMin);
				float cursorY = (touchPoints[i].y - yMin)/(yMax - yMin);
				cursorY = 1 - (touchPoints[i].y - yMin)/(yMax - yMin);//安東さん用
				TuioCursor* cursor = tuio->getClosestTuioCursor(cursorX,cursorY);
				// TODO improve tracking (don't move cursors away, that might be closer to another touch point)
				if (cursor == NULL || cursor->getTuioTime() == time) {
					tuio->addTuioCursor(cursorX, cursorY);
					//printf("addTuioCursor TuioServer(%f, %f)\n", cursorX, cursorY);
					//printf("addTuioCursor TuioServer(%f, %f)2\n", cursorX, cursorY2);
				} else {
					tuio->updateTuioCursor(cursor, cursorX, cursorY);
					//printf("updateTuioCursor TuioServer(%f, %f)\n", cursorX, cursorY);
					//printf("updateTuioCursor TuioServer(%f, %f)2\n", cursorX, cursorY2);
				}
		}

		tuio->stopUntouchedMovingCursors();
		tuio->removeUntouchedStoppedCursors();
		tuio->commitFrame();

		//--------------------
		// draw debug frame
		//--------------------
		// render depth to debug frame
		depth.convertTo(depth8, CV_8U, 255 / debugFrameMaxDepth);
		cvtColor(/* in */depth8, /* out*/debug, /* 変換方法 */CV_GRAY2BGR);

		// ヒートマップの描画
		debug.setTo(debugColor0, touch);  // touch mask
		//rectangle(debug, roi, debugColor1, 2); // surface boundaries

		// タッチ位置の描画
		for (unsigned int i = 0; i < touchPoints.size(); i++) { // touch points
			circle(debug, touchPoints[i], 5, debugColor2, CV_FILLED);
		}

		// render debug frame (with sliders)
		imshow(windowName, debug);
		//imshow("image", rgb);
	}
	die++;
	sleep(1);

	printf("main thread finished.\n");
	printf("\ttouchDepthMin = %d\n", touchDepthMin);
	printf("\ttouchDepthMax = %d\n", touchDepthMax);
	printf("\ttouchMinArea = %d\n", touchMinArea);

	return 0;
}
int main(int argc, const char** argv)
{
    //Tuio Parameters
    TuioServer *tuioServer;
    TuioTime currentTime;
    vector<TuioCursor*> cursors;
    help();
    
    //CommandLineParser parser(argc, argv, keys);
    bool useCamera=true;
    int camera=0;
    string file;
    if(argc == 3){
        if (strcmp(argv[1],"-c") == 0){
            camera=atoi(argv[2]);
        }else if (strcmp(argv[1],"-fn") == 0){
            useCamera=false;
            file=argv[2];
        }
    }
    VideoCapture cap;
    bool update_bg_model = true;
    int frames=0;
    
    if( useCamera )
        cap.open(camera);
    else
        cap.open(file.c_str());

    if( !cap.isOpened() )
    {
        printf("can not open camera or video file\n");
        return -1;
    }

    namedWindow("image", CV_WINDOW_KEEPRATIO);
    namedWindow("foreground mask", CV_WINDOW_KEEPRATIO);
    namedWindow("foreground image", CV_WINDOW_KEEPRATIO);
    namedWindow("outlines", CV_WINDOW_KEEPRATIO);

    BackgroundSubtractorMOG bg_model(100,25,0.5,10);
    //bg_model.set("noiseSigma", 10);
    
/*    SimpleBlobDetector::Params blobParams;
    blobParams.minDistBetweenBlobs = 10.0f;
    blobParams.filterByInertia = false;
    blobParams.filterByConvexity = false;
    blobParams.filterByColor = false;
    blobParams.filterByCircularity = false;
    blobParams.filterByArea = true;
    blobParams.minArea = 200.0f;
    blobParams.maxArea = 10000.0f;
    
    SimpleBlobDetector blobs(blobParams);
    vector<KeyPoint> blobKeypoints;
  */  
    vector<vector<Point> > contours,contoursAll;
    vector<Moments> contourMoments;    
    vector<Point2d> centers;
    

    Mat img, fgmask, fgmask_old, fgimg, temp, outline_img;
    tuioServer = new TuioServer("rb-mbp.local",3333);    
    //tuioServer = new TuioServer();    
    int niters=1;
    for(;;)
    {
        cap >> img;
        contours.clear();
        contoursAll.clear();
        contourMoments.clear();
        centers.clear();
        
        if( img.empty() )
            break;

        //cvtColor(_img, img, COLOR_BGR2GRAY);

        if( fgimg.empty() )
          fgimg.create(img.size(), img.type());

        if( outline_img.empty() )
          outline_img.create(img.size(), img.type());

        //update the model
        bg_model(img, fgmask, update_bg_model ? -1 : 0);


        //Fill in gaps in the mask using morphology functions        
        dilate(fgmask, temp, Mat(), Point(-1,-1), niters); 
        //erode(temp, temp, Mat(), Point(-1,-1), niters*2);
        //dilate(temp, temp, Mat(), Point(-1,-1), niters);
        threshold(temp,temp,200,255,CV_THRESH_BINARY);     
        temp.copyTo(fgmask);
        
        //detect movement.  Update bgimage when we have movement or every n frames
        /*
        if (fgmask_old.empty()){
            fgmask_old.create(fgmask.size(),fgmask.type());
        }
        if (sum(fgmask-fgmask_old)[0] > 1e6 || frames > 5){
            update_bg_model = true;
            frames = 0;
        }else {
            update_bg_model = false;
            frames++;
        }
        fgmask.copyTo(fgmask_old);
        */
    //    blobs.detect(fgmask,blobKeypoints);
    //    drawKeypoints(img,blobKeypoints,img);        
        /*
        **Find blobs using Contours
        **
        */
        fgimg = Scalar::all(0);        
        outline_img = Scalar::all(0); 
        findContours(temp,contoursAll,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);                
        
        for (int contour=0;contour < contoursAll.size(); contour++){
            Moments m = moments(contoursAll[contour]);
            if (m.m00 < 100)
                continue;
            contours.push_back(contoursAll[contour]);
            centers.push_back(Point2d(m.m10 / m.m00, m.m01 / m.m00));
            contourMoments.push_back(m);
        }
        drawContours(outline_img,contours,-1,Scalar(255,255,255));
        currentTime = TuioTime::getSessionTime();
        tuioServer->initFrame(currentTime);
        
        list<TuioCursor*> cursorList = tuioServer->getTuioCursors();
        for(list<TuioCursor *>::iterator cursor=cursorList.begin();cursor != cursorList.end();++cursor){
            tuioServer->removeTuioCursor(*cursor);
        }
            tuioServer->stopUntouchedMovingCursors();
            tuioServer->commitFrame();

        
        currentTime = TuioTime::getSessionTime();
        tuioServer->initFrame(currentTime);        
        for (int contour=0;contour < contours.size(); contour++){
            circle(outline_img,centers[contour],4,Scalar(0,0,255),-1);
            cursors.push_back(tuioServer->addTuioCursor((float)(centers[contour].x)/800.0,(float)(centers[contour]).y/600.0));
        }
        tuioServer->commitFrame();        
        
        
        img.copyTo(fgimg, fgmask);
        
        //bg_model.getBackgroundImage(bgimg);
        imshow("image", img);
        imshow("foreground mask", fgmask);
        
        imshow("foreground image", fgimg);
        imshow("outlines",outline_img);
        
        //if(!bgimg.empty())
        //  imshow("mean background image", bgimg );
        
        char k = (char)waitKey(30);
        if( k == 27 ) break;
        if( k == ' ' )
        {
            update_bg_model = !update_bg_model;
            if(update_bg_model)
                printf("Background update is on\n");
            else
                printf("Background update is off\n");
        }
    }

    return 0;
}