diff --git a/SpecPy.py b/SpecPy.py index 22c7628..81a8c22 100644 --- a/SpecPy.py +++ b/SpecPy.py @@ -9,8 +9,13 @@ import os import glob import numpy as np -import matplotlib import matplotlib.pyplot as plt +#matplotlib.use('Agg') +from matplotlib.figure import Figure +#import matplotlib.pyplot as plt + +import platform +#import gc import csv # Folder in which to save the output data @@ -19,12 +24,17 @@ CAMARA = 0 STREAMWIDTH = 680 STREAMHEIGHT = 480 +PLATFORM = platform.system() +""" + Class that defines a frame that wants to be captured +""" class CapturedFrame: - def __init__(self, frame, identifier, center, interval, path): + def __init__(self, frame, objectName, identifier, center, interval, path): self.image = frame self.center = center self.interval = interval + self.objectName = objectName self.identifier = identifier self.height = frame.shape[0] self.width = frame.shape[1] @@ -54,13 +64,22 @@ def calculateNormalIntensity(self): self.normalIntensity = self.intensity/max_value def saveFrame(self): - temp = self.path + "/%02d"%self.identifier + ".jpg" + temp = self.path +"/"+ self.objectName + "_%02d"%self.identifier + ".jpg" cv2.imwrite(temp, self.image) def saveData(self): + def csv2list(directory): + temp = [] + file = open(directory, 'r') + csvFile = csv.reader(file, delimiter=',') + for item in csvFile: + temp.append(item) + file.close() + return temp + directories = [self.path + "/Regular.csv", self.path + "/Normal.csv"] data_arrays = (self.intensity, self.normalIntensity) - if self.identifier == 0: + if not os.path.exists(directories[0]): for (inten, direc) in zip(data_arrays, directories): file = open(direc, "w") wr = csv.writer(file) @@ -70,71 +89,84 @@ def saveData(self): file.close() else: for(inten, direc) in zip(data_arrays, directories): - new_data = [] - file = open(direc, 'r') - data = csv.reader(file, delimiter=',') + data = csv2list(direc) + num_rows = len(data) - 1 # Because of the information row + columnNumber = len(data[0]) + num_inten_rows = len(inten) + inten = list(inten) + row_prototype = ["" for i in range(columnNumber)] + + if num_rows < num_inten_rows: + x = int(data[-1][0]) + 1 + while num_rows - 1 < num_inten_rows: + row = list(row_prototype) + row[0] = x + data.append(row) + num_rows += 1 + x += 1 + + elif num_inten_rows < num_rows: + while num_inten_rows < num_rows: + inten.append("") + num_inten_rows += 1 + inten.insert(0,"") i = 0 for (line, value) in zip(data, inten): if i == 0: - line.append(str(self.identifier)) - temp = line + line.append(self.objectName + ' ' + str(self.identifier)) else: line.append(str(value)) - temp = line - new_data.append(temp) i += 1 - file.close() + file = open(direc, 'w') wr = csv.writer(file) - for row in new_data: + for row in data: wr.writerow(row) file.close() - + + def changePath(self, path): + self.path = path + +""" + Class which handles the real time information plotting +""" class RealTimePlot: - fig, (ax1, ax2) = plt.subplots(2, figsize = (8, 4.5)) - ax1.set_ylabel("Normal intensity (a.u.)") - ax2.set_ylabel("Intensity (a.u.)") - ax2.set_xlabel("Pixel") -# plt.tight_layout() - linesNormal = [] - linesRegular = [] - def __init__(self, height, width, size = (8, 4.5)): - self.fig.set_size_inches(size) + def __init__(self, height, width): + self.fig = Figure() + print(self.fig) + self.ax1 = self.fig.add_subplot(211) + self.ax2 = self.fig.add_subplot(212) + self.ax1.set_ylabel("Normalized intensity") + self.ax2.set_ylabel("Intensity") + self.ax2.set_xlabel("Pixel") + self.fig.set_facecolor("None") self.height = height self.width = width self.ax1.set_xlim(0, self.width) self.ax1.set_ylim(0, 1) self.ax2.set_xlim(0, self.width) - self.ax2.set_ylim(0, self.height*200) - self.ax1.hold(True) - self.ax2.hold(True) + self.ax2.set_ylim(0, self.height*255) + self.ax1.grid() self.ax2.grid() -# self.fig.canvas.manager.window.attributes('-topmost', 1) - self.fig.show(False) - plt.draw() - self.background = self.fig.canvas.copy_from_bbox(self.ax1.get_figure().bbox) + + self.normalLines = [] + self.regularLines = [] + self.x = np.linspace(0, self.width, self.width) + self.changeAxesFontSize(self.ax1) + self.changeAxesFontSize(self.ax2) def includeCapturedFrame(self, captured_frame): intensity = captured_frame.intensity - normalintensity= captured_frame.normalIntensity + normalintensity = captured_frame.normalIntensity style = "-" - line = self.ax1.plot(self.x, normalintensity, style)[0] - self.linesNormal.append(line) - line = self.ax2.plot(self.x, intensity, style)[0] - self.linesRegular.append(line) - def plotRefresh(self): - self.fig.canvas.restore_region(self.background) - self.ax1.draw_artist(self.ax1.get_children()[0]) - for (line, lineR) in zip(self.linesNormal, self.linesRegular): - self.ax1.draw_artist(line) - self.ax2.draw_artist(lineR) - self.fig.canvas.blit(self.ax1.clipbox) + self.normalLines.append(self.ax1.plot(self.x, normalintensity, style)[0])#) + self.regularLines.append(self.ax2.plot(self.x, intensity, style)[0])#) def cleanLines(self): - for (lineN, lineR) in zip(self.linesNormal, self.linesRegular): + for (lineN, lineR) in zip(self.normalLines, self.regularLines): lineN.set_data([],[]) lineR.set_data([],[]) self.ax1.set_prop_cycle(None) @@ -144,65 +176,95 @@ def cleanPlot(self): self.cleanLines() self.linesNormal = [] self.linesRegular = [] - self.fig.canvas.draw() - self.background = self.fig.canvas.copy_from_bbox(self.ax1.get_figure().bbox) +# self.fig.canvas.draw() - def close(self): - plt.close() + def figureReturn(self): + return self.fig + + def changeAxesFontSize(self, axes): + for item in ([axes.title, axes.xaxis.label, axes.yaxis.label] + + axes.get_xticklabels() + axes.get_yticklabels()): + item.set_fontsize(10) + + def changeAxes(self): + self.ax1.set_xlim(0, self.width) + self.ax2.set_xlim(0, self.width) + self.x = np.linspace(0, self.width, self.width) class GuiWindow: - def __init__(self, name, camara, streamWidth, streamHeight, path): + def __init__(self, name, camara, objectName, streamWidth, streamHeight, + path, pos = 0, size = 0, brightness = 50, contrast = 50, saturation = 50, + hue = 50, gain = 50, exposure = 50, window = None): self.name = name self.trackBarName = "Settings" self.camara = camara self.path = path self.input = cv2.VideoCapture(camara) - - self.brightness = 50 - self.constrast = 50 - self.saturation = 50 - self.hue = 50 - self.gain = 50 - self.exposure = 50 - - self.frame = self.input.read()[1] - self.height, self.width, _ = self.frame.shape + self.objectName = objectName + self.resetSettings(pos, size, brightness, contrast, saturation, hue, + gain, exposure) + """ + Frame is presented one + """ + self.analysisFrame = self.input.read()[1] + self.analysisHeight, self.analysisWidth, _ = self.analysisFrame.shape self.streamHeight = streamHeight self.streamWidth = streamWidth - self.pixelLine = int(np.ceil(self.height/2)) - self.range = int(np.ceil(self.height/4)) + self.pixelLine = int(np.ceil(self.analysisHeight/2)) + self.range = int(np.ceil(self.analysisHeight/4)) self.kbkey = 0 - self.createTrackBars() - self.actualPlot = RealTimePlot(self.height, self.width) + + self.actualPlot = RealTimePlot(self.analysisHeight, self.analysisWidth) + self.figure = self.actualPlot.figureReturn() + + def squareInFrame(self): + cv2.rectangle(self.analysisFrame, (0, self.pixelLine-self.range), (self.analysisWidth, self.pixelLine-self.range), (0, 255, 255), 3) + cv2.rectangle(self.analysisFrame, (0, self.pixelLine+self.range), (self.analysisWidth, self.pixelLine+self.range), (0, 255, 255), 3) + cv2.rectangle(self.analysisFrame, (0, self.pixelLine), (self.analysisWidth, self.pixelLine), (0, 255, 0), 3) - self.brightnessTrackBar(self.brightness) - self.constrastTrackBar(self.constrast) - self.saturationTrackBar(self.saturation) - self.hueTrackBar(self.hue) - self.gainTrackBar(self.gain) - self.exposureTrackBar(self.exposure) + def resize(self): + self.frame = cv2.resize(self.analysisFrame, (self.streamWidth, self.streamHeight)) + + def captureData(self, temp_frame, fig_num): + temp_frameY, temp_frameX, _ = temp_frame.shape + if self.actualPlot.width != temp_frameX: + self.actualPlot.width = temp_frameX + self.actualPlot.changeAxes() + temp = CapturedFrame(temp_frame, self.objectName, fig_num, self.pixelLine, self.range, self.path) + try: + self.actualPlot.includeCapturedFrame(temp) + self.actualPlot.plotRefresh() + except: + pass + temp.image = self.analysisFrame + temp.saveFrame() + fig_num += 1 + return fig_num - def createTrackBars(self): - cv2.namedWindow(self.trackBarName) - cv2.createTrackbar("Position", self.trackBarName, self.pixelLine, self.height, self.posTrackBar) - cv2.createTrackbar("Size", self.trackBarName, self.range, self.height, self.rangeTrackBar) - cv2.createTrackbar("Brightness", self.trackBarName, self.brightness, 100, self.brightnessTrackBar) - cv2.createTrackbar("Contrast", self.trackBarName, self.constrast, 100, self.constrastTrackBar) - cv2.createTrackbar("Saturation", self.trackBarName, self.saturation, 100, self.saturationTrackBar) - cv2.createTrackbar("Hue", self.trackBarName, self.hue, 100, self.hueTrackBar) - cv2.createTrackbar("Gain", self.trackBarName, self.gain, 100, self.gainTrackBar) - cv2.createTrackbar("Exposure", self.trackBarName, self.exposure*100, 100, self.exposureTrackBar) + def cleanData(self): + self.actualPlot.cleanPlot() - cv2.resizeWindow(self.trackBarName, 100, 50) + def eachPhotogram(self): + ans, self.analysisFrame = self.input.read() + if not ans or any(value is np.nan for value in self.analysisFrame): + return False + self.notSquaredAnalysisFrame = self.analysisFrame.copy() + self.squareInFrame() + self.figure = self.actualPlot.figureReturn() + self.resize() + self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB) + return True - def squareInFrame(self): - cv2.rectangle(self.frame, (0, self.pixelLine-self.range), (self.width-2, self.pixelLine+self.range), (0, 255, 255), 2) - cv2.rectangle(self.frame, (0, self.pixelLine), (self.width-1, self.pixelLine), (0, 255, 0), 2) - - def textInFrame(self): - cv2.putText(self.frame, "Esc to exit", (5, 25), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255)) - cv2.putText(self.frame, "c to clear plot", (5, 45), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255)) - cv2.putText(self.frame, "Enter to capture frame", (5, 65), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255)) + def closeInput(self): +# self.actualPlot.close() + cv2.destroyAllWindows() + self.input.release() + + def changeWidth(self, width): + self.streamWidth = width + + def changeHeight(self, height): + self.streamHeight = height def posTrackBar(self, pos): self.pixelLine = pos @@ -212,67 +274,62 @@ def rangeTrackBar(self, size): def brightnessTrackBar(self, brightness): self.brightness = brightness - self.input.set(10, self.brightness/100) + if PLATFORM == "Linux": + self.brightness *= 1/100 + self.input.set(10, self.brightness) - def constrastTrackBar(self, constrast): - self.constrast = constrast - self.input.set(11, self.constrast/100) + def contrastTrackBar(self, contrast): + self.contrast = contrast + if PLATFORM == "Linux": + self.contrast *= 1/100 + self.input.set(10, self.contrast) def saturationTrackBar(self, saturation): self.saturation = saturation - self.input.set(12, self.saturation/100) - + if PLATFORM == "Linux": + self.saturation *= 1/100 + self.input.set(12, self.saturation) + def hueTrackBar(self, hue): self.hue = hue - self.input.set(13, self.hue/100) + if PLATFORM == "Linux": + self.hue *= 1/100 + self.input.set(13, self.hue) def gainTrackBar(self, gain): self.gain = gain - self.input.set(14, self.gain/100) + if PLATFORM == "Linux": + self.gain *= 1/100 + self.input.set(14, self.gain) def exposureTrackBar(self, exposure): self.exposure = exposure - self.input.set(15, self.exposure/100) - - def resize(self): - self.frame = cv2.resize(self.frame, (self.streamWidth, self.streamHeight)) + if PLATFORM == "Linux": + self.exposure *= 1/100 + self.input.set(15, self.exposure) - def show(self): - cv2.imshow(self.name, self.frame) - - def loop(self): - fig_num = 0 - closed = False - while True: - self.frame = self.input.read()[1] - temp_frame = self.frame.copy() - self.squareInFrame() - self.textInFrame() - self.kbkey = cv2.waitKey(1) & 0xff - if self.kbkey == 27: - break - - elif self.kbkey == 10: - temp = CapturedFrame(temp_frame, fig_num, self.pixelLine, self.range, self.path) - self.actualPlot.includeCapturedFrame(temp) - self.actualPlot.plotRefresh() - temp.image = self.frame - temp.saveFrame() - fig_num += 1 - - elif self.kbkey == ord('c'): - self.actualPlot.cleanPlot() - elif self.kbkey == 32: # Space bar - if closed: - self.createTrackBars() - else: - cv2.destroyWindow(self.trackBarName) - closed = not closed - self.resize() - self.show() - self.actualPlot.close() - cv2.destroyAllWindows() - self.input.release() + def setCaptureWidth(self, width): + self.analysisWidth = width + self.input.set(3, self.analysisWidth) + + def setCaptureHeight(self, height): + self.analysisHeight = height + self.input.set(4, self.analysisHeight) + + def resetSettings(self, pos, size, brightness, contrast, saturation, + hue, gain, exposure): + self.posTrackBar(pos) + self.rangeTrackBar(size) + self.brightnessTrackBar(brightness) + self.contrastTrackBar(contrast) + self.saturationTrackBar(saturation) + self.hueTrackBar(hue) + self.gainTrackBar(gain) + self.exposureTrackBar(exposure) + +""" +GUI +""" if __name__ == "__main__": if not os.path.exists(PATH): @@ -281,8 +338,3 @@ def loop(self): temp = glob.glob(PATH+'/*.jpg') for item in temp: os.remove(item) - - camara = 0 - cam = GuiWindow("Stream", CAMARA, STREAMWIDTH, STREAMHEIGHT, PATH) - cam.loop() - diff --git a/SpecPySplash.py b/SpecPySplash.py new file mode 100644 index 0000000..6c4eb9b --- /dev/null +++ b/SpecPySplash.py @@ -0,0 +1,264 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Jul 28 19:36:14 2016 + +@author: juan +""" + +from PyQt4.uic import loadUiType +from PyQt4 import QtCore, QtGui +import sys, GUI_data#, time + +app = QtGui.QApplication(sys.argv) +# Create and display the splash screen +splash_pix = QtGui.QPixmap(':/SpecPy.png') +splash = QtGui.QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint) +splash.show() +#time.sleep(3) +app.processEvents() + +import SpecPy as specpy +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt4agg import (FigureCanvasQTAgg as FigureCanvas) + +Ui_MainWindow, QMainWindow = loadUiType('mainwindow.ui') +CAMARA = 0 +CAPTUREWIDTH = 680 +CAPTUREHEIGHT = 480 +STREAMWIDTH = 100 +STREAMHEIGHT = int(3*STREAMWIDTH/4) + +PATH = "../Captures" +POS = int(CAPTUREHEIGHT/2) +SIZE = int(POS/2) +BRIGHTNESS = 50 +CONTRAST = 50 +SATURATION = 50 +HUE = 50 +GAIN = 50 +EXPOSURE = 50 + +class Main(QMainWindow, Ui_MainWindow): + def __init__(self, ): + super(Main, self).__init__() + self.setupUi(self) + + icon = QtGui.QIcon(':/Icon.png') + self.setWindowIcon(icon) + + self.coeffWH = CAPTUREHEIGHT/CAPTUREWIDTH + + self.objectName = self.objectLine.text() + + self.path = PATH + self.directoryLine.setText(self.path) + + self.pathCleaner(True) + self.videoStream() + + self.posSlider.valueChanged.connect(self.posChange) + self.posSlider.setMinimum(0) + self.posSlider.setMaximum(CAPTUREHEIGHT) + self.posSlider.setValue(POS) + + self.sizeSlider.valueChanged.connect(self.sizeChange) + self.sizeSlider.setMinimum(0) + self.sizeSlider.setMaximum(POS) + self.sizeSlider.setValue(SIZE) + + self.brightnessSlider.valueChanged.connect(self.brightnessChange) + self.contrastSlider.valueChanged.connect(self.contrastChange) + self.saturationSlider.valueChanged.connect(self.saturationChange) + self.hueSlider.valueChanged.connect(self.hueChange) + self.gainSlider.valueChanged.connect(self.gainChange) + self.exposureSlider.valueChanged.connect(self.exposureChange) + + self.captureButton.clicked.connect(self.captureData) + self.cleanButton.clicked.connect(self.cam.cleanData) + self.resetButton.clicked.connect(self.resetSettings) + + self.comboBox_2.addItem("680 x 480") + self.comboBox_2.addItem("1280 x 720") +# self.comboBox_2.addItem("1920 x 1080") + + self.comboBox_2.activated[str].connect(self.resolutionBox) + + self.canvas = None + + def videoStream(self): + self.cam = specpy.GuiWindow("Stream", CAMARA, self.objectName, STREAMWIDTH, STREAMHEIGHT, PATH, + POS, SIZE, BRIGHTNESS, CONTRAST, SATURATION, HUE, + GAIN, EXPOSURE, "canvas") + self.updateImage() + self.fig_num = 0 + + def qImage(self, width, height, bytesPerLine): + qImg = QtGui.QImage(self.cam.frame.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888) + pix = QtGui.QPixmap(qImg) + return pix + + def keyPressEvent(self, event): + keyPressed = event.key() + if keyPressed == QtCore.Qt.Key_Alt + QtCore.Qt.Key_F4: + self.cam.closeInput() + self.close() + elif keyPressed == QtCore.Qt.Key_Enter - 1: + self.captureData() + elif keyPressed == QtCore.Qt.Key_C: + self.cam.cleanData() + self.updatePlot() + elif keyPressed == QtCore.Qt.Key_R: + self.resetSettings() + + def updateImage(self): + width = self.CamaraStream.frameGeometry().width() + height = int(self.coeffWH*width) + realHeight = self.CamaraStream.frameGeometry().height() + if height > realHeight: + width = int(realHeight/self.coeffWH) + height = realHeight + self.cam.changeHeight(height) + self.cam.changeWidth(width) + bytesPerLine = 3*width + answer = self.cam.eachPhotogram() + if answer: + pix = self.qImage(width, height, bytesPerLine) + self.CamaraStream.setPixmap(pix) + + def update(self): + timer = QtCore.QTimer(self) + timer.timeout.connect(self.updateImage) + timer.start(33) + + # Creates first plot + self.updatePlot() + + def updatePlot(self): + def create(): + figure = self.cam.figure + if figure != None: + self.canvas = FigureCanvas(figure) + self.figureFrame.addWidget(self.canvas) + self.canvas.draw() + else: + self.canvas == None + + def removePlot(): + self.figureFrame.removeWidget(self.canvas) + self.canvas.close() + + if self.canvas == None: + create() + else: + removePlot() + create() + + def posSliderLimits(self): + self.posSlider.setMinimum(0) + temp = self.cam.analysisHeight + self.posSlider.setMaximum(temp)#CAPTUREHEIGHT) + self.posSlider.setValue(int(temp/2)) + + def sizeSliderLimits(self): + self.sizeSlider.setMinimum(0) + temp = self.cam.analysisHeight + self.sizeSlider.setMaximum(int(temp/2)) + self.sizeSlider.setValue(int(temp/4)) + + def posChange(self): + size = self.posSlider.value() + self.cam.posTrackBar(size) + + def sizeChange(self): + size = self.sizeSlider.value() + self.cam.rangeTrackBar(size) + + def brightnessChange(self): + size = self.brightnessSlider.value() + self.cam.brightnessTrackBar(size) + + def contrastChange(self): + size = self.contrastSlider.value() + self.cam.contrastTrackBar(size) + + def saturationChange(self): + size = self.saturationSlider.value() + self.cam.saturationTrackBar(size) + + def hueChange(self): + size = self.hueSlider.value() + self.cam.hueTrackBar(size) + + def gainChange(self): + size = self.gainSlider.value() + self.cam.gainTrackBar(size) + + def exposureChange(self): + size = self.exposureSlider.value() + self.cam.exposureTrackBar(size) + + def captureData(self): + self.objectNameChanger() + self.pathChanger() + self.fig_num = self.cam.captureData(self.cam.notSquaredAnalysisFrame, self.fig_num) + self.updatePlot() + + def resetSettings(self): + self.cam.resetSettings(POS, SIZE, BRIGHTNESS, CONTRAST, SATURATION, HUE, GAIN, EXPOSURE) + self.posSlider.setValue(POS) + self.sizeSlider.setValue(SIZE) + self.brightnessSlider.setValue(BRIGHTNESS) + self.contrastSlider.setValue(CONTRAST) + self.saturationSlider.setValue(SATURATION) + self.hueSlider.setValue(HUE) + self.gainSlider.setValue(GAIN) + self.exposureSlider.setValue(EXPOSURE) + self.path = PATH + self.directoryLine.setText(self.path) + self.objectName = "" + self.objectLine.setText(self.objectName) + self.comboBox_2.setCurrentIndex(0) + self.resolutionBox(self.comboBox_2.currentText()) + + def closeEvent(self, event): + self.cam.closeInput() + self.close() + + def resolutionBox(self, text): + parted_line = text.rpartition('x') + width, _, height = parted_line + width = int(width) + height = int(height) + self.coeffWH = height/width + self.cam.setCaptureHeight(height) + self.cam.setCaptureWidth(width) + self.posSliderLimits() + self.sizeSliderLimits() + + def objectNameChanger(self): + self.objectName = self.objectLine.text() + self.cam.objectName = self.objectName +# print(text) + + def pathChanger(self): + self.path = self.directoryLine.text() + self.cam.path = self.path + self.pathCleaner(False) + + def pathCleaner(self, delete): + import os, glob + if not os.path.exists(self.path): + os.makedirs(self.path) + if delete: + temp = glob.glob(self.path+'/*.jpg') + temp2 = glob.glob(self.path+'/*.csv') + temp += temp2 + for item in temp: + os.remove(item) + +main = Main() +main.show() +#pathCleaner() +splash.close() +main.update() +sys.exit(app.exec_()) diff --git a/build/Linux/SpecPy.py b/build/Linux/SpecPy.py index abae946..d63f2d3 100644 --- a/build/Linux/SpecPy.py +++ b/build/Linux/SpecPy.py @@ -9,8 +9,13 @@ import os import glob import numpy as np -import matplotlib import matplotlib.pyplot as plt + + +#from PyQt4.QtCore import * +#from PyQt4.QtGui import * +#from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas +#import sys import csv # Folder in which to save the output data @@ -92,13 +97,14 @@ def saveData(self): class RealTimePlot: fig, (ax1, ax2) = plt.subplots(2, figsize = (8, 4.5)) - ax1.set_ylabel("Normal intensity (a.u.)") - ax2.set_ylabel("Intensity (a.u.)") - ax2.set_xlabel("Pixel") -# plt.tight_layout() +# ax1.set_ylabel("Normal intensity (a.u.)") +# ax2.set_ylabel("Intensity (a.u.)") +# ax2.set_xlabel("Pixel") + fig.set_facecolor("None") + plt.tight_layout() linesNormal = [] linesRegular = [] - def __init__(self, height, width, size = (8, 4.5)): + def __init__(self, height, width, size = (8, 4.5), windowPath = None): self.fig.set_size_inches(size) self.height = height self.width = width @@ -109,10 +115,14 @@ def __init__(self, height, width, size = (8, 4.5)): self.ax1.hold(True) self.ax2.hold(True) self.ax1.grid() - self.ax2.grid() + self.ax2.grid() + if windowPath == None: + self.fig.show(False) # self.fig.canvas.manager.window.attributes('-topmost', 1) - self.fig.show(False) - plt.draw() +# self.fig.show(False) + plt.draw() + + self.background = self.fig.canvas.copy_from_bbox(self.ax1.get_figure().bbox) self.x = np.linspace(0, self.width, self.width) @@ -150,8 +160,11 @@ def cleanPlot(self): def close(self): plt.close() + def figureReturn(self): + return self.fig + class GuiWindow: - def __init__(self, name, camara, streamWidth, streamHeight, path): + def __init__(self, name, camara, streamWidth, streamHeight, path, window = None): self.name = name self.trackBarName = "Settings" self.camara = camara @@ -166,43 +179,74 @@ def __init__(self, name, camara, streamWidth, streamHeight, path): self.exposure = 50 self.frame = self.input.read()[1] + self.analysisFrame = self.frame.copy() self.height, self.width, _ = self.frame.shape self.streamHeight = streamHeight self.streamWidth = streamWidth self.pixelLine = int(np.ceil(self.height/2)) self.range = int(np.ceil(self.height/4)) self.kbkey = 0 - self.createTrackBars() - self.actualPlot = RealTimePlot(self.height, self.width) +# self.createTrackBars() + self.actualPlot = RealTimePlot(self.height, self.width, windowPath=window) + self.figure = self.actualPlot.figureReturn() +# self.canvas = self.canvas#self.actualPlot.figureReturn() + + def squareInFrame(self): + cv2.rectangle(self.frame, (0, self.pixelLine-self.range), (self.width, self.pixelLine-self.range), (0, 255, 255), 3) + cv2.rectangle(self.frame, (0, self.pixelLine+self.range), (self.width, self.pixelLine+self.range), (0, 255, 255), 3) + cv2.rectangle(self.frame, (0, self.pixelLine), (self.width, self.pixelLine), (0, 255, 0), 3) - self.brightnessTrackBar(self.brightness) - self.constrastTrackBar(self.constrast) - self.saturationTrackBar(self.saturation) - self.hueTrackBar(self.hue) - self.gainTrackBar(self.gain) - self.exposureTrackBar(self.exposure) + def resize(self): + self.frame = cv2.resize(self.frame, (self.streamWidth, self.streamHeight)) + + def captureData(self, temp_frame, fig_num): + temp = CapturedFrame(temp_frame, fig_num, self.pixelLine, self.range, self.path) + self.actualPlot.includeCapturedFrame(temp) + self.actualPlot.plotRefresh() + temp.image = self.frame + temp.saveFrame() + fig_num += 1 + return fig_num - def createTrackBars(self): - cv2.namedWindow(self.trackBarName) - cv2.createTrackbar("Position", self.trackBarName, self.pixelLine, self.height, self.posTrackBar) - cv2.createTrackbar("Size", self.trackBarName, self.range, self.height, self.rangeTrackBar) - cv2.createTrackbar("Brightness", self.trackBarName, self.brightness, 100, self.brightnessTrackBar) - cv2.createTrackbar("Contrast", self.trackBarName, self.constrast, 100, self.constrastTrackBar) - cv2.createTrackbar("Saturation", self.trackBarName, self.saturation, 100, self.saturationTrackBar) - cv2.createTrackbar("Hue", self.trackBarName, self.hue, 100, self.hueTrackBar) - cv2.createTrackbar("Gain", self.trackBarName, self.gain, 100, self.gainTrackBar) - cv2.createTrackbar("Exposure", self.trackBarName, self.exposure*100, 100, self.exposureTrackBar) + def cleanData(self): + self.actualPlot.cleanPlot() - cv2.resizeWindow(self.trackBarName, 100, 50) + def eachPhotogram(self): + self.frame = self.input.read()[1] + if self.frame == None: + return False - def squareInFrame(self): - cv2.rectangle(self.frame, (0, self.pixelLine-self.range), (self.width-2, self.pixelLine+self.range), (0, 255, 255), 2) - cv2.rectangle(self.frame, (0, self.pixelLine), (self.width-1, self.pixelLine), (0, 255, 0), 2) + self.analysisFrame = self.frame.copy() + self.squareInFrame() + self.kbkey = cv2.waitKey(1) & 0xff - def textInFrame(self): - cv2.putText(self.frame, "Esc to exit", (5, 25), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255)) - cv2.putText(self.frame, "c to clear plot", (5, 45), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255)) - cv2.putText(self.frame, "Enter to capture frame", (5, 65), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255)) + if self.kbkey == 10: + pass + + self.figure = self.actualPlot.figureReturn() + self.resize() + self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB) + return True + + def loop(self): + fig_num = 0 + closed = False + while True: + fig_num, closed = self.eachPhotogram(fig_num, closed) + if fig_num == None: + break + self.closeInput() + + def closeInput(self): +# self.actualPlot.close() + cv2.destroyAllWindows() + self.input.release() + + def changeWidth(self, width): + self.streamWidth = width + + def changeHeight(self, height): + self.streamHeight = height def posTrackBar(self, pos): self.pixelLine = pos @@ -233,46 +277,11 @@ def gainTrackBar(self, gain): def exposureTrackBar(self, exposure): self.exposure = exposure self.input.set(15, self.exposure/100) - - def resize(self): - self.frame = cv2.resize(self.frame, (self.streamWidth, self.streamHeight)) - def show(self): - cv2.imshow(self.name, self.frame) - - def loop(self): - fig_num = 0 - closed = False - while True: - self.frame = self.input.read()[1] - temp_frame = self.frame.copy() - self.squareInFrame() - self.textInFrame() - self.kbkey = cv2.waitKey(1) & 0xff - if self.kbkey == 27: - break - - elif self.kbkey == 10: - temp = CapturedFrame(temp_frame, fig_num, self.pixelLine, self.range, self.path) - self.actualPlot.includeCapturedFrame(temp) - self.actualPlot.plotRefresh() - temp.image = self.frame - temp.saveFrame() - fig_num += 1 - - elif self.kbkey == ord('c'): - self.actualPlot.cleanPlot() - elif self.kbkey == 32: # Space bar - if closed: - self.createTrackBars() - else: - cv2.destroyWindow(self.trackBarName) - closed = not closed - self.resize() - self.show() - self.actualPlot.close() - cv2.destroyAllWindows() - self.input.release() + +""" +GUI +""" if __name__ == "__main__": if not os.path.exists(PATH): @@ -281,6 +290,3 @@ def loop(self): temp = glob.glob(PATH+'/*.jpg') for item in temp: os.remove(item) - - cam = GuiWindow("Stream", CAMARA, STREAMWIDTH, STREAMHEIGHT, PATH) - cam.loop() diff --git a/build/Linux/SpecPySplash.py b/build/Linux/SpecPySplash.py index 33d5d7c..e364b0d 100644 --- a/build/Linux/SpecPySplash.py +++ b/build/Linux/SpecPySplash.py @@ -1,91 +1,106 @@ # -*- coding: utf-8 -*- """ -Created on Wed Jul 27 03:19:22 2016 +Created on Thu Jul 28 19:36:14 2016 @author: juan """ -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -import sys, time -import image_qr -import itertools +from PyQt4.uic import loadUiType +from PyQt4 import QtCore, QtGui +import sys, image_qr + +app = QtGui.QApplication(sys.argv) +# Create and display the splash screen +splash_pix = QtGui.QPixmap(':/SpecPy.png') +splash = QtGui.QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint) +splash.show() +app.processEvents() -#def variablename(var): -# return [tpl[0] for tpl in itertools.filter(lambda x: var is x[1], globals().items())] +import SpecPy as specpy +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt4agg import (FigureCanvasQTAgg as FigureCanvas) -SETTINGS_FILE = "settings.cpy" +Ui_MainWindow, QMainWindow = loadUiType('mainwindow.ui') CAMARA = 0 -PATH = "Captured" -STREAMWIDTH = 680 -STREAMHEIGHT = 480 +STREAMHEIGHT = 100 +STREAMWIDTH = int(4/3*STREAMHEIGHT)#300 -app = QApplication(sys.argv) -# Create and display the splash screen -splash_pix = QPixmap(':/SpecPy.png') -splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) -splash.show() -time.sleep(3) -app.processEvents() +PATH = "Captures" -from SpecPy import * +class Main(QMainWindow, Ui_MainWindow): + def __init__(self, ): + super(Main, self).__init__() + self.setupUi(self) + self.posSlider.valueChanged.connect(self.posChange) + self.sizeSlider.valueChanged.connect(self.sizeChange) + icon = QtGui.QIcon(':/SpecPy.png') + self.setWindowIcon(icon) -def settingsReader(settingsfile): - instructions = [] - file = open(settingsfile, 'r') - lines = file.readlines() - for line in lines: - parted_line = line.rpartition('=') - command = parted_line[0].replace(' ', '') - value = parted_line[-1].replace(' ', '').replace('\n', '') - instructions.append((command, value)) - file.close() - return instructions - -def settingsApplier(instructions): - global CAMARA, PATH, STREAMWIDTH, STREAMHEIGHT - for instruction in instructions: - command, value = instruction - if command == "camara": - if value.isdigit(): - CAMARA = int(value) + self.show() + + def videoStream(self): + self.cam = specpy.GuiWindow("Stream", CAMARA, STREAMWIDTH, STREAMHEIGHT, PATH, "canvas")#, self.MainWindow) + self.fig_num = 0 + def qImage(self, width, height, bytesPerLine): + qImg = QtGui.QImage(self.cam.frame.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888) + pix = QtGui.QPixmap(qImg) + return pix + + def update(self): + i = 0 + while self.fig_num != None: + height = self.CamaraStream.frameGeometry().height() + width = int(4/3*height) + self.cam.changeHeight(height) + self.cam.changeWidth(width) + bytesPerLine = 3 * width + answer = self.cam.eachPhotogram() + if not answer: + break + if i == 0: + self.updatePlot() + i += 1 else: - CAMARA = value - print("Camara set to: ", value) - elif command == "path": - PATH = value - print("Path set to:", value) - elif command == "streamheight": - STREAMHEIGHT = int(value) - print("Stream height set to:", value) - elif command == "streamwidth": - STREAMWIDTH = int(value) - print("Stream width set to:", value) - -def settingsHandler(settingsfile): - if os.path.exists(settingsfile): - instructions = settingsReader(settingsfile) - else: - file = open(settingsfile, "w") - file.write("camara =" + str(0)+"\n") - file.write("path = " + PATH + "\n") - file.write("streamheight = " + str(STREAMHEIGHT) + "\n") - file.write("streamwidth = " + str(STREAMWIDTH) + "\n") - file.close() - instructions = settingsReader(settingsfile) - settingsApplier(instructions) + self.removePlot() + self.updatePlot() + pix = self.qImage(width, height, bytesPerLine) + self.CamaraStream.setPixmap(pix) + + def keyPressEvent(self, event): + keyPressed = event.key() #& 0xff + if keyPressed == QtCore.Qt.Key_Escape: + self.cam.closeInput() + self.close() + elif keyPressed == QtCore.Qt.Key_Enter - 1: + self.fig_num = self.cam.captureData(self.cam.analysisFrame, self.fig_num) + elif keyPressed == QtCore.Qt.Key_C: + self.cam.cleanData() -settingsHandler(SETTINGS_FILE) - -if not os.path.exists(PATH): - os.makedirs(PATH) -else: - temp = glob.glob(PATH+'/*.jpg') - for item in temp: - os.remove(item) + def updatePlot(self): + self.canvas = FigureCanvas(self.cam.figure) + self.figureFrame.addWidget(self.canvas) + self.canvas.draw() -cam = GuiWindow("Stream", CAMARA, STREAMWIDTH, STREAMHEIGHT, PATH) + def removePlot(self): + self.figureFrame.removeWidget(self.canvas) + self.canvas.close() + + def posChange(self): + size = self.posSlider.value() + self.cam.posTrackBar(size) + + def sizeChange(self): + size = self.sizeSlider.value() + self.cam.rangeTrackBar(size) + +#aw = ApplicationWindow() +#aw.setWindowTitle("Try") +#aw.show() splash.finish(None) -cam.loop() +#app.exec_() +app = QtGui.QApplication(sys.argv) +main = Main() +main.videoStream() +main.update() sys.exit() +#app.exec_() \ No newline at end of file diff --git a/build/Linux/mainwindow.ui b/build/Linux/mainwindow.ui new file mode 100644 index 0000000..6c07014 --- /dev/null +++ b/build/Linux/mainwindow.ui @@ -0,0 +1,252 @@ + + + MainWindow + + + + 0 + 0 + 552 + 520 + + + + SpecPy + + + + + + + + 534 + 140 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 680 + 480 + + + + TextLabel + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + 720 + + + 360 + + + Qt::Vertical + + + true + + + false + + + + + + + + 0 + 0 + + + + 240 + + + 120 + + + 120 + + + Qt::Vertical + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + + + + + + + + + + + + 0 + 280 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + + + + + + + + + TopToolBarArea + + + false + + + + + + + 0 + 0 + 552 + 19 + + + + + File + + + + + Edit + + + + + Tools + + + + + true + + + Help + + + + + + + + + + + +