Beispiel #1
0
 def process(self):
     intensity = self.intensity_spin.value()
     invert = self.invert_check.isChecked()
     equalize = self.equalize_check.isChecked()
     blue_mode = self.blue_combo.currentIndex()
     dx, dy = cv.spatialGradient(cv.cvtColor(self.image, cv.COLOR_BGR2GRAY))
     if invert:
         dx = -dx
         dy = -dy
     red = ((dx.astype(np.float32) / np.max(np.abs(dx)) * 127) +
            127).astype(np.uint8)
     green = ((dy.astype(np.float32) / np.max(np.abs(dy)) * 127) +
              127).astype(np.uint8)
     if blue_mode == 0:
         blue = np.zeros_like(red)
     elif blue_mode == 1:
         blue = np.full_like(red, 255)
     elif blue_mode == 2:
         blue = normalize_mat(np.linalg.norm(cv.merge((red, green)),
                                             axis=2))
     else:
         blue = None
     gradient = cv.merge([blue, green, red])
     if intensity > 0:
         gradient = cv.LUT(gradient, create_lut(intensity, intensity))
     if equalize:
         gradient = equalize_image(gradient)
     self.grad_viewer.update_processed(gradient)
Beispiel #2
0
 def cv_SpatialGradient(input=('ImagePin', 0),
                        ksize=('IntPin', 3),
                        dx=(REF, ('ImagePin', 0)),
                        dy=(REF, ('ImagePin', 0))):
     """ Blurs An image."""
     x, y = cv2.spatialGradient(input.image, ksize)
     dx(x)
     dy(y)
Beispiel #3
0
def img_grad(img):
    dx = np.zeros(img.shape[:-1], dtype=np.int16)
    dy = dx.copy()
    for i in range(3):
        dx_curr, dy_curr = cv2.spatialGradient(img[:, :, i])

        for (d, d_curr) in [(dx, dx_curr), (dy, dy_curr)]:
            idx = abs(d_curr) > abs(d)
            d[idx] = d_curr[idx]

    d_ver, d_hor = dx[1:, 1:], dy[1:, 1:]
    return d_ver, d_hor
Beispiel #4
0
def get_silhouette_idt_grad_from_mask(fg_mask: ndarray):
    """fg_mask is a boolean mask that should be True where it is the foreground,
     and False in background."""
    fg_mask_uint = fg_mask.astype(np.uint8) * 255
    silhouette = cv2.Laplacian(fg_mask_uint, cv2.CV_8U)
    silhouette_bool = silhouette > 0
    pre_idt = np.where(silhouette_bool, 0, 255).astype(np.uint8)
    idt = image_distance_transform(pre_idt)
    idt = (idt / idt.max()) * 255
    dx, dy = cv2.spatialGradient(idt.astype(np.uint8))
    grad = np.stack((dx, dy), axis=-1)

    return silhouette_bool, idt, grad
Beispiel #5
0
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.intensity_spin = QSpinBox()
        self.intensity_spin.setRange(0, 100)
        self.intensity_spin.setValue(95)
        self.intensity_spin.setSuffix(self.tr(" %"))
        self.intensity_spin.setToolTip(self.tr("Tonality compression amount"))
        self.blue_combo = QComboBox()
        self.blue_combo.addItems([
            self.tr("None"),
            self.tr("Flat"),
            self.tr("Abs"),
            self.tr("Norm")
        ])
        self.blue_combo.setCurrentIndex(2)
        self.blue_combo.setToolTip(self.tr("Blue component inclusion mode"))
        self.invert_check = QCheckBox(self.tr("Invert"))
        self.invert_check.setToolTip(self.tr("Reverse lighting direction"))
        self.equalize_check = QCheckBox(self.tr("Equalize"))
        self.equalize_check.setToolTip(self.tr("Apply histogram equalization"))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.dx, self.dy = cv.spatialGradient(
            cv.cvtColor(self.image, cv.COLOR_BGR2GRAY))
        self.process()

        self.intensity_spin.valueChanged.connect(self.process)
        self.blue_combo.currentIndexChanged.connect(self.process)
        self.invert_check.stateChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Intensity:")))
        top_layout.addWidget(self.intensity_spin)
        top_layout.addWidget(QLabel(self.tr("Blue channel:")))
        top_layout.addWidget(self.blue_combo)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.equalize_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)

        self.setLayout(main_layout)
