Exemplo n.º 1
0
def sobel_filter(image):
    kernel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    kernel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])

    dst_x = img_convolve(image, kernel_x)
    dst_y = img_convolve(image, kernel_y)
    dst = np.sqrt((np.square(dst_x)) + (np.square(dst_y))).astype(np.uint8)
    degree = np.arctan2(dst_y, dst_x)
    return dst, degree
Exemplo n.º 2
0
def sobel_filter(image):
    kernel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    kernel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])

    dst_x = np.abs(img_convolve(image, kernel_x))
    dst_y = np.abs(img_convolve(image, kernel_y))
    # modify the pix within [0, 255]
    dst_x = dst_x * 255 / np.max(dst_x)
    dst_y = dst_y * 255 / np.max(dst_y)

    dst_xy = np.sqrt((np.square(dst_x)) + (np.square(dst_y)))
    dst_xy = dst_xy * 255 / np.max(dst_xy)
    dst = dst_xy.astype(np.uint8)

    theta = np.arctan2(dst_y, dst_x)
    return dst, theta
Exemplo n.º 3
0
def canny(image, threshold_low=15, threshold_high=30, weak=128, strong=255):
    image_row, image_col = image.shape[0], image.shape[1]
    # gaussian_filter
    gaussian_out = img_convolve(image, gen_gaussian_kernel(9, sigma=1.4))
    # get the gradient and degree by sobel_filter
    sobel_grad, sobel_theta = sobel_filter(gaussian_out)
    gradient_direction = np.rad2deg(sobel_theta)
    gradient_direction += PI

    dst = np.zeros((image_row, image_col))

    """
    Non-maximum suppression. If the edge strength of the current pixel is the largest
    compared to the other pixels in the mask with the same direction, the value will be
    preserved. Otherwise, the value will be suppressed.
    """
    for row in range(1, image_row - 1):
        for col in range(1, image_col - 1):
            direction = gradient_direction[row, col]

            if (
                0 <= direction < 22.5
                or 15 * PI / 8 <= direction <= 2 * PI
                or 7 * PI / 8 <= direction <= 9 * PI / 8
            ):
                W = sobel_grad[row, col - 1]
                E = sobel_grad[row, col + 1]
                if sobel_grad[row, col] >= W and sobel_grad[row, col] >= E:
                    dst[row, col] = sobel_grad[row, col]

            elif (PI / 8 <= direction < 3 * PI / 8) or (
                9 * PI / 8 <= direction < 11 * PI / 8
            ):
                SW = sobel_grad[row + 1, col - 1]
                NE = sobel_grad[row - 1, col + 1]
                if sobel_grad[row, col] >= SW and sobel_grad[row, col] >= NE:
                    dst[row, col] = sobel_grad[row, col]

            elif (3 * PI / 8 <= direction < 5 * PI / 8) or (
                11 * PI / 8 <= direction < 13 * PI / 8
            ):
                N = sobel_grad[row - 1, col]
                S = sobel_grad[row + 1, col]
                if sobel_grad[row, col] >= N and sobel_grad[row, col] >= S:
                    dst[row, col] = sobel_grad[row, col]

            elif (5 * PI / 8 <= direction < 7 * PI / 8) or (
                13 * PI / 8 <= direction < 15 * PI / 8
            ):
                NW = sobel_grad[row - 1, col - 1]
                SE = sobel_grad[row + 1, col + 1]
                if sobel_grad[row, col] >= NW and sobel_grad[row, col] >= SE:
                    dst[row, col] = sobel_grad[row, col]

            """
            High-Low threshold detection. If an edge pixel’s gradient value is higher
            than the high threshold value, it is marked as a strong edge pixel. If an
            edge pixel’s gradient value is smaller than the high threshold value and
            larger than the low threshold value, it is marked as a weak edge pixel. If
            an edge pixel's value is smaller than the low threshold value, it will be
            suppressed.
            """
            if dst[row, col] >= threshold_high:
                dst[row, col] = strong
            elif dst[row, col] <= threshold_low:
                dst[row, col] = 0
            else:
                dst[row, col] = weak

    """
    Edge tracking. Usually a weak edge pixel caused from true edges will be connected
    to a strong edge pixel while noise responses are unconnected. As long as there is
    one strong edge pixel that is involved in its 8-connected neighborhood, that weak
    edge point can be identified as one that should be preserved.
    """
    for row in range(1, image_row):
        for col in range(1, image_col):
            if dst[row, col] == weak:
                if 255 in (
                    dst[row, col + 1],
                    dst[row, col - 1],
                    dst[row - 1, col],
                    dst[row + 1, col],
                    dst[row - 1, col - 1],
                    dst[row + 1, col - 1],
                    dst[row - 1, col + 1],
                    dst[row + 1, col + 1],
                ):
                    dst[row, col] = strong
                else:
                    dst[row, col] = 0

    return dst
