I decided to spend a little time tinkering with a Raspberry Pi 3 and a Camera module and wanted to share some of the things I’ve been learning.

My current setup is a Raspberry Pi 3 running Raspbian Pixel, with a 10.1″ HDMI LCD display from Waveshare.com (~$80) with their RPi Camera ($19).



There are great resources available for getting started using the Camera in Python, but I haven’t come across any tutorials about how to combine the camera with an actual graphical user interface (GUI).

The first decision was to figure out which GUI toolkit to go with. I came across Bald Engineer’s post deciding to go with a Qt solution but I decided to go with wxPython. The main reason is that it seems to be easier to throw together a lightweight UI in wxPython without having to use a UI Designer tool and then cross compile and generate Python bindings like Qt. (Note, I’m not an expert at Qt, so there may be simple lightweight solutions that I’m not yet aware of).

Getting Started

wxPython

sudo apt-get install wx2.8 sudo apt-get install python-wxgtk2.8

To installon the Raspbian, I ran the following two commands (though I suspect according to the documentation only the latter is actually required):

Initially the new wx namespace wasn’t available in Python so I rebooted the Raspberry Pi and was good to go.

The Raspbian Pixel should already have the picamera module installed which lets you quickly capture and save images.

The following code will popup a full screen preview from the camera:

from picamera import PiCamera from time import sleep</code> camera = PiCamera() camera.start_preview(alpha=200) sleep(10) camera.stop_preview()

Note that out of the box the picamera module does not have any way to show the camera picture in a windowed mode, hence requiring us to get our hands dirty.

Windowed Mode Preview – Proof of Concept

With wxPython it’s pretty straightforward to create a UI with a wx.Image box and a button to save the camera image to a file then present it to the user.

This is a trivial example, in the future I’ll work on switching the capture to use a memory stream instead of a file and also go multi-threaded to allow the camera stream to update without halting the UI.

Finally, here is the code:

import os import wx import picamera class MainWindow(wx.Frame): def __init__(self, parent, title): frame = wx.Frame.__init__(self, parent, title=title, size=(600,600)) self.Center() self.CreateStatusBar() # A StatusBar in the bottom of the window # Setting up the menu. filemenu= wx.Menu() # wx.ID_ABOUT and wx.ID_EXIT are standard ids provided by wxWidgets. menuAbout = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program") menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program") # Creating the menubar. menuBar = wx.MenuBar() menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content. # Create Image self.Image = wx.StaticBitmap(self, bitmap=wx.EmptyBitmap(512, 300)) self.LoadImage() #Capture Button b = wx.Button(self, -1, "Capture") b.Bind(wx.EVT_BUTTON, self.Capture) # Using a Sizer to handle the layout box = wx.BoxSizer(wx.VERTICAL) # adding stretchable space before and after centers the image. box.Add((1,1),1) box.Add(self.Image, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.ADJUST_MINSIZE, 10) box.Add((1,1),1) box.Add(b, 0, wx.CENTER | wx.ALL,10) self.SetSizerAndFit(box) # Set events. self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) self.Bind(wx.EVT_MENU, self.OnExit, menuExit) self.Show(True) def Capture(self, event=None): with picamera.PiCamera() as camera: camera.vflip = True camera.capture('image.jpg') self.LoadImage() def LoadImage(self): # load the image Img = wx.Image("image.jpg", wx.BITMAP_TYPE_JPEG) # scale the image, preserving the aspect ratio W = Img.GetWidth() H = Img.GetHeight() Img = Img.Scale(512, 300) # convert it to a wx.Bitmap, and put it on the wx.StaticBitmap self.Image.SetBitmap(wx.BitmapFromImage(Img)) # You can fit the frame to the image, if you want. #self.Fit() #self.Layout() self.Refresh() def OnAbout(self,e): # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets. dlg = wx.MessageDialog( self, "A wxPython based tool for using picamera", "About Camera Monitor", wx.OK) dlg.ShowModal() # Show it dlg.Destroy() # finally destroy it when finished. def OnExit(self,e): self.Close(True) # Close the frame. app = wx.App(False) frame = MainWindow(None, "Camera Monitor") app.MainLoop()

Much of the wxPython framework code above comes from the wxPython website: https://wiki.wxpython.org/Getting%20Started

If this post was interesting or helpful, or leaves you with any questions, please drop a comment in the space below.