Beispiel #6
0
def FDO2(input):
    #First derivative operators - Sobel masks - Part II

    img = cv2.imread("eye.jpeg", cv2.IMREAD_GRAYSCALE)

    gx, gy = cv2.spatialGradient(img, ksize=3, borderType=cv2.BORDER_DEFAULT)
    g = np.abs(gx) + np.abs(gy)

    gx = scaleImage2_uchar(gx)
    gy = scaleImage2_uchar(gy)
    g = scaleImage2_uchar(g)

    while cv2.waitKey(1) != ord('q'):
        cv2.imshow("Original", img)
        cv2.imshow("New", g)
        cv2.imshow("Gx", gx)
        cv2.imshow("Gy", gy)
Beispiel #7
0
def simple_lucas_kanade(prev_img, next_img, prev_pts, win_size=25, mode='pyr'):
    '''
    Realization of simple Lucas-Kanade method, without image pyramid
    Input:
        prev_img - np.array, grayscale image of previous frame of video
        next_img - np.array, grayscale image of current frame of video
        prev_pts - np.array, special points to be tracked
        win_size - int, window size for Lucas-Kanade method
        mode - str, could be 'pyr' or 'simple'. In 'pyr' mode returns points
        velocity, in 'simple' mode returns new points.
    Output:
        velocities or new_points - np.array, depends on choosen mode
    '''
    # calc derivatives
    der_x, der_y = cv2.spatialGradient(next_img)
    der_t = cv2.subtract(next_img, prev_img)
    half = win_size // 2
    # for every point calc v and u in window
    new_points = np.zeros_like(prev_pts)
    veloc = np.zeros_like(prev_pts)
    for i, point in enumerate(prev_pts):
        x_c, y_c = point[0][0], point[0][1]
        # get coords of window
        # ADDED 1 TO GET REAL WINDOW
        x_coords = np.clip([x_c - half, x_c + half + 1], 0, next_img.shape[1])
        y_coords = np.clip([y_c - half, y_c + half + 1], 0, next_img.shape[0])
        # x1, x2 = int(np.rint(x_coords[0])), int(np.rint(x_coords[1]))
        # y1, y2 = int(np.rint(y_coords[0])), int(np.rint(y_coords[1]))
        x1, x2 = int(x_coords[0]), int(x_coords[1])
        y1, y2 = int(y_coords[0]), int(y_coords[1])
        cur_dx = der_x[y1:y2, x1:x2]
        cur_dy = der_y[y1:y2, x1:x2]
        cur_dt = der_t[y1:y2, x1:x2]
        A = np.array([[np.sum(cur_dx**2),
                       np.sum(cur_dx * cur_dy)],
                      [np.sum(cur_dx * cur_dy),
                       np.sum(cur_dy**2)]])
        b = np.array([-np.sum(cur_dx * cur_dt), -np.sum(cur_dy * cur_dt)]).T
        v, u = np.linalg.pinv(A) @ b
        new_points[i][0] = [x_c + v, y_c + u]
        veloc[i][0] = [v, u]
    if mode == 'pyr':
        return veloc
    if mode == 'simple':
        return new_points
Beispiel #8
0
def fdo_sobel_masks_2():
    img = cv2.imread('../../img/Lenna.png', cv2.IMREAD_GRAYSCALE)

    gx, gy = cv2.spatialGradient(img, ksize=3, borderType=cv2.BORDER_DEFAULT)
    g = np.abs(gx) + np.abs(gy)

    gx = scaleImage2_uchar(gx)
    gy = scaleImage2_uchar(gy)
    g = scaleImage2_uchar(g)

    cv2.imshow("Original", img)
    cv2.imshow("New", g)
    cv2.imshow("Gx", gx)
    cv2.imshow("Gy", gy)

    while True:
        if 0xFF & cv2.waitKey(1) == ord('q'):
            break

    cv2.destroyAllWindows()
