cvl-robot's diary

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

カメラ画像を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)

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