Ejemplo n.º 1
0
    def test_point_distance(self):
        l1 = Line((0, 0), (0, 1))
        point1 = (0, 0)
        point2 = (1, 0)

        self.assertEqual(l1.point_distance(point1), 0)
        self.assertEqual(l1.point_distance(point2), 1)
Ejemplo n.º 2
0
    def stopline(self, value):
        """
        Sets the stopline with specified offset, assuming that first vanishing point is in the top part of frame
        """

        self._stop_line = value

        left_edge_point = self.stopline.edge_points(info=self._info)[0]
        right_edge_point = self.stopline.edge_points(info=self._info)[1]

        self._stop_line = Line(
            point1=(left_edge_point[0],
                    left_edge_point[1] - constants.CORRIDORS_STOP_LINE_OFFSET),
            point2=(right_edge_point[0], right_edge_point[1] -
                    constants.CORRIDORS_STOP_LINE_OFFSET))

        left_edge_point = self.stopline.edge_points(info=self._info)[0]
        right_edge_point = self.stopline.edge_points(info=self._info)[1]

        top_line = Line(point1=(left_edge_point[0],
                                3 * left_edge_point[1] / 5),
                        point2=(right_edge_point[0],
                                3 * right_edge_point[1] / 5))

        self._info.update_area.change_area(top_line=top_line)
Ejemplo n.º 3
0
    def filter_lifelines(lifelines, vp1):
        """
        Filters given trajectories by those which have direction ti the first vanishing point.

        :param lifelines: given trajectories
        :param vp1: detected vanishing point
        :return: filtered trajectories
        """

        filtered = []

        for lifeline in lifelines:
            line_to_vp = Line(lifeline[0], vp1.point)

            try:
                lifeline_line = Line(lifeline[0], lifeline[-1])
            except SamePointError:
                continue

            if constants.TRACKER_TRAJECTORY_MIN_ANGLE < lifeline_line.angle(line_to_vp) < constants.TRACKER_TRAJECTORY_MAX_ANGLE:
                continue

            elif lifeline[0][1] < lifeline[-1][1]:
                continue

            else:
                filtered.append(lifeline)

        return filtered
Ejemplo n.º 4
0
    def middle_point(self):
        """
        :return: middle point of area
        """

        l1 = Line(point1=self._top_left, point2=self._bot_right)
        l2 = Line(point1=self._bot_left, point2=self._top_right)

        return l1.intersection(l2)
Ejemplo n.º 5
0
    def add_line(self):
        """
        Adds stop line
        """

        try:
            self.line = Line(self.point1, self.point2)
        except SamePointError:
            pass
Ejemplo n.º 6
0
    def test_angle(self):
        l1 = Line((0, 0), (0, 1))
        l2 = Line((0, 0), (1, 0))
        l3 = Line((0, 0), (1, 1))
        self.assertEqual(l1.angle(l2), 90)
        self.assertAlmostEqual(l1.angle(l3), 45, 4)

        l2.general_equation()
Ejemplo n.º 7
0
    def add_line(self):
        """
        Adds new line to storage
        """

        try:
            new_line = Line(self.point1, self.point2)

            if new_line.angle(Line.horizontal_line()) != 0:
                self.selected.append(Line(self.point1, self.point2))

        except SamePointError:
            pass
