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

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

新規登録して質問してみよう
ただいま回答率
85.38%
C++/CLI

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

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

ダイアログ

ユーザーにウィンドウやボックス等の形で個別で表示されるフォームであり、ユーザーに判断を促す目的で表示される。ユーザーが見逃す事のないよう、操作中のフォーム上にポップアップして表示される。

Q&A

解決済

2回答

23280閲覧

Bitmap、Mat間の変換

hsgru3

総合スコア22

C++/CLI

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

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

ダイアログ

ユーザーにウィンドウやボックス等の形で個別で表示されるフォームであり、ユーザーに判断を促す目的で表示される。ユーザーが見逃す事のないよう、操作中のフォーム上にポップアップして表示される。

0グッド

0クリップ

投稿2019/11/26 06:09

編集2019/11/27 06:47

前提・実現したいこと

C++/CLIのWindowsFormsアプリケーションで画像処理のプログラムを作成しています。
ファイル選択ダイアログで選択した画像を表示させ、その隣にOpenCVで画像処理したものを表示させようとしていますがファイル選択ダイアログで選択したビットマップファイルをMatへ変換及び、Matからビットマップファイルへの変換方法がわからず困っています。
Bitmap→Mat、Mat→Bitmapの変換について教えていただきたいです。

該当のソースコード

下記のコードはボタンをクリックするとファイル選択ダイアログが開かれ選択した画像をpicturebox1に表示し、画像処理したものをpicturebox2に表示させようとしています。

C++

