Esempio n. 1
0
def half_line(corners):
    """Divides a quadrilateral in half.

    The argument `corners` is a list of four points (tuples of (x, y)),
    representing the corners of a quadrilateral.  The list may start
    on any of the four corners, but must go around the quadrilateral in
    clockwise or counter-clockwise order; skipping around is not allowed.

    The function returns a line (a list of two points) that joins the
    midpoints of two oposite sides of the quadrilateral defined by the
    four passed-in corners.  Arbitrarily, the bisected sides are the
    one joining corner 0 and corner 1, and the one joining corner 2 and
    corner 3."""

    c = center(corners)

    # `d` is the perspective vanishing point for the two sides that
    # we're *not* bisecting.
    d = intersection(line(corners[0], corners[3]),
                     line(corners[1], corners[2]))
    if not d:
        # No vanishing point found: the two sides must be parallel.
        # So just use one of the sides as the direction.  This adds
        # the vector from corner[3] to corner[0] to the center point we
        # computed above.
        d = (c[0] + corners[0][0] - corners[3][0],
             c[1] + corners[0][1] - corners[3][1])

    l = line(c, d)
    p1 = intersection(l, line(corners[0], corners[1]))
    p2 = intersection(l, line(corners[2], corners[3]))
    return (p1, p2)
Esempio n. 2
0
def closest_node_on_segment_to_node(node, segment) -> Node.Node:
    A_start, B_start, C_start = perpendicular(segment.start, segment)
    A_end, B_end, C_end = perpendicular(segment.end, segment)
    if line_value(A_start, B_start, C_start, node) * line_value(
            A_end, B_end, C_end, node) < 0:
        node_A, node_B, node_C = perpendicular(node, segment)
        x = 10000
        y = (-node_A * x - node_C) / node_B
        end = Node.Node(x, y)
        node_segment = Edge.Edge(node, end)
        if geometry.intersect(segment, node_segment):
            closest_node = geometry.intersection(segment, node_segment)
        else:
            x = -10000
            y = (-node_A * x - node_C) / node_B
            end = Node.Node(x, y)
            node_segment = Edge.Edge(node, end)
            closest_node = geometry.intersection(segment, node_segment)
    else:
        closest_node = segment.start
        distance_to_start = dist(node, segment.start)
        distance_to_end = dist(node, segment.end)
        if distance_to_start > distance_to_end:
            closest_node = segment.end
    return closest_node
Esempio n. 3
0
def estimate(o_):
    r = []
    o = list(o_)
    o.append(o[0])
    res = []
    for i in range(0, len(o) - 1):
        o1 = o[i]
        o2 = o[i + 1]
        p1, p2 = intersection(o1, o2)
        if p1 is not None:
            r.append((p1, p2))
        else:
            p1, p2 = closest_non_intersecting(o1, o2)
            res.append(average([p1, p2]))

    r.append(r[0])
    for i in range(0, int(len(o_) / 2)):
        o1 = o[i]
        o2 = o[i + int(len(o_) / 2)]
        p1, p2 = intersection(o1, o2)
        if p1 is not None:
            r.append((p1, p2))
        else:
            p1, p2 = closest_non_intersecting(o1, o2)
            res.append(average([p1, p2]))
    for i in range(0, len(r) - 1):
        aux = [r[i][0], r[i][1], r[i + 1][0], r[i + 1][1]]
        p1, p2 = closest_pair(aux)
        if p1 is not None and p2 is not None:
            res.append(average([p1, p2]))
    return average(res)
Esempio n. 4
0
def half_line(corners):
    # TODO what is this?
    c = center(corners)
    d = intersection(line(corners[0], corners[3]), line(corners[1], corners[2]))
    if d:
        l = line(c, d)
    else:
        l = line(c, (c[0] + corners[0][0] - corners[3][0], 
                     c[1] + corners[0][1] - corners[3][1]))
    p1 = intersection(l, line(corners[0], corners[1]))
    p2 = intersection(l, line(corners[2], corners[3]))
    return (p1, p2)
Esempio n. 5
0
    def compare(a: Union[Point, Segment], b: Union[Point, Segment]):
        # get current ray
        ray = ray_getter()

        if isinstance(a, Point) and isinstance(b, Point):
            return dist(ray.p1, a) - dist(ray.p2, b)

        if isinstance(a, Point) and isinstance(b, Segment):
            pb = intersection(*ray,
                              *b,
                              restriction_1='ray',
                              restriction_2='segment')
            dist_a = dist(ray.p1, a)
            dist_b = dist(ray.p1, pb)
            if dist_a == dist_b:
                return -1
            return dist_a - dist_b

        if isinstance(a, Segment) and isinstance(b, Point):
            pa = intersection(*ray,
                              *a,
                              restriction_1='ray',
                              restriction_2='segment')
            dist_a = dist(ray.p1, pa)
            dist_b = dist(ray.p1, b)
            if dist_a == dist_b:
                return 1
            return dist_a - dist_b

        if isinstance(a, Segment) and isinstance(b, Segment):
            pa = intersection(*ray,
                              *a,
                              restriction_1='ray',
                              restriction_2='segment')
            pb = intersection(*ray,
                              *b,
                              restriction_1='ray',
                              restriction_2='segment')
            dist_a = dist(ray.p1, pa)
            dist_b = dist(ray.p1, pb)
            if dist_a == dist_b:
                pa2 = a.p1 if a.p2 == pa else a.p2
                pb2 = b.p1 if b.p2 == pb else b.p2
                return angle_between_points(ray.p1, ray.p2,
                                            pa2) - angle_between_points(
                                                ray.p1, ray.p2, pb2)
            return dist_a - dist_b

        raise ValueError(
            f'Comparator got unexpected types: {type(a)}, {type(b)}')
