コード例 #1
0
    def test_fft(self):
        data = gpu_util.get_array(np.random.normal(100, 100,
                                                   size=(4, 4)).astype(cfg.PRECISION.np_float))
        orig = gpu_util.get_host(data)
        data = ip.fft_2(data)
        ip.ifft_2(data)
        np.testing.assert_almost_equal(orig, data.get().real, decimal=4)

        # With a plan
        from pyfft.cl import Plan
        plan = Plan((4, 4), queue=cfg.OPENCL.queue)
        data = ip.fft_2(np.copy(orig), plan=plan)
        ip.ifft_2(data, plan=plan)
        np.testing.assert_almost_equal(orig, data.get().real, decimal=4)

        # Test double precision
        syris.init(double_precision=True, device_index=0)
        data = gpu_util.get_array(np.random.normal(100, 100,
                                                   size=(4, 4)).astype(cfg.PRECISION.np_float))
        gt = np.fft.fft2(data.get())
        data = ip.fft_2(data)
        np.testing.assert_almost_equal(gt, data.get(), decimal=4)

        gt = np.fft.ifft2(data.get())
        data = ip.ifft_2(data)
        np.testing.assert_almost_equal(gt, data.get(), decimal=4)
コード例 #2
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def pad(image, region=None, out=None, value=0, queue=None, block=False):
    """Pad a 2D *image*. *region* is the region to pad as (y_0, x_0, height, width). If not
    specified, the next power of two dimensions are used and the image is centered in the padded
    one. The final image dimensions are height x width and the filling starts at (y_0, x_0), *out*
    is the pyopencl Array instance, if not specified it will be created. *out* is also returned.
    *value* is the padded value. If *block* is True, wait for the copy to finish.
    """
    if region is None:
        shape = tuple([next_power_of_two(n) for n in image.shape])
        y_0 = (shape[0] - image.shape[0]) / 2
        x_0 = (shape[1] - image.shape[1]) / 2
        region = (y_0, x_0) + shape
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl_array.zeros(queue, (region[2], region[3]), dtype=image.dtype) + value
    image = g_util.get_array(image, queue=queue)

    n_bytes = image.dtype.itemsize
    y_0, x_0, height, width = region
    src_origin = (0, 0, 0)
    dst_origin = (n_bytes * x_0, y_0, 0)
    region = (n_bytes * image.shape[1], image.shape[0], 1)
    LOG.debug('pad, shape: %s, src_origin: %s, dst_origin: %s, region: %s', image.shape,
              src_origin, dst_origin, region)

    _copy_rect(image, out, src_origin, dst_origin, region, queue, block=block)

    return out
コード例 #3
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def crop(image, region, out=None, queue=None, block=False):
    """Crop a 2D *image*. *region* is the region to crop as (y_0, x_0, height, width), *out* is the
    pyopencl Array instance, if not specified it will be created. *out* is also returned. If *block*
    is True, wait for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl.array.Array(queue, (region[2], region[3]), dtype=image.dtype)
    image = g_util.get_array(image, queue=queue)

    n_bytes = image.dtype.itemsize
    y_0, x_0, height, width = region
    src_origin = (n_bytes * x_0, y_0, 0)
    dst_origin = (0, 0, 0)
    region = (n_bytes * width, height, 1)
    LOG.debug(
        "crop, shape: %s, src_origin: %s, dst_origin: %s, region: %s",
        image.shape,
        src_origin,
        dst_origin,
        region,
    )

    _copy_rect(image, out, src_origin, dst_origin, region, queue, block=block)

    return out
コード例 #4
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def decimate(image, shape, sigma=None, average=False, queue=None, block=False):
    """Decimate *image* so that its dimensions match the final *shape*, which has to be a divisor of
    the original shape. Remove low frequencies by a Gaussian filter with *sigma* pixels. If *sigma*
    is None, use the FWHM of one low resolution pixel. Use command *queue*, if *block* is True, wait
    for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    image = g_util.get_array(image, queue=queue)
    shape = make_tuple(shape)
    pow_shape = tuple([next_power_of_two(n) for n in image.shape])
    orig_shape = image.shape
    if image.shape != pow_shape:
        image = pad(image, region=(0, 0) + pow_shape, queue=queue)
    if sigma is None:
        sigma = tuple([fwnm_to_sigma(float(image.shape[i]) / shape[i], n=2) for i in range(2)])

    LOG.debug('decimate, shape: %s, final_shape: %s, sigma: %s, average: %s', image.shape, shape,
              sigma, average)

    fltr = get_gauss_2d(image.shape, sigma, fourier=True, queue=queue, block=block)
    image = image.astype(cfg.PRECISION.np_cplx)
    fft_2(image, queue=queue, block=block)
    image *= fltr
    ifft_2(image, queue=queue, block=block)
    image = crop(image.real, (0, 0) + orig_shape, queue=queue, block=block)

    return bin_image(image, shape, average=average, queue=queue, block=block)
