morefigs / pymba

Python wrapper for Allied Vision's Vimba C API
MIT License
105 stars 84 forks source link

GUI #53

Closed robmarkcole closed 5 years ago

robmarkcole commented 7 years ago

Has anyone made a GUI for pymba? e.g. using pyQT, wxPython

derricw commented 7 years ago

You mean like a gui with live view? I made one at work using pyqtgraph fairly easily.

robmarkcole commented 7 years ago

Precisely. Would like to do live background subtraction whilst doing alignment.

Any chance your code is on GitHub?

morefigs commented 7 years ago

I've previously made GUIs for pymba using PyQt for controlling the camera and OpenCV to display images in real time, which worked well. I don't have the code available to share unfortunately.

robmarkcole commented 7 years ago

@derricw any chance you can post your code? Cheers

robmarkcole commented 7 years ago

OK I discovered pymba/pymba/tests/opencv_liveview_example.py When I make a nice Gui I will add to Github. OpenCV appears the way to go. PyqtGraph looks fantastic for stills but can't get along with the video options.

jdahlen0441 commented 6 years ago

Here is an example GUI that I wrote using tkinter that displays a live video from an AVT camera using the pymba library.

I am using python 3.6

I am using a USB to Ethernet connector and a 235 camera. Both color and mono works fine.

I am not a professional programmer so if others could improve on this code that would be great.

Thanks to morefigs for making the library available, I really appreciate it.

I have organized the code into two files, the first being the AVT camera class: GIGECamera_2_1_18.py

The second being the tkinter class: Tkinter...py

Camera Class:


#Import libraries
import pymba #vimba package - Allied Vision Camera
import time #included in python - time delays
import numpy as np #numpy package - matrix
import cv2 #Used if bayerRGB format is selected to convert format into something tkinter can use

class GIGECamera():
    def __init__(self):
        vimba = pymba.Vimba()    
        vimba.startup()
        system = vimba.getSystem()
        system.runFeatureCommand("GeVDiscoveryAllOnce")
        time.sleep(0.2)

        try:
            camera_ids = vimba.getCameraIds()
            for cam_id in camera_ids:
                print("Camera found: ", cam_id)

            self.cam = vimba.getCamera(camera_ids[0])
            self.cam.openCamera()

            #Set Single Frame or Continuous operation
            self.cam.AcquisitionMode='SingleFrame'
            #self.cam.AcquisitionMode='Continuous'
            print(self.cam.AcquisitionMode)

            #self.cameraFeatureNames = self.cam.getFeatureNames()
            #for name in self.cameraFeatureNames:
            #    print('Camera feature:', name)

            #Set pixel format
            #Mono formats for 235
            #Mono8, Mono12Packed, Mono12
            #Color formats for 235
            #Mono8, BayerRG8, BayerRG12, RGB8Packed, BGR8Packed, YUV411Packed, YUV422Packed, YUV444Packed            
            self.cam.PixelFormat="Mono8"
            #self.cam.PixelFormat="RGB8Packed"
            #self.cam.PixelFormat="BayerRG8"

            #If we use the Bayer format - the speed is 4-5x more than RGB8Packed
            #https://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html
            #cv::COLOR_BayerBG2BGR, cv::COLOR_BayerGB2BGR, cv::COLOR_BayerRG2BGR, cv::COLOR_BayerGR2BGR, cv::COLOR_BayerBG2RGB, cv::COLOR_BayerGB2RGB, cv::COLOR_BayerRG2RGB, cv::COLOR_BayerGR2RGB 

            #Set Package size
            #The default is 8228 - but 1500 works with either the USB 2 or 3 adapter
            #Could not get anything higher than 1500 to work
            print(self.cam.GevSCPSPacketSize)
            self.cam.GevSCPSPacketSize=1500
            print(self.cam.GevSCPSPacketSize)

            #Set Payload Size
            #Default seems to work
            print(self.cam.PayloadSize)

            #Set Stream Bytes Per Second
            print(self.cam.StreamBytesPerSecond)
            self.cam.StreamBytesPerSecond = 115000000 #124000000 is the max I could get
            print(self.cam.StreamBytesPerSecond)

        except:
            #If any error
            print("Camera Not Connected Or Other Error")

    def start(self):
        #Runs once
        self.frame = self.cam.getFrame()
        self.frame.announceFrame()

    def getframe(self):
        #Runs each time a frame is captured
        try:
            self.cam.startCapture()
            self.frame.queueFrameCapture()
            self.cam.runFeatureCommand("AcquisitionStart")
            self.cam.runFeatureCommand("AcquisitionStop")
            self.frame.waitFrameCapture()
            frame_data = self.frame.getBufferByteData()
            #frame_data = cv2.cvtColor(frame_data,cv2.COLOR_BayerRG2RGB) #Convert color if using BayerRGB
            img = np.ndarray(buffer=frame_data,
                             dtype=np.uint8,
                             shape=(self.frame.height,self.frame.width,self.frame.pixel_bytes))
            self.cam.endCapture()
            self.cam.revokeAllFrames()
            return img
        except:
            #Once in a while it will throw a frame error - sometimes the camera recovers if you just run getFrame again
            #but other times it does not
            #Doing the reboot sequence seems to work consistently
            print("Frame Error")
            self.reboot()

    def reboot(self):
            #Reboot sequence if frame error    
            self.cam.flushCaptureQueue()
            self.cam.endCapture()
            self.cam.revokeAllFrames()
            self.start()
            self.getframe()

    def close(self):
        #Close camera unless it isn't open
        try:
            self.cam.revokeAllFrames()
            self.cam.closeCamera()
        except:
            pass

