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

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

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

imagepy
Yes, I am writing ImageJ(Python). And It is basicaly OK(can glue with scikit-image, opencv.... and supporting tools and macros), there is just some flaw(such as the drawing performance), you can have a look.

<<<return wximg.Scale(int(scale*width), int(scale*height))>>>
I think we cannot write like this, when the image is large, and scale is large, the memory will boom and Bitmat(image) will cost more memory !!!

<<<dc.DrawBitmap(bitmap, pad_w, pad_h, useMask=True)>>>
I had tested that, when the bitmap is large, also most are is out of the panel, dc will cost more time.

so, if there is a method draw with scale and offset, which can draw intellegent supported by C level!

<<<The wx.Frame has many other widgets for interacting with a microscope and control system, but it displays the images with no issues>>>
can you give me some clue about these widgets?I want to have a look!

----- 原始邮件 -----
发件人:Matt Newville <[hidden email]>
收件人:[hidden email]
主题:Re: [wxPython-users] Draw bitmap(Numpy) with scale and offset
日期:2017年06月27日 11点21分



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.

--
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: Re: [wxPython-users] Draw bitmap(Numpy) with scale and offset

Matt Newville
Hi,

On Tue, Jun 27, 2017 at 8:10 PM, <[hidden email]> wrote:
Yes, I am writing ImageJ(Python). And It is basicaly OK(can glue with scikit-image, opencv.... and supporting tools and macros), there is just some flaw(such as the drawing performance), you can have a look.

Yes, it looks very interesting!
 

<<<return wximg.Scale(int(scale*width), int(scale*height))>>>
I think we cannot write like this, when the image is large, and scale is large, the memory will boom and Bitmat(image) will cost more memory !!!

What is "large" to you?  I'm typically working with images that are color and 1 to 4 Megapixels.  For display purposes then, the scale ranges from ~0.25 to 2 -- any bigger than that and the image wouldn't fit on even the biggest highest resolution monitor I have.  And even then, the image arrays are smaller than 20 megabyte range.  I wouldn't call that large.  I wouldn't call the rate fast either, but being able to display an image at 10 to 15 fps is fine (at least for my needs and eyes).   The application I have for displaying such images is very responsive and easy to use for my limited target audience.


<<<dc.DrawBitmap(bitmap, pad_w, pad_h, useMask=True)>>>
I had tested that, when the bitmap is large, also most are is out of the panel, dc will cost more time.

OK. I rarely try to draw images with scale > 1 and never > 2.


so, if there is a method draw with scale and offset, which can draw intellegent supported by C level!

I don't know.  For the code I posted all the activity really happens in wxPython methods, so are not spending most of the time in Python.  Maybe it could be done faster.
 

<<<The wx.Frame has many other widgets for interacting with a microscope and control system, but it displays the images with no issues>>>
can you give me some clue about these widgets?I want to have a look!

This shows the live image from a 1360x1024 color GigE camera (an oldish Prosilica) for a custom microscope display.  It has controls for moving motorized stages, some basic settings for the camera, and a list of named motor positions and saved images that get put into a database for later use.

For the discussion here, the live image from the camera is converted from a numpy array to a wxImage then a Bitmap, and displayed at ~15 fps running on a modest Windows workstation.  The screen can be resized and the displayed image will be automatically scaled and padded to fit into the window.

Maybe that approach is not suitable for your needs, but it seemed similar. If nothing else, I hope it helped give you some ideas....

Cheers,

--Matt

--
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...