C#でOpenCVの画像を表示させたくて苦労する2
ゴールデンウィークはC#の文法の勉強してました。何となくわかってきましたが、.netの方が大きすぎてどこから手をつければいいのか戸惑ってます。イベントループとか.netの設計の思想とかまとめた資料はあるのかな。
前の日記でOpenCVの画像を表示させようとしましたが、謎の変換をしていて非常に気持ち悪いので、wpfは止めてフォームにしました。どうもcv::MatのアライメントがC#とは違うみたいで、p_mat_というポインタを作って何とかしています。OpenCVのC#向けライブラリを使うと簡単に変換できそうな気がするので(未確認ですが)、そちらを使った方がいいと思います。
見た目はこんな感じです。ボタンを押すとファイル選択ダイアログが表示されて、選択した画像がpicutureBoxに表示されます。
using System; using System.Threading.Tasks; using System.Windows.Forms; using Wrapper; namespace WindowsFormsApplication1 { public partial class Form1 : Form { private readonly ImageProcess _imageprocess = new ImageProcess(); public Form1() { InitializeComponent(); } private async void button1_Click(object sender, EventArgs e) { var fd = new OpenFileDialog { Filter = @"Image Files(*.jpg)|*.jpg" }; if (fd.ShowDialog() == DialogResult.OK) { this.toolStripStatusLabel1.Text = fd.FileName; var bitmap = await Task.Run(() => _imageprocess.Process(fd.FileName)); this.pictureBox1.Image = bitmap; } else { this.toolStripStatusLabel1.Text = @"画像がないよ"; } } private Task<System.Drawing.Bitmap> ProcessInNativeTaskAsync(string filename) { return Task.Run(() => _imageprocess.Process(filename)); } } }
#pragma once #using <System.Drawing.dll> #include <opencv2/core/core.hpp> namespace Wrapper { public ref class ImageProcess { public: ImageProcess(); ~ImageProcess(); !ImageProcess(); System::Drawing::Bitmap^ Process(System::String^ filename); private: System::Drawing::Bitmap^ GetBitmap(cv::Mat_<cv::Vec3b>& image); cv::Mat_<cv::Vec3b> *p_mat_; }; }
#include "ImageProcess.h" #using <System.Windows.Forms.dll> #include <msclr/marshal_cppstd.h> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> namespace Wrapper { ImageProcess::ImageProcess() : p_mat_(nullptr) { } ImageProcess::~ImageProcess() { this->!ImageProcess(); } ImageProcess::!ImageProcess() { if (p_mat_ != nullptr) delete p_mat_; } System::Drawing::Bitmap^ ImageProcess::Process(System::String^ filename) { using namespace msclr::interop; cv::Mat_<cv::Vec3b> image = cv::imread(marshal_as<std::string>(filename)); if (image.empty()) { System::Windows::Forms::MessageBox::Show(filename + "はないよ"); } return GetBitmap(image); } System::Drawing::Bitmap^ ImageProcess::GetBitmap(cv::Mat_<cv::Vec3b>& image) { const int alignment = 4; const int new_cols = cv::alignSize(image.cols, alignment); if (p_mat_ == nullptr) { p_mat_ = new cv::Mat_<cv::Vec3b>(image.rows, new_cols); } else if (p_mat_->cols != new_cols || p_mat_->rows != image.rows) { delete p_mat_; p_mat_ = new cv::Mat_<cv::Vec3b>(image.rows, new_cols); } cv::Mat_<cv::Vec3b> roi_mat(*p_mat_, cv::Rect(0, 0, image.cols, image.rows)); image.copyTo(roi_mat); System::Drawing::Bitmap^ dst = gcnew System::Drawing::Bitmap(roi_mat.cols, roi_mat.rows, roi_mat.step, System::Drawing::Imaging::PixelFormat::Format24bppRgb, System::IntPtr(roi_mat.data)); return dst; } }