Esempio n. 6
0
def _draw_beachline(e, beachline):
	#print beachline.T.dumps()
	for arc in beachline:
		end,start=None,None
		# plot intersections
		if beachline.predecessor(arc):
			#print 'waaat', type(beachline.predecessor(arc))
			start = intersection(beachline.predecessor(arc).site,arc.site,e.y)
			plt.plot(start[0],start[1],'o',color='black')
		if beachline.sucessor(arc):

			#print 'waaat', type(beachline.sucessor(arc))
			end = intersection(arc.site,beachline.sucessor(arc).site,e.y)
			plt.plot(end[0],end[1],'o',color='black')
		plot_parabola(arc.site,e.y,endpoints=[start,end],color='purple')
Esempio n. 7
0
def visibility_graph_brute(collection: Collection) -> Collection:
    """ Generates visibility graph in O(n^3) """

    # create graph
    graph = Collection(points=collection.all_points)

    # get all segments
    segments = collection.all_segments

    # get polygons for each point
    polygons = defaultdict(list)
    for poly in collection.polygons:
        for p in poly.points:
            polygons[p].append(poly)

    # for each pair of points
    for p1, p2 in combinations(collection.all_points, 2):
        s = Segment(p1, p2)

        # if this segment is a diagonal of polygon ignore it
        # if is_diagonal(s, polygons):
        #     continue

        # if segment intersects with any other segment
        if any(
                intersection(*s, *seg, restriction_1='segment', restriction_2='segment')
                for seg in segments
                if (p1 not in seg) and (p2 not in seg)
        ):
            continue

        # add to graph
        graph.segments.add(s)

    return graph
Esempio n. 8
0
def transform(
        wheel1: Point,
        wheel2: Point,
        tail: Point,
        scene_center: Point,
):
    """
    :return: (
        robot_position, # position against scene center;
        angle, # angle against scene center;
        distance, # distance to scene center;
        )
    """
    robot_center = midpoint(wheel1, wheel2)

    # finds the tail point's prime and its projection line - the main one
    tail_prime = two_points_90(wheel1, robot_center)
    intersection_line = line(wheel1, wheel2)
    if not pts_same_side(tail, tail_prime, intersection_line):
        tail_prime = two_points_90(wheel2, robot_center)
    main_projection_line = line(tail, tail_prime)

    # finds center line's prime
    center_line = line(scene_center, robot_center)
    side_line = line(tail, wheel1)
    side_intersection = intersection(center_line, side_line)
    if side_intersection:
        side_line_prime = line(tail_prime, wheel1)
    else:
        side_line = line(tail, wheel2)
        side_intersection = intersection(center_line, side_line)
        side_line_prime = line(tail_prime, wheel2)

    # noinspection PyTypeChecker
    side_intersection_projection_line = parallel_line(main_projection_line, side_intersection)
    side_intersection_prime = intersection(side_line_prime, side_intersection_projection_line)
    center_line_prime = line(robot_center, side_intersection_prime)

    # computes position, angle and distance
    center_line_projection = parallel_line(main_projection_line, scene_center)
    center_prime = intersection(center_line_projection, center_line_prime)
    dist = distance(center_prime, robot_center) / distance(robot_center, tail_prime)
    robot_position = robot_center - center_prime
    angle = math.degrees(normalize_angle(
        three_pts_angle(tail_prime, robot_center, center_prime) - math.pi))
    return Object(robot_position, angle, (dist * ROBOT_UNIT))
Esempio n. 9
0
def _lines(corners, n):
    # TODO what is this?
    if n == 0:
        x = half_line(corners)
        return (_lines([corners[0], x[0], x[1], corners[3]], 1) + [x] + 
                _lines([x[0], corners[1], corners[2], x[1]], 1))
    else:
        x = half_line(corners)
        c = intersection(line(x[0], corners[2]), line(corners[1], corners[3]))
        d = intersection(line(corners[0], corners[3]), line(corners[1], corners[2]))
        if d:
            l = (intersection(line(corners[0], corners[1]), line(c, d)),
                 intersection(line(corners[2], corners[3]), line(c, d)))
        else:
            lx = line(c, (c[0] + corners[0][0] - corners[3][0], 
                      c[1] + corners[0][1] - corners[3][1]))
            l = (intersection(line(corners[0], corners[1]), lx),
                 intersection(line(corners[2], corners[3]), lx))
        l2 = half_line([corners[0], l[0], l[1], corners[3]])
        if n == 1:
            return ([l, l2] + _lines([l[0], l2[0], l2[1], l[1]], 2)
                    + _lines([corners[0], l2[0], l2[1], corners[3]], 2)
                    + _lines([l[0], corners[1], corners[2], l[1]], 2))
        if n == 2:
            return [l, l2]
