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()
Пример #2
0
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)
Пример #4
0
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)