cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

カメラ画像をofxVideoGrabberで取得してofxTurboJpegでエンコードして、ofxZMQを通してネットワーク配信するプログラムサンプル

OpenCVを使わずに、openFrameworksのアドオンだけで動くように変更しました。
ofxZmq
GitHub - satoruhiga/ofxZmq

ofxTurboJpeg
GitHub - armadillu/ofxTurboJpeg: Rough OF addon that uses turbo-jpeg lib to read and write jpegs. 2-3 times faster than OF's freeImage based jpeg en/decoder

の2つのアドオンを使用しています。
今回はopenCV版とは違いofxZmqの改造は不要ですが、ofxTurboJpegのsave関数がprivateで定義されているのをpublicに変更してやる必要があります。(なんでprivateにされてるんだろう??)

ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxTurboJpeg.h"

class ofxZmqSubscriber;
class ofxZmqPublisher;

class ofApp : public ofBaseApp {

public:
	void setup();
	void update();
	void draw();

	void keyPressed(int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y);
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	void dragEvent(ofDragInfo dragInfo);
	void gotMessage(ofMessage msg);

	ofxZmqSubscriber* subscriber;
	ofxZmqPublisher* publisher;

	ofVideoGrabber cap;

	ofxTurboJpeg turbo;
	ofImage frame;
	ofBuffer send_buf;
	int params;

	ofImage image;
	ofBuffer recv_buf;
};

ofApp.cpp

#include "ofApp.h"

#include "ofxZmq.h"

//--------------------------------------------------------------
void ofApp::setup()
{
	ofSetFrameRate(30);

	cap.setVerbose(true);
	cap.setDeviceID(1);
	if (cap.initGrabber(640, 480)) {
		//frame.allocate(cap.getWidth(), cap.getHeight(), OF_IMAGE_COLOR);
		params = 90; // quality

		// start server
		publisher = new ofxZmqPublisher();
		publisher->setHighWaterMark(1);
		publisher->bind("tcp://*:9999");
	}

	// start client
	subscriber = new ofxZmqSubscriber();
	subscriber->setHighWaterMark(1);
	subscriber->connect("tcp://localhost:9999");
}

//--------------------------------------------------------------
void ofApp::update()
{
	while (subscriber->hasWaitingMessage()) {
		subscriber->getNextMessage(recv_buf);
		turbo.load(image, recv_buf); // turbo.load(recv_buf, image); 2022/08/27 updated

		cout << "received data: " << recv_buf.size() << endl;
	}

	cap.update();
	if (cap.isFrameNew()) {
		//frame = cap.getPixels();
		turbo.save(send_buf, cap.getPixelsRef(), 90);
		publisher->send(send_buf);
	}
}

//--------------------------------------------------------------
void ofApp::draw()
{
	cap.draw(0, 0);
	image.draw(cap.getWidth(), 0);
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}

その受信をofThread版。lock()しないで落ちないから書いてないけど、大丈夫かな。。。
ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxTurboJpeg.h"

class ofxZmqSubscriber;
class ofxZmqPublisher;

class ThreadedSubscriber : public ofThread
{
public:
	ThreadedSubscriber(ofxZmqSubscriber* ptr) : subscriber(ptr) { image.setUseTexture(true); }
	void threadedFunction();
	ofImage& getImage();

protected:
	ofxZmqSubscriber* subscriber;
	ofxTurboJpeg turbo;
	ofBuffer recv_buf;
	ofImage image;
};

class ofApp : public ofBaseApp {

public:
	void setup();
	void update();
	void draw();

	void keyPressed(int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y);
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	void dragEvent(ofDragInfo dragInfo);
	void gotMessage(ofMessage msg);

	ofxZmqSubscriber* subscriber;
	ofxZmqPublisher* publisher;

	ofVideoGrabber cap;

	ofxTurboJpeg turbo;
	ofImage frame;
	ofBuffer send_buf;
	int params;

	ThreadedSubscriber* threadedSubscriber;
	ofImage image;
};

ofApp.cpp

#include "ofApp.h"

#include "ofxZmq.h"

void ThreadedSubscriber::threadedFunction()
{
	while (isThreadRunning()) {
		while (subscriber->hasWaitingMessage()) {
			do {
				subscriber->getNextMessage(recv_buf);
			} while (subscriber->hasWaitingMessage());
			turbo.load(recv_buf, image);
			image.update();
			//image.saveImage("test.jpg");

			cout << "received data: " << recv_buf.size() << "\r";
		}
	}
}

ofImage& ThreadedSubscriber::getImage()
{
	return image;
}