Esempio n. 10
0
def merge_square_contours(cnts, width, height):
    """
    Merge overlapping contours. Only contours fully containing smaller contours are not merged.
    Processing each contour as a bounding box to perform union, contains and intersection operations.
    :param cnts: list of square contours
    :param width: width of the original image
    :param height: height of the original image
    :return: list of merged contours sorted by ranking
    """
    rects = []
    for cnt in cnts:
        rect = cv2.boundingRect(cnt)
        rects.append(rect)

    k = 0
    merged_squares = []

    while k < len(rects) - 1:
        if contains(rects[k], rects[k + 1]):
            merged_squares.append(rects[k])
            k += 1
        elif intersection(rects[k], rects[k + 1]) is not None:
            u = union(rects[k], rects[k + 1])
            new_rect = list([u[0], u[1], u[2], u[3]])
            rects[k + 1] = new_rect
            k += 1
            if k == len(rects) - 1:
                merged_squares.append(new_rect)
        else:
            merged_squares.append(rects[k])
            k += 1
    if k == len(rects) - 1:
        merged_squares.append(rects[k])

    np_merged_squares = []
    # transform squares back to contours
    for msq in merged_squares:
        np_merged_squares.append(
            np.array([[msq[0], msq[1]], [msq[0] + msq[2], msq[1]],
                      [msq[0] + msq[2], msq[1] + msq[3]],
                      [msq[0], msq[1] + msq[3]]]))
    sorted_merged_squares = sorted(
        np_merged_squares, key=lambda square: rank(square, width, height))
    return sorted_merged_squares
Esempio n. 11
0
def distance_node_to_segment(node: Node.Node, segment: Edge.Edge):
    # distance between node and segment, return min distance and closest point on segment to the node
    A_start, B_start, C_start = perpendicular(segment.start, segment)
    A_end, B_end, C_end = perpendicular(segment.end, segment)
    if line_value(A_start, B_start, C_start, node) * line_value(
            A_end, B_end, C_end, node) < 0:
        distance = abs(
            line_value(segment.A, segment.B, segment.C, node) /
            sqrt(segment.A**2 + segment.B**2))
        node_A, node_B, node_C = perpendicular(node, segment)
        x = 10000
        y = (-node_A * x - node_C) / node_B
        end = Node.Node(x, y)
        node_segment = Edge.Edge(node, end)
        if geometry.intersect(segment, node_segment):
            closest_node = geometry.intersection(segment, node_segment)
    else:
        distance = min(dist(node, segment.start), dist(node, segment.end))
    return distance
Esempio n. 12
0
def visible_vertices(point: Point, points: Iterable[Point],
                     segments: Dict[Point, List[Segment]]) -> Iterator[Point]:
    """ Yields points from given points that can be seen from given start point. """

    # remove point from points
    points = filter(lambda x: x != point, points)

    # sort points first by angle and then by distance from point
    points = sorted(points,
                    key=lambda x: (angle_to_xaxis(point, x), dist(point, x)))

    # create sorted list from segments that cross starting ray
    # list is sorted using ray that has to be updated
    ray = Segment(point, Point(point.x + 1, point.y))
    status = SortedList(
        iterable=(seg for seg in set(chain(*segments.values()))
                  if intersection(
                      *ray, *seg, restriction_1='ray', restriction_2='segment')
                  and point not in seg),
        key=status_key(lambda: ray))

    # for each point (they are sorted by angle)
    for p in points:

        # update ray
        ray = Segment(point, p)

        # if p is visible yield it
        if status.bisect_left(p) == 0:
            yield p

        # remove segments from this point
        for seg in segments[p]:
            if orient(point, p, seg.p1 if seg.p2 == p else seg.p2) < 0:
                status.remove(seg)

        # add segments to this point
        for seg in segments[p]:
            if orient(point, p, seg.p1 if seg.p2 == p else seg.p2) > 0:
                status.add(seg)
Esempio n. 13
0
def _lines(corners, n):
    # `mid_line` is a line that joins the midpoints of two oposite sides
    # of the quadrilateral defined by the four passed-in corners.
    mid_line = half_line(corners)

    # TODO what is this?
    if n == 0:
        # This recurses to look at the part of the quadrilateral on
        # *one* side of `mid_line`.  Returns all lines on that side,
        # not including `mid_line` but including the other edge.
        l0 = _lines([corners[0], mid_line[0], mid_line[1], corners[3]], 1)

        # This is just the mid-line.
        l1 = [mid_line]

        # This recurses to look at the part of the quadrilateral on the
        # *other* side of `mid_line`.  Returns all lines on that side,
        # not including `mid_line` but including the other edge.
        l2 = _lines([mid_line[0], corners[1], corners[2], mid_line[1]], 1)

        return (l0 + l1 + l2)

    else:
        c = intersection(line(mid_line[0], corners[2]),
                         line(corners[1], corners[3]))
        d = intersection(line(corners[0], corners[3]),
                         line(corners[1], corners[2]))
        if d:
            l = (intersection(line(corners[0], corners[1]), line(c, d)),
                 intersection(line(corners[2], corners[3]), line(c, d)))
        else:
            lx = line(c, (c[0] + corners[0][0] - corners[3][0],
                          c[1] + corners[0][1] - corners[3][1]))
            l = (intersection(line(corners[0], corners[1]), lx),
                 intersection(line(corners[2], corners[3]), lx))
        l2 = half_line([corners[0], l[0], l[1], corners[3]])
        if n == 1:
            return ([l, l2] + _lines([l[0], l2[0], l2[1], l[1]], 2) +
                    _lines([corners[0], l2[0], l2[1], corners[3]], 2) +
                    _lines([l[0], corners[1], corners[2], l[1]], 2))
        if n == 2:
            return [l, l2]
