Search This Blog

Thursday, November 23, 2017

OpenCV with wxWidgets

  1. နိဒါန်း
  2. Linux
  3. Windows
  4. အကိုးအကားများ

နိဒါန်း

OpenCV ကို wxWidgets နဲ့ တွဲသုံး တဲ့ အကြောင်း ဆွေးနွေး ချင် ပါတယ်။ အဲဒီ အတွက် OpenCV နဲ့ wxWidgets တို့ကို တပ်ဆင် ထားဖို့ လိုပါ တယ်။ သူတို့ ကို platform အမျိုးမျိုး အတွက် တပ်ဆင်တဲ့ အကြောင်း တွေကို အောက်က လင့်ခ် တွေမှာ ဖတ်နိုင် ပါတယ်။

Linux

Linux နဲ့ terminal ပေါ်မှာ command ရိုက်ထည့် ပြီး build လုပ်တာ လွယ်ကူ ရိုးရှင်း ပါတယ်။ နမူနာ အနေနဲ့ wxcvsimple.cpp (online) ဆိုတဲ့ ရိုးရှင်း တဲ့ ပရိုဂရမ် လေး တစ်ခု ရေးကြည့် ပါမယ်။ ပရိုဂရမ် အစမှာ Application ရဲ့ OnInit() ဆိုတဲ့ method ထဲမှာ
wxInitAllImageHandlers();
ဆိုတာကို ထည့်ပါမယ်။ အဲဒီနောက် MyFrame ဆိုတဲ့ wxFrame ရဲ့ derived class ထဲမှာ ပုံရိပ် တွေကို ဖော်ပြဖို့ wxStaticBitmap variable တွေကို ကြေငြာ လိုက် ပါမယ်။ MyFrame ရဲ့ constructor မှာ wxStaticBitmap တွေကို ဖန်တီးဖို့ အောက်က ကုဒ် ကို သုံးနိုင် ပါတယ်။

lena = new wxStaticBitmap(this,wxID_ANY,wxBitmap(wxT("lena.jpg"),
 wxBITMAP_TYPE_JPEG),wxPoint(0,0),wxSize(256, 256));


Image တွေ အတွက် OpenCV မှာသုံးတဲ့ Mat နဲ့ wxWidgets ရဲ့ wxImage ကို အပြန် အလှန် ပြောင်း ပေးတဲ့ mat_from_wx ၊ wx_from_mat အစ ရှိတဲ့ ဖန်ရှင် တွေကို အောက်က util.h (online) ဆိုတဲ့ စာရင်း ထဲမှာ ဖော်ပြ ထား ပါတယ် [Dad10; pkl15]။
//File: util.h
//Description: Functions to convert wxImage and OpenCV Mat
//Author: Yan Naing Aye
//MIT License - Copyright (c) 2017 Yan Naing Aye
#include < wx/wx.h >
#include < opencv2/opencv.hpp >
using namespace cv;
wxImage wx_from_mat(Mat &img) {
    Mat im2;
    if(img.channels()==1){cvtColor(img,im2,CV_GRAY2RGB);}
 else if (img.channels() == 4) { cvtColor(img, im2, CV_BGRA2RGB);}
    else {cvtColor(img,im2,CV_BGR2RGB);}
 long imsize = im2.rows*im2.cols*im2.channels();
    wxImage wx(im2.cols, im2.rows,(unsigned char*)malloc(imsize), false);
 unsigned char* s=im2.data;
 unsigned char* d=wx.GetData();
 for (long i = 0; i < imsize; i++) { d[i] = s[i];}
    return wx;
}
Mat mat_from_wx(wxImage &wx) {
    Mat im2(Size(wx.GetWidth(),wx.GetHeight()),CV_8UC3,wx.GetData());
    cvtColor(im2,im2,CV_RGB2BGR);
    return im2;
}
Listing. util.h

