def addOffsetStamp(self, leftFit, rightFit, image, origin, color=(255, 255, 255), fontScale=1.0, thickness=1):
        """
        Evaluating camera offset and adding it to a given image
        :param thickness: line thickness
        :param leftFit: left curve polynomial parameters
        :param rightFit: right curve polynomial parameters
        :param image: image where data being added
        :param origin: upper-left corner of the offset stamp
        :param color: stamp color
        :param fontScale: font scale
        :return: void (adds text to passed image)
        """

        imgW = image.shape[1]
        imgH = image.shape[0]

        yBottom = imgH - 1
        cameraCenter = imgW / 2
        lBottomX = aux.funcSpace(argSpace=yBottom, fitParams=leftFit) - self.imgMarginWidth
        rBottomX = aux.funcSpace(argSpace=yBottom, fitParams=rightFit) - self.imgMarginWidth
        laneWidth = rBottomX - lBottomX
        scaleX = 3.7 / laneWidth
        laneCenter = (lBottomX + rBottomX) / 2
        offSet = (cameraCenter - laneCenter) * scaleX
        aux.putText(img=image, text='Estimated Vehicle Offset: {:.2f} m'.format(offSet),
                    origin=origin, color=color, scale=fontScale, thickness=thickness)
    def secondarySearch(self, imgH, previousFit, nzX, nzY, margin, src, ratio=1., lineData=None):
        """
        Look Ahead search, when previous fits exist for guidance
        :param imgH: image height
        :param previousFit: previous fit used as a guidance
        :param nzX: nonZero X
        :param nzY: nonZero Y
        :param margin: detectionPointSize used for creation of search area
        :param src: source bird-eye binary
        :param ratio: used to limit search area by height
        :param lineData: used for visualization of available fits
        :return: fit + image with search process depicted
        """

        ySplit = int(imgH * (1 - ratio))

        filterKey = nzY >= ySplit

        nzY = nzY[filterKey]
        nzX = nzX[filterKey]

        srcRgb = np.dstack((src, src, src)) * 255

        leftFit, rightFit = self.borderFit(imgH=imgH, centralFit=previousFit, margin=margin)

        leftX = aux.funcSpace(argSpace=nzY, fitParams=leftFit)
        rightX = aux.funcSpace(argSpace=nzY, fitParams=rightFit)

        lineInds = ((nzX > leftX) & (nzX < rightX))

        fit = LaneFinding.getFit(lineInds, nzX, nzY)

        if lineData is not None:
            color = [255, 0, 0] if lineData['lineSpace'] == LineSpace.LEFT else [0, 0, 255]

            for lineFit in lineData['fits']:
                srcRgb = ip.Drawing.addLine(src=srcRgb, fit=lineFit, color=color, thickness=3, stepCount=20)

        srcRgb = ip.Drawing.addLine(src=srcRgb, fit=fit, color=[255, 0, 255], thickness=10, stepCount=20)

        winImg = np.zeros_like(srcRgb)

        y = np.linspace(start=0, stop=imgH - 1, num=imgH)

        xl = aux.funcSpace(argSpace=y, fitParams=leftFit)
        xr = aux.funcSpace(argSpace=y, fitParams=rightFit)

        line_window1 = np.array([np.transpose(np.vstack([xl, y]))])
        line_window2 = np.array([np.flipud(np.transpose(np.vstack([xr, y])))])
        line_pts = np.hstack((line_window1, line_window2))

        cv2.fillPoly(winImg, np.int_([line_pts]), (0, 255, 0))

        srcRgb = cv2.addWeighted(srcRgb, 1, winImg, 0.5, 0)

        return fit, srcRgb
