1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

M5UnitV2 & ncnnAdvent Calendar 2023

Day 18

M5UnitV2 から画像をブラウザへ配信する

Last updated at Posted at 2023-12-17

概要

M5UnitV2はディスプレイを搭載していないため、OpenCVのcv::imshow()関数などでの確認ができません。画像処理の結果を確認するために、画像をブラウザで配信して確認できるようにします。

環境構築

構築手順に入る前に、まずPCに以下のバージョンのUbuntuをインストールした環境で、構築しました。

M5UnitV2のクロスコンパイル環境を構築する手順

Ubuntu 22.04.3 LTS(x64)
OpenCV ver 0.4.4
ncnn ver 231027

Cpp MJPEG Streamerのダウンロード

GitHubからnadjieb氏のcpp-mjpeg-streamerのコードをダウンロードします。
Cpp MJPEG Streamerは、OpenCVの Video画像をJPEGに変換して、HTTP Streamingで配信するためのプログラムです。Cpp MJPEG StreamerはC++のプログラムをヘッダファイルのみでコンパイルして、HTTP Streamingサーバを動かすことができます。

% mkdir example
% cd example
% curl -LO https://raw.githubusercontent.com/nadjieb/cpp-mjpeg-streamer/master/single_include/nadjieb/mjpeg_streamer.hpp

CMakeLists.txt ファイルの作成

cmakeでコンパイルするために、CMakeLists.txtを作成します。

gedit CMakeLists.txt
CMakeLists.txt
SET(CMAKE_BUILD_TYPE "Release")

SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

# Ubuntuでデバックするためにx64を選択、UnitV2ではarmを指定
if(TARGET_COMPILER STREQUAL "arm")
    message(STATUS "TARGET_COMPILE STREQUAL arm")
    SET(CMAKE_CXX_COMPILER arm-none-linux-gnueabihf-g++)
    SET(CMAKE_C_COMPILER arm-none-linux-gnueabihf-gcc)
    SET(NCNN_INSTALL_DIR /opt/external/ncnn/install/arm/)
    SET(ZBAR_INSTALL_DIR /opt/external/zbar-0.10/build/arm)
    SET(OpenCV_DIR /opt/external/opencv/build/arm)
else()
    message(STATUS "TARGET_COMPILE STREQUAL X64")
    SET(NCNN_INSTALL_DIR /opt/external/ncnn/install/x64/)
    SET(ZBAR_INSTALL_DIR /opt/external/zbar-0.10/build/x64/)
    SET(OpenCV_DIR /opt/external/opencv/build/x64) 
endif()


PROJECT(mpegstream)
cmake_minimum_required(VERSION 3.8)
set(CMAKE_CXX_STANDARD 17)

if(OpenCV_FOUND)
 message(OPENCV_VERSION)
endif(OpenCV_FOUND)

find_package(OpenCV REQUIRED)

link_directories(${OpenCV_LIBRARY_DIRS})

include_directories(${OpenCV_INCLUDE_DIRS} )
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${NCNN_INSTALL_DIR}/include/ncnn)

add_executable(mpegstreamer main.cpp)
target_link_libraries(mpegstreamer ${OpenCV_LIBRARIES})
target_link_libraries(mpegstreamer ${NCNN_INSTALL_DIR}/lib/libncnn.a -fopenmp)

サンプルプログラム

MJPEG Streamerでサーバを建てるサンプルプログラムです。

% gedit main.cpp
main.cpp
#include <opencv2/opencv.hpp>
#include <mjpeg_streamer.hpp>
#include <net.h>
#include <pthread.h>

using namespace std;
using namespace cv;

using MJPEGStreamer = nadjieb::MJPEGStreamer;

int main(int argc, char **argv) {

    int VideoPort = 0;
    bool low_quality_mode = true;

    if(argc >= 2) {
        VideoPort = atoi(argv[1]);
    }

    VideoCapture cap(VideoPort);

    if(!cap.isOpened()) {
        std::cout << "Cannot open cam" << std::endl;
        return -1;
    }

    cap.set(cv::CAP_PROP_FOURCC, cv::CAP_OPENCV_MJPEG);
    if(!cap.set(cv::CAP_PROP_FRAME_WIDTH, 640))
        std::cout << "camera set width error" << std::endl;
    if(!cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480))
        std::cout << "camera set height error" << std::endl;
    
    MJPEGStreamer streamer;
    std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 90};
    streamer.start(7778);

    std::chrono::steady_clock::time_point Tbegin, Tend;

    
    while(cap.isOpened()) {
        Mat frame;
        Tbegin = std::chrono::steady_clock::now();
        cap >> frame;

        if(low_quality_mode == true)
            resize(frame, frame, Size(), 1.0f / 2.0f, 1.0f / 2.0f, INTER_AREA);

        Tend = std::chrono::steady_clock::now();
        float fps = std::chrono::duration_cast<std::chrono::milliseconds>(Tend - Tbegin).count();
      
        putText(frame, cv::format("FPS %0.2f", 1000.0/fps), cv::Point(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255));
#ifdef __x86_64__
        imshow("frame", frame);
        const int key = cv::waitKey(1);
#endif
        std::vector<uchar> buff_bgr;
        cv::imencode(".jpg", frame, buff_bgr, params);
        streamer.publish("/frame", std::string(buff_bgr.begin(), buff_bgr.end()));
    }
    streamer.stop();
    return 0;
}

ビルド

Ubuntu用のバイナリをcmakeでコンパイルして、生成されたバイナリを実行します。

% cmake -B build/x64 -DTARGET_COMPILE=x64 .
% cmake --build build/x64
% ./bin/x64/mpegstreamer

UnitV2(arm環境)で動くバイナリをビルドする場合は、Ubuntu用のバイナリで作成されたキャッシュを削除した上で、以下のコマンドでビルドします。

% cmake -B build/arm -DTARGET_COMPILE=arm .
% cmake --build build/arm
% ./bin/x64/mpegstreamer

For M5UnitV2(ARM)

プログラムを動かし、"http://127.0.0.1:7778/frame"へアクセスすると、カメラからのキャプチャ画像をブラウザへ配信して確認することができます。

プログラムの格納先

このプログラムは以下に格納しています。
https://github.com/nnn112358/MJPEGStreamer

参考資料

この記事を作成するにあたり、以下のウェブサイトを参考にしました。

nadjieb/cpp-mjpeg-streamer

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?