ဆက်ပြီး MyFrame ရဲ့ constructor ထဲမှာ သီရိ ရဲ့ ပုံကို OpenCV သုံးပြီး imread နဲ့ ဖတ်လိုက် ပါတယ်။ ဖတ်လို့ ရတဲ့ Mat အမျိုး အစား ပုံကို wx_from_mat ဖန်ရှင် ကို သုံးပြီး wxImage အမျိုး အစား ပြောင်းလိုက် ပါတယ်။ ပြီးတော့ wxStaticBitmap ရဲ့ SetBitmap method သုံးပြီး Frame ပေါ်မှာ ဖော်ပြ လိုက် ပါတယ်။

နောက်တစ်ခါ wxImage အမျိုး အစား variable တစ်ခု ကြေငြာ ပြီး LoadFile method နဲ့ လီနာ ရဲ့ ပုံကို wxWidget သုံးပြီး ဖတ်လိုက် ပါတယ်။ ရလာ တဲ့ wxImage အမျိုး အစား ပုံကို mat_from_wx ဆိုတဲ့ ဖန်ရှင် သုံးပြီး OpenCV အတွက် Mat အမျိုး အစား ပြောင်းလိုက် ပါတယ်။ ရလာတဲ့ ပုံရိပ်ကို OpenCV ရဲ့ imshow နဲ့ ဖော်ပြ လိုက် ပါတယ်။ ပရိုဂရမ် wxcvsimple.cpp ကို အောက်က စာရင်း wxcvsimple.cpp (online) မှာ တွေ့နိုင် ပါတယ်။
//File: wxcvsimple.cpp
//Description: A simple example to use OpenCV with wxWidgets
//Author: Yan Naing Aye
//Date: 2017 November 01
//MIT License - Copyright (c) 2017 Yan Naing Aye

#include < wx/wx.h >
#include < opencv2/opencv.hpp >
#include "util.h"
using namespace cv;

class MyFrame : public wxFrame
{
    wxStaticBitmap *lena;
    wxStaticBitmap *thiri;
public:
    MyFrame(const wxString& title);

};
MyFrame::MyFrame(const wxString& title)
  : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(512, 256))
{
    Centre();
    lena = new wxStaticBitmap(this,wxID_ANY,wxBitmap(wxT("lena.jpg"),
  wxBITMAP_TYPE_JPEG),wxPoint(0,0),wxSize(256, 256));
    thiri = new wxStaticBitmap(this,wxID_ANY,wxBitmap(wxT("lena.jpg"),
  wxBITMAP_TYPE_JPEG),wxPoint(256,0),wxSize(256, 256));

    //From opencv to wx
    Mat imcv1=imread("thiri.jpg",CV_LOAD_IMAGE_COLOR);
    wxBitmap imwx1=wx_from_mat(imcv1);
    thiri->SetBitmap(imwx1);

    //From wx to opencv
    wxImage imwx2;
    imwx2.LoadFile(wxT("lena.jpg"), wxBITMAP_TYPE_JPEG);
    Mat imcv2=mat_from_wx(imwx2);
    namedWindow("Img",CV_WINDOW_AUTOSIZE);
    imshow("Img",imcv2);
}

class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
    if ( !wxApp::OnInit() )
        return false;
    wxInitAllImageHandlers();
    MyFrame *frame = new MyFrame(wxT("Simple wxWidgets + OpenCV"));
    frame->Show(true);

    return true;
}
Listing. wxcvsimple.cpp

ပရို ဂရမ် ကို build လုပ်ဖို့ အတွက် terminal မှာ အောက်က command ကို သုံးနိုင် ပါတယ်။
g++ wxcvsimple.cpp util.h `wx-config --cxxflags --libs std`
        `pkg-config --cflags --libs opencv` -o wxcvsimple
./wxcvsimple ကို ရိုက်ပြီး run လိုက်တဲ့ အခါ ရလာတဲ့ ရလဒ် ကို အောက်က ပုံ မှာ တွေ့နိုင် ပါတယ်။

Figure. wxWidgets နှင့် OpenCV ကို တွဲစပ် အသုံးပြု ထားသည့် ရိုးရှင်းသော နမူနာ။


Code::Blocks

