カメラ画像をofxVideoGrabberで取得してofxTurboJpegでエンコードして、ofxZMQを通してネットワーク配信するプログラムサンプル
OpenCVを使わずに、openFrameworksのアドオンだけで動くように変更しました。
ofxZmq
GitHub - satoruhiga/ofxZmq
の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が一台あると、実験に便利そうです。でも流通が限定していて入手しづらいうえに高い。一般向けのこれで妥協するかどうか。
とか、思っていたら断然こっちの方がいいですね。新しいハイスピードカメラもっと調べてみよう。