コード例 #5
0
ファイル: imageprocessing.py プロジェクト: flmiot/syris-1
def bin_image(image, summed_shape, offset=(0, 0), average=False, out=None, queue=None,
              block=False):
    """Bin an *image*. The resulting buffer has shape *summed_shape* (y, x). *Offset* (y, x) is the
    offset to the original *image*. *summed_shape* has to be a divisor of the original shape minus
    the *offset*. If *average* is True, the summed pixel is normalized by the region area.  *out* is
    the pyopencl Array instance, if not specified it will be created. *out* is also returned. If
    *block* is True, wait for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl.array.Array(queue, summed_shape, dtype=cfg.PRECISION.np_float)
    image = g_util.get_array(image, queue=queue)
    orig_shape = (image.shape[0] - offset[0], image.shape[1] - offset[1])
    region = (orig_shape[0] / summed_shape[0], orig_shape[1] / summed_shape[1])
    if orig_shape[0] % summed_shape[0] or orig_shape[1] % summed_shape[1]:
        raise RuntimeError('Final shape {} must be a divisor '.format(summed_shape) +
                           'of the original shape {}'.format(image.shape))
    LOG.debug('bin_image, shape: %s, summed_shape: %s, offset: %s, average: %s', image.shape,
              summed_shape, offset, average)

    ev = cfg.OPENCL.programs['improc'].sum(queue,
                                           (summed_shape[::-1]),
                                           None,
                                           out.data,
                                           image.data,
                                           vec.make_int2(*region[::-1]),
                                           np.int32(image.shape[1]),
                                           vec.make_int2(*offset[::-1]),
                                           np.int32(average))
    if block:
        ev.wait()

    return out
コード例 #6
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def decimate(image, shape, sigma=None, average=False, queue=None, block=False):
    """Decimate *image* so that its dimensions match the final *shape*, which has to be a divisor of
    the original shape. Remove low frequencies by a Gaussian filter with *sigma* pixels. If *sigma*
    is None, use the FWHM of one low resolution pixel. Use command *queue*, if *block* is True, wait
    for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    image = g_util.get_array(image, queue=queue)
    shape = make_tuple(shape)
    pow_shape = tuple([next_power_of_two(n) for n in image.shape])
    orig_shape = image.shape
    if image.shape != pow_shape:
        image = pad(image, region=(0, 0) + pow_shape, queue=queue)
    if sigma is None:
        sigma = tuple([fwnm_to_sigma(float(image.shape[i]) / shape[i], n=2) for i in range(2)])

    LOG.debug(
        "decimate, shape: %s, final_shape: %s, sigma: %s, average: %s",
        image.shape,
        shape,
        sigma,
        average,
    )

    fltr = get_gauss_2d(image.shape, sigma, fourier=True, queue=queue, block=block)
    image = image.astype(cfg.PRECISION.np_cplx)
    fft_2(image, queue=queue, block=block)
    image *= fltr
    ifft_2(image, queue=queue, block=block)
    image = crop(image.real, (0, 0) + orig_shape, queue=queue, block=block)

    return bin_image(image, shape, average=average, queue=queue, block=block)