1 private: System::Void button_Click(System::Object^ sender, System::EventArgs^ e) { 2 //ファイルを開くダイアログの作成 3 OpenFileDialog^ dlg = gcnew OpenFileDialog; 4 //ファイルフィルタ 5 dlg->Filter = "画像ファイル(*.bmp,*.jpg,*.png,*.tif,*.ico)|*.bmp;*.jpg;*.png;*.tif;*.ico"; 6 //ダイアログの表示 (Cancelボタンがクリックされた場合は何もしない) 7 if (dlg->ShowDialog() == System::Windows::Forms::DialogResult::Cancel) return; 8 //ビットマップファイルから、元画像Bitmapを作成 9 Bitmap^ bmp1 = gcnew Bitmap(dlg->FileName); 10 //picturebox1に表示 11 pictureBox1->Image = bmp1; 12 //ビットマップファイルから、処理用Bitmapを作成 13 Bitmap^ bmp2 = gcnew Bitmap(dlg->FileName); 14-------------------------------- 15ファイル選択ダイアログで選択したbmp2をMatに変換 16            ↓ 17      OpenCVを用いて画像処理 18            ↓ 19画像処理済みのMatをビットマップファイル(bmp3とか)に変換 20-------------------------------- 21 //picturebox2に画像処理したものを表示 22         pictureBox2->Image = bmp3; 23 }

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

Visual studio community 2015
OpenCV 3.4.0

###追記

下記のコードはBitmapをMatに変換するのではなくファイル選択で選んだパス(dlg->FileName)をSystem::String ^型からstd::stringに変換してimreadで読み込ませています。そのあとimreadで読み込んだ画像を画像処理してからpicureBox2に表示させようとしています。
ここで問題なのですがimshowで表示させた時点で上下左右反転しdrawImage関数でpictureBox2に表示させると画像が崩れてしまいます。
申し訳ございませんがヒントや参考になりそうなサイト等でも教えていただけると幸いです。

C++

1 private: System::Void button_Click(System::Object^ sender, System::EventArgs^ e) { 2 //ファイルを開くダイアログの作成 3 OpenFileDialog^ dlg = gcnew OpenFileDialog; 4 //ファイルフィルタ 5 dlg->Filter = "画像ファイル(*.bmp,*.jpg,*.png,*.tif,*.ico)|*.bmp;*.jpg;*.png;*.tif;*.ico"; 6 //ダイアログの表示 (Cancelボタンがクリックされた場合は何もしない) 7 if (dlg->ShowDialog() == System::Windows::Forms::DialogResult::Cancel) return; 8 //ビットマップファイルから、元画像Bitmapを作成 9 Bitmap^ bmp1 = gcnew Bitmap(dlg->FileName); 10 //picturebox1に表示 11 pictureBox1->Image = bmp1; 12 13    //ファイル選択ダイアログで選択したファイルのパス(dlg->FileName(System::String ^型))をstd::stringに変換 14 string imgfl = msclr::interop::marshal_as<std::string>(dlg->FileName); 15 //imreadでよみこむ 16     Mat img = imread(imgfl); 17     -------------------------- 18      OpenCVを用いて画像処理 19 -------------------------- 20 //picturebox2に画像処理したものを表示 21 drawImage(pictureBox2, img); 22 } 23 //描画 24 private: System::Void drawImage(PictureBox^ pic, Mat mat) { 25 26 if ((pic->Image == nullptr) || (pic->Width != mat.cols) 27 || (pic->Height != mat.rows)) { 28 pic->Width = mat.cols; 29 pic->Height = mat.rows; 30 Bitmap^ bmpPicBox = gcnew Bitmap(pic->Width, pic->Height); 31 pic->Image = bmpPicBox; 32 } 33 Graphics^g = Graphics::FromImage(pic->Image); 34 Bitmap^ bmp = gcnew Bitmap(mat.cols, mat.rows, mat.step, 35 System::Drawing::Imaging::PixelFormat::Format32bppRgb, IntPtr(mat.data)); 36 g->DrawImage(bmp, 0, 0, mat.cols, mat.rows); 37 pic->Refresh(); 38 delete g; 39 }

左からBitmapで読み込んでpictureBox1に出力したもの、Matで読み込んでpictureBox2に表示させたもの、Matで読み込んでimshowで表示させたものです。
まずimreadで読み込まれた際になぜか上下左右が反転してしまい、pictureBox2に出力しようとすると画像が崩れてしまいます。
イメージ説明

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

OpenCVで直接、Bitmapファイルを読み込めますが、それは使えませんか?
入出力とGUI

.NETで読み込んだBitmap形式を OpenCVのMAT形式に変換するのは、ちょっと面倒でした。ただ、同様の質問もあり、Bitmapを変換する方法 は参考になるでしょうか?

読み込んだBitmap形式をMAT形式に変換した事もありますが、ちょっと面倒。
Bitmapデータのメモリ内のデータを直接、MAT形式にするのですが、.NETなので、内部データアクセスのため、メモリの直接、参照が必要。で、その後、配列データとして、MAT配列にコピー。即答できるほど中身を覚えてません。
調べるのは可能ですが、すぐに分かる人いないかな、、と。
なお、Bitmapのピクセル読み出しは、一桁以上遅くなります。ご注意を。

あと、タグに OpenCV も入れた方が回答付かないでしょうか?


既に解決済みとなっていますが、手元で、Bitmap(Format: Format24bppRgb)から、Matイメージに変換したコードです。

C++

1// Format24bppRgb イメージから、Matデータを作成 2void Bmp24ToMat(Bitmap ^img, cv::Mat *matImg) 3{ 4 Imaging::BitmapData ^bmpData = img->LockBits( 5 Rectangle(0, 0, img->Width, img->Height), 6 Imaging::ImageLockMode::ReadOnly, Imaging::PixelFormat::Format24bppRgb); 7 try { 8 *matImg = cv::Mat(img->Height, img->Width, CV_8UC3); 9 uchar *bmpSrc = (uchar *)bmpData->Scan0.ToPointer(); // Bitmapデータのポインタ 10 int srcLineSize = bmpData->Stride; // 1行あたりの byteサイズ 11 int imgHeight = img->Height; 12 int imgWidth = img->Width; 13 for (int line = 0; line < imgHeight; line++) { 14 uchar *src = (uchar *)&bmpSrc[line * srcLineSize]; 15 uchar *dst = matImg->ptr(line); 16 for (int cols = 0; cols < imgWidth; cols++) { 17 dst[0] = src[2]; // B 18 dst[1] = src[1]; // G 19 dst[2] = src[0]; // R 20 src += 3; 21 dst += 3; 22 } 23 } 24 } finally { 25 img->UnlockBits(bmpData); // ロックの解除 26 } 27}

24bitフォーマット限定なのは、手元のデータがこれで十分だったためと、他の形式を調べるのが面倒だったためです。
Bitmap と、MAT形式で、RGB(Bitmap)と、BGR(MAT)で順序が違うのに注意。

参考情報として置いておきます。

投稿2019/11/26 13:34

編集2019/11/27 13:27
pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hsgru3

2019/11/27 06:51

回答ありがとうございます。 教えていただいた通りBitmapのままimreadで読み込ませるやり方でしてみました。 BitmapのままOpenCVで読み込み画像処理後pictureBoxへの表示を試みました。 なんとかコンパイルを通るものはできましたが画像が崩れてしまいます。 何かヒント等ございましたら教えていただきたいです。
hsgru3

2019/11/27 08:53

返信ありがとうございます。 いろいろ試してみた結果、pictureBoxに表示するBitmap作成の時の引数を調整するとうまくいきました。 何度も対応していただきありがとうございました。
hsgru3

2019/11/28 04:10

追記ありがとうございます。 ヒントだけでなく関数まで教えていただき助かりました。 今後また質問させていただくと思いますで、その時はよろしくお願いいたします。
guest

0

ベストアンサー

以下と同じですかね?


C++/CLIです。
BitmapをOpenCVのMatに変換するにはどのようにしたらよいのでしょうか。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12161297752


追記:

手元のVS2015でNuGetからC++/CLIのテンプレで作ったプロジェクトにOpenCvSharpを入れてみましたが、
何故か参照に追加されなかったので手動で
(プロジェクトフォルダ)\packages\OpenCvSharp-AnyCPU.2.4.10.20170306\lib\net45*.dll
を追加しました。

あとは普通にコンパイルは通りました。
イメージ説明

OpenCVには詳しくないので適当な事を言いますが、
Bitmap型も各ピクセルにポインタ経由でアクセス出来ますので、
自分でコンバートすることもできそうかなと思いました。
フォーマットが違うとちょっと面倒くさいですが・・・。
(BitmapはGIFとか読み込むとRGBAにならなかったような気がしたので)

投稿2019/11/26 06:17

編集2019/11/26 08:42
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hsgru3

2019/11/26 07:21

回答ありがとうございます。 ページの通りNuGetでNuGetからOpenCvSharp-AnyCPUをインストールし、OpenCvSharp.Extensions.BitmapConverter.ToMat()を使って変換しようとしましたがエラーがでて実行までできませんでした。 やはりOpenCvSharpはあくまでC#でC++のOpenCVの機能を持たせるものなのかなとおもいましたので、挙げていただいたページの回答者はC++/CLIとC#を見間違えたのかなとも思いました。 しかしながらOpenCvSharp-AnyCPUのサポートページ?(https://shimat.github.io/opencvsharp_docs/html/b75b74b9-4126-5a73-6580-d07885a75e6d.htm)を見てみるとC++のタブもあり使えそうな感じもありました。
takabosoft

2019/11/26 07:24

.NETであればC#でもC++/CLIでもVBでも使えると思いますけどねえ。 もちろん、 OpenCvSharp::Extensions::BitmapConverter::ToMat()のようにC++の書き方をしないとコンパイルは通らないと思いますが。
hsgru3

2019/11/26 07:37

返信ありがとうございます。 返信していただいた通りC++の書き方をしていましたがコンパイルは通っていません。 初歩的な質問で申し訳ありませんが、名前の後に`::~`をつけることができるのは~~と表示されている場合はどういうところを確認するとよいのか教えていただきたいです。
takabosoft

2019/11/26 08:43

ちょいと質問の意味がわからなかったので、自分で試した結果を追記しておきます。
hsgru3

2019/11/26 09:17

追記ありがとうございます。 未熟なこちらの質問に答えていただきありがとうございます。 今後また何かお聞きすることがあると思いますのでその際はどうぞよろしくお願いいたします。
hsgru3

2019/11/26 09:57 編集

申し訳ございませんが、追記の通り手動で参照に追加してコンパイルしてみましたが未解決のトークン、外部シンボルがらみのエラーが散見されました。 ----------------------- エラー LNK2028 未解決のトークン (0A0006F4) "public: void __cdecl cv::UMat::copySize(class cv::UMat const &)" (?copySize@UMat@cv@@$$FQEAAXAEBV12@@Z) が関数 "public: __cdecl cv::UMat::UMat(class cv::UMat const &)" (??0UMat@cv@@$$FQEAA@AEBV01@@Z) で参照されました。 pollenpick C:\Users\aselab\Documents\Visual Studio 2015\Projects\pollenpick\pollenpick\main.obj 1 エラー LNK2019 未解決の外部シンボル "public: void __cdecl cv::UMat::copySize(class cv::UMat const &)" (?copySize@UMat@cv@@$$FQEAAXAEBV12@@Z) が関数 "public: __cdecl cv::UMat::UMat(class cv::UMat const &)" (??0UMat@cv@@$$FQEAA@AEBV01@@Z) で参照されました。 pollenpick C:\Users\aselab\Documents\Visual Studio 2015\Projects\pollenpick\pollenpick\main.obj 1 エラー LNK2019 未解決の外部シンボル "public: void __cdecl cv::Mat::copySize(class cv::Mat const &)" (?copySize@Mat@cv@@QEAAXAEBV12@@Z) が関数 "public: __cdecl cv::Mat::Mat(class cv::Mat const &)" (??0Mat@cv@@QEAA@AEBV01@@Z) で参照されました。 pollenpick C:\Users\aselab\Documents\Visual Studio 2015\Projects\pollenpick\pollenpick\main.obj 1 エラー LNK1120 3 件の未解決の外部参照 pollenpick C:\Users\aselab\Documents\Visual Studio 2015\Projects\pollenpick\x64\Debug\pollenpick.exe 1 ---------------------- なにか解決策があれば教えていただきたいです。
pepperleaf

2019/11/26 13:21

> Bitmap型も各ピクセルにポインタ経由でアクセス出来ますので、 各ピクセルを読み出す関数はありますが、それを使ってビットマップデータをMAT形式に変換すると、非常に時間がかかります。直接、参照すべきです。
takabosoft

2019/11/27 00:27 編集

〒hsgru3さん > 未解決のトークン、外部シンボルがらみのエラーが散見されました。 その辺のエラーってOpenCV 3.4.0側のリンクエラーじゃないですかね? 〒pepperleafさん > 各ピクセルを読み出す関数はありますが、それを使ってビットマップデータをMAT形式に変換すると、非常に時間がかかります。直接、参照すべきです。 「直接、参照」の意味がわかりませんが、楽な方法があるようでしたら提示してあげてください。 BitmapもGetPixelやSetPixelだと遅いですが、LockBitsしてポインタ操作で画素にアクセスしてあげれば、かなり高速に動作しますよ。
takabosoft

2019/11/27 00:39

OpenCvSharp::Extensions::BitmapConverter::ToMat()で戻ってくるのは OpenCvSharp::CPlusPlus::Mat^型なので、結局OpenCV 3.4.0側のMat型とは別のものになっているので、 なんかちょっと違う気がしてきました。 全部OpenCvSharpで出来るのでしたらそちらに統一した方が良いのかもしれません。 (足りない機能があったら困りますが。)
hsgru3

2019/11/27 06:58

返信ありがとうございます。 エラーに関してはOpenCV3.4.0がらみのものでした。教えていただきありがとうございます。 おっしゃっていただいた通りOpenCvSharp::CPlusPlus::Mat^型の扱いが難しそうなので追記のようにやり方を変えてみました。 発生した問題としてはMat型のものをBitmapに置き換えてpictureBoxに表示させるところで画像が崩れるところです。 何かヒント等ございましたら教えていただきたいです。
takabosoft

2019/11/27 08:13

OpenCV知らないのでなかなかドンピシャな回答だせなくてすみません。 pepperleafさんの回答の「入出力とGUI」をみた感じでは、 OpenCVで画像処理をしたあとに、そのままファイル出力もできるようなので、一旦PNGで書き出したあとに、Bitmapで読んだらどうでしょうか? これが一番ラクな気がします。
hsgru3

2019/11/27 08:52

返信ありがとうございます。 いろいろ試してみた結果、pictureBoxに表示するBitmap作成の時の引数を調整するとうまくいきました。 何度も対応していただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.38%

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

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

質問する

関連した質問