Ejemplo n.º 8
0
    def draw_trajectories(self, image, method="second"):
        """
        Helper method for drawing car trajectories (trajectories of center point)

        :param image: selected image
        :param method: method of trajectory obtaining to be printed
        :return: updated image
        """

        if method == "second":
            for index, point in enumerate(self._history):
                cv2.circle(img=image,
                           center=point.tuple(),
                           color=constants.COLOR_BLUE,
                           radius=5,
                           thickness=constants.FILL)

                try:
                    cv2.line(img=image,
                             pt1=point.tuple(),
                             pt2=self._history[index + 1].tuple(),
                             color=constants.COLOR_BLUE,
                             thickness=2)

                except IndexError:
                    pass

        if method == "first":
            try:
                Line(self._history[0].tuple(),
                     self._history[-1].tuple()).draw(image,
                                                     constants.COLOR_RED, 1)
            except SamePointError:
                return

            cv2.circle(img=image,
                       center=self._history[0].tuple(),
                       color=constants.COLOR_BLUE,
                       radius=5,
                       thickness=constants.FILL)

            cv2.circle(img=image,
                       center=self._history[-1].tuple(),
                       color=constants.COLOR_BLUE,
                       radius=5,
                       thickness=constants.FILL)

            cv2.line(img=image,
                     pt1=self._history[0].tuple(),
                     pt2=self._history[-1].tuple(),
                     color=constants.COLOR_BLUE,
                     thickness=2)

        position_history = [
            coordinates.tuple() for coordinates in self._history
        ]
        line, value = ransac(position_history, position_history, 1)

        if line is not None and value > 5:
            line.draw(image, constants.COLOR_RED, 2)
Ejemplo n.º 9
0
    def find_stop_line(self):
        """
        Finds stop line from stored stop-points.
        For stop line is used second vanishing point which is used as anchor for all detected stop line points.
        Stop line is detected using RANSAC algorithm.
        """

        best_line_ratio = 0
        best_line = None

        vp2 = self._info.vanishing_points[1]

        test_image = np.zeros(shape=(self._info.height, self._info.width))

        for point in self._stop_places:
            cv2.circle(test_image,
                       point.tuple(),
                       radius=5,
                       color=255,
                       thickness=5)

        cv2.imwrite("stopky.png", test_image)

        for point2 in self._stop_places:
            try:
                line = Line(vp2.point, point2.tuple())
            except SamePointError:
                continue
            except VanishingPointError:
                line = Line(point1=point2.tuple(), direction=vp2.direction)

            num = 0
            ransac_threshold = constants.CORRIDORS_RANSAC_THRESHOLD
            for point in self._stop_places:
                distance = line.point_distance(point.tuple())

                if distance < ransac_threshold:
                    num += 1

            if num > best_line_ratio:
                best_line_ratio = num
                best_line = line

        self.stopline = best_line
        self._stopline_found = True
Ejemplo n.º 10
0
    def _calculate_third_vp(self):
        """
        Because principal point is said to be in midle, the third vanishing point can be obtained by simple
        mathematics.

        After vanishing point is being found it propagates this information to InputInfo where it adds VanishingPoint
        to corresponding list
        """

        vp1 = self._info.vanishing_points[0].point

        try:
            vp2 = self._info.vanishing_points[1].point
            vp1_to_vp2 = Line(point1=vp1, point2=vp2)

        except VanishingPointError:
            vp1_to_vp2 = Line(
                point1=vp1, direction=self._info.vanishing_points[1].direction)

        self._info.vanishing_points.append(
            VanishingPoint(direction=vp1_to_vp2.normal_direction()))
Ejemplo n.º 11
0
    def _find_corridors(self, lifelines):
        """
        After both vanishing points are found corridors can be constructed with the information of car trajectories.

        :param lifelines: trajectories of cars
        """

        filtered_lifelines = TrackedObject.filter_lifelines(
            lifelines, self._info.vp1)
        mask = np.zeros(shape=(self._info.height, self._info.width, 3),
                        dtype=np.uint8)

        # for history in filtered_lifelines:
        #     line, value = ransac(history, history, 1)
        #
        #     if line is not None and value > 5:
        #         bottom_point = Coordinates(*line.find_coordinate(y=self._info.height)).tuple()
        #
        #         cv2.line(img=mask,
        #                  pt1=bottom_point,
        #                  pt2=self._info.vp1.point,
        #                  color=params.COLOR_LIFELINE,
        #                  thickness=100)

        for history in filtered_lifelines:
            helper_mask = np.zeros_like(mask)

            first_point = history[0]

            line = Line(first_point, self._info.vp1.point)
            line.draw(image=helper_mask,
                      color=constants.COLOR_LIFELINE,
                      thickness=100)

            mask = cv2.add(mask, helper_mask)

        cv2.imwrite("lifeline.jpg", mask)

        self._info.corridors_repository.find_corridors(
            lifelines_mask=mask, vp1=self._info.vanishing_points[0])