コード例 #7
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def _fft_2(data, inverse=False, queue=None, block=True):
    """Execute FFT on *data*, which is first converted to a pyopencl array and retyped to
    complex.
    """
    if not queue:
        queue = cfg.OPENCL.queue
    thread = ocl_api().Thread(queue)
    data = g_util.get_array(data, queue=queue)
    if data.dtype != cfg.PRECISION.np_cplx:
        data = data.astype(cfg.PRECISION.np_cplx)

    if queue not in cfg.OPENCL.fft_plans:
        cfg.OPENCL.fft_plans[queue] = {}
    if data.shape not in cfg.OPENCL.fft_plans[queue]:
        LOG.debug("Creating FFT Plan for {} and shape {}".format(queue, data.shape))
        _fft = FFT(data, axes=(0, 1))
        cfg.OPENCL.fft_plans[queue][data.shape] = _fft.compile(thread, fast_math=False)
    plan = cfg.OPENCL.fft_plans[queue][data.shape]

    LOG.debug("fft_2, shape: %s, inverse: %s", data.shape, inverse)
    # plan.execute(data.data, inverse=inverse, wait_for_finish=block)
    plan(data, data, inverse=inverse)
    if block:
        thread.synchronize()

    return data
コード例 #8
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def pad(image, region=None, out=None, value=0, queue=None, block=False):
    """Pad a 2D *image*. *region* is the region to pad as (y_0, x_0, height, width). If not
    specified, the next power of two dimensions are used and the image is centered in the padded
    one. The final image dimensions are height x width and the filling starts at (y_0, x_0), *out*
    is the pyopencl Array instance, if not specified it will be created. *out* is also returned.
    *value* is the padded value. If *block* is True, wait for the copy to finish.
    """
    if region is None:
        shape = tuple([next_power_of_two(n) for n in image.shape])
        y_0 = (shape[0] - image.shape[0]) // 2
        x_0 = (shape[1] - image.shape[1]) // 2
        region = (y_0, x_0) + shape
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl_array.zeros(queue, (region[2], region[3]), dtype=image.dtype) + value
    image = g_util.get_array(image, queue=queue)

    n_bytes = image.dtype.itemsize
    y_0, x_0, height, width = region
    src_origin = (0, 0, 0)
    dst_origin = (n_bytes * x_0, y_0, 0)
    region = (n_bytes * image.shape[1], image.shape[0], 1)
    LOG.debug(
        "pad, shape: %s, src_origin: %s, dst_origin: %s, region: %s",
        image.shape,
        src_origin,
        dst_origin,
        region,
    )

    _copy_rect(image, out, src_origin, dst_origin, region, queue, block=block)

    return out
コード例 #9
0
ファイル: test_gpu_util.py プロジェクト: flmiot/syris-1
 def _test():
     shape = 8, 4
     dtypes = ['i', 'u', 'f']
     lengths = [2, 4, 8]
     types = [
         np.dtype('{}{}'.format(dt, length))
         for dt, length in itertools.product(dtypes, lengths)
     ]
     types.append(np.dtype('i1'))
     types.append(np.dtype('u1'))
     types += [np.dtype('c8'), np.dtype('c16')]
     for dtype in types:
         np_data = np.arange(shape[0] *
                             shape[1]).reshape(shape).astype(dtype)
         # host -> Array
         cl_data = gu.get_array(np_data)
         np.testing.assert_equal(np_data, cl_data.get())
         # Array -> Array
         res = gu.get_array(cl_data)
         np.testing.assert_equal(res.get(), cl_data.get())
         # Array -> host
         host_data = gu.get_host(cl_data)
         np.testing.assert_equal(np_data, host_data)
         # host -> host
         host_data = gu.get_host(np_data)
         np.testing.assert_equal(np_data, host_data)
         if dtype.kind != 'c':
             # numpy -> Image and Image -> Array
             image = gu.get_image(np_data)
             back = gu.get_array(image).get()
             np.testing.assert_equal(back, np_data)
             # Image -> host
             host_data = gu.get_host(image)
             np.testing.assert_equal(host_data, np_data)
             # Array -> Image
             image = gu.get_image(cl_data)
             back = gu.get_array(image).get()
             np.testing.assert_equal(back, np_data)
             # Image -> Image
             image_2 = gu.get_image(image)
             back = gu.get_array(image_2).get()
             np.testing.assert_equal(back, np_data)