//--------------------------------------------------------------
void ofApp::setup()
{
	ofSetFrameRate(30);

	cap.setVerbose(true);
	cap.setDeviceID(1);
	if (cap.initGrabber(640, 480)) {
		params = 90; // quality

		// start server
		publisher = new ofxZmqPublisher();
		publisher->setHighWaterMark(1);
		publisher->bind("tcp://*:9999");
	}

	// start client
	subscriber = new ofxZmqSubscriber();
	subscriber->setHighWaterMark(1);
	subscriber->connect("tcp://localhost:9999");

	threadedSubscriber = new ThreadedSubscriber(subscriber);
	threadedSubscriber->startThread(false);
}

//--------------------------------------------------------------
void ofApp::update()
{
	cap.update();
	if (cap.isFrameNew()) {
		//frame = cap.getPixels();
		turbo.save(send_buf, cap.getPixelsRef(), 100);
		publisher->send(send_buf);
	}
}

//--------------------------------------------------------------
void ofApp::draw()
{
	cap.draw(0, 0);
	
	image = threadedSubscriber->getImage();
	image.draw(cap.getWidth(), 0);
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}


ofxZmq作者の方のサンプルの方が勉強になりそうです。
github.com

今日のハイスピードカメラ

CASIO EX-100Proが一台あると、実験に便利そうです。でも流通が限定していて入手しづらいうえに高い。一般向けのこれで妥協するかどうか。

とか、思っていたら断然こっちの方がいいですね。

新しいハイスピードカメラもっと調べてみよう。

カメラ画像をOpenCVで取得してJpegエンコードして、ZeroMQを通してネットワーク配信するプログラムサンプル(その2.受信をマルチスレッド化)

testApp.h

#pragma once

#include "ofMain.h"

#include "opencv2/opencv.hpp"

class ofxZmqSubscriber;
class ofxZmqPublisher;

class ThreadedSubscriber : public ofThread
{
public:
	ThreadedSubscriber(ofxZmqSubscriber* ptr) : subscriber(ptr) {};
	void threadedFunction();
	void draw();

protected:
	ofxZmqSubscriber* subscriber;
	cv::Mat image;
	std::vector<unsigned char> recv_buf;
};

class testApp : public ofBaseApp{

	public:
		~testApp();

		void setup();
		void update();
		void draw();