Esempio n. 14
0
def app(input_file, output_file):
    gauge = process_image.Gauge()
    host = housekeeping.OS()
    # setup image
    reuse_circle = housekeeping.test_time()
    im = host.get_image(DEF.SAMPLE_PATH, input_file)
    gray_im = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
    prep = gray_im  # copy of grayscale image to be preprocessed for angle detection
    mask = np.zeros_like(prep)
    canvas = np.zeros_like(im)  # output image
    np.copyto(canvas, im)
    error_screen = np.zeros_like(im)
    height, width = gray_im.shape
    assert height == DEF.HEIGHT
    assert width == DEF.WIDTH

    # mask_bandpass is a mask of the gauge obtained from histogram peaks
    hist0, mask_bandpass = hist_an.bandpass(gray_im)
    # prep is binary image ready for line detection
    prep = process_image.blur_n_threshold(prep, do_blur=1)
    prep = process_image.erode_n_dilate(prep)
    # host.write_image(("mask_bandpass.jpg", mask_bandpass))
    # Hough transforms
    if reuse_circle:
        print "reusing previous circle"
        circle_x, circle_y, radius = housekeeping.return_circle()
        circle_x = int(circle_x)
        circle_y = int(circle_y)
    else:
        circles = hough_transforms.hough_c(gray_im)
        for c in circles[:1]:
            # scale factor makes applicable area slightly larger just to be safe we are not missing anything
            cv2.circle(mask, (c[0], c[1]), int(c[2] * DEF.CIRCLE_SCALE_FACTOR),
                       (255, 255, 255), -1)
            prep = cv2.bitwise_and(prep, mask)
            cv2.circle(canvas, (c[0], c[1]), c[2], (0, 255, 0), DEF.THICKNESS)
            circle_x = c[0]
            circle_y = c[1]
            radius = int(c[2])

    cv2.circle(mask, (int(circle_x), int(circle_y)),
               int(radius * DEF.CIRCLE_SCALE_FACTOR), (255, 255, 255), -1)
    cv2.circle(canvas, (int(circle_x), int(circle_y)), radius, (0, 255, 0),
               DEF.THICKNESS)
    cv2.circle(canvas, (int(circle_x), int(circle_y - 12)), 25, (0, 255, 0),
               DEF.THICKNESS)
    prep = cv2.bitwise_and(prep, mask)

    prep = cv2.bitwise_and(mask_bandpass, prep)
    thresholded = np.copy(prep)
    prep = process_image.find_contour(prep, draw=True)

    lines = hough_transforms.hough_l(prep)

    for line in lines[:10]:
        for (rho, theta) in line:
            # blue for infinite lines (only draw the 2 strongest)
            x0 = np.cos(theta) * rho
            y0 = np.sin(theta) * rho
            pt1 = (int(x0 + (height + width) * (-np.sin(theta))),
                   int(y0 + (height + width) * np.cos(theta)))
            pt2 = (int(x0 - (height + width) * (-np.sin(theta))),
                   int(y0 - (height + width) * np.cos(theta)))
            gauge.lines.append((pt1, pt2))
            gauge.angles_in_radians.append(theta)
            gauge.angles_in_degrees.append(geometry.rad_to_degrees(theta))
            # cv2.line(canvas, pt1, pt2, (255, 255, 0), DEF.THICKNESS / 3)
    # check standard deviation of angles to catch angle wrap-around (359 to 0)
    angle_std = np.std(gauge.angles_in_degrees)
    if angle_std > 50:
        for i in range(len(gauge.angles_in_degrees)):
            if gauge.angles_in_degrees[i] < 20:
                gauge.angles_in_degrees[i] += 180
                gauge.angles_in_radians[i] += np.pi
    angle_index = geometry.get_angles(gauge.angles_in_degrees)
    if len(gauge.lines) < 2:
        EX.error_output(error_screen,
                        err_msg="unable to find needle from lines")
        sys.exit("unable to find needle form lines")

    line_found = False
    for this_pair in angle_index:
        # print "angle1: ", gauge.angles_in_degrees[this_pair[0]]
        # print "angle2: ", gauge.angles_in_degrees[this_pair[1]]
        print this_pair
        line1 = geometry.make_line(gauge.lines[this_pair[0]])
        line2 = geometry.make_line(gauge.lines[this_pair[1]])
        intersecting_pt = geometry.intersection(line1, line2)
        if intersecting_pt is not None:
            print "Intersection detected:", intersecting_pt
            cv2.circle(canvas, intersecting_pt, 10, DEF.RED, 3)
        else:
            print "No single intersection point detected"

        # Although we found a line coincident with the gauge needle,
        # we need to find which of the two direction it is pointing
        # guess1 and guess2 are 180 degrees apart
        avg_theta = (gauge.angles_in_radians[this_pair[0]] +
                     gauge.angles_in_radians[this_pair[1]]) / 2
        guess1 = [avg_theta, (0, 0)]
        guess2 = [avg_theta + np.pi, (0, 0)]
        if guess2[0] > 2 * np.pi:  # in case adding pi made it greater than 2pi
            guess2[0] -= 2 * np.pi
        print "guess1: ", guess1[0]
        print "guess2: ", guess2[0]
        guess1[1] = (int(circle_x + radius * np.sin(guess1[0])),
                     int(circle_y - radius * np.cos(guess1[0])))
        guess2[1] = (int(circle_x + radius * np.sin(guess2[0])),
                     int(circle_y - radius * np.cos(guess2[0])))
        # find the distance between our guess and intersection of gauge needle lines
        # the guess that is closer to the intersection is the correct one
        dist1 = math.hypot(intersecting_pt[0] - guess1[1][0],
                           intersecting_pt[1] - guess1[1][1])
        dist2 = math.hypot(intersecting_pt[0] - guess2[1][0],
                           intersecting_pt[1] - guess2[1][1])
        print "dist1: ", dist1
        print "dist2: ", dist2
        if dist1 < DEF.MAX_DISTANCE or dist2 < DEF.MAX_DISTANCE:
            line_found = True
            if dist1 < dist2:
                correct_guess = guess1
            else:
                correct_guess = guess2

        if line_found is True:
            cv2.circle(canvas, guess1[1], 10, DEF.GREEN, 3)
            cv2.circle(canvas, guess2[1], 10, DEF.BLUE, 3)
            # cv2.line(canvas, gauge.lines[this_pair[0]][0], gauge.lines[this_pair[0]][1], (255, 0, 0),
            #          DEF.THICKNESS)
            # cv2.line(canvas, gauge.lines[this_pair[1]][0], gauge.lines[this_pair[1]][1], (255, 0, 0),
            #          DEF.THICKNESS)
            break

    if line_found is False:
        EX.error_output(error_screen, err_msg="no positive pair")
        needle_angle = 0.0
    else:
        ref_offset = np.pi
        needle_angle = geometry.rad_to_degrees(correct_guess[0] - ref_offset)
    if needle_angle < 0.0:
        needle_angle += 360
    print "original_guess: ", needle_angle

    angle_adjustment_set = np.arange(needle_angle - 5.0, needle_angle + 5.0,
                                     0.1)
    sum_pixels = []
    for adj_angle in angle_adjustment_set:
        gauge.update_needle(adj_angle)
        gauge.get_needle((circle_x, circle_y - 10))
        overlap = cv2.bitwise_and(thresholded, gauge.needle_canvas)
        sum_pixels.append(np.sum(overlap / 255))
    adjustment_index = sum_pixels.index(max(sum_pixels))
    needle_angle = angle_adjustment_set[adjustment_index]
    gauge.update_needle(needle_angle)
    gauge.get_needle((circle_x, circle_y - 10))
    needle_rgb = cv2.cvtColor(gauge.needle_canvas, cv2.COLOR_GRAY2BGR)
    canvas = cv2.add(canvas, needle_rgb / 2)
    print "updated_guess: ", needle_angle

    pressure = np.interp(
        needle_angle, [DEF.GAUGE_MIN['angle'], DEF.GAUGE_MAX['angle']],
        [DEF.GAUGE_MIN['pressure'], DEF.GAUGE_MAX['pressure']])
    pressure_str = str(round(pressure, 2))
    print "pressure = ", pressure
    display_values(canvas, pressure_str)
    final_line_pt1 = (
        int(circle_x +
            radius * np.sin(geometry.degrees_to_radians(needle_angle))),
        int(circle_y -
            radius * np.cos(geometry.degrees_to_radians(needle_angle))))
    final_line_pt2 = (
        int(circle_x +
            radius * np.sin(geometry.degrees_to_radians(needle_angle + 180))),
        int(circle_y -
            radius * np.cos(geometry.degrees_to_radians(needle_angle + 180))))
    cv2.line(canvas,
             final_line_pt1,
             final_line_pt2,
             DEF.RED,
             thickness=DEF.THICKNESS * 2)
    prep = cv2.bitwise_and(prep, mask)
    # plt.subplot(231)
    # plt.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
    # plt.subplot(232)
    # plt.imshow(255 - mask_bandpass, 'gray')
    # plt.subplot(233)
    # plt.imshow(prep, 'gray')
    # plt.subplot(234)
    # plt.imshow(cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB))
    # plt.subplot(235)
    # plt.plot(hist0)
    # plt.xlim([0, 256])
    # plt.ylim([0, 50000])
    # plt.show()

    cv2.circle(prep, (circle_x, circle_y), 25, (0, 255, 0), DEF.THICKNESS)
    prep = cv2.cvtColor(prep, cv2.COLOR_GRAY2BGR)
    canvas = np.concatenate((im, canvas), axis=1)
    host.write_to_file('w', "Pressure: " + pressure_str + " MPa",
                       "Temperature: " + str(host.read_temp()))
    host.write_to_file('a', "circle_x:" + str(circle_x),
                       "circle_y:" + str(circle_y), "radius:" + str(radius))
    # pass in tuples ("filename.ext", img_to_write)
    image_path = re.sub('file', str(output_file), DEF.OUTPUT_PATH)
    host.write_image((image_path, canvas))
    image_path = re.sub('file', str(output_file), DEF.THRESH_PATH)
    host.write_image((image_path, thresholded))
