How to keep drawing on one panel and play movie in another (back) panel in wxpython?

I am working on an application where i need to play a movie and the user can draw different shapes on it.

For this purpose i am using two different panels. First panel (background) is used to show the movie frame and second panel (foreground, transparent) is used for drawing.

The problem is the drawing appears on the first frame only and then the repainting of background panel removes it.

I am new to wxpython so if my approach is wrong please correct me.

My Code:

import wx
import cv2

class MoviePanel(wx.Panel):
    def __init__(self, parent, capture):
        wx.Panel.__init__(self, parent, size=(840,480))

        self.Bind(wx.EVT_PAINT, self.OnPaint, self)

        self.capture = capture

        ret, frame = self.capture.read()

        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        frame = cv2.resize(frame,(840,480))

        self.bmp = wx.Bitmap.FromBuffer(840, 480, frame)

        self.timer = wx.Timer(self)
        self.timer.Start(1000./60)
        self.Bind(wx.EVT_TIMER, self.NextFrame)

        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

    def OnEraseBackground(self,evt):
        pass

    def OnPaint(self, evt):
        dc = wx.BufferedPaintDC(self)
        dc.DrawBitmap(self.bmp, 0, 0)

    def NextFrame(self, evt):
        ret, frame = self.capture.read()
        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame,(840,480))
            self.bmp.CopyFromBuffer(frame)
            self.Refresh()

class DrawPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, size=(840,480),
                          style=wx.TRANSPARENT_WINDOW)

        self.Bind(wx.EVT_PAINT, self.OnPaintDrawPanel)

        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

    def OnEraseBackground(self,evt):
        pass

    def OnPaintDrawPanel(self, evt):
        pdc = wx.BufferedPaintDC(self)
        dc = wx.GCDC(pdc)
        dc.SetPen(wx.Pen('#4c4c4c',7))
        dc.DrawLine(20, 240, 800, 240)

class Frame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, size=(840, 480))

        capture = cv2.VideoCapture(0)

        self.MovieP = MoviePanel(self, capture)

        self.DrawP = DrawPanel(self)

if __name__ == '__main__':
    app = wx.App()
    frame = Frame(None)
    frame.Show()
    app.MainLoop()

``

Jaideep Singh wrote:

I am working on an application where i need to play a movie and the
user can draw different shapes on it.

For this purpose i am using two different panels. First panel
(background) is used to show the movie frame and second panel
(foreground, transparent) is used for drawing.

The problem is the drawing appears on the first frame only and then
the repainting of background panel removes it.

Right. You have a couple of choices.

1. You can force the top window to repaint every time you repaint the
movie. That will cause flickering.

2. You can do the merge yourself. Instead of drawing to a panel, do
your drawing to a bitmap, then apply the bitmap to every new frame
before you present it. That avoids flickering.

3. You can use OpenGL and allow your graphics card to do the blending.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Sir,
Sorry for late reply.
Since i am new to python and wxpython it took a while to test your proposals.
Actually i wanted to make tracking application where a user can draw a rectangle on screen and the software will track an object based on an algorithm. I have completed my application on MATLAB. But MATLAB is slow when it is time to play movies on screen.
So, i am shifting my code to python using opencv for image and video processing and wxpython as gui.
For the purpose of drawing a search region(tracking) and plotting track trajectory, i want to have a separate panel(transparent) above the movie panel so that user can see both the movie and plot.
As proposed by you i tried implementing your second approach. I tried to draw on a transparent bitmap so that it can later be merged with the movie for display.
The problem is that the transparent bitmap is white and opaque when i draw it on the screen.
So, please guide me on this.

demo.py (2.08 KB)

Not an exclusively wx mechanism for doing this but you can use OpenCV to
draw your marker around your tracked item see

and

for some examples - of course you can use the wx back-end and possibly
freeze frame while selecting your target.

Hope that helps.

···

On 19/08/2017 08:19, Jaideep Singh wrote:

Sir,
Sorry for late reply.
Since i am new to python and wxpython it took a while to test your
proposals.
Actually i wanted to make tracking application where a user can draw a
rectangle on screen and the software will track an object based on an
algorithm. I have completed my application on MATLAB. But MATLAB is slow
when it is time to play movies on screen.
So, i am shifting my code to python using opencv for image and video
processing and wxpython as gui.
For the purpose of drawing a search region(tracking) and plotting track
trajectory, i want to have a separate panel(transparent) above the movie
panel so that user can see both the movie and plot.
As proposed by you i tried implementing your second approach. I tried to
draw on a transparent bitmap so that it can later be merged with the
movie for display.
The problem is that the transparent bitmap is white and opaque when i
draw it on the screen.
So, please guide me on this.

