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

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

新規登録して質問してみよう
ただいま回答率
86.12%
YOLO

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

C++/CLI

C++/CLIは、.NET Frameworkの共通言語基盤であるCLI向けにC++を拡張したプログラム言語です。前身のC++マネージ拡張と比較するとシンプルで分かりやすい構文になっており、高い可読性を持ちます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

受付中

opencv dnnモジュールで連続して検出できない

Soogle44
Soogle44

総合スコア8

YOLO

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

C++/CLI

C++/CLIは、.NET Frameworkの共通言語基盤であるCLI向けにC++を拡張したプログラム言語です。前身のC++マネージ拡張と比較するとシンプルで分かりやすい構文になっており、高い可読性を持ちます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

1回答

0リアクション

0クリップ

707閲覧

投稿2021/08/21 08:09

編集2021/08/27 02:22

前提・実現したいこと

C++/CLIにて学習済みのモデルを使って物体検出のプログラムの作成をしています。

https://github.com/opencv/opencv/blob/3.4.15/samples/dnn/object_detection.cpp
こちらのopencvのサンプルを参考にファイル選択ダイアログで画像、設定ファイル(.cfg,.prototxt)、モデルファイル(.weights,.caffemodel)を選択して、ピクチャーボックスに検出結果を表示するようなWindowsフォームアプリケーションを作成しました。

アプリの動作の流れとしては画像選択→設定ファイル・モデルファイル選択→検出→検出結果画像の描画となっています。
困っていることとしては、アプリを起動して1度目は検出結果画像の描画までうまくいくのですが、その後選択するモデルを切り替えてもう一度検出しようとすると、うまく検出できていない画像が表示されてしまいます。
(画像選択→設定ファイル・モデルファイル選択→検出→検出結果画像の描画→別の設定ファイル・モデルファイル選択→検出→検出結果画像の描画の順序だとうまくいかない)

なにかアイデアなどあれば教えていただきたいです。
よろしくお願いいたします。

発生している問題・エラーメッセージ

アプリ起動後はじめのyolo検出
イメージ説明

yolo検出後のmobilenetssd検出
イメージ説明

アプリ起動後はじめのmobilenetssd検出
イメージ説明

mobilenetssd検出後のyolo検出
イメージ説明

該当のソースコード

c++

#pragma once #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <msclr\marshal_cppstd.h> #include <opencv2/opencv.hpp> #include "common.hpp" std::string imgpath = "", cfg = "", model = ""; dnn::Net *net = NULL; std::vector<cv::String> outNames; int selectModel = NOMODEL; namespace opencvdetectgui { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; //////////////////////////////////////////////////////////////////////// ////////////////////省略//////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// } #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { //ファイル選択ダイアログでもととなる画像を選択して左側のピクチャーボックスに描画 } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {     //ファイル選択ダイアログで設定ファイル(.cfg,.prototxt)、モデルファイル(.weights,.caffemodel)の選択 } private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) { //接待ファイル、モデルの読み込み dnn::Net net = readNet(model, cfg); net.setPreferableBackend(0); net.setPreferableTarget(0); outNames = net.getUnconnectedOutLayersNames(); //ビデオキャプチャの取得(後々カメラ映像で検出したいためこのように書いています) VideoCapture cap; if (imgpath != "") cap.open(imgpath); else cap.open(0); cv::Mat frame, blob; cap >> frame; //yolo,mobilenetssdそれぞれのパラメータで読み込んで検出 if (selectModel == YOLO) { preprocess(frame, net, cv::Size(416, 416), 0.00392, cv::Scalar(0, 0, 0), true); } else if (selectModel == SSD) { preprocess(frame, net, cv::Size(300, 300), 0.007843, cv::Scalar(127.5, 127.5, 127.5), false); } std::vector<Mat> outs; net.forward(outs, outNames); postprocess(frame, outs, net, 0); //検出したバウンディングボックスの書き込み std::vector<double> layersTimes; double freq = getTickFrequency() / 1000; double t = net.getPerfProfile(layersTimes) / freq; std::string label = format("Inference time: %.2f ms", t); putText(frame, label, cv::Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0)); //検出結果画像を右側のピクチャーボックスのサイズに調整してから表示 cv::Mat mat_pb(pictureBox2->Height, pictureBox2->Width, CV_8U); cv::resize(frame, frame, mat_pb.size()); drawImage(pictureBox2, frame); } }; }

common.hppは以下のものをコピペしました。
(https://github.com/opencv/opencv/blob/3.4.15/samples/dnn/common.hpp)

試したこと

アプリ起動→yolo検出(正常)→mobilenetssd検出(異常)→yolo検出(正常)
となるのでなにかの変数が検出ごとに初期化されずに保存されていることが原因なのですが、その変数がわからず困っています。
common.hppの関数でstaticで宣言されているところも確認しましたが改善されませんでした。

補足情報(FW/ツールのバージョンなど)

opencv 3.4.15
visual studio 2019
Windows 10 64 bit

追記

モデルを読み込んでから検出して描画まで複数の関数があるのですが、その中でどの関数を検出手法間で共有(SSDで使ってからYOLOで使う)すると不具合が起きるのか調べてみました。

調べたところ、postprocess()という関数を共有すると不具合が起こっているようです。
一応postprocess()と内容が同じ関数のpostprocess_yolo()とpostprocess_ssd()を定義して、共有しないようにするととりあえず画像に関しては連続して(SSD検出後にYOLO検出)は問題なくできるようにはなりました。

ただ理由がわからず困っています。

以下のような質問にはリアクションをつけましょう

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

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

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

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

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

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

YOLO

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

C++/CLI

C++/CLIは、.NET Frameworkの共通言語基盤であるCLI向けにC++を拡張したプログラム言語です。前身のC++マネージ拡張と比較するとシンプルで分かりやすい構文になっており、高い可読性を持ちます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。