Ejemplo n.º 12
0
    def __init__(self, info, top_left, bottom_right, top_right, bottom_left):
        """
        :param info: instance of InputInfo
        :param top_left: top left anchor of area
        :param bottom_right: bottom right anchor of area
        :param top_right: top right anchor of area
        :param bottom_left: bottom left anchor of area
        """

        self._top_left = top_left.tuple()
        self._bot_right = bottom_right.tuple()
        self._top_right = top_right.tuple()
        self._bot_left = bottom_left.tuple()

        self.top_line = Line(point1=self._top_left, point2=self._top_right)
        self.left_line = Line(point1=self._top_left, point2=self._bot_left)
        self.bottom_line = Line(point1=self._bot_left, point2=self._bot_right)
        self.right_line = Line(point1=self._top_right, point2=self._bot_right)

        self._info = info
Ejemplo n.º 13
0
    def draw_line(self, image, point, color, thickness):
        """
        Helper function to dra line from point to this vanishing point. Works in both cases - when vanishing point
        is defined by a point or when defined by an angle

        :param image: selected image to draw on
        :param point: selected point as origin
        :param color: color of line
        :param thickness: thickness of line
        """

        if self.infinity:
            line = Line(point1=point, direction=self.direction)
        else:
            line = Line(point1=point, point2=self.point)

        line.draw(image=image, color=color, thickness=thickness)
Ejemplo n.º 14
0
 def test_vertical(self):
     self.assertFalse(Line((0, 1), (2, 1)).vertical)
     self.assertTrue(Line((0, 1), (0, 2)).vertical)
Ejemplo n.º 15
0
import numpy as np

from primitives.point import Point
from primitives.line import Line

# testing point creation
pointa = Point(1, 2)
pointb = Point(3, 4)
print(pointa.coords)

# test line object creation with coordinates
linea = Line([pointa.coords, pointb.coords])

# test setter with point objects
lineb = Line([pointb, pointa])
print(lineb.coords)

# test exception handling for line
# linec = Line(["asdkjalskdfj", pointa])

# test coordinate setting from point coordinates
points = [pointa.coords, pointb.coords]
lineb.setcoords(points)

# test coordinate setting from point objects
lineb.setcoords([pointb, pointa])