Beispiel #9
0
def detect_inner_corners(hsv_white_only, img_id=0):
    # Parameters ###########################
    second_blur_size = 49
    ignore_border_size = 3
    corner_harris_block_size = 4

    # Define valid intensity range for the median of a corner
    min_intensity_average = 170
    max_intensity_average = 240
    ########################################

    # hsv_origin = hsv.copy()

    blur = make_gaussian_blurry(hsv_white_only, 5)
    double_blur = make_gaussian_blurry(blur, second_blur_size)

    # Sub-pixel:
    dst = cv2.cornerHarris(blur, corner_harris_block_size, 3, 0.04)
    dst = cv2.dilate(dst, None)
    ret, dst = cv2.threshold(dst, 0.01 * dst.max(), 255, 0)
    dst = np.uint8(dst)

    # find centroids
    ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)

    # define the criteria to stop and refine the corners
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
    corners = cv2.cornerSubPix(blur, np.float32(centroids), (5, 5), (-1, -1),
                               criteria)

    # Filter the corners
    number_of_corners = len(corners)
    x_min = np.array([ignore_border_size] * number_of_corners)
    x_max = np.array([IMG_HEIGHT - ignore_border_size] * number_of_corners)
    y_min = np.array([ignore_border_size] * number_of_corners)
    y_max = np.array([IMG_WIDTH - ignore_border_size] * number_of_corners)

    # Keep corners within the border limit
    corners_clipped_on_border = corners[np.logical_and(
        np.logical_and(
            np.greater(corners[:, 1], x_min),  # Add top limit
            np.less(corners[:, 1], x_max)  # Add bottom limit
        ),
        np.logical_and(
            np.greater(corners[:, 0], y_min),  # Add left limit
            np.less(corners[:, 0], y_max)  # Add right limit
        ))]
    corner_x = np.int0(corners_clipped_on_border[:, 1])
    corner_y = np.int0(corners_clipped_on_border[:, 0])
    number_of_corners = len(corner_x)

    min_intensity = np.array([min_intensity_average] * number_of_corners)
    max_intensity = np.array([max_intensity_average] * number_of_corners)

    # Filter out the corners that belong to an "outer corner"
    # and outliers that are inside the white area
    corners_clipped_on_intensity = corners_clipped_on_border[np.logical_and(
        np.greater(double_blur[corner_x, corner_y],
                   min_intensity),  # Add top limit
        np.less(double_blur[corner_x, corner_y],
                max_intensity)  # Add bottom limit
    )]
    corner_x = np.int0(corners_clipped_on_intensity[:, 1])
    corner_y = np.int0(corners_clipped_on_intensity[:, 0])

    if np.ndim(corner_x) == 0:
        number_of_corners = 1
        corners = np.array([[corner_x, corner_y]])
    else:
        corners = np.stack((corner_x, corner_y), axis=1)
        number_of_corners = len(corners)

    # print "Number of corners:", number_of_corners

    if number_of_corners == 0 or number_of_corners > 4:
        print("Invalid number of corners")
        return None, None

    ######################
    # Define the corners #

    if number_of_corners == 1:
        corner_0 = corners[0]

    if number_of_corners == 2:
        left_corner_id = np.argmin(corner_y)
        right_corner_id = 1 - left_corner_id

        corner_0 = corners[left_corner_id]
        corner_1 = corners[right_corner_id]

    if number_of_corners == 3:
        distances = np.array([
            np.linalg.norm(corners[0] - corners[1]),
            np.linalg.norm(corners[1] - corners[2]),
            np.linalg.norm(corners[2] - corners[0])
        ])

        min_dist_id = np.argmin(distances)

        if min_dist_id == 0:
            relevant_corners = np.stack((corners[0], corners[1]), axis=0)
        elif min_dist_id == 1:
            relevant_corners = np.stack((corners[1], corners[2]), axis=0)
        elif min_dist_id == 2:
            relevant_corners = np.stack((corners[2], corners[0]), axis=0)
        else:
            print(
                "ERROR: In fn. detect_sub_pixecl_corners(); min_dist_id out of bounds"
            )
            return None, None

        dist_0_1, dist_1_2, dist_2_0 = distances[0], distances[1], distances[2]

        # Pick the corner with the lowest y-coordinate
        left_corner_id = np.argmin(relevant_corners, axis=0)[1]
        right_corner_id = 1 - left_corner_id

        corner_0 = relevant_corners[left_corner_id]
        corner_1 = relevant_corners[right_corner_id]

    if number_of_corners == 4:
        # For the first corner, chose the corner closest to the top
        # This will belong to the top cross-bar
        top_corner_id = np.argmin(corner_x)
        top_corner = corners[top_corner_id]
        top_corner_stack = np.array([top_corner] * 3)
        rest_corners = np.delete(corners, top_corner_id, 0)
        dist = np.linalg.norm(rest_corners - top_corner_stack, axis=1)

        # For the second corner, chose the corner closest to top corner
        top_corner_closest_id = np.argmin(dist)
        top_corner_closest = rest_corners[top_corner_closest_id]

        relevant_corners = np.stack((top_corner, top_corner_closest), axis=0)

        # Choose the corner with the lowest y-coordinate as the first corner
        left_corner_id = np.argmin(relevant_corners, axis=0)[1]
        right_corner_id = 1 - left_corner_id

        corner_0 = relevant_corners[left_corner_id]
        corner_1 = relevant_corners[right_corner_id]

    ##################################
    # Define mid point and direction #'
    mid_point = None
    dir_vector = None

    # Calculate spatial gradient
    dy, dx = cv2.spatialGradient(
        blur)  # Invert axis, since OpenCV operates with x=column, y=row

    if number_of_corners == 1:
        grad_0 = np.array(
            [dx[corner_0[0]][corner_0[1]], dy[corner_0[0]][corner_0[1]]])
        grad_0_normalized = normalize_vector(grad_0)

        mid_point_offset = 5  # px-distance
        mid_point = np.int0(corner_0 + grad_0_normalized * mid_point_offset)

        dir_vector = grad_0_normalized

    else:
        grad_0 = np.array(
            [dx[corner_0[0]][corner_0[1]], dy[corner_0[0]][corner_0[1]]])
        grad_1 = np.array(
            [dx[corner_1[0]][corner_1[1]], dy[corner_1[0]][corner_1[1]]])
        grad_sum = grad_0 + grad_1
        grad_sum_normalized = normalize_vector(grad_sum)

        cross_over_vector = corner_1 - corner_0
        mid_point = np.int0(corner_0 + 0.5 * (cross_over_vector))
        mid_value = double_blur[mid_point[0]][mid_point[1]]

    if number_of_corners == 2 and mid_value < 200:
        print "The two corners form the longitudinal bar"
        # Choose to focus on the left point

        v_long = corner_0 - corner_1
        v_long_norm = normalize_vector(v_long)

        grad_0_normalized = normalize_vector(grad_0)

        if grad_0_normalized[0] < 0:
            long_bar_norm = np.array(
                [-cross_over_vector[1], cross_over_vector[0]])
        else:
            long_bar_norm = np.array(
                [cross_over_vector[1], -cross_over_vector[0]])
        long_bar_norm_normalized = normalize_vector(long_bar_norm)

        dist_to_top_edge = corner_0[0]
        dist_to_bottom_edge = IMG_HEIGHT - corner_0[0]
        dist_to_nearest_edge = min(dist_to_top_edge, dist_to_bottom_edge)
        mid_point_offset = dist_to_nearest_edge / 2  # px-distance
        mid_point = np.int0(corner_0 +
                            long_bar_norm_normalized * mid_point_offset)

        dir_vector = v_long_norm

    elif number_of_corners != 1:
        if grad_sum_normalized[0] < 0:
            cross_over_norm = np.array(
                [-cross_over_vector[1], cross_over_vector[0]])
        else:
            cross_over_norm = np.array(
                [cross_over_vector[1], -cross_over_vector[0]])

        dir_vector = normalize_vector(cross_over_norm)

    ###################
    # Draw the result #

    direction_length = 20
    direction_point = np.int0(mid_point + dir_vector * direction_length)

    # img_grad = hsv_origin.copy()
    # img_grad = cv2.arrowedLine(img_grad, (mid_point[1], mid_point[0]),
    #     (direction_point[1], direction_point[0]),
    #     color = (255,0,0), thickness = 2, tipLength = 0.5)

    # hsv_save_image(img_grad, "5_gradient")
    # hsv_save_image(img_grad, str(img_id) +"_gradient")

    return mid_point, corners
 while cv2.waitKey(1) != ord('q'):
     cv2.imshow("Original", img)
     cv2.imshow("New", g)
     cv2.imshow("Gx", gx)
     cv2.imshow("Gy", gy)