		void keyPressed  (int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
		
		ofxZmqSubscriber* subscriber;
		ofxZmqPublisher* publisher;

		cv::VideoCapture cap;

		cv::Mat frame;
		std::vector<unsigned char> send_buf;
		std::vector<int> params;
		string type;

		ThreadedSubscriber* threadedSubscriber;
};

testApp.cpp

#include "testApp.h"

#include "ofxZmq.h"

#include "opencv2/opencv.hpp"

#pragma comment(lib, "opencv_calib3d310.lib")
#pragma comment(lib, "opencv_core310.lib")
#pragma comment(lib, "opencv_features2d310.lib")
#pragma comment(lib, "opencv_flann310.lib")
#pragma comment(lib, "opencv_highgui310.lib")
#pragma comment(lib, "opencv_imgcodecs310.lib")
#pragma comment(lib, "opencv_imgproc310.lib")
#pragma comment(lib, "opencv_ml310.lib")
#pragma comment(lib, "opencv_objdetect310.lib")
#pragma comment(lib, "opencv_photo310.lib")
#pragma comment(lib, "opencv_shape310.lib")
#pragma comment(lib, "opencv_stitching310.lib")
#pragma comment(lib, "opencv_superres310.lib")
#pragma comment(lib, "opencv_ts310.lib")
#pragma comment(lib, "opencv_video310.lib")
#pragma comment(lib, "opencv_videoio310.lib")
#pragma comment(lib, "opencv_videostab310.lib")


void ThreadedSubscriber::threadedFunction()
{
	while (isThreadRunning()) {
		while (subscriber->hasWaitingMessage())
		{
			do {
				subscriber->getNextMessage(recv_buf);
			} while (subscriber->hasWaitingMessage());
			lock();
			image = cv::imdecode(recv_buf, CV_LOAD_IMAGE_COLOR);
			//image = buf.clone();
			unlock();

			cout << "received data: " << recv_buf.size() << endl;
			//sleep(1);
		}
	}
}

void ThreadedSubscriber::draw()
{
	lock();
	if (!image.empty()) {
		cv::imshow("received", image);
	}
	unlock();
}

testApp::~testApp() {
        if (threadedSubscriber->isThreadRunning()) {
	        threadedSubscriber->stopThread();
        }
	subscriber->disconnect("tcp://localhost:9999");
	cap.release();
}

//--------------------------------------------------------------
void testApp::setup()
{
	ofSetFrameRate(30);

	bool ret = cap.open(0);
	
	if (cap.isOpened()) {
		cout << "Camera is ready!" << endl;
		cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
		cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
		cap.set(cv::CAP_PROP_FPS, 30);

		//type = ".jpg";
		type = ".webp";
		if (type == ".jpg") {
			params.push_back(CV_IMWRITE_JPEG_QUALITY);
			params.push_back(100);
			params.push_back(CV_IMWRITE_JPEG_OPTIMIZE);
			params.push_back(0);
			params.push_back(CV_IMWRITE_JPEG_PROGRESSIVE);
			params.push_back(0);
		}
		else if (type == ".webp") {
			params.push_back(CV_IMWRITE_WEBP_QUALITY);
			params.push_back(70);
		}

		// start server
		publisher = new ofxZmqPublisher();
		publisher->setHighWaterMark(1);
		publisher->bind("tcp://*:9999");
	}

	// start client
	subscriber = new ofxZmqSubscriber();
	subscriber->setHighWaterMark(0);
	subscriber->connect("tcp://localhost:9999");
	//subscriber->connect("tcp://10.254.20.46:9999");

	threadedSubscriber = new ThreadedSubscriber(subscriber);
	threadedSubscriber->startThread(true, false);
}

//--------------------------------------------------------------
void testApp::update()
{	
	if (!cap.isOpened()) return;

	if (cap.grab()) {
		bool res = cap.read(frame);

		if (res) {
			int msec_start = ofGetElapsedTimeMillis();
			bool ret = cv::imencode(type, frame, send_buf, params);
			int msec_stop = ofGetElapsedTimeMillis();

			if (ret) {
				publisher->send(send_buf);

				int lap = msec_stop - msec_start;
				int fps = (lap) ? 1000.0 / lap : ofGetFrameRate();
				cout << "encoded size(" << type << ") : " << send_buf.size()
					<< ", time : " << lap << ", fps : " << fps << endl;
			}
		}
	}
}

//--------------------------------------------------------------
void testApp::draw()
{
	threadedSubscriber->draw();
}

//--------------------------------------------------------------
void testApp::keyPressed(int key)
{
	if (threadedSubscriber->isThreadRunning()) {
                threadedSubscriber->stopThread();
	        subscriber->disconnect("tcp://localhost:9999");
	        subscriber->connect("tcp://localhost:9999");
	        threadedSubscriber->startThread(true, false);
        }
}

//--------------------------------------------------------------
void testApp::keyReleased(int key)
{

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y)
{

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button)
{

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button)
{

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button)
{

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h)
{

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg)
{

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo)
{

}

今日の理想のリビングアイテム

テレビは、4Kなど映像のクオリティはうなぎのぼりで良くなっていますが、音響がついて行っていません。音と映像は、クオリティの均衡がとれてないとお互いの足を引っ張ってしまいますので、良い映像には良い音響が必要です。ヤマハのテレビ台型サラウンドスピーカーはかなり良いです。台の間が狭いので、高さのある機器を置けないのは減点ですが。色は黒と茶の2色ありますが、ヤマハは黒に限ります。

ヤマハ 壁寄せ金具 (1台) ブラック YTS-V1200(B)

ヤマハ 壁寄せ金具 (1台) ブラック YTS-V1200(B)

まず、こんな良いやつが置ける部屋が欲しいです。

ofxFaceTrackerで遊んでみる

(メモ)

オリジナルソース
github.com

FaceTrackerのオリジナル論文の解説
d.hatena.ne.jp

Visual Studioでのインストール時の修正
C/C++->OUTPUT Objects: $(IntDir)/%(RelativeDir)/
forum.openframeworks.cc

顔の置き換え
github.com

マルチフェイストラッキング
github.com

笑い男
monitorgazer.blogspot.jp

顔パーツのモデル
blog.kidapu.com

サンプル解説楽しいことをしたい: 【openframeworks】ofxFaceTrackerで遊んでみた。サンプル解説

応用例1:顔で制御、応用例2:顔を交換
yoppa.org

ライオンマスク
www.honeycomb-lab.co.jp

マンガの吹き出し
http://hackist.jp/?p=2979hackist.jp

インタラクティブアート
http://nickhardeman.com/tag/ofxfacetracker/nickhardeman.com

顔を楽器
http://golancourses.net/2014/haris/02/06/face-wah-wah-using-ofxfacetracker-and-ofxmidi/golancourses.net

講義資料
http://nakayasu.com/lecture/openframeworks-facetracker/6770nakayasu.com

SMILE to SMILE
www.bbmedia.co.jp

口から煙
http://ryujiyoshida.com/blog/category/studyryujiyoshida.com

顔のモーフィング
labs.1-10.com

カラオケ顔変換
http://www.kazushi.info/wp-content/uploads/2015/09/433149.pdf

MacOSXでのインストール例
qiita.com

MacOSXでの修正点
ryotakatoh.hatenablog.com

Twitterのハッシュ宅ofxtracker
twitter.com

動画集

vimeo.com

www.youtube.com

vimeo.com

www.youtube.com

これと組み合わせると、面白いかも。
Video Magnification
github.com



固有値の説明
qiita.com


ちまたでは、OpenFaceなるライブラリが注目を集めています。
OpenFace

今日の睡眠

シングルベッドに最低限必要な3点セットで6万円.ただのスポンジのくせに高いよなー.

[asin:B00JH8ATRU:detail]

hiro_handleをpyzmq経由で呼び出せるようにする

(作業メモ)
まずOpenRTM-aistをPython2.7.10環境で構築しなおします。
python2.6はサポートが終了してしまうようで、pipを使ってpyzmqをすんなりインストールすることができません。
http://www.openrtm.org/openrtm/node/5768
32bit用 Windowsインストーラ OpenRTM-aist-Python_1.1.0-RELEASE_x86.msi
Python-2.7 python-2.7.10.msi
をダウンロードしてインストールします。Python2.7.11では駄目だそうです。

JointDataTypes.idlの追加

この節は使わないので、すっ飛ばしてもかまいません。
OpenRTM-aist-Python_1.1.0.zipを解凍して,setup.pyを編集します。
C:\workspace\OpenRTM-aist-Python-1.1.0\OpenRTM_aist\RTM_IDLの下にJointDataTypes.idlをコピーして追加します。
JointDataTypes.idlは,HIROのgrx/share/hpsys/idlにある。

..
baseidl_files = [
  "BasicDataType.idl",
  "DataPort.idl",
  "ExtendedDataTypes.idl",
  "InterfaceDataTypes.idl",
  "Manager.idl",
  "OpenRTM.idl",
  "RTC.idl",
  "SDOPackage.idl",
  "JointDataTypes.idl" # added
  ]
..

そのあと、
python setup.py build
python setup.py install
をする。
cd OpenRTM_aist\RTM_IDL
してから、
omniidl -bpython JointDataTypes.idl

あとは普通にhiro_handleをインストール

http://cvl-robot.hateblo.jp/entry/2013/10/07/211346

pyzmqのインストール

pip install --upgrade pip
pip install pyzmq-static

今日のバスマット

ソイルが欲しいのですが、その前にきれいな浴室のある部屋が欲しいです。

soil 珪藻土 バスマット ライト

soil 珪藻土 バスマット ライト

カメラキャリブレーションのための自動撮影機能を背景差分を使って作る

動体検知をして、動いたものを見つけた後、一定時間画面に変化がないとシャッターを切ります。
単純な閾値処理しかしていませんが、結構ちゃんと動きます。
ただし、閾値がカメラ解像度に依存する上に、閾値の設定次第で使いやすさがまるで変ってしまいますが。
OpenFrameworks9.3とOpenCV3.1を使っています。
ofxGuiアドオンとofxHistoryPlot( GitHub - armadillu/ofxHistoryPlot: Visualize value history on a configurable graph )も使います。

ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxGui.h"
#include "ofxHistoryPlot.h"

#include "opencv2/opencv.hpp"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);

