pythonimageimage-processingwxpythonmedical

Loading an Image generated from an array into a wxpython frame


I am trying to get produce a programme to display DICOM images and move through slices using event buttons. I want to test it first on moving through the z-slices of a np.array. The code is based on an example file viewer online.

How can i get the test button to call up the randomly generated image?

I have simplified the code to only show one 200x200 pixel array and not to travel through slices, but it still cant display the generated image.

import os
import wx
import numpy as np
from PIL import Image

data = np.random.randint(low = 0, high = 255, size =(200, 200)) #generation of random array
test_img = Image.fromarray(data.astype('uint8')) #turn array into image

class PhotoCtrl(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)
        self.frame = wx.Frame(None, title='Slice Viewer')
        self.panel = wx.Panel(self.frame) 
        self.PhotoMaxSize = 200 
        self.createWidgets()
        self.frame.Show()

    def createWidgets(self):
        instructions = 'Browse for an image'
        img = wx.EmptyImage(200,200)
        self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, 
                                         wx.BitmapFromImage(img))

        instructLbl = wx.StaticText(self.panel, label=instructions)
        self.photoTxt = wx.TextCtrl(self.panel, size=(100,-1))
        browseBtn = wx.Button(self.panel, label='Browse')
        browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)

        up_btn = wx.Button(self.panel, label='Up')
        up_btn.Bind(wx.EVT_BUTTON, self.on_press_up) 

        down_btn = wx.Button(self.panel, label='Down')
        down_btn.Bind(wx.EVT_BUTTON, self.on_press_down)

        test_btn = wx.Button(self.panel, label='Test')
        test_btn.Bind(wx.EVT_BUTTON, self.onViewTest)

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 0, wx.ALL|wx.EXPAND, 5)
        self.mainSizer.Add(instructLbl, 0, wx.ALL, 5)
        self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
        self.sizer.Add(self.photoTxt, 0, wx.ALL, 5)
        self.sizer.Add(browseBtn, 0, wx.ALL, 5)   
        self.mainSizer.Add(up_btn, 0, wx.ALL, 5)
        self.mainSizer.Add(down_btn, 0, wx.ALL, 5)
        self.mainSizer.Add(test_btn, 0, wx.ALL, 5)
        self.mainSizer.Add(self.sizer, 0, wx.ALL, 5)

        self.panel.SetSizer(self.mainSizer)
        self.mainSizer.Fit(self.frame)

        self.panel.Layout()

    def onBrowse(self, event):
        """ 
        Browse for file mode for later testing
        """
        wildcard = "JPEG files (*.jpg)|*.jpg"
        dialog = wx.FileDialog(None, "Choose a file",
                               wildcard=wildcard,
                               style=wx.FD_OPEN)
        if dialog.ShowModal() == wx.ID_OK:
            self.photoTxt.SetValue(dialog.GetPath())
        dialog.Destroy() 
        self.onView()

    def onView(self):
        """
        Part of later data selection
        """
        filepath = self.photoTxt.GetValue()
        img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
        # scale the image, preserving the aspect ratio
        W = img.GetWidth()
        H = img.GetHeight()
        if W > H:
            NewW = self.PhotoMaxSize
            NewH = self.PhotoMaxSize * H / W
        else:
            NewH = self.PhotoMaxSize
            NewW = self.PhotoMaxSize * W / H
        img = img.Scale(NewW,NewH)

        self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
        self.panel.Refresh()

    def onViewTest(self):
        """
        Problem code area, trying to call the generated image and display
        """
        img = wx.Image(test_img, wx.BITMAP_TYPE_ANY)
        self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
        self.panel.Refresh()

    def on_press_up(self, event):
        print('up')

    def on_press_down(self, event):
        print('down')


if __name__ == '__main__':
    app = PhotoCtrl()
    app.MainLoop()