Tkinter class


import os #included in python - OS
import time #included in python - time delays
import numpy as np #numpy package - matrix
import cv2 #opencv package - image analysis
from PIL import Image, ImageTk #convert cv2 image to tkinter
import pymba #vimba package - Allied Vision Camera
import tkinter as tk  #included in python - GUI
from tkinter import filedialog #dialog boxes
E = tk.E
W = tk.W
N = tk.N
S = tk.S
ypadding = 1.5 #ypadding just to save time - used for both x and y

import threading as threading
import datetime as datetime
import queue as queue

#Set working directory to import user defined python programs
os.chdir('C:\\Projects\\Python\\')
#import GIGECamera as GIGECamera
from GIGECamera_2_1_18 import GIGECamera #import AVT camera code

class MainApplication(tk.Frame):
    #This is the root window so it does not require a parent
    #But we will utilize the parent so that we can cross reference the different classes
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

        #<create the rest of your GUI here>
        #For each frame - we are passing self to the frame - which is the parent for the other scripts
        #So here - self
        #But in the other frames - self.parent

        #Camera Frame
        self.cameraframe = CameraFrame(self)
        self.cameraframe.grid(row=0, column=0, padx=ypadding, pady=ypadding, sticky=E+S+W+N)

class CameraFrame(tk.Frame):
    def __init__(self,parent):
        tk.Frame.__init__(self, parent, width=250, height = 300, highlightthickness=2, highlightbackground="#111")
        self.parent = parent
        self.mainWidgets()

    def mainWidgets(self):
        self.cameraview = tk.Label(self)
        self.cameraview.grid(row=1,column=0,sticky=N+S+E+W, pady=ypadding)

        try:
            camera.start()
            self.queue = queue.Queue(maxsize=1)
            ThreadedCamera(self.parent,self.queue).start()
        except:
            pass

    def process_queue(self):
        try:
            img = self.queue.get()
            #1936 x 1216 original
            #picsize = 1936
            picsize = 1500
            r = picsize / img.shape[1]
            dim = (picsize, int(img.shape[0] * r))
            # perform the actual resizing of the image and show it
            resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
            imgresized = Image.fromarray(resized)
            imgtk = ImageTk.PhotoImage(image=imgresized)
            self.cameraview.configure(image=imgtk)
            self.cameraview.image = imgtk #If you don't have this - it will flicker the image since it gets deleted during one
        except:
            pass

class ThreadedCamera(threading.Thread):
    def __init__(self, parent,queue):
        threading.Thread.__init__(self)
        #Very import to import the parent
        self.parent = parent
        self.queue = queue

    def run(self):
        while True:
            if(self.queue.empty()):
                try:
                    camera.cam.ExposureTimeAbs=90000
                    img = camera.getframe()
                    #img = cv2.cvtColor(img,cv2.COLOR_BayerRG2BGR) #Remove this if using the RGB8Packed
                    self.queue.put(img)
                    self.parent.cameraframe.process_queue()
                except:
                    pass

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("1500x700")
    root.attributes('-topmost',True)
    root.after_idle(root.attributes,'-topmost',False)
    root.wm_title("Tkinter AVT GUI") #Makes the title that will appear in the top left

    #Setup the AVT camera
    camera = GIGECamera()
    time.sleep(0.2)

    #load main application
    MainApplication(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

    #Close Camera
    try:
        camera.close() 
    except:
        pass