		cv::Mat frame;
		cv::Mat fgMask;
		cv::Mat bgMask;
		cv::Ptr<cv::BackgroundSubtractorMOG2> pMOG2;
		cv::VideoCapture cap;

		ofxPanel gui;
		ofxFloatSlider  background_ratio;
		ofxFloatSlider  complexity_reduction_threshold;
		ofxToggle shadow_detection_flag;
		ofxIntSlider history;			// the number of last frames that affect the background model
		ofxIntSlider nMixtures;			// the number of gaussian components in the background model
		ofxFloatSlider shadow_threshold;
		ofxIntSlider shadow_value;
		ofxFloatSlider varInit;			// the initial variance of each gaussian component
		ofxFloatSlider varMax;
		ofxFloatSlider varMin;
		ofxFloatSlider varThreshold;	// the variance threshold for the pixel - model match
		ofxFloatSlider varThresholdGen;	// the variance threshold for the pixel - model match used for new mixture component generation.

		void BackgroundRatioChanged(float& value) { pMOG2->setBackgroundRatio(value); }
		void ComplexityReductionThresholdChanged(float& value) { pMOG2->setComplexityReductionThreshold(value); }
		void ShadowDetectionFlagChanged(bool& value) { pMOG2->setDetectShadows(value); }
		void HistoryChanged(int & value) { pMOG2->setHistory(value); }
		void nMixturesChanged(int & value) { pMOG2->setNMixtures(value); }
		void ShadowThresholdChanged(float & value) { pMOG2->setShadowThreshold(value); }
		void ShadowValueChanged(int & value) { pMOG2->setShadowValue(value); }
		void VarInitChanged(float & value) { pMOG2->setVarInit(value); }
		void VarMaxChanged(float & value) { pMOG2->setVarMax(value); varMin.setMax(value); }
		void VarMinChanged(float & value) { pMOG2->setVarMin(value); varMax.setMin(value); }
		void VarThresholdChanged(float & value) { pMOG2->setVarThreshold(value); }
		void VarThresholdGenChanged(float & value) { pMOG2->setVarThresholdGen(value); }		

