예제 #1
0
def test_farid_h_horizontal():
    """Horizontal Farid on an edge should be a horizontal line."""
    i, j = np.mgrid[-5:6, -5:6]
    image = (i >= 0).astype(float)
    result = filters.farid_h(image)
    # Check if result match transform direction
    assert np.all(result[i == 0] == result[i == 0][0])
    assert_allclose(result[np.abs(i) > 2], 0, atol=1e-10)
예제 #2
0
def test_farid_h_horizontal():
    """Horizontal Farid on an edge should be a horizontal line."""
    i, j = np.mgrid[-5:6, -5:6]
    image = (i >= 0).astype(float)
    result = filters.farid_h(image)
    # Fudge the eroded points
    i[np.abs(j) == 5] = 10000
    assert np.all(result[i == 0] == result[i == 0][0])
    assert_allclose(result[np.abs(i) > 2], 0, atol=1e-10)
예제 #3
0
def test_farid_h_vertical():
    """Horizontal Farid on a vertical edge should be zero."""
    i, j = np.mgrid[-5:6, -5:6]
    image = (j >= 0).astype(float) * np.sqrt(2)
    result = filters.farid_h(image)
    assert_allclose(result, 0, atol=1e-10)
예제 #4
0
def test_farid_h_mask():
    """Horizontal Farid on a masked array should be zero."""
    result = filters.farid_h(np.random.uniform(size=(10, 10)),
                             np.zeros((10, 10), dtype=bool))
    assert (np.all(result == 0))
예제 #5
0
def test_farid_h_zeros():
    """Horizontal Farid on an array of all zeros."""
    result = filters.farid_h(np.zeros((10, 10)), np.ones((10, 10), dtype=bool))
    assert (np.all(result == 0))
예제 #6
0
# #Farid_and_Simoncelli_Derivatives

x, y = np.mgrid[-10:10:255j, -10:10:255j]
img = np.sin(x**2 + y**2)

imgx = 2 * x * np.cos(x**2 + y**2)
imgy = 2 * y * np.cos(x**2 + y**2)


def angle(dx, dy):
    return np.mod(np.arctan2(dy, dx), np.pi)


true_angle = angle(imgx, imgy)

angle_farid = angle(farid_h(img), farid_v(img))
angle_sobel = angle(sobel_h(img), sobel_v(img))
angle_scharr = angle(scharr_h(img), scharr_v(img))
angle_prewitt = angle(prewitt_h(img), prewitt_v(img))


def diff_angle(angle_1, angle_2):
    return np.minimum(np.pi - np.abs(angle_1 - angle_2),
                      np.abs(angle_1 - angle_2))


diff_farid = diff_angle(true_angle, angle_farid)
diff_sobel = diff_angle(true_angle, angle_sobel)
diff_scharr = diff_angle(true_angle, angle_scharr)
diff_prewitt = diff_angle(true_angle, angle_prewitt)
예제 #7
0
x, y = np.mgrid[-10:10:255j, -10:10:255j]
image_rotinv = np.sin(x**2 + y**2)

image_x = 2 * x * np.cos(x**2 + y**2)
image_y = 2 * y * np.cos(x**2 + y**2)


def angle(dx, dy):
    """Calculate the angles between horizontal and vertical operators."""
    return np.mod(np.arctan2(dy, dx), np.pi)


true_angle = angle(image_x, image_y)

angle_farid = angle(filters.farid_h(image_rotinv),
                    filters.farid_v(image_rotinv))
angle_sobel = angle(filters.sobel_h(image_rotinv),
                    filters.sobel_v(image_rotinv))
angle_scharr = angle(filters.scharr_h(image_rotinv),
                     filters.scharr_v(image_rotinv))
angle_prewitt = angle(filters.prewitt_h(image_rotinv),
                      filters.prewitt_v(image_rotinv))


def diff_angle(angle_1, angle_2):
    """Calculate the differences between two angles."""
    return np.minimum(np.pi - np.abs(angle_1 - angle_2),
                      np.abs(angle_1 - angle_2))

