JPEGで画像を取得する (c++/Linux)

 

本ページは i-PRO株式会社 の有志メンバーにより記載されたものです。
本ページの情報は ライセンス に記載の条件で提供されます。

 

 

 

本ページでは、i-PRO カメラとLinux OS の PCを HTTPで接続してJPEG映像を連続で表示するプログラムを c++ で作成します。

Python の記事は こちら を参照ください。

 



 

1. JPEG 表記仕様

[概要]

JPEG(1shot要求)で接続するための表記を以下に記載します。

「ネットワークカメラCGIコマンドインターフェース仕様書 統合版」[1] で下記に記載されている情報です。

http://<カメラのIPアドレス>/cgi-bin/camera?resolution={resolution}

 

補足説明:

 

 

2. i-PRO カメラと JPEG 接続して映像を表示してみる

[概要]

Linux の c++ と OpenCV を使って、PC と i-PRO カメラを HTTPで接続してJPEG映像を連続で表示してみます。

 

[評価環境]

開発環境 :

GNU
build-essensial
CMake
9.4.0
12.8
3.16.3
ライブラリ : OpenCV
libcurl4
4.6.0
7.68.0-1ubuntu2.14 amd64
OS : ubuntu 20.04 LTS

 

[環境準備]

以下のコマンドを実施して環境を準備します。

sudo apt update -y && sudo apt upgrade -y
sudo apt install build-essential libopencv-dev cmake -y
sudo apt install libcurl4-openssl-dev -y
sudo apt update -y && sudo apt upgrade -y

 

 

[プログラム]

サンプルプログラムのソースコードを以下に示します。

 

[プログラムソース "opencv_jpeg.cpp"]

/*
======================================================================================

[Abstract]
Try connecting to an i-PRO camera with RTSP.
HTTPで接続してJPEGの連続表示で i-PRO カメラと接続してみる

[Details]
Let's try first.
まずはやってみる

[Library install]
sudo apt update -y && sudo apt upgrade -y
sudo apt install build-essential libopencv-dev cmake -y
sudo apt install libcurl4-openssl-dev -y 
sudo apt update -y && sudo apt upgrade -y

======================================================================================
*/

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utility.hpp>
#include <curl/curl.h>

const std::string user_id     = "user-id";         // Change to match your camera setting
const std::string user_pw     = "password";        // Change to match your camera setting
const std::string host        = "192.168.0.10";    // Change to match your camera setting
const std::string winname     = "VIDEO";           // Window title

const std::string cameraURL   = "http://" + host + "/cgi-bin/camera";

// data receive callback function

/// <summary>
/// onReceive function
/// </summary>
/// <returns>segment size of recive data</returns>
size_t onReceive(void* ptr, size_t size, size_t nmemb, void* userdata) {

    std::vector<char>* receiveBuffer = (std::vector<char>*)userdata;
    const size_t sizes = size * nmemb;

    receiveBuffer->insert(receiveBuffer->end(), (char*)ptr, (char*)ptr + sizes);

    return sizes;
}


/// <summary>
/// main function
/// </summary>
/// <returns>Always returns EXIT_SUCCESS(0).</returns>
int main() {

    char ret;
    std::vector<char> receiveBuffer;
    CURL* curl = NULL;
    CURLcode res;

    while (true) {

        // initialize curl.
        curl = curl_easy_init();
        if (!curl) {
            printf("curl_easy_init() failed...\n");
            break;
        }

        // curl option for digest authentication
        curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
        std::string user_id_pw = user_id + ":" + user_pw;
        curl_easy_setopt(curl, CURLOPT_USERPWD, user_id_pw.c_str());

        // curl option
        curl_easy_setopt(curl, CURLOPT_URL, cameraURL.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &receiveBuffer); 
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onReceive);

        // execute
        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            printf("curl_easy_perform() failed...%s\n", curl_easy_strerror(res));
            break;
        }
        curl_easy_cleanup(curl); 

        // JPEG decode
        cv::Mat frame = cv::imdecode(receiveBuffer, cv::IMREAD_UNCHANGED);

        // Clear all received data.
        receiveBuffer.clear();

        // Please modify the value to fit your PC screen size.
        resize(frame, frame, cv::Size(), 0.5, 0.5); // Setting by magnification.

        // Display video.
        cv::imshow(winname, frame);

        ret = (char)cv::waitKey(1); // necessary to display the video by cv::imshow().

        // Press the "q" key to finish.
        if (ret == 'q') {
            break;
        }
    }

    cv::destroyAllWindows();

    return EXIT_SUCCESS;

}