		ofxHistoryPlot * plot;

		ofxPanel auto_shutter;
		ofxFloatSlider high_threshold;
		ofxFloatSlider low_threshold;
		int detection_state;
		void HighThresholdChanged(float & value) { low_threshold.setMax(value); }
		void LowThresholdChanged(float & value) { high_threshold.setMin(value); }

		vector<cv::Mat> calib;
};

ofApp.cpp

#include "ofApp.h"

#include "opencv2/opencv.hpp"

#pragma comment(lib, "opencv_calib3d310.lib")
#pragma comment(lib, "opencv_core310.lib")
#pragma comment(lib, "opencv_features2d310.lib")
#pragma comment(lib, "opencv_flann310.lib")
#pragma comment(lib, "opencv_highgui310.lib")
#pragma comment(lib, "opencv_imgcodecs310.lib")
#pragma comment(lib, "opencv_imgproc310.lib")
#pragma comment(lib, "opencv_ml310.lib")
#pragma comment(lib, "opencv_objdetect310.lib")
#pragma comment(lib, "opencv_photo310.lib")
#pragma comment(lib, "opencv_shape310.lib")
#pragma comment(lib, "opencv_stitching310.lib")
#pragma comment(lib, "opencv_superres310.lib")
#pragma comment(lib, "opencv_ts310.lib")
#pragma comment(lib, "opencv_video310.lib")
#pragma comment(lib, "opencv_videoio310.lib")
#pragma comment(lib, "opencv_videostab310.lib")

//--------------------------------------------------------------
void ofApp::setup() {
	cap.open(1);
	cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
	cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
	if (!cap.isOpened()) {
		cout << "Can't open the camera" << endl;
		ofExit();
	}
	cap >> frame;

	int initHistory = 200;
	float initVarThreshold = 16;
	bool bShadowDetection = true;
	pMOG2 = cv::createBackgroundSubtractorMOG2(initHistory, initVarThreshold, bShadowDetection);
	pMOG2->setVarThreshold(10);

	gui.setup("settings", "settings.xml", 10, 10);
	gui.add(background_ratio.setup("background ratio", pMOG2->getBackgroundRatio(), 0.0, 1.0));
	gui.add(complexity_reduction_threshold.setup("complexity reduction", pMOG2->getComplexityReductionThreshold(), 0.0, 1.0));
	gui.add(shadow_detection_flag.setup("shadow detection flag", pMOG2->getDetectShadows()));
	gui.add(history.setup("hisotry", pMOG2->getHistory(), 1, 1000));
	gui.add(nMixtures.setup("nMixtures", pMOG2->getNMixtures(), 1, 100));
	gui.add(shadow_threshold.setup("shadow threshold", pMOG2->getShadowThreshold(), -1.0, 1.0));
	gui.add(varInit.setup("varInit", pMOG2->getVarInit(), 0.0, 100.0));
	gui.add(varMax.setup("varMax", pMOG2->getVarMax(), pMOG2->getVarMin(), 10000.0));
	gui.add(varMin.setup("varMin", pMOG2->getVarMin(), 0.0, pMOG2->getVarMax()));
	gui.add(varThreshold.setup("varThreshold", pMOG2->getVarThreshold(), 0.0, 10000.0));
	gui.add(varThresholdGen.setup("varThresholdGen", pMOG2->getVarThresholdGen(), 0.0, 10000.0));

	background_ratio.addListener(this, &ofApp::BackgroundRatioChanged);
	complexity_reduction_threshold.addListener(this, &ofApp::ComplexityReductionThresholdChanged);
	shadow_detection_flag.addListener(this, &ofApp::ShadowDetectionFlagChanged);
	history.addListener(this, &ofApp::HistoryChanged);
	nMixtures.addListener(this, &ofApp::nMixturesChanged);
	shadow_threshold.addListener(this, &ofApp::ShadowThresholdChanged);
	varInit.addListener(this, &ofApp::VarInitChanged);
	varMax.addListener(this, &ofApp::VarMaxChanged);
	varMin.addListener(this, &ofApp::VarMinChanged);
	varThreshold.addListener(this, &ofApp::VarThresholdChanged);
	varThresholdGen.addListener(this, &ofApp::VarThresholdGenChanged);

	// History Plot
	int numSamples = 350;

	plot = new ofxHistoryPlot(NULL, "Ratio", numSamples, false); //NULL cos we don't want it to auto-update. confirmed by "true"
	plot->setRange(0, 10000.f / sqrt(frame.cols * frame.rows) ); //hard range, will not adapt to values off-scale
	plot->addHorizontalGuide(ofGetHeight() / 2, ofColor(255, 0, 0)); //add custom reference guides
	plot->setColor(ofColor(0, 255, 0)); //color of the plot line
	plot->setShowNumericalInfo(true);   //show the current value and the scale in the plot
	plot->setRespectBorders(true);	    //dont let the plot draw on top of text
	plot->setLineWidth(1);		    //plot line width
	plot->setBackgroundColor(ofColor(0, 220)); //custom bg color
								     //custom grid setup
	plot->setDrawGrid(true);
	plot->setGridColor(ofColor(30)); //grid lines color
	plot->setGridUnit(14);
	plot->setCropToRect(true);

	normalize_ratio = 1.0f / sqrt(frame.cols*frame.rows);
	auto_shutter.setup("shutter");
	auto_shutter.add(high_threshold.setup("high", 3200.f * normalize_ratio, 1800.f * normalize_ratio, 10000.f * normalize_ratio));
	auto_shutter.add(low_threshold.setup("low", 1800.f * normalize_ratio, 0, high_threshold));

	high_threshold.addListener(this, &ofApp::HighThresholdChanged);
	low_threshold.addListener(this, &ofApp::LowThresholdChanged);

	detection_state = 0;
}