# test adding points from coordinates
pointc = Point(0, 0)
lineb.addPoint(pointc.coords)
Ejemplo n.º 16
0
    def _detect_second_vanishing_point(self, new_frame, boxes_mask,
                                       boxes_mask_no_border,
                                       light_status) -> None:
        """
        Calculates second vanishing point using information about car positions and detection of edges supporting
        second vanishing point. It is being detected only if green light status is present on current frame.
        Detected lines from edges are accumulated into parallel coordinate space - RANSAC algorithm is used
        for intersection detection - Vanishing Point.


        After vanishing point is being found it propagates this information to InputInfo where it adds VanishingPoint
        to corresponding list

        :param new_frame: examined frame
        :param boxes_mask: mask used for selecting parts of image where cars exists
        :param boxes_mask_no_border: mask used for selecting parts of image where cars exists
        :param light_status: current light status
        """

        if light_status in [Color.RED, Color.RED_ORANGE]:
            return

        selected_areas = cv2.bitwise_and(
            new_frame, cv2.cvtColor(boxes_mask, cv2.COLOR_GRAY2RGB))
        blured = cv2.GaussianBlur(selected_areas, (7, 7), 0)

        canny = cv2.Canny(blured, 50, 150, apertureSize=3)
        no_border_canny = cv2.bitwise_and(canny, boxes_mask_no_border)

        no_border_canny = cv2.bitwise_and(no_border_canny,
                                          no_border_canny,
                                          mask=self._info.update_area.mask())
        lines = cv2.HoughLinesP(
            image=no_border_canny,
            rho=1,
            theta=np.pi / 350,
            threshold=constants.CALIBRATOR_HLP_THRESHOLD,
            minLineLength=constants.CALIBRATOR_MIN_LINE_LENGTH,
            maxLineGap=constants.CALIBRATOR_MAX_LINE_GAP)

        vp1 = self._info.vanishing_points[0]

        canny = cv2.cvtColor(no_border_canny, cv2.COLOR_GRAY2RGB)

        if lines is not None:
            for (x1, y1, x2, y2), in lines:
                point1 = x1, y1
                point2 = x2, y2

                try:
                    if vp1.coordinates.distance(Coordinates(
                            x1, y1)) > vp1.coordinates.distance(
                                Coordinates(x2, y2)):
                        line_to_vp = Line(point1, vp1.point)
                    else:
                        line_to_vp = Line(point2, vp1.point)

                    if Line(point1, point2).angle(line_to_vp) < 30 or Line(
                            point1, point2).angle(line_to_vp) > 150:
                        cv2.line(canny, point1, point2, constants.COLOR_RED, 2)
                        continue

                    self._pc_lines.add_to_pc_space(point1, point2)
                    cv2.line(canny, point1, point2, constants.COLOR_BLUE, 2)
                except SamePointError:
                    continue

            cv2.imwrite("test.jpg", canny)

        if self._pc_lines.count > constants.CALIBRATOR_VP2_TRACK_MINIMUM:
            new_vanishing_point = self._pc_lines.find_most_lines_cross()

            x, y = new_vanishing_point
            if y is not None:
                self._info.vanishing_points.append(
                    VanishingPoint(point=new_vanishing_point))
            else:
                dx = np.cos(np.deg2rad(x))
                dy = np.sin(np.deg2rad(x))
                direction = dx, dy
                self._info.vanishing_points.append(
                    VanishingPoint(direction=direction))

            self._pc_lines.clear()