Code::Blocks မှာ wxWidgets ကို OpenCV နဲ့ တွဲသုံး ဖို့အတွက် wxWidgets project အသစ် တစ်ခု ကို အောက်က ပုံ မှာ ဖော်ပြ ထားတဲ့ အတိုင်း empty project တစ်ခု ဖန်တီးပြီး wxcv (online) ဆိုတဲ့ project နာမည် ပေးလိုက် ပါမယ်။ ပြီးတဲ့ အခါ GNU GCC Compiler ကို ရွေး ပါမယ်။

Figure. Code::Blocks တွင် Empty project တစ်ခု ဖန်တီးခြင်း။


File Menu → New → Empty File ကို နှိပ်ပြီး အောက်က စာရင်း မှာ ပြထားတဲ့ wxcv.cpp ဖိုင်ကို ဖန်တီး လိုက် ပါမယ်။
#include < wx/wx.h >
#include < opencv2/opencv.hpp >
using namespace cv;

class Simple : public wxFrame
{
public:
    Simple(const wxString& title);

};
Simple::Simple(const wxString& title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
{
  Centre();
  Mat img=imread("grove.jpg",CV_LOAD_IMAGE_COLOR);
  namedWindow("Img",CV_WINDOW_AUTOSIZE);
  imshow("Img",img);
}

class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
    Simple *simple = new Simple(wxT("Simple"));
    simple->Show(true);

    return true;
}
Listing. wxcv.cpp

ပြီးရင် Project Menu → Build Options... ကို နှိပ်ပြီး Compiler settings tab → Other compiler options မှာ အောက်က ပုံ အတိုင်း
`wx-config --cxxflags` `pkg-config --cflags opencv` 
ကို Debug အတွက်ရော၊ Release အတွက်ပါ သတ်မှတ် နိုင် ပါတယ်။

Figure. Compiler options များသတ်မှတ်ခြင်း။


နောက်တစ်ခါ Linker settings tab → Other linker options မှာ လည်း ပုံ မှာ ပြထား သလို
`wx-config --libs std` `pkg-config  --libs opencv`
ကို ထပ် သတ်မှတ်ပါမယ်။

Figure. Linker options များသတ်မှတ်ခြင်း။


နောက်ဆုံးမှာ F9 ခလုပ်ကို နှိပ်ပီး Build and run လုပ်လိုက် တဲ့အခါ အောက်က ပုံမှာ ပြထား သလို ပရိုဂရမ် ရဲ့ output ကို တွေ့နိုင် ပါတယ်။

Figure. OpenCV နှင့် wxWidgets နမူနာ ပရိုဂရမ်ကို Code::Blocks တွင် run ခြင်း။
ပရောဂျက် နဲ့ ပတ်သက် တဲ့ အချက်အလက် တွေကို IDE ကို ပိုပြီး သိစေချင်ရင် optional အဆင့်တွေ အနေနဲ့ Project Menu → Build Options... ကို နှိပ်ပြီး Search directories tab → Compiler tab မှာ /usr/local/include နဲ့ /usr/local/include/wx-3.0 ကို Debug အတွက်ရော၊ Release အတွက်ပါ သတ်မှတ် နိုင် ပါတယ်။ နောက်တစ်ခါ ဘေးဘက် က Linker tab မှာ လည်း lib တွေရဲ့ လမ်းကြောင်း /usr/local/lib ကို သတ်မှတ်နိုင် ပါတယ်။

Windows

Visual Studio

Windows ပေါ်မှာ wxWidgets နဲ့ OpenCV ကို တွဲသုံးဖို့ အတွက် C:/wxWidgets303/samples/ ထဲက minimal ဆိုတဲ့ folder ကို minimalcv ဆိုတဲ့ နာမည်နဲ့ duplicate လုပ်လိုက် ပါမယ် ([Eme17] တွင် ကိုးကားပါ)။ ပြီးတဲ့ အခါ minimal_vc9.vcproj ကို ဖွင့်လိုက် ပါမယ်။ အောက်ပါ link မှာရှိတဲ့ OpenCV320.props ကို ယူပြီး ပရောဂျက် အခန်း ထဲမှာ ကူးထည့် လိုက် ပါမယ်။