//--------------------------------------------------------------
void ofApp::update() {
	if (cap.grab()) {
		cap >> frame;

		pMOG2->apply(frame, fgMask);
		pMOG2->getBackgroundImage(bgMask);

		cv::Scalar v = cv::sum(fgMask);
		plot->update(sqrt(v[0]) * normalize_ratio);

		if (detection_state == 0) {
			if (sqrt(v[0]) * normalize_ratio > high_threshold) {
				detection_state = 1;
			}
		}
		else if (detection_state == 1) {
			if (sqrt(v[0]) * normalize_ratio < low_threshold) {
				detection_state = 0;

				calib.push_back(cv::Mat());
				frame.copyTo(calib.back());

				cv::imshow("calib", calib.back());
				cout << "calib" << std::to_string(calib.size()) << endl;
			}
		}
	}
}

//--------------------------------------------------------------
void ofApp::draw() {
	if (!fgMask.empty()) {
		cv::imshow("FG", fgMask);
	}
	if (!bgMask.empty()) {
		cv::imshow("BG", bgMask);
	}
	gui.draw();
	plot->draw(220, 10, 640, 240);
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key) {
    if (key == 's') {
		int cameraIdx = 0;

		for (int i = 0; i < calib.size(); i++) {
			stringstream ss;
			ss << to_string(cameraIdx) << '-' << /* std::setw(3) << std::setfill('0') <<*/ i << ".png";
			imwrite(ss.str(), calib[i]);
			cout << "wrote " << ss.str() << endl;
		}
	}
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key) {

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {

}

f:id:cvl-robot:20160419223815p:plain

本日の防災

乾電池はある程度手元にないと不安ですね。

Amazonベーシック アルカリ乾電池 単3形20個パック

Amazonベーシック アルカリ乾電池 単3形20個パック

Amazonベーシック アルカリ乾電池 単4形20個パック

Amazonベーシック アルカリ乾電池 単4形20個パック

(メモ)OpenCV3.1で背景差分MOG2を使う時のサンプル

createBackgroundSubtractorMOG2なる関数を使うようです。

ofApp.h

#pragma once

#include "ofMain.h"

#include "opencv2/opencv.hpp"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);

		cv::Mat frame;
		cv::Mat fgMask;
		cv::Ptr<cv::BackgroundSubtractorMOG2> pMOG2;
		cv::VideoCapture cap;
};

ofApp.cpp

#include "ofApp.h"

#include "opencv2/opencv.hpp"

