def helpBtn(self): msg = ft.QMessageBox(self) msg.setText( """Manual Tracking allows you to track a flame with a point-and-click method. 'Tracking points #' defines the number of mouse clicks to record for each frame before moving to the next one (the default is one click per frame). By clicking on 'Start tracking', a pop-up window will show the first frame (press 'Esc' to exit at any time, but note that the progress will be lost). The following frames will show the horizontal lines corresponding to the points clicked. These lines can be hidden by unchecking 'Show tracking lines' before starting the analysis. After the tracking, the position vs time and spread rate vs time values will be shown in the windows in the 'Analysis box' when the slider in the 'Preview box' is used. The 'Flame direction' determines the positive increment of the flame location along the horizontal coordinate. If there is a flashing or strobe light in the recorded video, you can click on 'Pick bright region' to choose a rectangular region (in the same way that the ROI is selected) that is illuminated when the light is on and dark when it is off. Note that this region is independent from the ROI specified in the 'Preview box', and will show up of the left window in the 'Analysis box'. From the dropdown menu, select the option 'Frames light on' to consider only the frames where the light is on, or 'Frames light off' to consider only the frames without the light. By default all the frames are considered. By clicking on 'Absolute values', the x-axis of the tracked data will be shifted to the origin. Click on 'Save data' to export a csv file with all the tracking results (position in pixel and mm for each point tracked, and their corresponding spread rate). """) msg.exec()
def HSVTracking(self): scale = True if not self.scaleIn.text(): scale = False msg = ft.QMessageBox(self) msg.setText('The scale [px/mm] has not been specified') # if self.pyqtVer == '5': # msg.exec_() # elif self.pyqtVer == '6': msg.exec() firstFrame = int(self.firstFrameIn.text()) lastFrame = int(self.lastFrameIn.text()) self.connectivity = self.connectivityGroup.checkedAction() self.connectivity = self.connectivity.text() currentFrame = firstFrame self.xRight_px = list() self.xLeft_px = list() self.xRight_mm = list() self.xLeft_mm = list() flameLength_mm = list() self.frameCount = list() flameArea = list() if self.exportVideo_HT.isChecked() or self.exportTrackOverlay_HT.isChecked( ): fps = (float(self.vFps)) / (int(self.skipFrameIn.text()) + 1) vName = self.fPath + '-trackedVideo.' + str( self.vFormat ) # alternative: 'output.{}'.format(vFormat); self.fNameLbl.text() fourcc = ft.cv2.VideoWriter_fourcc(*self.codec) size = (int(self.roiThreeIn.text()), int(self.roiFourIn.text())) # open and set properties vout = ft.cv2.VideoWriter() vout.open(vName, fourcc, fps, size, True) if scale: #this condition prevents crashes in case the scale is not specified xAxis_lbl1 = self.xAxis_lbl1.currentText() yAxis_lbl1 = self.yAxis_lbl1.currentText() xAxis_lbl2 = self.xAxis_lbl2.currentText() yAxis_lbl2 = self.yAxis_lbl2.currentText() while (currentFrame < lastFrame): # print('Frame #:', currentFrame) frame, frameCrop = ft.checkEditing(self, currentFrame) if self.filterLight_HT.isChecked() == True: if self.lightROI_HT_recorded == True: # looking for frames with a light on (which would increase the red and green channel values of the background) low = ([5, 5, 10] ) # blueLow, greenLow, redLow (see color tracking) high = ([255, 255, 255]) # blueHigh, greenHigh, redHigh low = ft.np.array( low, dtype='uint8') #this conversion is necessary high = ft.np.array(high, dtype='uint8') currentLightROI = frame[self.lightROI_HT[1]:( self.lightROI_HT[1] + self.lightROI_HT[3]), self.lightROI_HT[0]:( self.lightROI_HT[0] + self.lightROI_HT[2])] newMask = ft.cv2.inRange(currentLightROI, low, high) frame_light = ft.cv2.bitwise_and(currentLightROI, currentLightROI, mask=newMask) grayFrame_light = ft.cv2.cvtColor(frame_light, ft.cv2.COLOR_BGR2GRAY) (thresh_light, frameBW_light) = ft.cv2.threshold(grayFrame_light, 0, 255, ft.cv2.THRESH_BINARY) flamePx_light = ft.np.where(frameBW_light == [255]) #beta area_lightROI = int(self.lightROI_HT[3] * self.lightROI_HT[2]) else: msg = ft.QMessageBox(self) msg.setText( 'Before the tracking, please click on "Pick a bright region" to select a region where the light is visible.' ) # if self.pyqtVer == '5': # msg.exec_() # elif self.pyqtVer == '6': msg.exec() break if len( flamePx_light[0] ) < 0.5 * area_lightROI: #if the bright area is larger than the ROI area getFilteredFrame(self, frameCrop) print('frame counted') else: currentFrame = currentFrame + 1 + int( self.skipFrameIn.text()) print('frame not counted') continue else: getFilteredFrame(self, frameCrop) self.xRight_px.append(self.xRight) self.xLeft_px.append(self.xLeft) self.xRight_mm.append(self.xRight / float(self.scaleIn.text())) self.xLeft_mm.append(self.xLeft / float(self.scaleIn.text())) flameArea.append(self.flameArea) self.frameCount.append(currentFrame) if self.exportVideo_HT.isChecked( ) and not self.exportTrackOverlay_HT.isChecked(): vout.write(self.currentFrameRGB_HT) elif self.exportTrackOverlay_HT.isChecked(): #CAS Add Track lines over cropped video trackframe = ft.np.copy(frameCrop) # frame is 1080 x 1920 trackframe[:, min( self.xRight - 1 - int(self.roiOneIn.text( )), ft.np.size(trackframe, 1) )] = 255 # white out line to mark where tracked flame, using relative distance vout.write(trackframe) # print('Progress: ', round((currentFrame - firstFrame)/(lastFrame - firstFrame) * 10000)/100, '%') print('Progress: ', round((currentFrame - firstFrame) / (lastFrame - firstFrame) * 10000) / 100, '%', '(Frame #: ', currentFrame, ')', end='\r') currentFrame = currentFrame + 1 + int(self.skipFrameIn.text()) try: self.flameArea = [ areaN / (float(self.scaleIn.text())**2) for areaN in flameArea ] self.flameArea = ft.np.round(self.flameArea, 3) self.flameArea = self.flameArea.tolist() self.timeCount = [ frameN / float(self.vFpsLbl.text()) for frameN in self.frameCount ] except: pass # CAS Add tracking line from flameTracker.py #if self.HSVTrackingValue == True: # # Start tracking for export # #HSVTracking(self) # # #findFlameEdges_HT(self, frameBW, flamePx) # getHSVFilteredFrame(self, currentFrame) # trackframe = frameCrop # frame is 1080 x 1920 # import numpy # #print(type(frame), numpy.size(frame, 0), 'x', numpy.size(frame, 1)) # #print(type(frameCrop), numpy.size(frameCrop, 0), 'x', numpy.size(frameCrop, 1)) # trackframe[:, min(self.xRight-1 - int(self.roiOneIn.text()), numpy.size(trackframe,1))] = 255 # white out line to mark where tracked flame, using relative distance # #if self.xRight-1 > numpy.size(trackframe,1): # # print('xRight would have errored here with value:', self.xRight) # #cv2.imshow('Frame_With_255_TrackLine', trackframe) for i in range(len(self.xRight_mm)): flameLength_mm.append(abs(self.xRight_mm[i] - self.xLeft_mm[i])) flameLength_mm = ft.np.round(flameLength_mm, 2) self.flameLength_mm = flameLength_mm.tolist() print('Progress: 100 % - Tracking completed') self.msgLabel.setText('Tracking completed') if self.exportVideo_HT.isChecked( ) or self.exportTrackOverlay_HT.isChecked(): vout.release() self.msgLabel.setText('Tracking completed and video created.') # the following approach to calculate the spread rate is the same one used for lumaTracking movAvgPt = int( self.movAvgIn_HT.text() ) #this number is half of the interval considered for the spread rate (movAvgPt = 2 means I am considering a total of 5 points (my point, 2 before and 2 after)) self.spreadRateRight = list() self.spreadRateLeft = list() if movAvgPt == 0: for i in range(len(self.timeCount) - 1): xCoeffRight = ft.np.polyfit(self.timeCount[(i):(i + 2)], self.xRight_mm[(i):(i + 2)], 1) xCoeffLeft = ft.np.polyfit(self.timeCount[(i):(i + 2)], self.xLeft_mm[(i):(i + 2)], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) #repeat the last value self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) else: #here we calculate the instantaneous spread rate based on the moving avg. I also included the initial and final points for i in range(len(self.timeCount)): if i - movAvgPt < 0: xCoeffRight = ft.np.polyfit( self.timeCount[0:(i + movAvgPt + 1)], self.xRight_mm[0:(i + movAvgPt + 1)], 1) xCoeffLeft = ft.np.polyfit( self.timeCount[0:(i + movAvgPt + 1)], self.xLeft_mm[0:(i + movAvgPt + 1)], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) elif i >= movAvgPt: xCoeffRight = ft.np.polyfit( self.timeCount[(i - movAvgPt):(i + movAvgPt + 1)], self.xRight_mm[(i - movAvgPt):(i + movAvgPt + 1)], 1) xCoeffLeft = ft.np.polyfit( self.timeCount[(i - movAvgPt):(i + movAvgPt + 1)], self.xLeft_mm[(i - movAvgPt):(i + movAvgPt + 1)], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) elif i + movAvgPt > len(self.timeCount): xCoeffRight = ft.np.polyfit( self.timeCount[(i - movAvgPt):], self.xRight_mm[(i - movAvgPt):], 1) xCoeffLeft = ft.np.polyfit(self.timeCount[(i - movAvgPt):], self.xLeft_mm[(i - movAvgPt):], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) self.spreadRateRight = ft.np.round(self.spreadRateRight, 3) self.spreadRateRight = self.spreadRateRight.tolist() self.spreadRateLeft = ft.np.round(self.spreadRateLeft, 3) self.spreadRateLeft = self.spreadRateLeft.tolist() self.plot1_HT.setLabel('left', str(yAxis_lbl1), color='black', size=14) self.plot1_HT.setLabel('bottom', str(xAxis_lbl1), color='black', size=14) self.plot1_HT.getAxis('bottom').setPen(color=(0, 0, 0)) self.plot1_HT.getAxis('left').setPen(color=(0, 0, 0)) self.plot1_HT.addLegend( offset=[1, 0.1] ) # background color modified in line 122 and 123 of Versions/3.7/lib/python3.7/site-packages/pyqtgraph/graphicsItems self.plot2_HT.setLabel('left', str(yAxis_lbl2), color='black', size=14) self.plot2_HT.setLabel('bottom', str(xAxis_lbl2), color='black', size=14) self.plot2_HT.getAxis('bottom').setPen(color=(0, 0, 0)) self.plot2_HT.getAxis('left').setPen(color=(0, 0, 0)) self.plot2_HT.addLegend( offset=[1, 0.1] ) # background color modified in line 122 and 123 of Versions/3.7/lib/python3.7/site-packages/pyqtgraph/graphicsItems xPlot1, yRight1, yLeft1 = selectAxes(self, xAxis_lbl1, yAxis_lbl1) xPlot2, yRight2, yLeft2 = selectAxes(self, xAxis_lbl2, yAxis_lbl2) if yAxis_lbl1 == 'Flame length [mm]': HSVTrackingPlot(self.plot1_HT, xPlot1, yRight1, 'flame length', 'o', 'b') elif yAxis_lbl1 == 'Flame area [mm2]': HSVTrackingPlot(self.plot1_HT, xPlot1, yRight1, 'flame area', 'o', 'b') else: HSVTrackingPlot(self.plot1_HT, xPlot1, yRight1, 'right edge', 'o', 'b') HSVTrackingPlot(self.plot1_HT, xPlot1, yLeft1, 'left edge', 't', 'r') if yAxis_lbl2 == 'Flame length [mm]': HSVTrackingPlot(self.plot2_HT, xPlot2, yRight2, 'flame length', 'o', 'b') elif yAxis_lbl2 == 'Flame area [mm2]': HSVTrackingPlot(self.plot2_HT, xPlot2, yRight2, 'flame area', 'o', 'b') else: HSVTrackingPlot(self.plot2_HT, xPlot2, yRight2, 'right edge', 'o', 'b') HSVTrackingPlot(self.plot2_HT, xPlot2, yLeft2, 'left edge', 't', 'r') self.win1_HT.setCurrentIndex( 1) #to activate the preview tab in the analysis box self.win2_HT.setCurrentIndex(1)
def startTracking(self): global clk, nClicks #, flameDir # select the variables to plot based on user input xAxis_lbl1 = self.xAxis_lbl1.currentText() yAxis_lbl1 = self.yAxis_lbl1.currentText() xAxis_lbl2 = self.xAxis_lbl2.currentText() yAxis_lbl2 = self.yAxis_lbl2.currentText() self.plot1_MT.clear() self.plot1_MT.setLabel('left', str(yAxis_lbl1), color='black', size=14) self.plot1_MT.setLabel('bottom', str(xAxis_lbl1), color='black', size=14) self.plot1_MT.getAxis('bottom').setPen(color=(0, 0, 0)) self.plot1_MT.getAxis('left').setPen(color=(0, 0, 0)) self.plot1_MT.addLegend(offset=[1, 0.1]) firstFrame = int(self.firstFrameIn.text()) lastFrame = int(self.lastFrameIn.text()) # scale = True #Set up the first frame for analysis and clk for the mouse event currentFrame = firstFrame clk = False # False unless the mouse is clicked posX = dict() posX_mm = dict() posY = dict() posY_mm = dict() frameCount = dict() timeCount = dict() # find out how many points to be selected in each frame try: nClicks = int(self.nClicksLbl.text()) except: nClicks = 1 self.msgLabel.setText('Clicks not specified (=1)') while (currentFrame < lastFrame): print('Frame #:', currentFrame, end='\r') if not self.scaleIn.text(): # scale = False msg = ft.QMessageBox(self) msg.setText('The scale [px/mm] has not been specified') msg.exec() break frame, frameCrop = ft.checkEditing(self, currentFrame) if self.lightROI_MT_recorded == True: # looking for frames with a light on (which would increase the red and green channel values of the background) # low and high are the thresholds for each color channel low = ([5, 5, 10]) # blueLow, greenLow, redLow high = ([255, 255, 255]) # blueHigh, greenHigh, redHigh low = ft.np.array(low, dtype='uint8') #this conversion is necessary high = ft.np.array(high, dtype='uint8') currentLightROI = frame[self.lightROI_MT[1]:(self.lightROI_MT[1] + self.lightROI_MT[3]), self.lightROI_MT[0]:(self.lightROI_MT[0] + self.lightROI_MT[2])] newMask = ft.cv2.inRange(currentLightROI, low, high) frame_light = ft.cv2.bitwise_and(currentLightROI, currentLightROI, mask=newMask) grayFrame_light = ft.cv2.cvtColor(frame_light, ft.cv2.COLOR_BGR2GRAY) (thresh_light, BW_light) = ft.cv2.threshold(grayFrame_light, 0, 255, ft.cv2.THRESH_BINARY) flamePx_light = ft.np.where(BW_light == [255]) area_light = int(self.lightROI_MT[3] * self.lightROI_MT[2]) # if lightStatus == 'lightOff': if self.filterLight_MT.currentText() == 'Frames light off': if len(flamePx_light[0]) > 0.5 * area_light: #avoid this frame currentFrame = currentFrame + 1 + int( self.skipFrameIn.text()) continue # elif lightStatus == 'lightOn': elif self.filterLight_MT.currentText() == 'Frames light on': if len(flamePx_light[0]) < 0.5 * area_light: #avoid this frame currentFrame = currentFrame + 1 + int( self.skipFrameIn.text()) continue # create the window and the line over the first point clicked ft.cv2.namedWindow('manualTracking', ft.cv2.WINDOW_AUTOSIZE) ft.cv2.setWindowTitle('manualTracking', f'MT, frame #: {currentFrame}') # ft.cv2.namedWindow(f'ManualTracking; frame #: {currentFrame}', ft.cv2.WINDOW_AUTOSIZE) ft.cv2.setMouseCallback('manualTracking', click) # ft.cv2.setMouseCallback(f'ManualTracking; frame #: {currentFrame}', click) #if currentFrame > firstFrame: if len(posY) > 0: for n in range(nClicks): if self.showLines_MT.isChecked() == True: ft.cv2.line(frameCrop, (0, int(posY[str(n + 1)][0])), (int( self.roiThreeIn.text()), int(posY[str(n + 1)][0])), (0, 245, 184), 2) ft.cv2.imshow('manualTracking', frameCrop) # ft.cv2.imshow(f'ManualTracking; frame #: {currentFrame}',frameCrop) self.msgLabel.setText('Tracking started, press (Esc) to quit.') for n in range(nClicks): # wait for the mouse event or 'escape' key while (True): if clk == True: clk = False # the zero location changes based on the flame direction if self.directionBox.currentText() == 'Left to right': xClick = xPos + int(self.roiOneIn.text()) elif self.directionBox.currentText() == 'Right to left': xClick = self.vWidth - int(self.roiOneIn.text()) - xPos break if ft.cv2.waitKey(1) == 27: #ord('q') ft.cv2.destroyAllWindows() return # update each position and frame list for the current click if str(n + 1) in posX: posX[str(n + 1)].append(xClick) posX_mm[str(n + 1)].append(xClick / float(self.scaleIn.text())) posY[str(n + 1)].append(yPos) posY_mm[str(n + 1)].append(yPos / float(self.scaleIn.text())) if n == 0: #frames and time are the same for all the clicks frameCount[str(n + 1)].append(currentFrame) timeCount[str(n + 1)].append(currentFrame / float(self.vFpsLbl.text())) else: posX[str(n + 1)] = [xClick] posX_mm[str(n + 1)] = [xClick / float(self.scaleIn.text())] posY[str(n + 1)] = [yPos] posY_mm[str(n + 1)] = [yPos / float(self.scaleIn.text())] if n == 0: #frames and time are the same for all the clicks frameCount[str(n + 1)] = [currentFrame] timeCount[str(n + 1)] = [ currentFrame / float(self.vFpsLbl.text()) ] currentFrame = currentFrame + 1 + int(self.skipFrameIn.text()) print('Tracking completed') self.msgLabel.setText('Tracking completed') if len(timeCount) == 0: msg = ft.QMessageBox(self) msg.setText( 'No frames were detected, please check ROI size and light settings.' ) msg.exec() ft.cv2.destroyAllWindows() self.posX_px = posX self.posX_plot = posX_mm self.frames_plot = frameCount self.time_plot = timeCount # moving average of the spread rate values self.spreadRate = dict() # if scale: for n in range(nClicks): for i in range(len(timeCount['1']) - 1): xCoeff = ft.np.polyfit(timeCount['1'][(i):(i + 2)], posX_mm[str(n + 1)][(i):(i + 2)], 1) spreadRate = xCoeff[0] if str(n + 1) in self.spreadRate: self.spreadRate[str(n + 1)].append(spreadRate) else: self.spreadRate[str(n + 1)] = [spreadRate] #repeat the last value self.spreadRate[str(n + 1)].append(xCoeff[0]) self.lbl2_MT.clear() self.lbl2_MT.addLegend( offset=[1, 0.1] ) # background color modified in line 122 and 123 of python3.7/site-packages/pyqtgraph/graphicsItems color = ['b', 'r', 'k', 'g', 'c', 'y'] for n in range(nClicks): name = 'click{}'.format([n + 1]) try: clr = color[n] except: if n > len(color): self.msgLabel.setText('Not enough colors for plotting.') xPlot1, yPlot1 = selectAxes(self, xAxis_lbl1, yAxis_lbl1, n) xPlot2, yPlot2 = selectAxes(self, xAxis_lbl2, yAxis_lbl2, n) # manualTrackingPlot(self.lbl1_MT, self.time_plot['1'], self.posX_plot[str(n+1)], name, 'o', clr) manualTrackingPlot(self.plot1_MT, xPlot1, yPlot1, name, 'o', clr) # manualTrackingPlot(self.lbl2_MT, self.time_plot['1'], self.spreadRate[str(n+1)], name, 'o', clr) manualTrackingPlot(self.lbl2_MT, xPlot2, yPlot2, name, 'o', clr) self.plot1_MT.show() self.win1_MT.setCurrentIndex(1)
def RGBTracking(self): scale = True if not self.scaleIn.text(): scale = False msg = ft.QMessageBox(self) msg.setText('The scale [px/mm] has not been specified') msg.exec() firstFrame = int(self.firstFrameIn.text()) lastFrame = int(self.lastFrameIn.text()) self.connectivity = self.connectivityGroup.checkedAction() self.connectivity = self.connectivity.text() currentFrame = firstFrame self.xRight_px = list() self.xLeft_px = list() self.xRight_mm = list() self.xLeft_mm = list() flameLength_mm = list() self.frameCount = list() flameArea = list() if self.exportVideo_RT.isChecked(): fps = (float(self.vFps)) / (int(self.skipFrameIn.text()) + 1) vName = self.fPath + '-trackedVideo.' + str(self.vFormat) fourcc = ft.cv2.VideoWriter_fourcc(*self.codec) size = (int(self.roiThreeIn.text()), int(self.roiFourIn.text())) # open and set properties vout = ft.cv2.VideoWriter() vout.open(vName, fourcc, fps, size, True) if scale: #this condition prevents crashes in case the scale is not specified xAxis_lbl1 = self.xAxis_lbl1.currentText() yAxis_lbl1 = self.yAxis_lbl1.currentText() xAxis_lbl2 = self.xAxis_lbl2.currentText() yAxis_lbl2 = self.yAxis_lbl2.currentText() while (currentFrame < lastFrame): # print('Frame #:', currentFrame) frame, frameCrop = ft.checkEditing(self, currentFrame) if self.filterLight_RT.isChecked() == True: if self.lightROI_RT_recorded == True: #beta # looking for frames with a light on (which would increase the red and green channel values of the background) low = ([5, 5, 10]) # blueLow, greenLow, redLow high = ([255, 255, 255]) # blueHigh, greenHigh, redHigh low = ft.np.array( low, dtype='uint8') #this conversion is necessary high = ft.np.array(high, dtype='uint8') currentLightROI = frame[self.lightROI_RT[1]:( self.lightROI_RT[1] + self.lightROI_RT[3]), self.lightROI_RT[0]:( self.lightROI_RT[0] + self.lightROI_RT[2])] newMask = ft.cv2.inRange(currentLightROI, low, high) frame_light = ft.cv2.bitwise_and(currentLightROI, currentLightROI, mask=newMask) grayFrame_light = ft.cv2.cvtColor(frame_light, ft.cv2.COLOR_BGR2GRAY) (thresh_light, frameBW_light) = ft.cv2.threshold(grayFrame_light, 0, 255, ft.cv2.THRESH_BINARY) flamePx_light = ft.np.where(frameBW_light == [255]) #beta area_lightROI = int(self.lightROI_RT[3] * self.lightROI_RT[2]) else: msg = ft.QMessageBox(self) msg.setText( 'Before the tracking, please click on "Pick a bright region" to select a region where the light is visible.' ) msg.exec() break if len( flamePx_light[0] ) < 0.5 * area_lightROI: #if the bright area is larger than the ROI area getFilteredFrame(self, frameCrop) else: currentFrame = currentFrame + 1 + int( self.skipFrameIn.text()) continue else: getFilteredFrame(self, frameCrop) self.xRight_px.append(self.xRight) self.xLeft_px.append(self.xLeft) self.xRight_mm.append(self.xRight / float(self.scaleIn.text())) self.xLeft_mm.append(self.xLeft / float(self.scaleIn.text())) flameArea.append(self.flameArea) self.frameCount.append(currentFrame) if self.exportVideo_RT.isChecked(): vout.write(self.currentFrameRGB_RT) print('Progress: ', round((currentFrame - firstFrame) / (lastFrame - firstFrame) * 10000) / 100, '%', '(Frame #: ', currentFrame, ')', end='\r') currentFrame = currentFrame + 1 + int(self.skipFrameIn.text()) try: self.flameArea = [ areaN / (float(self.scaleIn.text())**2) for areaN in flameArea ] self.flameArea = ft.np.round(self.flameArea, 3) self.flameArea = self.flameArea.tolist() self.timeCount = [ frameN / float(self.vFpsLbl.text()) for frameN in self.frameCount ] except: pass for i in range(len(self.xRight_mm)): flameLength_mm.append(abs(self.xRight_mm[i] - self.xLeft_mm[i])) flameLength_mm = ft.np.round(flameLength_mm, 2) self.flameLength_mm = flameLength_mm.tolist() print('Progress: 100 % - Tracking completed') self.msgLabel.setText('Tracking completed') if self.exportVideo_RT.isChecked(): vout.release() self.msgLabel.setText('Tracking completed and video created.') # the following approach to calculate the spread rate is the same one used for lumaTracking movAvgPt = int( self.movAvgIn_RT.text() ) #this number is half of the interval considered for the spread rate (movAvgPt = 2 means I am considering a total of 5 points (my point, 2 before and 2 after)) self.spreadRateRight = list() self.spreadRateLeft = list() if movAvgPt == 0: for i in range(len(self.timeCount) - 1): xCoeffRight = ft.np.polyfit(self.timeCount[(i):(i + 2)], self.xRight_mm[(i):(i + 2)], 1) xCoeffLeft = ft.np.polyfit(self.timeCount[(i):(i + 2)], self.xLeft_mm[(i):(i + 2)], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) #repeat the last value self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) else: #here we calculate the instantaneous spread rate based on the moving avg. I also included the initial and final points for i in range(len(self.timeCount)): if i - movAvgPt < 0: xCoeffRight = ft.np.polyfit( self.timeCount[0:(i + movAvgPt + 1)], self.xRight_mm[0:(i + movAvgPt + 1)], 1) xCoeffLeft = ft.np.polyfit( self.timeCount[0:(i + movAvgPt + 1)], self.xLeft_mm[0:(i + movAvgPt + 1)], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) elif i >= movAvgPt: xCoeffRight = ft.np.polyfit( self.timeCount[(i - movAvgPt):(i + movAvgPt + 1)], self.xRight_mm[(i - movAvgPt):(i + movAvgPt + 1)], 1) xCoeffLeft = ft.np.polyfit( self.timeCount[(i - movAvgPt):(i + movAvgPt + 1)], self.xLeft_mm[(i - movAvgPt):(i + movAvgPt + 1)], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) elif i + movAvgPt > len(self.timeCount): xCoeffRight = ft.np.polyfit( self.timeCount[(i - movAvgPt):], self.xRight_mm[(i - movAvgPt):], 1) xCoeffLeft = ft.np.polyfit(self.timeCount[(i - movAvgPt):], self.xLeft_mm[(i - movAvgPt):], 1) self.spreadRateRight.append(xCoeffRight[0]) self.spreadRateLeft.append(xCoeffLeft[0]) self.spreadRateRight = ft.np.round(self.spreadRateRight, 3) self.spreadRateRight = self.spreadRateRight.tolist() self.spreadRateLeft = ft.np.round(self.spreadRateLeft, 3) self.spreadRateLeft = self.spreadRateLeft.tolist() self.plot1_RT.setLabel('left', str(yAxis_lbl1), color='black', size=14) self.plot1_RT.setLabel('bottom', str(xAxis_lbl1), color='black', size=14) self.plot1_RT.getAxis('bottom').setPen(color=(0, 0, 0)) self.plot1_RT.getAxis('left').setPen(color=(0, 0, 0)) self.plot1_RT.addLegend(offset=[1, 0.1]) self.plot2_RT.setLabel('left', str(yAxis_lbl2), color='black', size=14) self.plot2_RT.setLabel('bottom', str(xAxis_lbl2), color='black', size=14) self.plot2_RT.getAxis('bottom').setPen(color=(0, 0, 0)) self.plot2_RT.getAxis('left').setPen(color=(0, 0, 0)) self.plot2_RT.addLegend(offset=[1, 0.1]) xPlot1, yRight1, yLeft1 = selectAxes(self, xAxis_lbl1, yAxis_lbl1) xPlot2, yRight2, yLeft2 = selectAxes(self, xAxis_lbl2, yAxis_lbl2) if yAxis_lbl1 == 'Flame length [mm]': RGBTrackingPlot(self.plot1_RT, xPlot1, yRight1, 'flame length', 'o', 'b') elif yAxis_lbl1 == 'Flame area [mm2]': RGBTrackingPlot(self.plot1_RT, xPlot1, yRight1, 'flame area', 'o', 'b') else: RGBTrackingPlot(self.plot1_RT, xPlot1, yRight1, 'right edge', 'o', 'b') RGBTrackingPlot(self.plot1_RT, xPlot1, yLeft1, 'left edge', 't', 'r') if yAxis_lbl2 == 'Flame length [mm]': RGBTrackingPlot(self.plot2_RT, xPlot2, yRight2, 'flame length', 'o', 'b') elif yAxis_lbl2 == 'Flame area [mm2]': RGBTrackingPlot(self.plot2_RT, xPlot2, yRight2, 'flame area', 'o', 'b') else: RGBTrackingPlot(self.plot2_RT, xPlot2, yRight2, 'right edge', 'o', 'b') RGBTrackingPlot(self.plot2_RT, xPlot2, yLeft2, 'left edge', 't', 'r') self.win1_RT.setCurrentIndex( 1) #to activate the preview tab in the analysis box self.win2_RT.setCurrentIndex(1)