Ejemplo n.º 17
0
class Area:
    """
    Representing interesting area on image. Specified by anchors. Can be any 4 corner object.
    """
    def __init__(self, info, top_left, bottom_right, top_right, bottom_left):
        """
        :param info: instance of InputInfo
        :param top_left: top left anchor of area
        :param bottom_right: bottom right anchor of area
        :param top_right: top right anchor of area
        :param bottom_left: bottom left anchor of area
        """

        self._top_left = top_left.tuple()
        self._bot_right = bottom_right.tuple()
        self._top_right = top_right.tuple()
        self._bot_left = bottom_left.tuple()

        self.top_line = Line(point1=self._top_left, point2=self._top_right)
        self.left_line = Line(point1=self._top_left, point2=self._bot_left)
        self.bottom_line = Line(point1=self._bot_left, point2=self._bot_right)
        self.right_line = Line(point1=self._top_right, point2=self._bot_right)

        self._info = info

    @property
    def middle_point(self):
        """
        :return: middle point of area
        """

        l1 = Line(point1=self._top_left, point2=self._bot_right)
        l2 = Line(point1=self._bot_left, point2=self._top_right)

        return l1.intersection(l2)

    @property
    def defined(self):
        """
        :return: if area is defined
        """

        return self._top_left is not None and self._bot_right is not None

    def change_area(self,
                    top_line=None,
                    bot_line=None,
                    left_line=None,
                    right_line=None):
        """
        Changes area shape

        :param top_line: new top line
        :param bot_line: new bot line
        :param left_line: new left line
        :param right_line: new right line
        """

        self.top_line = top_line if top_line is not None else self.top_line
        self.bottom_line = bot_line if bot_line is not None else self.bottom_line
        self.right_line = right_line if right_line is not None else self.right_line
        self.left_line = left_line if left_line is not None else self.left_line

    def draw(self, image, color=constants.COLOR_AREA):
        """
        Helper function to draw an area

        :param image: selected image to draw on
        :param color: selected color to draw
        :return: updated image
        """

        if self.defined:
            self.top_line.draw(image, color, constants.AREA_THICKNESS)

        return image

    def anchors(self):
        """
        :return: top left nad bottom right anchor of the area
        """

        return self._top_left, self._bot_right

    def __contains__(self, coordinates):
        if not self.defined:
            return False

        if self.top_line.find_coordinate(x=coordinates.x)[1] > coordinates.y:
            return False

        if self.bottom_line.find_coordinate(
                x=coordinates.x)[1] < coordinates.y:
            return False

        if self.right_line.find_coordinate(y=coordinates.y)[0] < coordinates.x:
            return False

        if self.left_line.find_coordinate(y=coordinates.y)[0] > coordinates.x:
            return False

        return True

    def mask(self):
        """
        Generates binary mask of area

        :return: binary mask of area
        """

        mask = np.zeros(shape=(self._info.height, self._info.width),
                        dtype=np.uint8)

        self.draw(image=mask, color=constants.COLOR_WHITE_MONO)

        mask_with_border = np.pad(mask, 1, 'constant', constant_values=255)

        cv2.floodFill(image=mask,
                      mask=mask_with_border,
                      seedPoint=(int(self.middle_point[0]),
                                 int(self.middle_point[1])),
                      newVal=constants.COLOR_WHITE_MONO)

        return mask
Ejemplo n.º 18
0
 def test_same_points(self):
     with self.assertRaises(SamePointError):
         Line((3, 3), (3, 3))
Ejemplo n.º 19
0
 def setUpClass(cls):
     p1 = Point(0, 0)
     p2 = Point(1, 1)
     l = Line([p1, p2])
Ejemplo n.º 20
0
    def test_angle_90(self):
        l1 = Line((0, 1), (0, 0))
        l2 = Line((0, 0), (1, 0))

        self.assertEqual(l1.angle(l2), 90.)
Ejemplo n.º 21
0
    def test_point(self):
        l1 = Line((1, 1), (2, 2))

        self.assertTrue(l1.on_line((3, 3)))
        self.assertFalse(l1.on_line((-3, 3)))
Ejemplo n.º 22
0
    def test_angle_019(self):
        l1 = Line((1, 2), (3, 5))
        l2 = Line((3, 4), (2, 5))

        self.assertAlmostEqual(l1.angle(l2), 78.7, 1)
Ejemplo n.º 23
0
    def test_intersection(self):
        l1 = Line((0, 0), (1, 0))
        l2 = Line((0, 0), (0, 1))

        self.assertEqual(l1.intersection(l2), (0, 0))