cv2.destroyAllWindows()


#%%

# First derivative operators - Sobel masks - Part II

 img = cv2.imread("img/lena.png", cv2.IMREAD_GRAYSCALE)

 gx, gy = cv2.spatialGradient(img, ksize=3, borderType=cv2.BORDER_DEFAULT)
 g = np.abs(gx) + np.abs(gy)

 gx = scaleImage2_uchar(gx)
 gy = scaleImage2_uchar(gy)
 g = scaleImage2_uchar(g)

 while cv2.waitKey(1) != ord('q'):
     cv2.imshow("Original", img)
     cv2.imshow("New", g)
     cv2.imshow("Gx", gx)
     cv2.imshow("Gy", gy)


cv2.destroyAllWindows()
Beispiel #11
0
def task2(img, name=None):
    if img is not None:
        # Convert the image to greyscale
        grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # Get the sobel gradient on both the X and Y directions, and sum them together
        sobX, sobY = cv2.spatialGradient(grey, None, None, 3)
        sob = np.square(sobX) + np.square(sobY)
        # Sum down each of the columns (axis=0)
        col_sum = np.sum(sob, axis=0)
        col_sum = col_sum / col_sum.max()  # Normalise between 0 and 1.0

        # Get the Lower and Upper X coordinates where an approximation of the sign lies
        minX, maxX = thresh_sweep(col_sum, 0.001, 0.22)

        # Extract a working area that is a little wider than the sign's best match area, ensuring valid bounds
        roi = grey[:,
                   max(0, int(minX * 0.9)):min(grey.shape[1], int(maxX * 1.1))]
        roi_rgb = img[:,
                      max(0, int(minX * 0.9)):min(grey.shape[1], int(maxX *
                                                                     1.1))]

        # Adaptive threshold the macro ROI and then apply contouring
        roi_thresh = cv2.adaptiveThreshold(roi, 255,
                                           cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                           cv2.THRESH_BINARY, 25, 1)
        _, contours, heir = cv2.findContours(roi_thresh, cv2.RETR_TREE,
                                             cv2.CHAIN_APPROX_SIMPLE)

        # First pass classification to find the ARROWS on the sign only. This step is to align the sign
        digit_regions = list()
        for cont in contours:
            # Return the (x,y) and width and height of a bounding rectangle for this contour
            x, y, w, h = cv2.boundingRect(cont)
            # Only consider regions that are the correct shape and aspect initially.
            if 40 < w * h < 5000 and 0.6 * w < h < 1.4 * w:
                # Get the underlying greyscale region for this bounding box for classification
                possible_digit = roi[y:y + h, x:x + w]
                classify, errors = cl.classify(possible_digit)
                # If the confidence of this digit is below the threshold and it is a Left arrow (10) or right arrow (11)
                if np.sum(errors) < 3.0 * cl.FEATURES and (
                        int(classify) == 10 or int(classify) == 11):
                    #cv2.rectangle(roi_rgb, (x, y), (x+w, y+h), (0, 255, 255), thickness=2)
                    # Calculate the full region with digits and arrow from the size of the arrow
                    rx = max(0, x - int(3.9 * w))
                    ry = max(0, y - int(0.6 * h))
                    rw = int(4.9 * w)
                    rh = int(2.2 * h)
                    # Create a Digit Region and populate the data
                    dr = DigitRegion(rx, ry, rw, rh, x, y, w, h, int(classify))
                    digit_regions.append(dr)
                    #cv2.rectangle(roi_rgb, (rx, ry), (rx + rw, ry + rh), (0, 255, 0), thickness=1)
                #else:
                #cv2.rectangle(roi_rgb, (x, y), (x+w, y+h), (255, 0, 0), thickness=1)

        # Sort the list by the Y Coordinate
        digit_regions.sort(key=lambda dr: dr.ry)

        # Crop the sign down to only include the arrows and numbers
        region_output, cropped = crop_sign(roi_rgb, roi, digit_regions)

        # Upscale the image by 2 times and adaptive threshold it.
        cropped = cv2.resize(cropped,
                             (cropped.shape[1] * 2, cropped.shape[0] * 2),
                             cv2.INTER_LINEAR)
        up_thresh = cv2.adaptiveThreshold(cropped, 255,
                                          cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                          cv2.THRESH_BINARY, 21, 1)
        # Contour the upscaled threshold image
        _, contours, heir = cv2.findContours(up_thresh, cv2.RETR_TREE,
                                             cv2.CHAIN_APPROX_SIMPLE)

        # 3 channel greyscale for drawing coloured rectangles on
        warped_rgb = cv2.cvtColor(cropped, cv2.COLOR_GRAY2BGR)

        # Make a new list to store the new warped regions
        digit_regions = list()
        # Find the digit regions based on the location and size of the arrows
        for cont in contours:
            x, y, w, h = cv2.boundingRect(cont)
            # If the region area is within the threshold and that the width height ratio is acceptable.
            if (np.power(cropped.shape[1],
                         2)) // 40 < w * h < 5000 and 0.8 * w < h < 1.2 * w:
                possible_digit = cropped[y:y + h, x:x + w]
                classify, errors = cl.classify(possible_digit)
                # See if the digit is classified as an arrow and is sufficiently low in error. 10 = left, 11 = right
                if np.sum(errors) < 3.0 * cl.FEATURES and (
                        int(classify) == 10 or int(classify) == 11):
                    cv2.rectangle(warped_rgb, (x, y), (x + w, y + h),
                                  (0, 255, 255),
                                  thickness=2)
                    rx = 0  # Use the full sign width
                    ry = max(0, y - int(.5 * h))
                    rw = cropped.shape[1]  # Using the full sign width
                    rh = int(2.0 * h)
                    # Make it a DigitRegion and add it to the list
                    dr = DigitRegion(rx, ry, rw, rh, x, y, w, h, classify)
                    digit_regions.append(dr)
                    cv2.rectangle(warped_rgb, (rx, ry), (rx + rw, ry + rh),
                                  (0, 255, 0),
                                  thickness=1)
                else:
                    cv2.rectangle(warped_rgb, (x, y), (x + w, y + h),
                                  (255, 0, 0),
                                  thickness=1)

        # Order the List by ascending region Y coordinate
        digit_regions.sort(key=lambda dr: dr.ry)

        # Allocate a list to store the text on the sign, eg "113R"
        numbers_on_sign = list()

        # For each of the regions, sweep in from teh left hand side, checking which gives the best classification,
        #  which indicates the true edge of the sign has been found.
        for dr in digit_regions:
            digits = cropped[dr.ry:dr.ry + dr.rh, dr.rx:rx + dr.rw]
            digits = cv2.threshold(digits, 120, 255, cv2.THRESH_OTSU)[1]

            width = int(dr.w * 1.2)
            # Noise reduction matches. Find the best image classification from left hand side inward
            bests = list()
            for sweep in range(0, width // 2):
                part = digits[:, sweep:width]
                part = crop_height(part)
                #cv2.imshow('part', part)
                classify, errors = cl.classify(part)
                bests.append([classify, np.sum(errors * errors), sweep])

            # sort the best matches by their lowest distance classification
            bests.sort(key=lambda x: x[1])

            # get the coordinate of the best digit, and crop the digit region
            digits = digits[:, int(bests[0][2]):]

            # first try left to right full height classification
            num1, num2, num3, num4 = classify_digits(digits)

            # Multiple attempts if for some reason the numebrs returned were illogical. E.g. an arrow where a digit is
            if not validate_classify(num1, num2, num3, num4):
                # Try only the top 70% of the digits image, all digits still form blocks here
                num1, num2, num3, num4 = classify_digits(
                    digits[:int(digits.shape[0] * 0.70), :], digits)

            #if not validate_classify(num1, num2, num3, num4):
            # Try the full image in back to front order
            #num1, num2, num3, num4 = classify_digits(digits, reverse=True)

            #if not validate_classify(num1, num2, num3, num4):
            #num1, num2, num3, num4 = classify_digits(digits[:int(digits.shape[0] * 0.70), :], digits, reverse=True)

            # Save the output string of numbers
            output = str(num1) + str(num2) + str(num3)

            dir = num4
            # If the direction is Left
            if dir == 10:
                output += "L"
            elif dir == 11:  # if it is right
                output += "R"

            # Add the numbers to the list of directions on this sign
            numbers_on_sign.append(output)

        # return the numbers on the sign as a list and as a region
        return np.array(numbers_on_sign), region_output
    else:
        # Not a valid image, return error
        return "????", np.zeros((1, 1))
Beispiel #12
0
def gradient(plane, k=3):
    gx, gy = cv2.spatialGradient(plane, k, k)
    return np.concatenate([gx[..., None], gy[..., None]], axis=2).astype(
        np.float32) / 255.0
Beispiel #13
0
def find_goal_point(hsv_white_only, inner_corners):
    number_of_corners = len(inner_corners)
    average_filter_size = 19
    img_average_intensity = make_circle_average_blurry(hsv_white_only,
                                                       average_filter_size)

    ######################
    # Define the inner_corners #

    if number_of_corners == 1:
        corner_0 = inner_corners[0]

    elif number_of_corners == 2:
        left_corner_id = np.argmin(inner_corners[:, 1])
        right_corner_id = 1 - left_corner_id

        corner_0 = inner_corners[left_corner_id]
        corner_1 = inner_corners[right_corner_id]

    elif number_of_corners == 3:
        distances = np.array([
            np.linalg.norm(inner_corners[0] - inner_corners[1]),
            np.linalg.norm(inner_corners[1] - inner_corners[2]),
            np.linalg.norm(inner_corners[2] - inner_corners[0])
        ])

        median = np.median(distances)
        median_id = np.where(distances == median)[0][0]
        print "median:", median
        print "median_id:", median_id

        if median_id == 0:
            relevant_corners = np.stack((inner_corners[0], inner_corners[1]),
                                        axis=0)
        elif median_id == 1:
            relevant_corners = np.stack((inner_corners[1], inner_corners[2]),
                                        axis=0)
        elif median_id == 2:
            relevant_corners = np.stack((inner_corners[2], inner_corners[0]),
                                        axis=0)
        else:
            print(
                "ERROR: In fn. detect_sub_pixecl_corners(); min_dist_id out of bounds"
            )
            return None, None

        dist_0_1, dist_1_2, dist_2_0 = distances[0], distances[1], distances[2]

        # Pick the corner with the lowest y-coordinate
        left_corner_id = np.argmin(relevant_corners, axis=0)[1]
        right_corner_id = 1 - left_corner_id

        corner_0 = relevant_corners[left_corner_id]
        corner_1 = relevant_corners[right_corner_id]

    elif number_of_corners == 4:
        # For the first corner, chose the corner closest to the top
        # This will belong to the top cross-bar
        top_corner_id = np.argmin(inner_corners[:, 0])  # Find lowest x-index
        top_corner = inner_corners[top_corner_id]
        top_corner_stack = np.array([top_corner] * 3)
        rest_corners = np.delete(inner_corners, top_corner_id, 0)
        dist = np.linalg.norm(rest_corners - top_corner_stack, axis=1)

        # For the second corner, chose the corner closest to top corner
        top_corner_closest_id = np.argmin(dist)
        top_corner_closest = rest_corners[top_corner_closest_id]

        relevant_corners = np.stack((top_corner, top_corner_closest), axis=0)

        # Choose the corner with the lowest y-coordinate as the first corner
        left_corner_id = np.argmin(relevant_corners, axis=0)[1]
        right_corner_id = 1 - left_corner_id

        corner_0 = relevant_corners[left_corner_id]
        corner_1 = relevant_corners[right_corner_id]

    else:
        print("Invalid number of corners")
        return None, None

    ##################################
    # Define goal point and direction #'
    goal_point = None
    goal_direction = None

    # Calculate spatial gradient
    dy, dx = cv2.spatialGradient(
        hsv_white_only
    )  # Invert axis, since OpenCV operates with x=column, y=row

    if number_of_corners == 1:
        grad_0 = np.array(
            [dx[corner_0[0]][corner_0[1]], dy[corner_0[0]][corner_0[1]]])
        grad_0_normalized = normalize_vector(grad_0)

        goal_point_offset = 5  # px-distance
        goal_point = np.int0(corner_0 + grad_0_normalized * goal_point_offset)

        goal_direction = grad_0_normalized
    else:
        grad_0 = np.array(
            [dx[corner_0[0]][corner_0[1]], dy[corner_0[0]][corner_0[1]]])
        grad_1 = np.array(
            [dx[corner_1[0]][corner_1[1]], dy[corner_1[0]][corner_1[1]]])
        grad_sum = grad_0 + grad_1
        grad_sum_normalized = normalize_vector(grad_sum)

        cross_over_vector = corner_1 - corner_0
        goal_point = np.int0(corner_0 + 0.5 * (cross_over_vector))
        goal_value = img_average_intensity[goal_point[0]][goal_point[1]]

    if (number_of_corners == 2 or number_of_corners == 3) and goal_value < 200:
        print "The two inner_corners form the longitudinal bar"
        # wp
        # Choose to focus on the uppermost corner,
        # since it is assumed the orientation is approximately right
        longitudinal_corners = np.stack((corner_0, corner_1))

        upper_corner_id = np.argmin(longitudinal_corners[:, 0])
        lower_corner_id = 1 - upper_corner_id

        upper_corner = longitudinal_corners[upper_corner_id]
        lower_corner = longitudinal_corners[lower_corner_id]

        longitudinal_vector = upper_corner - lower_corner
        longitudinal_unit_vector = normalize_vector(longitudinal_vector)

        upper_corner_gradient = get_gradient_of_point(upper_corner, dx, dy)
        upper_corner_unit_gradient = normalize_vector(upper_corner_gradient)

        longitudinal_length = np.linalg.norm(longitudinal_vector)
        travese_length = longitudinal_length * REL_TRAV_LONG
        length_from_upper_corner_to_goal = travese_length / 2.0

        arrow_length = 10
        grad_start = upper_corner
        grad_end = np.int0(upper_corner +
                           upper_corner_unit_gradient * arrow_length)

        angle = calc_angle_between_vectors(longitudinal_vector,
                                           upper_corner_unit_gradient)
        l_x, l_y = longitudinal_unit_vector[0], longitudinal_unit_vector[1]
        if angle > 0:
            # This means the gradient is pointing to the left
            dir_vector = np.array([-l_y, l_x])
        else:
            # The gradient is pointing to the right (or is parallel)
            dir_vector = np.array([l_y, -l_x])
        goal_point = np.int0(upper_corner +
                             dir_vector * length_from_upper_corner_to_goal)
        goal_point = limit_point_to_be_inside_image(goal_point)

        print "Angle:", np.degrees(angle)

        hsv_drawn_vectors = hsv_white_only.copy()
        hsv_drawn_vectors = draw_arrow(hsv_drawn_vectors, grad_start, grad_end)
        hsv_drawn_vectors = draw_arrow(hsv_drawn_vectors, upper_corner,
                                       goal_point)
        hsv_save_image(hsv_drawn_vectors, "0_drawn_vectors", is_gray=True)

        goal_direction = longitudinal_unit_vector

    elif number_of_corners != 1:
        if grad_sum_normalized[0] < 0:
            cross_over_norm = np.array(
                [-cross_over_vector[1], cross_over_vector[0]])
        else:
            cross_over_norm = np.array(
                [cross_over_vector[1], -cross_over_vector[0]])

        goal_direction = normalize_vector(cross_over_norm)

    ###################
    # Draw the result #

    # direction_length = 20
    # direction_point = np.int0(goal_point + dir_vector*direction_length)

    # img_grad = hsv_origin.copy()
    # img_grad = cv2.arrowedLine(img_grad, (goal_point[1], goal_point[0]),
    #     (direction_point[1], direction_point[0]),
    #     color = (255,0,0), thickness = 2, tipLength = 0.5)

    # hsv_save_image(img_grad, "5_gradient")
    # hsv_save_image(img_grad, str(img_id) +"_gradient")

    return goal_point, goal_direction