質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.05%

pythonからC++に画像を渡したい。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 433

score 17

前提・実現したいこと

pythonプログラムでimreadした画像データをC++に渡したいです。

c++で画像処理したデータをBoost::pythonでPythonで使えるようにするのが目標です。
c++単体で動かすときには以下の方法で動作します。

C++単体のスクリプト

#include <iostream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>

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

  // コマンドライン引数を読む
  if (argc < 3) {
    std::cerr << "画像ファイルのパスを指定してください。" << std::endl;
    return -1;
  }
  std::string input_image_path  = argv[1];
  std::string output_image_path = argv[2];

  // 画像を読み込む
  // アルファチャンネル付きに対応するため IMREAD_UNCHANGED を使う
  cv::Mat input_image = cv::imread(input_image_path, cv::IMREAD_UNCHANGED);

  // Haar 特徴ベースのカスケード分類器による物体検出の準備
  // 顔検出用のカスケード分類器を使用
  std::string face_cascade_name =
    "/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml";
  cv::CascadeClassifier face_cascade;
  if (!face_cascade.load(face_cascade_name)) {
    std::cerr << "分類器の読み込みに失敗しました。" << std::endl;
    return -1;
  };

  // 顔を検出
  std::vector<cv::Rect> faces;
  face_cascade.detectMultiScale(input_image, faces);

  // 出力画像データを入れるオブジェクト
  // アルファチャンネル付きに対応するため CV_8UC4 を使う
  // CV_<bit-depth>{U|S|F}C(<number_of_channels>)
  // CV_8U: ビット深度=符号なし8ビット整数(0〜255)
  // C4: チャンネル数=4
  cv::Mat output_image(input_image.size(), CV_8UC4);

  // 入力画像データを出力画像データにコピー
  input_image.copyTo(output_image);

  for (size_t i=0; i<faces.size(); i++) {
    // 検出した顔の座標を出力
    std::cout << "Face: " << faces[i] << std::endl;
    // 顔の位置に楕円を描画
    cv::Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
    cv::Size size(faces[i].width / 2, faces[i].height / 2);
    cv::Scalar color(255, 0, 255, 255); // Blue, Green, Red, Alpha
    double angle = 0;
    double startAngle = 0;
    double endAngle = 360;
    int thickness = 4;
    cv::ellipse(output_image, center, size, angle, startAngle, endAngle, color, thickness);
  }

  // 画像を出力
  cv::imwrite(output_image_path, output_image);

  return 0;
}

問題点、わからないところ

基本的にはPython側で処理をしていて重い作業をC++で行う予定です。

Pythonで読み込んだデータをC++でOpencvで画像処理をする場合はどのように受け渡しをするのかが今まで行ったことがないのでわかりません。

Q.pythonでimreadしたデータを上記のように、Matという型の変数で受け取るとるのは間違っていますか?

それとも処理ごとにファイルの書き込みを行って、共有ファイルとして画像を毎回imreadしていくのでしょうか?

基本がわからないのでご教授いただけたら嬉しいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

Pythonで読み込んだデータをC++でOpencvで画像処理をする

C++でやりたいことがOpenCVに用意されてる関数を実行することだけなら、Pythonでopencv-pythonまたはopencv-contrib-pythonをimportしてopencvの関数を実行するのと、上記は実質変わりません
Pythonでopencvの関数を実行する際には、OpenCVの共有ライブラリ内の関数がPythonから呼び出されて実行されるのですが、その共有ライブラリはC++のOpenCVのコードをコンパイルして作られたものだからです

もちろん、自分で画像処理をC++で書いて、それをPythonから呼び出すのであれば、A_kirisakiさんもお書きになっているように、ctypesとかcffiとかpybind11とか使って組み込む必要があります

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/01/03 22:01

    > I_am_ さん
    Boost::Python は C++ の中で Python を動かす仕組みなので関係がひっくり返ってるかもしれません。Python でデータを読んでもらって C++ に渡すと考えたら逆の感じがしません?

    キャンセル

  • 2021/01/03 22:02

    > Boostpythonではなくてctypesとかcffiとかpybind11を使用して組み込みを行う方がいいということでしょうか??

    このあたりを参考に
    https://qiita.com/ignis_fatuus/items/c7523c0fe2bc2f415d50
    https://buildersbox.corp-sansan.com/entry/2019/12/09/110000

    キャンセル

  • 2021/01/03 22:32

    >A_kirisaki
    なるほど理解しました!
    >jbpb0さんの紹介していただいた記事を参考に、Python/C APIで開発を進めてみます。
    Python/C API::https://cpp-learning.com/python_c_api_step1/

    キャンセル

+2

このようなケースでは Python が親プログラムとなり C++ が子プログラムとして関数を差し出しそれを Python が呼び出す、という形になります。そのようなことを実現するために ctypes というパッケージが用意されています。ただし渡せる型は限られていること、メモリの管理を覚える必要があることに注意して使ってください。

追記:
jbpb0 さんが述べられている通り OpenCV はコンパイル済みのバイナリを呼び出しますので C++ で呼び出しても実行速度はほぼ変わりません。C++ 側で追加の画像処理をガッツリ書く必要がある場合でないと有効でないでしょう。また、ppaul さんによればわたしの挙げた ctypes より Python/C API の方がより高速だそうです(知らんかった……)。

いずれにせよ問題点は「高速化」ということらしいですので OpenCV ならば GPU が使えないか検討すると良いかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る