--

--
Steve (Gadget) Barnes
Any opinions in this message are my personal opinions and do not reflect
those of my employer.

---
This email has been checked for viruses by AVG.

Yes, thank you Sir, it is a good approach and can work perfectly.
But after tracking is over and user plays the movie again all the points will gone. I have to redraw them all again and again.
Is there anyway to draw the track trajectory once and keep them on a playing movie.

You can always create a new video file with the overlays added - one
example, purely using python & OpenCV is at

but you can also use cv.writeImage to save the frames to sequentially
numbered frames and then another tool, such as FFMPEG, possibly via
moviepy to put them together into a video format.

···

On 19/08/2017 14:50, Jaideep Singh wrote:

Yes, thank you Sir, it is a good approach and can work perfectly.
But after tracking is over and user plays the movie again all the points
will gone. I have to redraw them all again and again.
Is there anyway to draw the track trajectory once and keep them on a
playing movie.

--
You received this message because you are subscribed to the Google
Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to wxpython-users+unsubscribe@googlegroups.com
<mailto:wxpython-users+unsubscribe@googlegroups.com>.
For more options, visit https://groups.google.com/d/optout.

--
Steve (Gadget) Barnes
Any opinions in this message are my personal opinions and do not reflect
those of my employer.

---
This email has been checked for viruses by AVG.

Thank you for your valuable inputs sir, I’ll definitely look into it.

This community is so helpful, much appreciated.

This is exactly what I told you in my first reply. Did you not like it, or did you not understand it?

···

On Aug 19, 2017, at 6:50 AM, Jaideep Singh <jaideepsingh602@gmail.com> wrote:

Yes, thank you Sir, it is a good approach and can work perfectly.
But after tracking is over and user plays the movie again all the points will gone. I have to redraw them all again and again.
Is there anyway to draw the track trajectory once and keep them on a playing movie.


Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

This is exactly what I told you in my first reply. Did you not like it, or did you not understand it?
Sir,

I have tried implement your second approach of drawing to a transparent bitmap and display it onto the transparent panel above the movie panel and when the user will play the movie i will just create a mask of transparent bitmap and set the mask to the movie frame before displaying it.

But i wasn’t able to display the transparent bitmap on the panel. It is white and opaque when i draw it on the screen.

If you can guide to me to do the same it will be very helpful.

I have asked you about this problem on 19 Aug.

demo.py (2.08 KB)

The transparent window does not do what you think it does. When something is situated against the desktop background, it can be nice, but it is not much use when you have several windows drawing simultaneously, as you have seen.

You need to do the blending yourself. Don’t use a separate panel for the annotations. Draw the annotations into a bitmap with an alpha channel, where the alpha channel starts out all 0. Then, every time you draw the movie frame, you can draw the annotations bitmap over the top, using a bit that blends the alpha channel.

···

On Aug 20, 2017, at 12:50 AM, Jaideep Singh jaideepsingh602@gmail.com wrote:

This is exactly what I told you in my first reply. Did you not like it, or did you not understand it?

I have tried implement your second approach of drawing to a transparent bitmap and display it onto the transparent panel above the movie panel and when the user will play the movie i will just create a mask of transparent bitmap and set the mask to the movie frame before displaying it.

But i wasn’t able to display the transparent bitmap on the panel. It is white and opaque when i draw it on the screen.


Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Sir,

Is there any example of this approach in demo folder of wxpython phoenix?

Since, i’m new to wxpython any help will be appreciated.

Have you worked with alpha blending before? That's a very old concept in graphics where you have an extra channel (besides R, G, and B) that basically tells how transparent the pixel is. A pixel with an alpha if 0 is transparent, a pixel with an alpha of 255 is opaque.

So, create your drawing bitmap with a depth of 32, and clear it to color (0,0,0,0) - black with transparent alpha. Now, when you do your drawing, set the color to one with alpha=255.

Now, when you go to draw your movie frame, you can Blit the drawing bitmap onto the movie frame, which will blend the opaque pixels and leave the transparent ones alone.

···

On Aug 20, 2017, at 11:43 PM, Jaideep Singh <jaideepsingh602@gmail.com> wrote:

Is there any example of this approach in demo folder of wxpython phoenix?

Since, i'm new to wxpython any help will be appreciated.


Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Sir,

Thank you for clearing up the approach. I’ll try to implement it.