Draw bitmap(Numpy) with scale and offset

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Draw bitmap(Numpy) with scale and offset

imagepy
 Hey everyone:
    I am working on a image process framework ImagePy based on wxphoenix which is esay to glue with scipy, skimage, opencv... It is a friendly interactive gui program, you just need to config the core function, it can wrap opencv like photoshop for no-programer.
    now it is basicly OK, but I have a question:

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

by the way: Is anyone intrested in this program? I am not very good at ui, if you can join, you are welcom!
                                                                                                                                                YXDragon


--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Draw bitmap(Numpy) with scale and offset

Matt Newville


On Mon, Jun 26, 2017 at 1:54 PM, <[hidden email]> wrote:
 Hey everyone:
    I am working on a image process framework ImagePy based on wxphoenix which is esay to glue with scipy, skimage, opencv... It is a friendly interactive gui program, you just need to config the core function, it can wrap opencv like photoshop for no-programer.
    now it is basicly OK, but I have a question:

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


I don't know that it is exactly transferable, but I have an application that reads numpy images from GigE cameras and displays them on a wxPython display.  For a 1928x1448 color camera, I can display images at about 15 fps. The wx.Frame can be resized, and padding is used so that the displayed image is both scaled and padded to fit on the wx.Panel.  The wx.Frame has many other widgets for interacting with a microscope and control system, but it displays the images with no issues.

The approach is numpy array -> wxImage -> Scaled wxImage -> Bitmap -> draw.  The code I use is based on wxPython examples found over the years.  It is sort of too embedded in my apps to cleanly pull out (it's at https://github.com/pyepics/epicsapps/tree/master/sampleviewer/lib if you're interested).  It's poorly documented, but goes basically like this:

# Step 1: convert  to wx.Image (use ImageFromData for pre-Phoenix wxPython)
def Get_WxImage(image_ndarray,  scale=1.0):
     """convert numpy array `image_ndarray` of shape (3, width, height) to
     a scaled wx.Image
     """
     image_ndarray = image_ndarray.astype(np.uint8)
     nrgb, width, height = image_ndarray.shape
     wximg= wx.Image(width, height, image_ndarray)
     return wximg.Scale(int(scale*width), int(scale*height))

# Step 2: Panel.onPaint, bound to wx.EVT_PAINT for display wx.Panel  
def onPaint(self, event=None):

     # somehow get / store latest image_ndarray:
     wximage = Get_WxImage(self.image_ndarray, scale=self.scale)

     bitmap = wx.Bitmap(wximage)    # BitmapFromImage for pre-Phoenix code

     img_w, img_h = self.bitmap_size = bitmap.GetSize()
     pan_w, pan_h = self.panel_size  = self.GetSize()
     pad_w, pad_h = int(1+(pan_w-img_w)/2.0), int(1+(pan_h-img_h)/2.0)
     dc = wx.AutoBufferedPaintDC(self)
     dc.Clear()
     dc.DrawBitmap(bitmap, pad_w, pad_h, useMask=True)

# Step 3: determine scale: Panel.onSize bound to wx.EVT_SIZE for display wx.Panel
def onSize(self, event=None):
        frame_w, frame_h = evt.GetSize()
        # img_w, img_h are the expected display size, perhaps 800.0, 600.0
        self.scale = min(frame_w/self.img_w,  frame_h/self.img_h)
        self.Refresh()
        event.Skip()    

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.


by the way: Is anyone intrested in this program? I am not very good at ui, if you can join, you are welcom!

I would be very interested to see some of the features of ImageJ in a Python app.  I'm afraid I don't have much time to work on that myself.

--Matt Newville

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Draw bitmap(Numpy) with scale and offset

Chris Barker - NOAA Federal

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

[hidden email]

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Loading...