def test_convolve_filter():
    # laplace diagonals
    Laplace = array([[0.25, 0.5, 0.25], [0.5, -3, 0.5], [0.25, 0.5, 0.25]])
    res = conv.img_convolve(gray, Laplace).astype(uint8)
    assert res.any()
Exemplo n.º 5
0
def hog_feature(image, gamma=0.4, cell_size=6, bin_size=18, block_size=4):
    rows, cols = image.shape[0], image.shape[1]
    """
    Gamma normalization, however, the author point out this step can be omitted in HOG descriptor computation.
    """
    norm = (image + 0.5) / 255
    norm = np.power(norm, 1 / gamma)
    img_norm = 255 * norm - 0.5

    # Get gradient and angle, the kernel below perform better than others(3x3 Sobel).
    kernel_x = np.array([[-1, 0, 1]])
    kernel_y = np.array([[-1], [0], [1]])

    dst_x = img_convolve(img_norm, kernel_x)
    dst_y = img_convolve(img_norm, kernel_y)

    dst_xy = np.sqrt((np.square(dst_x)) + (np.square(dst_y)))
    dst_xy = dst_xy * 255 / np.max(dst_xy)
    gradient_magnitude_global = dst_xy

    # Get the angles and convert them in range (0, 360)
    theta = np.arctan2(dst_y, dst_x)
    gradient_angle_global = np.rad2deg(theta)  # range(-180, 180)
    gradient_angle_global = np.where(gradient_angle_global < 0,
                                     gradient_angle_global + 360,
                                     gradient_angle_global)  # range(0, 360)
    """
    Orientation binning, The second step of calculation is creating the cell histograms. Each pixel within the cell 
    casts a weighted vote for an orientation-based histogram channel based on the values found in the gradient 
    computation. In tests, the gradient magnitude itself generally produces the best results.
    """
    angle_unit = 360 / bin_size
    cell_gradient_mtx = np.zeros(
        (rows // cell_size, cols // cell_size, bin_size))
    for i in range(cell_gradient_mtx.shape[0]):
        for j in range(cell_gradient_mtx.shape[1]):
            pixes_grad_per_cell = gradient_magnitude_global[i *
                                                            cell_size:(i + 1) *
                                                            cell_size, j *
                                                            cell_size:(j + 1) *
                                                            cell_size]
            pixes_angle_per_cell = gradient_angle_global[i *
                                                         cell_size:(i + 1) *
                                                         cell_size, j *
                                                         cell_size:(j + 1) *
                                                         cell_size]

            orientation_centers = [0] * bin_size
            for cell_i in range(pixes_grad_per_cell.shape[0]):
                for cell_j in range(pixes_grad_per_cell.shape[1]):
                    gradient_strength = pixes_grad_per_cell[cell_i][cell_j]
                    gradient_angle = pixes_angle_per_cell[cell_i][cell_j]

                    bin_index = int(gradient_angle / angle_unit)
                    if gradient_angle == 360:
                        bin_index = 0
                    orientation_centers[bin_index] += gradient_strength

            cell_gradient_mtx[i][j] = orientation_centers
    """
    Descriptor blocks. Grouping cells into larger spatial blocks and contrast normalizing each 
    block separately. The final descriptor is then the vector of all components of the normalized cell
    responses from all of the blocks in the detection window.
    """
    hog_descriptor_mtx = []
    out_rows, out_cols = cell_gradient_mtx.shape[
        1] - block_size + 1, cell_gradient_mtx.shape[0] - block_size + 1
    for i in range(0, out_rows):
        for j in range(0, out_cols):
            block_vector = np.ravel(cell_gradient_mtx[i:i + block_size,
                                                      j:j + block_size, :])

            # Block L2 normalization
            eps = 1e-5
            block_vector = block_vector / np.sqrt(
                np.sum(block_vector**2) + eps**2)
            hog_descriptor_mtx.append(block_vector)

    # showing hog
    hog_dst_image = np.zeros([rows, cols])
    cell_gradient = cell_gradient_mtx
    cell_width = cell_size // 2
    max_mag = np.array(cell_gradient).max()
    for x in range(cell_gradient.shape[0]):
        for y in range(cell_gradient.shape[1]):
            cell_grad = cell_gradient[x][y]
            cell_grad /= max_mag
            angle = 0
            angle_gap = angle_unit
            for magnitude in cell_grad:
                angle_radian = math.radians(angle)
                x1 = int(x * cell_size +
                         magnitude * cell_width * math.cos(angle_radian))
                y1 = int(y * cell_size +
                         magnitude * cell_width * math.sin(angle_radian))
                x2 = int(x * cell_size -
                         magnitude * cell_width * math.cos(angle_radian))
                y2 = int(y * cell_size -
                         magnitude * cell_width * math.sin(angle_radian))

                strength = int(255 * math.sqrt(magnitude))
                cv2.line(hog_dst_image, (y1, x1), (y2, x2), strength)

                angle += angle_gap

    return hog_descriptor_mtx, hog_dst_image