diff --git a/AscCam.py b/AscCam.py index 1b0c110..ebb6208 100755 --- a/AscCam.py +++ b/AscCam.py @@ -1,311 +1,353 @@ #!/usr/bin/python3 # Few required libraries import tkinter as tk import os import time +import numpy as np +import matplotlib from picamera import PiCamera +matplotlib.use('TkAgg') + +from matplotlib.figure import Figure +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg + # Main Tkinter class class GUI(tk.Frame): # Initialization of the class def __init__(self, master=None): super().__init__(master) self.master = master # Create the GUI self.create_widgets() # Instantiate the camera self.camera = PiCamera(sensor_mode=3, resolution=PiCamera.MAX_RESOLUTION, framerate=10) + self.data = np.empty((round(self.camera.resolution[1]/32)*32, round(self.camera.resolution[0]/32)*32, 3), dtype=np.uint8) + # filepath for output: self.basePath = '/home/pi/Desktop/Imaging/{}'.format(time.strftime('%Y-%m-%d')) if not os.path.exists(self.basePath): os.mkdir(self.basePath) os.chown(self.basePath, 1000, 1000) # Parameter for the timelapse self.isTLOn = False self.tlInterval = 60000 + self.dt = 0 + self.prevTime = None self.timelapsePath = self.basePath self.job = None # Create the main GUI def create_widgets(self): # Create separate frames to group similar buttons frame1 = tk.Frame(master=self.master, bd=2, relief="ridge") - frame1.grid(row=0, column=0, columnspan=1, rowspan=3, sticky="N") + frame1.grid(row=0, column=0, columnspan=1, rowspan=1, sticky="N") frame2 = tk.Frame(master=self.master, bd=2) - frame2.grid(row=0, column=1, columnspan=2, rowspan=1, sticky="NW") + frame2.grid(row=0, column=1, columnspan=1, rowspan=1, sticky="NW") frame3 = tk.Frame(master=self.master, bd=2, relief="ridge") - frame3.grid(row=2, column=1, columnspan=2, rowspan=2, sticky="NW") + frame3.grid(row=0, column=2, columnspan=1, rowspan=1, sticky="NW") # In Frame1 the general handling buttons # Place the first item (a label) in the first frame self.camLabel = tk.Label(master=frame1, text="CAMERA") self.camLabel.pack() # Then the preview buttons self.camOnButt = tk.Button(master=frame1, text="ON", fg="green", command=self.camOn) self.camOnButt.pack() self.camOffButt = tk.Button(master=frame1, text="OFF", fg="red", command=self.camOff) self.camOffButt.pack() # the acquisition section self.camResLabel = tk.Label(master=frame1, text=" Acquisition ") self.camResLabel.pack() self.camSnapButt = tk.Button(master=frame1, text="Snapshot", command=self.camSnap) self.camSnapButt.pack() - self.camTLButt = tk.Button(master=frame1, text="Time Lapse", command=self.camTL) - self.camTLButt.pack() self.camRecButt = tk.Button(master=frame1, text="Video", command=self.camRec) self.camRecButt.pack() + # Time lapse with interval + self.camTLButt = tk.Button(master=frame1, text="Time Lapse", command=self.camTL) + self.camTLButt.pack() + self.intervalVar = tk.IntVar(value=1) + self.camInterval = tk.Scale(master=frame1, label="interval (min)", + variable=self.intervalVar, from_=1, + to=1000, resolution=1, orient="horizontal") + self.camInterval.set(1) + self.camInterval.pack() + # The Exit section self.camResLabel = tk.Label(master=frame1, text=" Exit ") self.camResLabel.pack(fill="x") self.quit= tk.Button(master=frame1, text="QUIT", fg="blue", command=self.master.destroy) self.quit.pack() # In Frame 2, the camera's options # Digital zoom self.zoomVar = tk.IntVar(value=1) self.camZoom = tk.Scale(master=frame2, label="Digi Zoom", variable=self.zoomVar, from_=1, to=10, resolution=1, orient="horizontal", command=self.setZoom) self.camZoom.set(1) self.camZoom.pack() # Image rotation self.rotVar = tk.IntVar(value=90) self.camRot = tk.Scale(master=frame2, label="Rotation", variable=self.rotVar, from_=0, to=270, resolution=90, orient="horizontal", command=self.setRot) self.camRot.set(90) self.camRot.pack() # Brightness self.brightVar = tk.IntVar(value=50) self.camBright = tk.Scale(master=frame2, label="Brightness", variable=self.brightVar, from_=0, to=100, resolution=5, orient="horizontal", command=self.setBright) self.camBright.set(50) self.camBright.pack() # Contrast self.contrVar = tk.IntVar(value=0) self.camContrast = tk.Scale(master=frame2, label="Contrast", variable=self.contrVar, from_=-100, to=100, resolution=10, orient="horizontal", command=self.setContrast) self.camContrast.set(0) self.camContrast.pack() # Exposure mode and duration self.expLabel = tk.Label(master=frame2, text=" Exposure modes ") self.expLabel.pack(fill="x") exp_options = list(PiCamera.EXPOSURE_MODES.keys()) self.expVar = tk.StringVar() self.expVar.set("auto") self.expMenu = tk.OptionMenu(frame2, self.expVar, *exp_options, command=self.setExpMode) self.expMenu.pack(fill="x") self.expVar = tk.IntVar(value=50) self.camExp = tk.Scale(master=frame2, label="exposure (ms)", variable=self.expVar, from_=1, to=100, resolution=1, orient="horizontal", command=self.setExp, state=tk.DISABLED) self.camExp.set(50) self.camExp.pack() - # Time lapse interval - self.intervalVar = tk.IntVar(value=60) - self.camInterval = tk.Scale(master=frame2, label="TL interval (s)", - variable=self.intervalVar, from_=10, - to=10000, resolution=10, orient="horizontal") - self.camInterval.set(60) - self.camInterval.pack() - # In frame 3 the white-balance # First the modes self.wbLabel = tk.Label(master=frame3, text=" White-balance modes ") self.wbLabel.pack(fill="x") wb_options = list(PiCamera.AWB_MODES.keys()) self.wbVar = tk.StringVar() self.wbVar.set("auto") self.wbMenu = tk.OptionMenu(frame3, self.wbVar, *wb_options, command=self.setAWBMode) self.wbMenu.pack(fill="x") # And then the gains self.redVar = tk.DoubleVar(value=1.2) self.wbRed = tk.Scale(master=frame3, label="red gain", variable=self.redVar, from_=0.0, to=8.0, resolution=0.1, orient="horizontal", command=self.setGain, state=tk.DISABLED) self.wbRed.set(1.2) self.wbRed.pack() self.greenVar = tk.DoubleVar(value=1.2) self.wbGreen = tk.Scale(master=frame3, label="green gain", variable=self.greenVar, from_=0.0, to=8.0, resolution=0.1, orient="horizontal", command=self.setGain, state=tk.DISABLED) self.wbGreen.set(1.2) self.wbGreen.pack() + # Then the preview buttons + self.camHistButt = tk.Button(master=frame3, text="Histogram", command=self.camHist) + self.camHistButt.pack() + + self.fig = Figure(figsize=(2,2), dpi=100) + self.axes = self.fig.add_subplot(111) + self.canevas = FigureCanvasTkAgg(self.fig, master=frame3) + self.canevas.get_tk_widget().pack() + self.canevas.show() + def camOn(self): self.camera.start_preview(fullscreen=False, window=(0, 0, 640, 480)) return def camOff(self): self.camera.stop_preview() return def camSnap(self): photoPath = self.basePath + '/snaps/' #check to see if the snap output folder is present: if not os.path.exists(photoPath): #if not, create it: os.makedirs(photoPath) os.chown(photoPath, 1000, 1000) # Camera warm-up time time.sleep(1) self.camera.capture(photoPath + 'snap_' + time.strftime("%Y-%m-%d-%H-%M-%S") + '.png') return def camTL(self): if self.isTLOn: if self.job is not None: root.after_cancel(self.job) self.job = None + self.prevTime = None + self.dt = 0 self.camTLButt.configure(text="Time Lapse") self.camInterval.configure(state=tk.NORMAL) self.camRecButt.configure(state=tk.NORMAL) else: - self.timelapsePath = self.basePath + '/timelapse_' + - time.strftime("%Y-%m-%d-%H-%M-%S") + self.timelapsePath = (self.basePath + '/timelapse_' + + time.strftime("%Y-%m-%d-%H-%M-%S")) #check to see if the snap output folder is present: if not os.path.exists(self.timelapsePath): #if not, create it: os.makedirs(self.timelapsePath) os.chown(self.timelapsePath, 1000, 1000) self.camRecButt.configure(state=tk.DISABLED) self.camInterval.configure(state=tk.DISABLED) - self.tlInterval = int(self.camInterval.get())*1000; + self.tlInterval = int(self.camInterval.get())*60000; + self.dt = 0 self.camTLButt.configure(text="STOP TL") self.isTLOn = not self.isTLOn if self.isTLOn: self.acquireTL() return def acquireTL(self): if self.isTLOn: # Camera warm-up time time.sleep(1) - self.camera.capture(self.timelapsePath + 'timelapse_' + - time.strftime("%Y-%m-%d-%H-%M-%S") + '.png') + self.camera.capture(self.timelapsePath + '/timelapse_' + + time.strftime("%d-%H-%M-%S") + '.png') + + now = time.time() + if self.prevTime is not None: + self.dt = self.dt + self.tlInterval - round((now - self.prevTime)*1000) - self.job = self.root.after(self.tlInterval, self.acquireTL) + self.prevTime = now + + self.job = root.after(self.tlInterval + self.dt, self.acquireTL) return def camRec(self): return + def camHist(self): + + self.camera.capture(self.data, 'rgb') + color = ('r', 'g', 'b') + self.axes.clear() + for channel in range(3): + hist,bins = np.histogram(self.data[:,:,channel], 256, [0, 256]) + self.axes.plot(hist, color=color[channel]) + self.canevas.draw() + + return + def setZoom(self, zoom): zoomSide = 1 / float(zoom) edge = (1 - zoomSide)*0.5 self.camera.zoom = (edge, edge, zoomSide, zoomSide) return def setRot(self, rot): self.camera.rotation = int(rot) return def setAWBMode(self, awb): if self.camera.awb_mode == "off" and awb != "off": self.wbRed.configure(state=tk.DISABLED) self.wbGreen.configure(state=tk.DISABLED) self.camera.awb_mode = awb if awb == "off": self.wbRed.configure(state=tk.NORMAL) self.wbGreen.configure(state=tk.NORMAL) self.setGain(0) return def setGain(self, gain): red = self.wbRed.get() green = self.wbRed.get() self.camera.awb_gains = (red, green) return def setBright(self, bright): self.camera.brightness = int(bright) return - def setConstrast(self, contr): + def setContrast(self, contr): self.camera.contrast = int(contr) return def setExpMode(self, exp): if self.camera.exposure_mode == "off" and exp != "off": self.setExp(0) self.camExp.configure(state=tk.DISABLED) self.camera.exposure_mode = exp if exp == "off": self.camExp.configure(state=tk.NORMAL) self.setExp(self.camExp.get()) return def setExp(self, exp): exp = int(exp)*1000 self.camera.shutter_speed = exp return root = tk.Tk() root.title("AscCam 0.01") root.resizable(width=False, height=False) root.geometry("+15+400") app = GUI(master=root) app.mainloop()