예제 #8
0
    def main(
            image_path,
            filename,
            paper_size: str = '11x17 inches',
            border: float = 20,  # mm
            image_rescale_factor: float = 0.25,
            smooth_disk_size: int = 2,
            hist_clip_limit=0.1,
            hist_nbins=32,
            intensity_min=0.,
            intensity_max=1.,
            hatch_spacing_min=0.3,  # mm
            hatch_spacing_max=1.,  # mm
            pixel_width=0.9,  # mm
            pixel_height=0.9,  # mm
            angle_jitter='0',  # degrees
            pixel_rotation='0',  # degrees
            merge_tolerances=[0.3, 0.4, 0.5],  # mm
            simplify_tolerances=[0.2],  # mm
            savedir='/mnt/c/code/side/plotter_images/oned_outputs'):

        # make page
        paper = Paper(paper_size)
        drawbox = paper.get_drawbox(border)

        # load
        img = rgb2gray(io.imread(Path(image_path)))
        img_rescale = rescale(img, image_rescale_factor)

        #
        img_renorm = exposure.equalize_adapthist(img_rescale,
                                                 clip_limit=hist_clip_limit,
                                                 nbins=hist_nbins)

        # calc dominant angle
        selem = disk(smooth_disk_size)
        filt_img = filters.rank.mean(img_renorm, selem)
        angle_farid = local_angle(filters.farid_h(filt_img),
                                  filters.farid_v(filt_img))

        # make pixel polys
        prms = []
        for y, row in tqdm(enumerate(img_renorm)):
            for x, intensity in enumerate(row):

                p = gp.centered_box(Point(x, y),
                                    width=pixel_width,
                                    height=pixel_height)
                a = np.degrees(angle_farid[y, x])
                prm = {
                    'geometry': p,
                    'x': x,
                    'y': y,
                    'raw_pixel_width': pixel_width,
                    'raw_pixel_height': pixel_height,
                    'intensity': intensity,
                    'angle': a,
                    'group': 'raw_hatch_pixel',
                }
                prms.append(prm)
        raw_hatch_pixels = geopandas.GeoDataFrame(prms)

        #  rescale polys to fit in drawbox
        bbox = box(*raw_hatch_pixels.total_bounds)
        _, transform = gp.make_like(bbox, drawbox, return_transform=True)
        A = gp.AffineMatrix(**transform)
        scaled_hatch_pixels = raw_hatch_pixels.copy()
        scaled_hatch_pixels['geometry'] = scaled_hatch_pixels.affine_transform(
            A.A_flat)
        scaled_hatch_pixels['scaled_pixel_height'] = scaled_hatch_pixels[
            'geometry'].apply(gp.get_height)
        scaled_hatch_pixels['scaled_pixel_width'] = scaled_hatch_pixels[
            'geometry'].apply(gp.get_width)

        # distributions etc
        angle_jitter_gen = gp.make_callable(eval(angle_jitter))
        pixel_rotation_gen = gp.make_callable(eval(pixel_rotation))

        scaled_hatch_pixels['angle_jitter'] = angle_jitter_gen(
            len(scaled_hatch_pixels))
        scaled_hatch_pixels['hatch_angle'] = scaled_hatch_pixels[
            'angle'] + scaled_hatch_pixels['angle_jitter']
        scaled_hatch_pixels['pixel_rotation'] = pixel_rotation_gen(
            len(scaled_hatch_pixels))

        example_height = scaled_hatch_pixels.loc[0, 'scaled_pixel_height']
        example_width = scaled_hatch_pixels.loc[0, 'scaled_pixel_width']
        print(f'pixel size = {example_width:.2}x{example_height:.2}mm')

        spacing_func = functools.partial(np.interp,
                                         xp=[intensity_min, intensity_max],
                                         fp=[
                                             hatch_spacing_max,
                                             hatch_spacing_min,
                                         ])
        scaled_hatch_pixels['spacing'] = spacing_func(
            1 - scaled_hatch_pixels['intensity'])
        new_rows = []
        for i, row in tqdm(scaled_hatch_pixels.iterrows(),
                           total=len(scaled_hatch_pixels)):
            r = row.copy()

            p = r['geometry']
            if abs(r['pixel_rotation']) > np.finfo(float).eps:
                p = sa.rotate(p, r['pixel_rotation'])
            f = gp.hatchbox(p, spacing=r['spacing'], angle=r['hatch_angle'])
            r['geometry'] = f
            new_rows.append(r)

        fills = geopandas.GeoDataFrame(new_rows)
        fills = fills[fills.length > 0]
        fill_layer = gp.merge_LineStrings(fills.geometry)

        sk = vsketch.Vsketch()
        sk.size(paper.page_format_mm)
        sk.scale('1mm')
        sk.stroke(1)
        sk.geometry(fill_layer)

        sk.vpype('linesort')

        for tolerance in merge_tolerances:
            sk.vpype(f'linemerge --tolerance {tolerance}mm')

        for tolerance in simplify_tolerances:
            sk.vpype(f'linesimplify --tolerance {tolerance}mm')

        sk.vpype('linesort')

        savepath = Path(savedir).joinpath(filename).as_posix()
        sk.save(savepath)