コード例 #10
0
ファイル: test_gpu_util.py プロジェクト: ufo-kit/syris
 def _test():
     shape = 8, 4
     dtypes = ["i", "u", "f"]
     lengths = [2, 4, 8]
     types = [
         np.dtype("{}{}".format(dt, length))
         for dt, length in itertools.product(dtypes, lengths)
     ]
     types.append(np.dtype("i1"))
     types.append(np.dtype("u1"))
     types += [np.dtype("c8"), np.dtype("c16")]
     for dtype in types:
         np_data = np.arange(shape[0] *
                             shape[1]).reshape(shape).astype(dtype)
         # host -> Array
         cl_data = gu.get_array(np_data)
         np.testing.assert_equal(np_data, cl_data.get())
         # Array -> Array
         res = gu.get_array(cl_data)
         np.testing.assert_equal(res.get(), cl_data.get())
         # Array -> host
         host_data = gu.get_host(cl_data)
         np.testing.assert_equal(np_data, host_data)
         # host -> host
         host_data = gu.get_host(np_data)
         np.testing.assert_equal(np_data, host_data)
         if gu.are_images_supported() and dtype.kind != "c":
             # numpy -> Image and Image -> Array
             image = gu.get_image(np_data)
             back = gu.get_array(image).get()
             np.testing.assert_equal(back, np_data)
             # Image -> host
             host_data = gu.get_host(image)
             np.testing.assert_equal(host_data, np_data)
             # Array -> Image
             image = gu.get_image(cl_data)
             back = gu.get_array(image).get()
             np.testing.assert_equal(back, np_data)
             # Image -> Image
             image_2 = gu.get_image(image)
             back = gu.get_array(image_2).get()
             np.testing.assert_equal(back, np_data)
コード例 #11
0
    def test_fft(self):
        data = gpu_util.get_array(
            np.random.normal(100, 100, size=(4, 4)).astype(cfg.PRECISION.np_float)
        )
        orig = gpu_util.get_host(data)
        data = ip.fft_2(data)
        ip.ifft_2(data)
        np.testing.assert_almost_equal(orig, data.get().real, decimal=4)

        # Test double precision
        default_syris_init(double_precision=True)
        data = gpu_util.get_array(
            np.random.normal(100, 100, size=(4, 4)).astype(cfg.PRECISION.np_float)
        )
        gt = np.fft.fft2(data.get())
        data = ip.fft_2(data)
        np.testing.assert_almost_equal(gt, data.get(), decimal=4)

        gt = np.fft.ifft2(data.get())
        data = ip.ifft_2(data)
        np.testing.assert_almost_equal(gt, data.get(), decimal=4)
コード例 #12
0
def main():
    args = parse_args()
    syris.init()
    # Propagate to 20 cm
    d = 5 * q.cm
    # Compute grid
    n_camera = 256
    n = n_camera * args.supersampling
    shape = (n, n)
    material = get_material("pmma_5_30_kev.mat")
    energy = 15 * q.keV
    ps = 1 * q.um
    ps_hd = ps / args.supersampling
    radius = n / 4.0 * ps_hd

    fmt = "                     Wavelength: {}"
    print(fmt.format(energy_to_wavelength(energy)))
    fmt = "Pixel size used for propagation: {}"
    print(fmt.format(ps_hd.rescale(q.um)))
    print("                  Field of view: {}".format(n *
                                                       ps_hd.rescale(q.um)))
    fmt = "                Sphere diameter: {}"
    print(fmt.format(2 * radius))

    sample = make_sphere(n, radius, pixel_size=ps_hd, material=material)
    projection = sample.project((n, n), ps_hd).get() * 1e6
    projection = decimate(projection, (n_camera, n_camera), average=True).get()
    # Propagation with a monochromatic plane incident wave
    hd = propagate([sample], shape, [energy], d, ps_hd).get()
    ld = decimate(hd, (n_camera, n_camera), average=True).get()

    kernel = compute_tie_kernel(n_camera, ps, d, material, energy)
    mju = material.get_attenuation_coefficient(energy).rescale(1 /
                                                               q.m).magnitude
    f_ld = fft_2(ld)
    f_ld *= get_array(kernel.astype(cfg.PRECISION.np_float))
    retrieved = ifft_2(f_ld).get().real
    retrieved = -1 / mju * np.log(retrieved) * 1e6

    if args.output_thickness:
        imageio.imwrite(args.output_thickness, projection)
    if args.output_projection:
        imageio.imwrite(args.output_projection, ld)
    if args.output_retrieved:
        imageio.imwrite(args.output_retrieved, retrieved)

    show(hd, title="High resolution")
    show(ld, title="Low resolution (detector)")
    show(retrieved, title="Retrieved [um]")
    show(projection, title="Projection [um]")
    show(projection - retrieved, title="Projection - retrieved")
    plt.show()