難しい事をしているように見えますが、HTTPサーバーからJPEGファイルを保存するサンプルコードを元にしてソースコードを書いています。
curl_easy_setoptでコールバック関数を呼び出すようにして、コールバック関数で受信バッファにデータを書き込んでいます。
GETがおわるとcurl_easy_perform関数から抜けるので、受信バッファに格納されたJPEGデータをデコードして、受信バッファをクリアしています。

 

 

[ビルド]

ビルドにおいて環境依存を極力するなくするため、以下の手順でビルドします。

  1. CMakeでMakefileを生成する
  2. 生成したMakefileを使ってビルドする

 

ソースコード(opencv_jpeg.cpp)と同じディレクトリに以下のように中身が書かれたCMakeLists.txtを配置してください。

CMakeの知識がある方は、内容をカスタマイズしてお使いください。

 

["CMakeLists.txt"]

# 変数SOURCE_CORDEを宣言し、ソースコードのファイル名の拡張子無くした値を入れる。
# cmake -D SOURCE_CODE=(ソース名)で上書き可
set(SOURCE_CODE opencv_jpeg CACHE NAME "Target object name")

# CMakeの最低バージョンを記述
cmake_minimum_required(VERSION 2.8)

# ソリューション名を指定
project( ${SOURCE_CODE} )

# OpenCVのパッケージを探す
find_package( OpenCV REQUIRED )

#ヘッダファイルのパスを指定
include_directories( ${OpenCV_INCLUDE_DIRS} )

# CURLのパッケージを探す
find_package( CURL REQUIRED )

#ヘッダファイルのパスを指定
include_directories( ${CURL_INCLUDE_DIR} )

# 実行ファイル名とソース指定(ここではソースと同じ名前の実行ファイルを作ります)
add_executable( ${SOURCE_CODE} ${SOURCE_CODE}.cpp )

#リンク先のライブラリを指定
target_link_libraries( ${SOURCE_CODE} ${OpenCV_LIBS} ${CURL_LIBRARIES})

 

ビルド環境を作成してアプリケーションを構築するため、以下のコマンドを実施します。

mkdir build && cd build
cmake ..
make

 

これにより、buildディレクトリに[opencv_jpeg]という実行ファイルができましたので、以下のようにコマンドを実施すればアプリケーションが実施されます

./opencv_jpeg

 

ソースコードの変更をする場合は、すでにビルド環境ができていますので、buildディレクトリで以下のようにすれば更新が可能です。

ライブラリを追加する場合は CMakeLists.txtの追記を行い、build ディレクトリを削除してcmakeをやり直してください。

make clean
make

 

 

ソースコード所在

本ページで紹介のソースコードは、下記 github より取得できます。

下記 github のソースコードと本ページの内容は差異がある場合があります。

i-pro-corp/cpp-examples: c++ sample programs for i-PRO camera. (github.com)

 

 

ライセンス

本ページの情報は、特記無い限り下記ライセンスで提供されます。


Copyright 2023 i-PRO Co., Ltd.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

 

 

参考

 


 

変更履歴

2023/3/22 - 新規作成, 蓬田 康雄

 

i-PRO - Programming Items トップページ

プライバシーポリシー