#pragma comment(lib, "opencv_calib3d310.lib")
#pragma comment(lib, "opencv_core310.lib")
#pragma comment(lib, "opencv_features2d310.lib")
#pragma comment(lib, "opencv_flann310.lib")
#pragma comment(lib, "opencv_highgui310.lib")
#pragma comment(lib, "opencv_imgcodecs310.lib")
#pragma comment(lib, "opencv_imgproc310.lib")
#pragma comment(lib, "opencv_ml310.lib")
#pragma comment(lib, "opencv_objdetect310.lib")
#pragma comment(lib, "opencv_photo310.lib")
#pragma comment(lib, "opencv_shape310.lib")
#pragma comment(lib, "opencv_stitching310.lib")
#pragma comment(lib, "opencv_superres310.lib")
#pragma comment(lib, "opencv_ts310.lib")
#pragma comment(lib, "opencv_video310.lib")
#pragma comment(lib, "opencv_videoio310.lib")
#pragma comment(lib, "opencv_videostab310.lib")

//--------------------------------------------------------------
void ofApp::setup(){
	cap.open(1);
	if (!cap.isOpened()) {
		cout << "Can't open the camera" << endl;
		ofExit();
	}

	int history = 500;
	float varThreshold = 16;
	bool bShadowDetection = true;
	pMOG2 = cv::createBackgroundSubtractorMOG2(history, varThreshold, bShadowDetection);
	pMOG2->setVarThreshold(10);
}

//--------------------------------------------------------------
void ofApp::update(){
	if (cap.grab()) {
		cap >> frame;
	
		pMOG2->apply(frame, fgMask);
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	if (!fgMask.empty()) {
		cv::imshow("MOG2", fgMask);
	}
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}


パラメータ調整GUI付きサンプル

#pragma once

#include "ofMain.h"
#include "ofxGui.h"

#include "opencv2/opencv.hpp"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);

		cv::Mat frame;
		cv::Mat fgMask;
		cv::Mat bgMask;
		cv::Ptr<cv::BackgroundSubtractorMOG2> pMOG2;
		cv::VideoCapture cap;

		ofxPanel gui;
		ofxFloatSlider  background_ratio;
		ofxFloatSlider  complexity_reduction_threshold;
		ofxToggle shadow_detection_flag;
		ofxIntSlider history;			// the number of last frames that affect the background model
		ofxIntSlider nMixtures;			// the number of gaussian components in the background model
		ofxFloatSlider shadow_threshold;
		ofxIntSlider shadow_value;
		ofxFloatSlider varInit;			// the initial variance of each gaussian component
		ofxFloatSlider varMax;
		ofxFloatSlider varMin;
		ofxFloatSlider varThreshold;	// the variance threshold for the pixel - model match
		ofxFloatSlider varThresholdGen;	// the variance threshold for the pixel - model match used for new mixture component generation.

		void BackgroundRatioChanged(float& value) { pMOG2->setBackgroundRatio(value); }
		void ComplexityReductionThresholdChanged(float& value) { pMOG2->setComplexityReductionThreshold(value); }
		void ShadowDetectionFlagChanged(bool& value) { pMOG2->setDetectShadows(value); }
		void HistoryChanged(int & value) { pMOG2->setHistory(value); }
		void nMixturesChanged(int & value) { pMOG2->setNMixtures(value); }
		void ShadowThresholdChanged(float & value) { pMOG2->setShadowThreshold(value); }
		void ShadowValueChanged(int & value) { pMOG2->setShadowValue(value); }
		void VarInitChanged(float & value) { pMOG2->setVarInit(value); }
		void VarMaxChanged(float & value) { pMOG2->setVarMax(value); varMin.setMax(value); }
		void VarMinChanged(float & value) { pMOG2->setVarMin(value); varMax.setMin(value); }
		void VarThresholdChanged(float & value) { pMOG2->setVarThreshold(value); }
		void VarThresholdGenChanged(float & value) { pMOG2->setVarThresholdGen(value); }		
};
#include "ofApp.h"

#include "opencv2/opencv.hpp"

#pragma comment(lib, "opencv_calib3d310.lib")
#pragma comment(lib, "opencv_core310.lib")
#pragma comment(lib, "opencv_features2d310.lib")
#pragma comment(lib, "opencv_flann310.lib")
#pragma comment(lib, "opencv_highgui310.lib")
#pragma comment(lib, "opencv_imgcodecs310.lib")
#pragma comment(lib, "opencv_imgproc310.lib")
#pragma comment(lib, "opencv_ml310.lib")
#pragma comment(lib, "opencv_objdetect310.lib")
#pragma comment(lib, "opencv_photo310.lib")
#pragma comment(lib, "opencv_shape310.lib")
#pragma comment(lib, "opencv_stitching310.lib")
#pragma comment(lib, "opencv_superres310.lib")
#pragma comment(lib, "opencv_ts310.lib")
#pragma comment(lib, "opencv_video310.lib")
#pragma comment(lib, "opencv_videoio310.lib")
#pragma comment(lib, "opencv_videostab310.lib")