コード例 #13
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def compute_intensity(wavefield, queue=None, out=None, block=False):
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl.array.Array(queue, wavefield.shape, dtype=cfg.PRECISION.np_float)
    wavefield = g_util.get_array(wavefield, queue=queue)

    ev = cfg.OPENCL.programs["improc"].compute_intensity(
        queue, wavefield.shape[::-1], None, wavefield.data, out.data
    )
    if block:
        ev.wait()

    return out
コード例 #14
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def compute_intensity(wavefield, queue=None, out=None, block=False):
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl.array.Array(queue, wavefield.shape, dtype=cfg.PRECISION.np_float)
    wavefield = g_util.get_array(wavefield, queue=queue)

    ev = cfg.OPENCL.programs['improc'].compute_intensity(queue,
                                                         wavefield.shape[::-1],
                                                         None,
                                                         wavefield.data,
                                                         out.data)
    if block:
        ev.wait()

    return out
コード例 #15
0
ファイル: imageprocessing.py プロジェクト: ufo-kit/syris
def crop(image, region, out=None, queue=None, block=False):
    """Crop a 2D *image*. *region* is the region to crop as (y_0, x_0, height, width), *out* is the
    pyopencl Array instance, if not specified it will be created. *out* is also returned. If *block*
    is True, wait for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    if out is None:
        out = cl.array.Array(queue, (region[2], region[3]), dtype=image.dtype)
    image = g_util.get_array(image, queue=queue)

    n_bytes = image.dtype.itemsize
    y_0, x_0, height, width = region
    src_origin = (n_bytes * x_0, y_0, 0)
    dst_origin = (0, 0, 0)
    region = (n_bytes * width, height, 1)
    LOG.debug('crop, shape: %s, src_origin: %s, dst_origin: %s, region: %s', image.shape,
              src_origin, dst_origin, region)

    _copy_rect(image, out, src_origin, dst_origin, region, queue, block=block)

    return out
コード例 #16
0
ファイル: imageprocessing.py プロジェクト: flmiot/syris-1
def _fft_2(data, inverse=False, plan=None, queue=None, block=True):
    """Execute FFT on *data*, which is first converted to a pyopencl array and retyped to
    complex.
    """
    data = g_util.get_array(data, queue=queue)
    if data.dtype != cfg.PRECISION.np_cplx:
        data = data.astype(cfg.PRECISION.np_cplx)

    if not plan:
        if not queue:
            queue = cfg.OPENCL.queue
        if queue not in cfg.OPENCL.fft_plans:
            cfg.OPENCL.fft_plans[queue] = {}
        if data.shape not in cfg.OPENCL.fft_plans[queue]:
            LOG.debug('Creating FFT Plan for {} and shape {}'.format(queue, data.shape))
            cfg.OPENCL.fft_plans[queue][data.shape] = Plan(data.shape,
                                                           dtype=cfg.PRECISION.np_cplx,
                                                           queue=queue)
        plan = cfg.OPENCL.fft_plans[queue][data.shape]

    LOG.debug('fft_2, shape: %s, inverse: %s', data.shape, inverse)
    plan.execute(data.data, inverse=inverse, wait_for_finish=block)

    return data
コード例 #17
0
 def __init__(self, thickness, pixel_size, material=None, queue=None):
     super(StaticBody, self).__init__(material)
     self.thickness = g_util.get_array(thickness.simplified.magnitude, queue=queue)
     self.pixel_size = make_tuple(pixel_size, num_dims=2)