del app
'''

Currently i get a positional argument error, but don't understand why as the browse function works with only one argument.

Solution

  • This is your code amended for wxpython 4.0.4 with python 3
    You'll note:

    A change in how the test image is generated
    A change to the if statement when selecting an image file
    The def of onViewTest

    Hopefully these changes will give you what you want.
    If you are still using wxPython 2.8 you may need to retain some of your existing image manipulations, as wxPython 4+ has changed a few of these.

    import os
    import wx
    import numpy as np
    from PIL import Image
    
    data = np.random.randint(low = 0, high = 255, size =(200, 200)) #generation of random array
    #test_img = Image.fromarray(data.astype('uint8')) #turn array into image
    
    class PhotoCtrl(wx.App):
        def __init__(self, redirect=False, filename=None):
            wx.App.__init__(self, redirect, filename)
            self.frame = wx.Frame(None, title='Slice Viewer')
            self.panel = wx.Panel(self.frame)
            self.PhotoMaxSize = 200
            self.createWidgets()
            self.frame.Show()
    
        def createWidgets(self):
            instructions = 'Browse for an image'
            img = wx.Image(200,200)
            self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY,
                                             wx.Bitmap(img))
    
            instructLbl = wx.StaticText(self.panel, label=instructions)
            self.photoTxt = wx.TextCtrl(self.panel, size=(100,-1))
            browseBtn = wx.Button(self.panel, label='Browse')
            browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)
    
            up_btn = wx.Button(self.panel, label='Up')
            up_btn.Bind(wx.EVT_BUTTON, self.on_press_up)
    
            down_btn = wx.Button(self.panel, label='Down')
            down_btn.Bind(wx.EVT_BUTTON, self.on_press_down)
    
            test_btn = wx.Button(self.panel, label='Test')
            test_btn.Bind(wx.EVT_BUTTON, self.onViewTest)
    
            self.mainSizer = wx.BoxSizer(wx.VERTICAL)
            self.sizer = wx.BoxSizer(wx.HORIZONTAL)
    
            self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 0, wx.ALL|wx.EXPAND, 5)
            self.mainSizer.Add(instructLbl, 0, wx.ALL, 5)
            self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
            self.sizer.Add(self.photoTxt, 0, wx.ALL, 5)
            self.sizer.Add(browseBtn, 0, wx.ALL, 5)
            self.mainSizer.Add(up_btn, 0, wx.ALL, 5)
            self.mainSizer.Add(down_btn, 0, wx.ALL, 5)
            self.mainSizer.Add(test_btn, 0, wx.ALL, 5)
            self.mainSizer.Add(self.sizer, 0, wx.ALL, 5)
    
            self.panel.SetSizer(self.mainSizer)
            self.mainSizer.Fit(self.frame)
    
            self.panel.Layout()
    
        def onBrowse(self, event):
            """
            Browse for file mode for later testing
            """
            wildcard = "JPEG files (*.jpg)|*.jpg"
            dialog = wx.FileDialog(None, "Choose a file",
                                   wildcard=wildcard,
                                   style=wx.FD_OPEN)
            if dialog.ShowModal() == wx.ID_OK:
                self.photoTxt.SetValue(dialog.GetPath())
                dialog.Destroy()
                self.onView()
    
        def onView(self):
            """
            Part of later data selection
            """
            filepath = self.photoTxt.GetValue()
            img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
            # scale the image, preserving the aspect ratio
            W = img.GetWidth()
            H = img.GetHeight()
            if W > H:
                NewW = self.PhotoMaxSize
                NewH = self.PhotoMaxSize * H / W
            else:
                NewH = self.PhotoMaxSize
                NewW = self.PhotoMaxSize * W / H
            img = img.Scale(NewW,NewH)
    
            self.imageCtrl.SetBitmap(wx.Bitmap(img))
            self.panel.Refresh()
    
        def onViewTest(self, event):
            """
            Problem code area, trying to call the generated image and display
            """
    #        img = wx.Image(test_img, wx.BITMAP_TYPE_ANY)
    #        self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
            img = wx.Image(200,200)
            img.SetData(data)
            self.imageCtrl.SetBitmap(wx.Bitmap(img))
            self.panel.Refresh()
    
        def on_press_up(self, event):
            print('up')
    
        def on_press_down(self, event):
            print('down')
    
    
    if __name__ == '__main__':
        app = PhotoCtrl()
        app.MainLoop()
    
    del app
    

    Your random test image

    Your "random" test image being displayed