Exemple #3
0
 def addOffsetStamp(self, leftFit, rightFit, image, origin, color=(255, 255, 255), fontScale=1.0, thickness=1):
     imgW = image.shape[1]
     imgH = image.shape[0]
     yBottom = imgH - 1
     cameraCenter = imgW / 2
     lBottomX = aux.funcSpace(argSpace=yBottom, fitParams=leftFit) - self.imgMarginWidth
     rBottomX = aux.funcSpace(argSpace=yBottom, fitParams=rightFit) - self.imgMarginWidth
     laneWidth = rBottomX - lBottomX
     scaleX = 3.7 / laneWidth
     laneCenter = (lBottomX + rBottomX) / 2
     offSet = (cameraCenter - laneCenter) * scaleX
     aux.putText(img=image, text='Смещение объекта автомобиля: {:.2f} m'.format(offSet),
                 origin=origin, color=color, scale=fontScale, thickness=thickness)
    def addPolygon(srcShape, lFit, rFit, stepCount=10, color=(0, 255, 0)):
        """
        Adds polygon to empty image with a shape of a source
        :param srcShape: shape of a source image
        :param lFit: left 2-nd order polynomial line params
        :param rFit: right 2-nd order polynomial line params
        :return: image with polygon between lines
        :param stepCount: number of steps
        :param color: 
        """

        imgH = srcShape[0]
        imgW = srcShape[1]

        cL = lFit[2]

        cR = rFit[2]

        mask = np.zeros(shape=srcShape, dtype=np.uint8)

        rOutstand = max(0, (int(math.ceil(cR)) - (imgW - 1)))

        if rOutstand > 0:
            r_filler = np.zeros((imgH, rOutstand), dtype=np.uint8)
            mask = np.hstack((mask, r_filler))

        lOutstand = abs(min(0, int(math.floor(cL))))

        if lOutstand > 0:
            lFiller = np.zeros((imgH, lOutstand), dtype=np.uint8)
            mask = np.hstack((lFiller, mask))

        outImg = np.dstack((mask, mask, mask))

        y = np.linspace(0, imgH - 1, stepCount)

        xl = aux.funcSpace(argSpace=y, fitParams=lFit)
        xr = aux.funcSpace(argSpace=y, fitParams=rFit)

        leftLinePoints = np.array(
            [np.transpose(np.vstack([xl + lOutstand, y]))])
        rightLinePoints = np.array(
            [np.flipud(np.transpose(np.vstack([xr + lOutstand, y])))])

        points = np.hstack((leftLinePoints, rightLinePoints))

        cv2.fillPoly(img=outImg, pts=np.int_(points), color=color)

        return outImg, lOutstand, rOutstand
    def borderFit(imgH, centralFit, margin):
        """
        Generates a region of interest outstanding to a given detectionPointSize from the center fit 
        as a perpendicular to the tangent line at each point
        :param imgH: image height
        :param centralFit: central fit
        :param margin: 
        :return: left and right fits approximating area tangentially equidistant 
        from central fit at both sides
        """

        a = centralFit[0]
        b = centralFit[1]

        y = np.linspace(start=0, stop=imgH - 1, num=imgH)
        x = aux.funcSpace(argSpace=y, fitParams=centralFit)

        dy = 2 * a * y + b  # Line slope as the derivative

        alpha = np.arctan(dy)  # Negative for negative slopes
        deltaY = abs(margin * np.sin(alpha))  # Negative for negative alphas
        deltaX = margin * np.cos(alpha)

        xLeft = x - deltaX
        xRight = x + deltaX

        yLeft = y + deltaY * np.sign(dy)
        yRight = y - deltaY * np.sign(dy)

        leftFit = np.polyfit(x=yLeft, y=xLeft, deg=2)
        rightFit = np.polyfit(x=yRight, y=xRight, deg=2)

        return leftFit, rightFit
Exemple #6
0
    def reScanWithPrimary(self, src):
        """
        Allows to initiate box search with xPrimary obtained from previously found fits.
        :param src: binary bird-eye image
        :return: fit + fitType + image with search process depicted
        fitType used for debugging purposes (may be ignored)
        """

        imgH = src.shape[0]

        yBottom = imgH - 1

        self.fits = self.fits[:len(self.fits) - 1]  # Remove newest fit

        finder = LaneFinding()

        nzX, nzY = self.nz(src=src)

        currFit = self.currentFit()

        if currFit is not None:
            x_primary = aux.funcSpace(yBottom, currFit)
        else:
            x_primary = None

        fit, srcRgb = finder.primarySearchPolyMargin(src=src, lineSpace=self.lineSpace,
                                                     winCount=self.winCount, margin=self.margin, minpix=50,
                                                     nzX=nzX, nzY=nzY, windowSplit=self.windowSplit,
                                                     xPrimary=x_primary)
        if fit is not None:
            self.addFit(fit)

        return self.currentFit(), 'reScan', srcRgb
    def addLine(src, fit, color, stepCount=10, thickness=2):

        if fit is not None:
            imgH = src.shape[0]

            y = np.linspace(0, imgH - 1, stepCount)

            x = aux.funcSpace(argSpace=y, fitParams=fit)

            for i in range(stepCount - 1):
                x1 = int(round(x[i], 0))
                y1 = int(round(y[i], 0))

                x2 = int(round(x[i + 1], 0))
                y2 = int(round(y[i + 1], 0))
                pt1 = (x1, y1)
                pt2 = (x2, y2)
                src = cv2.line(img=src,
                               pt1=pt1,
                               pt2=pt2,
                               color=color,
                               thickness=thickness)

        return src