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が一台あると、実験に便利そうです。でも流通が限定していて入手しづらいうえに高い。一般向けのこれで妥協するかどうか。

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

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