Esempio n. 15
0
	def key(self,directrix):
		if self.q is None:
			return self.p[0]
		else:
			return intersection(self.p, self.q, directrix)[0]
Esempio n. 16
0
def center(corners):
    """Given a list of four corner points, return the center of the square."""
    return intersection(line(corners[0], corners[2]), 
                        line(corners[1], corners[3]))
Esempio n. 17
0
def app(input_file, output_file):
    gauge = process_image.Gauge()
    host = housekeeping.OS()
    # setup image
    reuse_circle = housekeeping.test_time()
    im = host.get_image(DEF.SAMPLE_PATH, input_file)
    gray_im = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
    prep = gray_im  # copy of grayscale image to be preprocessed for angle detection
    mask = np.zeros_like(prep)
    canvas = np.zeros_like(im)  # output image
    np.copyto(canvas, im)
    error_screen = np.zeros_like(im)
    height, width = gray_im.shape
    assert height == DEF.HEIGHT
    assert width == DEF.WIDTH

    # mask_bandpass is a mask of the gauge obtained from histogram peaks
    hist0, mask_bandpass = hist_an.bandpass(gray_im)
    # prep is binary image ready for line detection
    prep = process_image.blur_n_threshold(prep, do_blur=1)
    prep = process_image.erode_n_dilate(prep)
    # host.write_image(("mask_bandpass.jpg", mask_bandpass))
    # Hough transforms
    if reuse_circle:
        print "reusing previous circle"
        circle_x, circle_y, radius = housekeeping.return_circle()
        circle_x = int(circle_x)
        circle_y = int(circle_y)
    else:
        circles = hough_transforms.hough_c(gray_im)
        for c in circles[:1]:
            # scale factor makes applicable area slightly larger just to be safe we are not missing anything
            cv2.circle(mask, (c[0], c[1]), int(c[2] * DEF.CIRCLE_SCALE_FACTOR), (255, 255, 255), -1)
            prep = cv2.bitwise_and(prep, mask)
            cv2.circle(canvas, (c[0], c[1]), c[2], (0, 255, 0), DEF.THICKNESS)
            circle_x = c[0]
            circle_y = c[1]
            radius = int(c[2])

    cv2.circle(mask, (int(circle_x), int(circle_y)), int(radius * DEF.CIRCLE_SCALE_FACTOR), (255, 255, 255), -1)
    cv2.circle(canvas, (int(circle_x), int(circle_y)), radius, (0, 255, 0), DEF.THICKNESS)
    cv2.circle(canvas, (int(circle_x), int(circle_y-12)), 25, (0, 255, 0), DEF.THICKNESS)
    prep = cv2.bitwise_and(prep, mask)

    prep = cv2.bitwise_and(mask_bandpass, prep)
    thresholded = np.copy(prep)
    prep = process_image.find_contour(prep, draw=True)

    lines = hough_transforms.hough_l(prep)

    for line in lines[:10]:
        for (rho, theta) in line:
            # blue for infinite lines (only draw the 2 strongest)
            x0 = np.cos(theta) * rho
            y0 = np.sin(theta) * rho
            pt1 = (int(x0 + (height + width) * (-np.sin(theta))), int(y0 + (height + width) * np.cos(theta)))
            pt2 = (int(x0 - (height + width) * (-np.sin(theta))), int(y0 - (height + width) * np.cos(theta)))
            gauge.lines.append((pt1, pt2))
            gauge.angles_in_radians.append(theta)
            gauge.angles_in_degrees.append(geometry.rad_to_degrees(theta))
            # cv2.line(canvas, pt1, pt2, (255, 255, 0), DEF.THICKNESS / 3)
    # check standard deviation of angles to catch angle wrap-around (359 to 0)
    angle_std = np.std(gauge.angles_in_degrees)
    if angle_std > 50:
        for i in range(len(gauge.angles_in_degrees)):
            if gauge.angles_in_degrees[i] < 20:
                gauge.angles_in_degrees[i] += 180
                gauge.angles_in_radians[i] += np.pi
    angle_index = geometry.get_angles(gauge.angles_in_degrees)
    if len(gauge.lines) < 2:
        EX.error_output(error_screen, err_msg="unable to find needle from lines")
        sys.exit("unable to find needle form lines")

    line_found = False
    for this_pair in angle_index:
        # print "angle1: ", gauge.angles_in_degrees[this_pair[0]]
        # print "angle2: ", gauge.angles_in_degrees[this_pair[1]]
        print this_pair
        line1 = geometry.make_line(gauge.lines[this_pair[0]])
        line2 = geometry.make_line(gauge.lines[this_pair[1]])
        intersecting_pt = geometry.intersection(line1, line2)
        if intersecting_pt is not None:
            print "Intersection detected:", intersecting_pt
            cv2.circle(canvas, intersecting_pt, 10, DEF.RED, 3)
        else:
            print "No single intersection point detected"

        # Although we found a line coincident with the gauge needle,
        # we need to find which of the two direction it is pointing
        # guess1 and guess2 are 180 degrees apart
        avg_theta = (gauge.angles_in_radians[this_pair[0]] + gauge.angles_in_radians[this_pair[1]]) / 2
        guess1 = [avg_theta, (0, 0)]
        guess2 = [avg_theta + np.pi, (0, 0)]
        if guess2[0] > 2 * np.pi:  # in case adding pi made it greater than 2pi
            guess2[0] -= 2 * np.pi
        print "guess1: ", guess1[0]
        print "guess2: ", guess2[0]
        guess1[1] = (int(circle_x + radius * np.sin(guess1[0])), int(circle_y - radius * np.cos(guess1[0])))
        guess2[1] = (int(circle_x + radius * np.sin(guess2[0])), int(circle_y - radius * np.cos(guess2[0])))
        # find the distance between our guess and intersection of gauge needle lines
        # the guess that is closer to the intersection is the correct one
        dist1 = math.hypot(intersecting_pt[0] - guess1[1][0], intersecting_pt[1] - guess1[1][1])
        dist2 = math.hypot(intersecting_pt[0] - guess2[1][0], intersecting_pt[1] - guess2[1][1])
        print "dist1: ", dist1
        print "dist2: ", dist2
        if dist1 < DEF.MAX_DISTANCE or dist2 < DEF.MAX_DISTANCE:
            line_found = True
            if dist1 < dist2:
                correct_guess = guess1
            else:
                correct_guess = guess2

        if line_found is True:
            cv2.circle(canvas, guess1[1], 10, DEF.GREEN, 3)
            cv2.circle(canvas, guess2[1], 10, DEF.BLUE, 3)
            # cv2.line(canvas, gauge.lines[this_pair[0]][0], gauge.lines[this_pair[0]][1], (255, 0, 0),
            #          DEF.THICKNESS)
            # cv2.line(canvas, gauge.lines[this_pair[1]][0], gauge.lines[this_pair[1]][1], (255, 0, 0),
            #          DEF.THICKNESS)
            break

    if line_found is False:
        EX.error_output(error_screen, err_msg="no positive pair")
        needle_angle = 0.0
    else:
        ref_offset = np.pi
        needle_angle = geometry.rad_to_degrees(correct_guess[0] - ref_offset)
    if needle_angle < 0.0:
        needle_angle += 360
    print "original_guess: ", needle_angle

    angle_adjustment_set = np.arange(needle_angle-5.0,needle_angle+5.0,0.1)
    sum_pixels = []
    for adj_angle in angle_adjustment_set:
        gauge.update_needle(adj_angle)
        gauge.get_needle((circle_x, circle_y-10))
        overlap = cv2.bitwise_and(thresholded, gauge.needle_canvas)
        sum_pixels.append(np.sum(overlap/255))
    adjustment_index = sum_pixels.index(max(sum_pixels))
    needle_angle = angle_adjustment_set[adjustment_index]
    gauge.update_needle(needle_angle)
    gauge.get_needle((circle_x, circle_y-10))
    needle_rgb = cv2.cvtColor(gauge.needle_canvas, cv2.COLOR_GRAY2BGR)
    canvas = cv2.add(canvas, needle_rgb/2)
    print "updated_guess: ", needle_angle

    pressure = np.interp(needle_angle, [DEF.GAUGE_MIN['angle'], DEF.GAUGE_MAX['angle']],
                         [DEF.GAUGE_MIN['pressure'], DEF.GAUGE_MAX['pressure']])
    pressure_str = str(round(pressure, 2))
    print "pressure = ", pressure
    display_values(canvas, pressure_str)
    final_line_pt1 = (int(circle_x + radius * np.sin(geometry.degrees_to_radians(needle_angle))), int(circle_y - radius * np.cos(geometry.degrees_to_radians(needle_angle))))
    final_line_pt2 = (int(circle_x + radius * np.sin(geometry.degrees_to_radians(needle_angle + 180))), int(circle_y - radius * np.cos(geometry.degrees_to_radians(needle_angle + 180))))
    cv2.line(canvas, final_line_pt1, final_line_pt2, DEF.RED, thickness=DEF.THICKNESS*2)
    prep = cv2.bitwise_and(prep, mask)
    # plt.subplot(231)
    # plt.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
    # plt.subplot(232)
    # plt.imshow(255 - mask_bandpass, 'gray')
    # plt.subplot(233)
    # plt.imshow(prep, 'gray')
    # plt.subplot(234)
    # plt.imshow(cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB))
    # plt.subplot(235)
    # plt.plot(hist0)
    # plt.xlim([0, 256])
    # plt.ylim([0, 50000])
    # plt.show()

    cv2.circle(prep, (circle_x, circle_y), 25, (0, 255, 0), DEF.THICKNESS)
    prep = cv2.cvtColor(prep, cv2.COLOR_GRAY2BGR)
    canvas = np.concatenate((im, canvas), axis=1)
    host.write_to_file('w', "Pressure: " + pressure_str + " MPa", "Temperature: " + str(host.read_temp()))
    host.write_to_file('a', "circle_x:" + str(circle_x), "circle_y:" + str(circle_y), "radius:" + str(radius))
    # pass in tuples ("filename.ext", img_to_write)
    image_path = re.sub('file', str(output_file), DEF.OUTPUT_PATH)
    host.write_image((image_path, canvas))
    image_path = re.sub('file', str(output_file), DEF.THRESH_PATH)
    host.write_image((image_path, thresholded))
    def make_box(self, site_edges):
        site = site_edges[0]
        edges = map(copy.deepcopy, site_edges[1])

        def edge_intersects_box(edge):
            for box_edge in self.box_edges:
                if intersects(edge, box_edge):
                    return True
            return False

        filtered_edges = filter(edge_intersects_box, edges)

        edge_collisions = {}
        for box_edge in self.box_edges:
            edge_collisions[box_edge] = []
            for voronoi_edge in filtered_edges:
                if intersects(box_edge, voronoi_edge):
                    edge_collisions[box_edge].append(voronoi_edge)

        unmatched_edges = []
        for box_edge, collision_list in zip(
                edge_collisions.keys(),
                edge_collisions.values(),
                ):
            if len(collision_list) == 0:
                pass
            elif len(collision_list) == 1:
                unmatched_edges.append(
                    (box_edge, collision_list[0]),
                    )
            else:
                new_start = intersection(
                    collision_list[0],
                    box_edge,
                    )
                new_end = intersection(
                    collision_list[1],
                    box_edge,
                    )
                new_edge = Edge(new_start, end_point=new_end)
                edges.append(new_edge)
                break

        if len(unmatched_edges) > 0:
            first_start = unmatched_edges[0][0].start_point
            first_end = unmatched_edges[0][0].end_point
            second_start = unmatched_edges[1][0].start_point
            second_end = unmatched_edges[1][0].end_point
            if first_start == second_start or first_start == second_end:
                common_corner = first_start
            elif first_end == second_start or first_end == second_end:
                common_corner = first_end
            else:
                raise ValueError("no common corner")
            first_intersection = intersection(
                unmatched_edges[0][0],
                unmatched_edges[0][1],
                )
            first_new_edge = Edge(
                first_intersection,
                end_point=common_corner,
                )
            second_intersection = intersection(
                unmatched_edges[1][0],
                unmatched_edges[1][1],
                )
            second_new_edge = Edge(
                second_intersection,
                end_point=common_corner,
                )
            edges.append(first_new_edge)
            edges.append(second_new_edge)

        return (site, edges)
    def process_event(self, current_vertex):
        """
        this function determine event type for current_vertex
        and maintain current edge list
        """
        position = {}
        # end node is a selected node far away on sweep line
        end_up_node = Node(current_vertex.node.x, 1000)
        end_down_node = Node(current_vertex.node.x, -1000)
        sweepline = Edge(end_up_node, end_down_node)
        obstacle = vertex_in_obstacle(current_vertex, self.obstacle)
        for i in range(len(current_vertex.edge_list)):
            # position[edge]= left or right
            position[current_vertex.edge_list[i]] = left_or_right(
                current_vertex, current_vertex.edge_list[i])
        # determine if upper or lower
        if current_vertex.edge_list[0].start != current_vertex.node:
            if current_vertex.edge_list[1].start != current_vertex.node:
                if current_vertex.edge_list[
                        0].start.y > current_vertex.edge_list[1].start.y:
                    E_upper = current_vertex.edge_list[0]
                    E_lower = current_vertex.edge_list[1]
                else:
                    E_upper = current_vertex.edge_list[1]
                    E_lower = current_vertex.edge_list[0]
            else:
                if current_vertex.edge_list[
                        0].start.y > current_vertex.edge_list[1].end.y:
                    E_upper = current_vertex.edge_list[0]
                    E_lower = current_vertex.edge_list[1]
                else:
                    E_upper = current_vertex.edge_list[1]
                    E_lower = current_vertex.edge_list[0]
        else:
            if current_vertex.edge_list[1].start != current_vertex.node:
                if current_vertex.edge_list[
                        0].end.y > current_vertex.edge_list[1].start.y:
                    E_upper = current_vertex.edge_list[0]
                    E_lower = current_vertex.edge_list[1]
                else:
                    E_upper = current_vertex.edge_list[1]
                    E_lower = current_vertex.edge_list[0]
            else:
                if current_vertex.edge_list[
                        0].end.y > current_vertex.edge_list[1].end.y:
                    E_upper = current_vertex.edge_list[0]
                    E_lower = current_vertex.edge_list[1]
                else:
                    E_upper = current_vertex.edge_list[1]
                    E_lower = current_vertex.edge_list[0]

        if position[E_upper][0] == "right" and position[E_lower][0] == "right":
            # insert E_upper and E_lower into current_edge
            self.current_edge_list.insert(E_upper, E_upper)
            self.current_edge_list.insert(E_lower, E_lower)
            prev = self.getPred(E_lower)
            succ = self.getSucc(E_upper)
        elif position[E_upper][0] == "right" and position[E_lower][0] == "left":
            # delete E_lower and insert E_upper
            prev = self.getPred(E_lower)
            self.current_edge_list.remove(E_lower)
            self.current_edge_list.insert(E_upper, E_upper)
            succ = self.getSucc(E_upper)
        elif position[E_upper][0] == "left" and position[E_lower][0] == "right":
            # delete E_upper and insert E_lower
            succ = self.getSucc(E_upper)
            self.current_edge_list.remove(E_upper)
            self.current_edge_list.insert(E_lower, E_lower)
            prev = self.getPred(E_lower)
        else:
            # delete E_upper and E_lower
            succ = self.getSucc(E_upper)
            prev = self.getPred(E_lower)
            self.current_edge_list.remove(E_upper)
            self.current_edge_list.remove(E_lower)
        if prev is not None:
            if not edge_in_polygon(prev, obstacle):
                inter1 = intersection(prev, sweepline)
                self.vertical_extension.append(
                    Edge(current_vertex.node, inter1))
        if succ is not None:
            if not edge_in_polygon(succ, obstacle):
                inter2 = intersection(succ, sweepline)
                self.vertical_extension.append(
                    Edge(current_vertex.node, inter2))