wxBitmap + OpenCV video file display

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
steven.pyae
Earned a small fee
Earned a small fee
Posts: 16
Joined: Wed Dec 04, 2019 9:08 am

wxBitmap + OpenCV video file display

Post by steven.pyae » Wed Dec 18, 2019 9:05 am

Hi All and Doublemax,

Sorry for being absent for a while.
I have successfully created the image panel, it was due to my lack of knowledge on Child Frames and Parent Frames.
I also created a new cpp file to get the file path and convert the input file into wxBitmap using appropriate channel.
The tutorial I followed is https://wiki.wxwidgets.org/An_image_panel

The resulting image looks like this.
Capture.JPG
Now, I want to move onto displaying a video file which is resized.
For resizing i used OpenCV resize to get my desired size.
Now I am stuck on how to convert those frames in the video into wxBitmap and display according to the framerate of the video.
Any suggestions?

User avatar
doublemax
Moderator
Moderator
Posts: 14875
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBitmap + OpenCV video file display

Post by doublemax » Wed Dec 18, 2019 10:42 am

For converting the video frame into a wxBitmap use wxPixelData:
https://docs.wxwidgets.org/trunk/classw ... _data.html.

As for displaying the video frames according to the frame rate: In theory it's simple: Create a timer that corresponds to the frame rate, e.g. for a 25fps video, you need a timer that fires every 40ms (1000/25).

Unfortunately under Windows, the timer granularity is 15.625 ms by default. That means, no matter what value you use when creating your timer, it will only fire at the next multiple of 15.625ms.

You can change this by calling timeBeginPeriod. E.g. calling timeBeginPeriod(1) will change the timer granularity to 1ms.
https://docs.microsoft.com/en-us/window ... eginperiod

But: This is a system-wide setting and it can theoretically change the behavior of other applications. Read the remarks section in above MSDN link.
Use the source, Luke!

steven.pyae
Earned a small fee
Earned a small fee
Posts: 16
Joined: Wed Dec 04, 2019 9:08 am

Re: wxBitmap + OpenCV video file display

Post by steven.pyae » Thu Dec 19, 2019 8:44 am

Hello Doublemax and Everyone seeing this.

I have improved on my code and tried to convert to bitmap frame by frame.

Code: Select all

wxImage cShowVideo::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;
	return wxImage();
}
As OpenCV is showing frame by frame via https://www.learnopencv.com/read-write- ... pp-python/

To display there are 4 lines of codes

Code: Select all

VideoCapture vid(filepath);
	 while(vid.grab()==true)
	{	Mat Test;
		vid>> Test;
		imshow ("Frame", Test); 
	}
Hence, I take frame by frame and convert to Bitmap in the while loop. and Cast it into wxPanel.

However, the result is a flickering video. Any explanation?
Oh Doublemax, for the wxPixelData. how can I implement it? the example they provided is a bit confusing

steven.pyae
Earned a small fee
Earned a small fee
Posts: 16
Joined: Wed Dec 04, 2019 9:08 am

Re: wxBitmap + OpenCV video file display

Post by steven.pyae » Thu Dec 19, 2019 8:53 am

To add on with my Previous Post,
Ì have also looked at buffered PaintDC, double buffered paintdc and Image Panel.
Tested with the code and it doesn't give me the result I needed.

User avatar
doublemax
Moderator
Moderator
Posts: 14875
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBitmap + OpenCV video file display

Post by doublemax » Thu Dec 19, 2019 9:39 am

Add this line to the wxImagePanel constructor:

Code: Select all

SetBackgroundStyle(wxBG_STYLE_CUSTOM);
That should get rid of the flickering.

As for the raw bitmap access. Here's code that takes an image from an OpenCV camera and converts it to wxBitmap.

Code: Select all

typedef wxAlphaPixelData PixelData;

void mainFrame::OnTimer(wxTimerEvent& event)
{
  wxLogDebug(wxT("OnTimer"));

  if(m_cam != NULL)
  {
    IplImage *img = cvQueryFrame(m_cam);
    if( img != NULL )
    {
      int w = img->width;
      int h = img->height;
      int c = img->nChannels;
      wxLogDebug(wxT("image captured: w:%d h:%d c:%d d:%d s:%d"), w, h, c, img->depth, img->widthStep);

      if(m_bitmap==NULL || m_bitmap->GetWidth()!=w || m_bitmap->GetHeight()!=h)
      {
        delete m_bitmap;
        m_bitmap = new wxBitmap(w, h, 32);
      }

      PixelData bmdata(*m_bitmap);
      if(!bmdata) return;

      // use raw bitmap access to write RGB data directly into the bitmap
      unsigned char *imgdata = (unsigned char *)img->imageData;
      PixelData::Iterator dst(bmdata);

      for(int y=0; y<h; y++)
      {
        unsigned char *imgdata_y = imgdata;
        dst.MoveTo(bmdata, 0, y);
        for(int x=0; x<w; x++)
        {
          dst.Blue() = *imgdata_y++;
          dst.Green() = *imgdata_y++;
          dst.Red() = *imgdata_y++;
          dst++;
        }
        imgdata += img->widthStep;
      }
      this->Refresh();
    }
  }

  m_timer.Start(TIMERVALUE, true);
}
Use the source, Luke!

steven.pyae
Earned a small fee
Earned a small fee
Posts: 16
Joined: Wed Dec 04, 2019 9:08 am

Re: wxBitmap + OpenCV video file display

Post by steven.pyae » Fri Dec 20, 2019 2:43 am

Hi DoubleMax Appreciate your reply and there were no more flickering
There is one more issue the wx_Bitmap is shown in the video in the link below.
I am guessing that wx_bitmap is not deleting the original bitmap frame when it is receiving a new bitmap or it has like an array that needs to be repainted or updated.
For reference, all I need to do is to draw on the panel is to call this class function to draw on the application.

Code: Select all

#include "cPanel.h"
#include <wx/rawbmp.h>
#include <wx/image.h>
#include <wx/wxprec.h>

BEGIN_EVENT_TABLE(cPanel, wxPanel)
	EVT_PAINT(cPanel::paintEvent)
END_EVENT_TABLE()

cPanel::cPanel(wxMDIParentFrame* parent, wxString filepath, wxBitmap bitmap) : wxPanel(parent, window::panelid::Panel_ID, wxPoint(20,100), wxSize(650,500))
{
	SetBackgroundStyle(wxBG_STYLE_CUSTOM);
	wx_bitmap = bitmap;
}

cPanel::~cPanel()
{
}
void cPanel::paintEvent(wxPaintEvent& evt)
{
	wxPaintDC dc(this);
	render(dc);
}
//void cPanel::paintNow()
//{
//	wxClientDC dc(this);
//	render(dc);
//}

void cPanel::render(wxPaintDC& dc)
{
	dc.DrawBitmap(wx_bitmap, 0, 0, false);
}
Couldn't attach video so here is a link
https://vimeo.com/user106580825/review/ ... de62457fcc
That is my current application looks like

User avatar
doublemax
Moderator
Moderator
Posts: 14875
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBitmap + OpenCV video file display

Post by doublemax » Fri Dec 20, 2019 8:52 am

The video link doesn't work for me.
Use the source, Luke!

Post Reply