回复:Re: [wxPython-users] Draw bitmap(Numpy) with scale and offset

34 views
Skip to first unread message

ima...@sina.com

unread,
Sep 9, 2017, 12:08:30 AM9/9/17
to wxpython-users
Hi Chris Barker:
    I just know you are the author of FloatCanvas, As I asked befor, I want to draw numpy on panel. (Infact I am building a ImageProcessing framework based on wx, which can plugin any numpy based function and libs, such as scipy.ndimage, skimag, opencv, itk..., just like ImageJ, a famous Java app)
    I follow floatcanvas for a long time, But I cannot find more information in wx's document, But I found a demo on project's demo folder...(forgive me). I want to make sure two questions:
  1. If canvas can update image directly? (I know we can remove the old one, then add the new one, if we can share memory?)
  2. I need to draw ROI(Polygon and lines) on canvas, and I need to edit them. If I can use the same memory? when I change a point's xy, then update on canvas? (some times the shape is very complex)

by the way, are you intresting imagepy? I think it's a good project, but I am not very good at ui, (draw numpy, multi thread process and update...)

YXDragon
----- 原始邮件 -----
发件人:Chris Barker <chris....@noaa.gov>
收件人:wxpython-users <wxpytho...@googlegroups.com>
主题:Re: [wxPython-users] Draw bitmap(Numpy) with scale and offset
日期:2017年07月06日 04点52分


I need to draw a Numpy array on panel (zoom out and in ...). I use buffer to give the pixel data to the wxbitmap, but I did not find a method in dc can draw bitmap with offset and scale. so I must trans the wxbitmap to wximage, then scale and trans back to wxbitmap to draw.

yes, I think that's what you need to do :-)

though I would suspect that skimage would have a scaling ability -- maybe scale in numpy , then draw to wx.

but it cost so much memory and time (when the picture is large and scale large, a 1000 * 1000 picture scale 100 times will be 100000 * 100000). so I do a lot of work to count the final extent and corp the Numpy array first,

yup -- that's what you need to do -- again, unless skimage has this functionality.

in wx.lib.floatcanvas ScaledBitmap2, that's how I do it -- (though not from a numpy array) -- a bit of finicky code, but you really can't expect to scale up an entire huge image in memory -- so you need to crop it first.

I'm not trying to get any kind of "frame rate" with FC -- but it seems snappy enough.


then: numpy -> bitmap -> image -> scale -> bitmap -> draw. It works, but so complex, and with a bad performance (Far inferior to Java's drawImage...)

you should be able to:

crop_in_numpy->wxImage->scale->wxBitmap-Draw

wxImage is scaling in C++, so you're not going to get much faster unless you can use a particularly smart algorithm (or simple one -- are you interpolation, or ???


I hope that is enough to get you started, or inspire a correction from someone who knows a better way.  I should admit that I have not tested this approach thoroughly with Python 3.

nor have I :-(
 

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris....@noaa.gov

--
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-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris Barker

unread,
Sep 11, 2017, 1:36:11 PM9/11/17
to wxpython-users
On Fri, Sep 8, 2017 at 9:08 PM, <ima...@sina.com> wrote:
    I just know you are the author of FloatCanvas, As I asked befor, I want to draw numpy on panel. (Infact I am building a ImageProcessing framework based on wx, which can plugin any numpy based function and libs, such as scipy.ndimage, skimag, opencv, itk..., just like ImageJ, a famous Java app)
    I follow floatcanvas for a long time, But I cannot find more information in wx's document, But I found a demo on project's demo folder...(forgive me).

Sorry -- documentation is sparse, but we have an old TRAC project here:


and the source is in the wxpython source.

But the original source is here, with a bunch of demos:


I really need to clean that all up and put it in a modern gitHub repo, but for now...
 
I want to make sure two questions:
  1. If canvas can update image directly? (I know we can remove the old one, then add the new one, if we can share memory?)

There are currently two bitmap objects:

floatcanvas.Bitmap stores a wx.Bitmap internally -- it can be replaced without making a new Floatcanvas DrawObject, but I don't think there is a way for a wx.Bitmap to be changed in place.

floatCanvas.ScaledBitmap (and ScaledBitmap2) stores a wx.Image internally -- it, also could be replaced in-place, and _maybe_ you could have it share memory with a numpy array or some-such and be able to update it in place as well -- though it's been a long time since I've investigated this.

I'm not sure of your use-case, but I suspect you might be best off subclassing (or re-implimenting) ScaledBitmap2, and having it store a numpy array internally, and then that array would be manipulated, and only converted to a wxImage / wxBitmap when you go to draw it.

Here is part of that code:

    def _DrawSubBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
        """
        Subsets just the part of the bitmap that is visible
        then scales and draws that.

        """
        (snip) -- code to figure out the subset needed
        ....

        if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (Xb, Yb, Wb, Hb, Ws, Ws) ):
            Img = self.Image.GetSubImage(wx.Rect(Xb, Yb, Wb, Hb))
            Img.Rescale(Ws, Hs, quality=self._scale_quality)
            bmp = wx.BitmapFromImage(Img)
            self.ScaledBitmap = ((Xb, Yb, Wb, Hb, Ws, Ws), bmp)# this defines the cached bitmap
        ...

        dc.DrawBitmapPoint(bmp, XYs, True)

So you could re-implement that part to use numpy to subset and scale, then then draw...
 
  2. I need to draw ROI(Polygon and lines) on canvas, and I need to edit them. If I can use the same memory? when I change a point's xy, then update on canvas? (some times the shape is very complex)

I'm not sure what you mean here, but FloatCanvas is double buffered, so the everything that is drawn is drawn to a off-screen bitmap (and actually has two -- one for the background, and one for the foreground) -- that is the same bitmap with the same memory, except when the canvas is re-sized -- it clealy needs a new one there.

FloatCanvas was designed to display on screen, though it can be used without an active Window showing, if you want to simply draw off screen images. here is a simple example of that:


note that you do need to create a Frame, but you don't need to Show() it.

by the way, are you intresting imagepy? I think it's a good project, but I am not very good at ui, (draw numpy, multi thread process and update...)

Yes, that does look like a really interesting project.

It may make sense to build it on top of FloatCanvas.

But I'm afraid I have far more projects I am interested in than I have time for ...

But I would love to set FloatCanvas get some attention -- if you or anyone else wants to add features or refactor it some, I"d be glad to set it up as a proper gitHub project and review PRs, etc....

-CHB

Reply all
Reply to author
Forward
0 new messages