//--------------------------------------------------------------
void ofApp::setup(){
	cap.open(1);
	if (!cap.isOpened()) {
		cout << "Can't open the camera" << endl;
		ofExit();
	}

	int initHistory = 500;
	float initVarThreshold = 16;
	bool bShadowDetection = true;
	pMOG2 = cv::createBackgroundSubtractorMOG2(initHistory, initVarThreshold, bShadowDetection);
	pMOG2->setVarThreshold(10);

	gui.setup("settings", "settings.xml", 10, 10);
	gui.add(background_ratio.setup("background ratio", pMOG2->getBackgroundRatio(), 0.0, 1.0));
	gui.add(complexity_reduction_threshold.setup("complexity reduction", pMOG2->getComplexityReductionThreshold(), 0.0, 1.0));
	gui.add(shadow_detection_flag.setup("shadow detection flag", pMOG2->getDetectShadows()));
	gui.add(history.setup("hisotry", pMOG2->getHistory(), 1, 1000));
	gui.add(nMixtures.setup("nMixtures", pMOG2->getNMixtures(), 1, 100));
	gui.add(shadow_threshold.setup("shadow threshold", pMOG2->getShadowThreshold(), -1.0, 1.0));
	gui.add(varInit.setup("varInit", pMOG2->getVarInit(), 0.0, 100.0));
	gui.add(varMax.setup("varMax", pMOG2->getVarMax(), pMOG2->getVarMin(), 10000.0));
	gui.add(varMin.setup("varMin", pMOG2->getVarMin(), 0.0, pMOG2->getVarMax()));
	gui.add(varThreshold.setup("varThreshold", pMOG2->getVarThreshold(), 0.0, 10000.0));
	gui.add(varThresholdGen.setup("varThresholdGen", pMOG2->getVarThresholdGen(), 0.0, 10000.0));

	background_ratio.addListener(this, &ofApp::BackgroundRatioChanged);
	complexity_reduction_threshold.addListener(this, &ofApp::ComplexityReductionThresholdChanged);
	shadow_detection_flag.addListener(this, &ofApp::ShadowDetectionFlagChanged);
	history.addListener(this, &ofApp::HistoryChanged);
	nMixtures.addListener(this, &ofApp::nMixturesChanged);
	shadow_threshold.addListener(this, &ofApp::ShadowThresholdChanged);
	varInit.addListener(this, &ofApp::VarInitChanged);
	varMax.addListener(this, &ofApp::VarMaxChanged);
	varMin.addListener(this, &ofApp::VarMinChanged);
	varThreshold.addListener(this, &ofApp::VarThresholdChanged);
	varThresholdGen.addListener(this, &ofApp::VarThresholdGenChanged);
}

//--------------------------------------------------------------
void ofApp::update(){
	if (cap.grab()) {
		cap >> frame;
	
		pMOG2->apply(frame, fgMask);
		pMOG2->getBackgroundImage(bgMask);
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	if (!fgMask.empty()) {
		cv::imshow("FG", fgMask);
	}
	if(!bgMask.empty()) {
		cv::imshow("BG", bgMask);
	}
	gui.draw();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
	
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}

f:id:cvl-robot:20160418161225p:plain

OpenFrameworksのofxGuiとofParameterの仕様が変わってしまい、とても使いにくくなっていますね。
Qtでもあった現象ですが、綺麗にプログラムが書ける人がライブラリを書き直すと、プログラム的には美しくしくても使いづらい関数が続発するという悲しい事態に陥ります。方言を許容したまま開発を進めてほしいものです。

[1] OpenCV: segment_objects.cpp

今日の防災

Kindle版無料だそうですから、ダウンロードして一読しておくのが良いですね。

東京防災

東京防災

簡易トイレも買っておいた方が良いでしょうか。

サッと固まる非常用トイレ袋(30回分) 災害での断水時でもトイレが使える!

サッと固まる非常用トイレ袋(30回分) 災害での断水時でもトイレが使える!

openframeworksでネットワーク同期の方法

(メモ)
anagmaさんのofxNetworkSync addonが便利です。
github.com
ofNetworkアドオンも使用しています。

ofxNetworkSyncServerとofxNetworkSyncClientを同時に起動すると、
右耳と左耳で同期して音がなるので同期を確認することができます。


これ、すごく良さそうだけど、高いですね。。。