Exemplo n.º 1
0
def lightROIBtn(self):
    frame, frameCrop = ft.checkEditing(self, self.frameNumber)
    self.lightROI_HT = ft.cv2.selectROI(frame)
    ft.cv2.destroyAllWindows()
    self.lightROI_HT_recorded = True
Exemplo n.º 2
0
def filterParticleSldr(self):
    frame, frameCrop = ft.checkEditing(self, self.frameNumber)
    getFilteredFrame(self, frameCrop)
    self.lbl1_HT.setPixmap(ft.QPixmap.fromImage(self.frame))
    self.lbl2_HT.setPixmap(ft.QPixmap.fromImage(self.frameBW))
    self.filterParticleSldr_HT.setMaximum(int(self.particleSldrMax.text()))
Exemplo n.º 3
0
def HSVSlider_released(self):
    frame, frameCrop = ft.checkEditing(self, self.frameNumber)
    getFilteredFrame(self, frameCrop)
    self.lbl1_HT.setPixmap(ft.QPixmap.fromImage(self.frame))
    self.lbl2_HT.setPixmap(ft.QPixmap.fromImage(self.frameBW))
Exemplo n.º 4
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)
Exemplo n.º 6
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)