https://github.com/yan9a/OpenCV_Projects/blob/master/img_wins_vs2015_x64/img_wins/OpenCV320.props

အပေါ် menu bar မှာရှိတဲ့ View → Other Windows → Property Manager ကိုသွားဖွင့် ပြီးတဲ့ အခါ အောက်က ပုံ မှာ ပြထား သလို ညာဘက် Property window ထဲက minimal ပေါ်မှာ ညာဘက် ကလစ် နှိပ်ပြီး Add existing property sheet ကို ရွေး၊ OpenCV320.props ကို ရွေးထည့် လိုက် ပါမယ်။

Figure. OpenCV Property Sheet ကို ထည့်ခြင်း။


အပေါ်က Solution Platforms ဆိုတဲ့ drop down list မှာ x64 ကို ရွေးထား လိုက် ပါမယ်။ Solution Explorer ထဲက Source Files ပေါ်မှာ ညာဘက် ကလစ် နှိပ်ပြီး Add Existing Item ... ကို ရွေးပြီး အပေါ်က util.h (online) ဆိုတဲ့ စာရင်း မှာ ဖော်ပြ ထားတဲ့ util.h ကိုလည်း ထည့်ထား လိုက် ပါမယ်။ ပြီးတဲ့ အခါ minimal.cpp (online) ကို အောက်က စာရင်း မှာ ပြထား သလို ပြင်လိုက် ပါမယ်။ အဲဒီနောက် ပရိုဂရမ် ကို run လိုက်ရင် အောက်က ပုံ မှာ ပြထား သလို OpenCV နဲ့ process လုပ်ထား တဲ့ ပုံရိပ်ကို wxWidgets ရဲ့ frame ပေါ်မှာ ဖော်ပြ ထားတဲ့ output ကို တွေ့နိုင် ပါတယ်။
//File: minimalcv.cpp
//Description: A simple example to use OpenCV with wxWidgets
//Author: Yan Naing Aye
//Date: 2017 November 07
//MIT License - Copyright (c) 2017 Yan Naing Aye

#include < wx/wx.h >
#include < opencv2/opencv.hpp >
#include "util.h"
#include < string >
using namespace std;
using namespace cv;

class MyFrame : public wxFrame
{
 wxStaticBitmap *thiri;
public:
 MyFrame(const wxString& title);

};
MyFrame::MyFrame(const wxString& title)
 : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(512, 600))
{
 Centre();
 thiri = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("C:/opencv/thiri.png"), 
                    wxBITMAP_TYPE_PNG), wxPoint(256, 0), wxSize(512,512));

 //From opencv to wx
 Mat imcv1 = imread("C:/opencv/thiri.png",IMREAD_UNCHANGED);
 string str = "Channels:" + to_string(imcv1.channels());
 putText(imcv1, str, Point(100, 100), FONT_HERSHEY_PLAIN, 4.0, CV_RGB(128, 0, 128), 4.0);
 wxBitmap imwx1 = wx_from_mat(imcv1);
 thiri->SetBitmap(imwx1);
}

class MyApp : public wxApp
{
public:
 virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
 if (!wxApp::OnInit())
  return false;
 wxInitAllImageHandlers();
 MyFrame *frame = new MyFrame(wxT("Simple wxWidgets and OpenCV"));
 frame->Show(true);

 return true;
}
Listing. minimal.cpp


Figure. wxWidgets နှင့် OpenCV ကို Windows ပေါ်တွင် Visual Studio ဖြင့် အသုံးပြုခြင်း။




Related Posts



အကိုးအကားများ

[Dad10] Jive Dadson. OpenCV Image and wxImage Conversion. 2010.
url: https://stackoverflow.com/a/2241517.

[pkl15] pklab. Alpha from cv::mat for wxWidgets::wxImage. 2015.
url: http://answers.opencv.org/question/76540/how-to-obtain-alpha-from-cvmat-for-wxwidgetswximage/.

[Eme17] Cool Emerald. Cross-platform C++ programming with wxWidgets. 2017.
url: http://coolemerald.blogspot.sg/2017/10/cross-platform-c-programming-with.html#wxvs.

No comments:

Post a Comment