Ejemplo n.º 24
0
    def find_corridors(self, lifelines_mask, vp1):
        """
        Finds corridors on frame using first positions of cars and detected first vanishing point to construct
        mask on which thresholding is used to detect separate corridors.
        By computation is used only 1px wide age around left, bottom and right edge of frame.

        :param lifelines_mask: mask of lifelines
        :param vp1: detected first vanishing point
        """

        # extract left-bot-right 1px border around lifeline image and make "1D array"
        left_edge = lifelines_mask[:, :1]
        bottom_edge = lifelines_mask[-1:, :].transpose(1, 0, 2)
        right_edge = np.flip(lifelines_mask[:, -1:])
        frame_edge = np.concatenate((left_edge, bottom_edge, right_edge))

        # greyscale image and reduce noise by multiple blur and threshold
        edge_grey = cv2.cvtColor(frame_edge, cv2.COLOR_RGB2GRAY)

        edge_grey_blured = cv2.medianBlur(edge_grey, 11)
        _, threshold = cv2.threshold(edge_grey_blured, 50, 255,
                                     cv2.THRESH_BINARY)
        threshold = cv2.dilate(threshold, (5, 5), iterations=5)

        height, width = edge_grey_blured.shape
        edge_grey_canny = cv2.Canny(threshold, 50, 150)
        coordinates = []

        # border image with 0
        edge_grey_canny[0][0] = 0
        edge_grey_canny[-1][0] = 0

        for i in range(height):
            if edge_grey_canny[i][0] == 255:
                coordinates.append(i)

        points = np.array(coordinates).reshape(-1, 2)

        for index, point in enumerate(points):
            try:
                half_diff = int((points[index + 1][0] - point[1]) / 2)
            except IndexError:
                break

            point[1] += half_diff
            points[index + 1][0] -= half_diff

        for point in points:
            points = []

            for coordinate in list(point):
                if coordinate < self._info.height:
                    points.append((0, coordinate))

                elif coordinate < self._info.height + self._info.width:
                    points.append((coordinate - self._info.height,
                                   self._info.height - 1))

                else:
                    points.append((self._info.width - 1, self._info.width +
                                   2 * self._info.height - coordinate))

            left_bottom = tuple(points[0])
            right_bottom = tuple(points[1])
            left_top = right_top = vp1.point

            self.create_new_corridor(left_line=Line(left_bottom, left_top),
                                     right_line=Line(right_bottom, right_top))

        # cv2.imwrite("mask.jpg", self.get_mask())

        self._corridor_mask = cv2.bitwise_and(
            self._corridor_mask,
            self._corridor_mask,
            mask=self._info.update_area.mask())
        self._corridors_found = True
Ejemplo n.º 25
0
class StopLineMaker(LineDrag):
    """
    Used for stop line creation
    """
    def __init__(self, image):
        super().__init__(image)

        self.line = None

    def add_line(self):
        """
        Adds stop line
        """

        try:
            self.line = Line(self.point1, self.point2)
        except SamePointError:
            pass

    def draw(self, image):
        """
        Helper function to draw stop line

        :param image: selected image
        """

        super().draw(image)

        if self.line is not None:
            self.line.draw(
                image,
                color=constants.COLOR_RED,
                thickness=constants.CORRIDORS_LINE_SELECTOR_THICKNESS)

    def run(self, info) -> []:
        """
        Infinite loop until user selects stop line

        :param info: instance of InputInfo
        """

        cv2.namedWindow("select_stop_line")
        cv2.setMouseCallback("select_stop_line", mouse_callback, self)

        while True:
            image_copy = np.copy(self.base_image)

            self.draw(image_copy)
            cv2.imshow("select_stop_line", image_copy)

            key = cv2.waitKey(1)

            if key == 13:
                self.line.draw(image_copy, constants.COLOR_BLUE,
                               constants.CORRIDORS_LINE_SELECTOR_THICKNESS)
                cv2.imshow("select_stop_line", image_copy)

                key = cv2.waitKey(0)
                if key == 13:
                    cv2.destroyWindow("select_stop_line")
                    return self.line

                if key == 8:
                    self.clear()

            if key == 8:
                self.erase_last()

    def erase_last(self):
        """
        Deletes last selected stopline
        """

        self.line = None
Ejemplo n.º 26
0
 def test_same(self):
     l1 = Line((-3, 2), (-3, 3))
     l2 = Line((-2, 2), (-2, 3))
     with self.assertRaises(NoIntersectionError):
         l1.intersection(l2)
Ejemplo n.º 27
0
 def test_horizontal(self):
     self.assertTrue(Line((0, 1), (2, 1)).horizontal)
     self.assertFalse(Line((0, 1), (2, 1)).vertical)