Exemple #1
0
def fast_warp(img, tf, output_shape, mode='constant', mode_cval=0, order=0):
    """Warp an image according to a given coordinate transformation.

        This wrapper function is faster than skimage.transform.warp
    Args:
        img: `ndarray`, input image
        tf: For 2-D images, you can directly pass a transformation object
            e.g. skimage.transform.SimilarityTransform, or its inverse.
        output_shape: tuple, (rows, cols)
        mode: mode for transformation
            available modes: {`constant`, `edge`, `symmetric`, `reflect`, `wrap`}
        mode_cval: float, Used in conjunction with mode `constant`, the value outside the image boundaries
        order: int, The order of interpolation. The order has to be in the range 0-5:
            0: Nearest-neighbor
            1: Bi-linear (default)
            2: Bi-quadratic
            3: Bi-cubic
            4: Bi-quartic
            5: Bi-quintic

    Returns:
        warped, double `ndarray`
    """
    m = tf.params
    t_img = np.zeros((img.shape[0], ) + output_shape, img.dtype)
    for i in range(t_img.shape[0]):
        t_img[i] = _warp_fast(img[i],
                              m,
                              output_shape=output_shape,
                              mode=mode,
                              cval=mode_cval,
                              order=order)
    return t_img
Exemple #2
0
def fast_warp(img, tf, output_shape, mode="constant", order=0):
    """
    This wrapper function is faster than skimage.transform.warp
    """
    m = tf.params
    t_img = np.zeros((img.shape[0],) + output_shape, img.dtype)
    for i in range(t_img.shape[0]):
        t_img[i] = _warp_fast(img[i], m, output_shape=output_shape, mode=mode, order=order)
    return t_img
Exemple #3
0
def fast_warp(img, tf, output_shape, mode='constant', order=0):
    """
    This wrapper function is faster than skimage.transform.warp
    """
    m = tf.params
    t_img = np.zeros((img.shape[0],) + output_shape, img.dtype)
    for i in range(t_img.shape[0]):
        t_img[i] = _warp_fast(img[i], m, output_shape=output_shape, 
                              mode=mode, order=order)
    return t_img
def compute_drt(img, angles=None, n_beams=600):
    if (img.ndim != 2):
        raise ValueError("Error: Input image must be 2D")
    if (angles is None):
        angles = np.arange(360)  # full 360 degrees for rotational invariance

    # Scale image for desired beam count
    scale = n_beams / np.ceil(np.sqrt(2) * max(img.shape))
    img = rescale(img, scale=scale, mode="reflect")

    # Pad image (same as radon_transform.py)
    diagonal = np.sqrt(2) * max(img.shape)
    pad = [int(np.ceil(diagonal - s)) for s in img.shape]
    new_center = [(s + p) // 2 for s, p in zip(img.shape, pad)]
    old_center = [s // 2 for s in img.shape]
    pad_before = [nc - oc for oc, nc in zip(old_center, new_center)]
    pad_width = [(pb, p - pb) for pb, p in zip(pad_before, pad)]
    padded_image = np.pad(img, pad_width, mode="constant", constant_values=0)

    assert padded_image.shape[0] == padded_image.shape[
        1]  # assert padded image is square

    # Define radon image vars
    sinogram = np.zeros((padded_image.shape[0], len(angles)))
    center = padded_image.shape[0] // 2

    shift0 = np.array([[1, 0, -center], [0, 1, -center], [0, 0, 1]])
    shift1 = np.array([[1, 0, center], [0, 1, center], [0, 0, 1]])

    # Construct matrix for rotating (beam directions)
    def build_rotation(angle):
        T = np.deg2rad(angle)
        R = np.array([[np.cos(T), np.sin(T), 0], [-np.sin(T),
                                                  np.cos(T), 0], [0, 0, 1]])
        return shift1.dot(R).dot(shift0)

    # Build sinogram
    for i in range(len(angles)):
        rotated_img = _warp_fast(padded_image, build_rotation(angles[i]))

        # Compute ith angle beam sum vector, i.e. all beams on current angle
        sinogram[:, i] = rotated_img.sum(0)

    return sinogram
Exemple #5
0
	def __radon(self, image, theta=None):

		if image.ndim != 2:
			raise ValueError('The input image must be 2-D')
		if theta is None:
			raise ValueError('there is no theta in __radon!!!')

		height, width = image.shape
		diagonal = np.sqrt(height**2 + width**2)
		
		heightpad = np.ceil(diagonal - height)
		widthpad = np.ceil(diagonal - width)
		
		#padding image, so whole img is visible to "rays" while rotating
		padded_image = np.zeros((int(height + heightpad), int(width + widthpad)))
		y0, y1 = int(np.ceil(heightpad / 2)), int((np.ceil(heightpad / 2) + height))
		x0, x1 = int((np.ceil(widthpad / 2))), int((np.ceil(widthpad / 2) + width))
		padded_image[y0:y1, x0:x1] = image
		
		#plt.imshow(padded_image, cmap=plt.cm.Greys_r)
		#plt.show()
		
		if self.__firstGen:
			sinogram = np.zeros((padded_image.shape[0], len(theta)))
		else:
			sinogram = np.zeros((self.__detNum, len(theta)))

		h, w = padded_image.shape
		dh, dw = h // 2, w // 2
		

		for i in xrange(len(theta)):
			# apply transformation matrix to img, requires inverse of transformation matrix
			rotated = _warp_fast(padded_image, np.linalg.inv(self.__build_rotation(-theta[i], dw, dh)), mode="wrap")
			#rotated = warp(padded_image, np.linalg.inv(self.__build_rotation(-theta[i], dw, dh)))		

			if not self.__firstGen:
				sinogram[:, i] = self.__radon_view(rotated)
			else:
				sinogram[:, i] = rotated.sum(0)[::-1]

		return sinogram
Exemple #6
0
def fast_warp(img, tf, mode='constant', order=0):
    m = tf.params
    t_img = np.zeros(img.shape, img.dtype)
    for i in range(t_img.shape[0]):
        t_img[i] = _warp_fast(img[i], m, mode=mode, order=order)
    return t_img
Exemple #7
0
    def perform(self, node, inputs, out_storage):
        x, rot, shear, scale, trans, oshape = inputs
        #foobar.append_ndarray_signature(x, 'AffineImageWarp x')

        aff = AffineTransform(rotation=rot, shear=shear, scale=scale,
                translation=trans)

        if str(x.dtype) != node.inputs[0].dtype:
            raise TypeError("Wrong dtype argument to AffineImageWarp", x.dtype)

        if np.any(x < 0):
            raise ValueError('X should be positive')

        if np.any(x > 1.0):
            raise ValueError('X should be less than 1')

        N, C, H, W = x.shape
        rows, cols = oshape

        rval = out_storage[0][0]
        rval_shape = (N, C, rows, cols)

        if ((rval is None)
                or (rval.dtype != x.dtype)
                or rval.shape != rval_shape):
            rval3 = np.empty((N * C, rows, cols), dtype=x.dtype)
            bg_check = True
        else:
            rval3 = rval.reshape((N * C, rows, cols))
            bg_check = False

        xx = x.reshape(N * C, H, W)

        # -- a small exactly-representable float for out-of-bounds pixels
        oob = -1.0 / 2 ** 16
        order = 1  # TODO: TRY ORDER=2 (WHY DOES RANGE GET LARGER?)

        tform = np.linalg.inv(aff._matrix)

        for i in xrange(N * C):
            if bg_check and i == 0:
                rval3[i] = _warp_fast(xx[i], tform,
                        output_shape=oshape, order=order,
                        cval=oob)
                oob_ratio = np.mean(rval3[i] == oob)
                if oob_ratio > 0.5:
                    raise InvalidDescription('too much background', oob_ratio)
                rval3[i] = np.maximum(0, rval3[i])
            else:
                rval3[i] = _warp_fast(xx[i], np.linalg.inv(aff._matrix),
                        output_shape=oshape, order=order,
                        cval=0)

            if 0 and i == 0:
                print 'Debugprint from AffineImageWarp...'
                for sym in 'rot', 'shear', 'scale', 'trans', 'oshape':
                    print sym, ':', locals()[sym]
                import matplotlib.pyplot as pl
                pl.subplot(2, 1, 1)
                pl.imshow(xx[i], cmap=pl.cm.gray)
                pl.subplot(2, 1, 2)
                pl.imshow(rval3[i], cmap=pl.cm.gray)
                pl.show()
                time.sleep(2)  # -- give some time to ctrl-C

        if np.any(rval3 > 1.001) or np.any(rval3 < 0.0):
            min3 = np.min(rval3)
            max3 = np.max(rval3)
            raise ValueError('interpolated pixel values out of range',
                             (min3, max3))

        out_storage[0][0] = rval3.reshape(rval_shape)
def fast_warp(img, tf, mode='constant', order=0):
    m = tf.params
    t_img = np.zeros(img.shape, img.dtype)
    for i in range(t_img.shape[0]):
        t_img[i] = _warp_fast(img[i], m, mode=mode, order=order)
    return t_img
Exemple #9
0
	def __iradon(self, radon_image, theta=None, output_size=None, fft_filter=False, filter="ramp"):

		th = (np.pi / 180.0) * theta

		n = radon_image.shape[0]

		img = radon_image.copy()


		if fft_filter: #fft filter
			# resize image to next power of two for fourier analysis
			# speeds up fourier and lessens artifacts
			order = max(64., 2**np.ceil(np.log(2 * n) / np.log(2)))
			# zero pad input image
			img.resize((order, img.shape[1]))


			#construct the fourier filter
			f = fftshift(abs(np.mgrid[-1:1:2 / order])).reshape(-1, 1)
			w = 2 * np.pi * f
			# start from first element to avoid divide by zero
			if filter == "ramp":
				pass
			elif filter == "shepp-logan":
				f[1:] = f[1:] * np.sin(w[1:] / 2) / (w[1:] / 2)
			elif filter == "cosine":
				f[1:] = f[1:] * np.cos(w[1:] / 2)
			elif filter == "hamming":
				f[1:] = f[1:] * (0.54 + 0.46 * np.cos(w[1:]))
			elif filter == "hann":
				f[1:] = f[1:] * (1 + np.cos(w[1:])) / 2
			elif filter == None:
				f[1:] = 1
			else:
				raise ValueError("Unknown filter: %s" % filter)

			filter_ft = np.tile(f, (1, len(theta)))

			# apply filter in fourier domain
			projection = fft(img, axis=0) * filter_ft
			radon_filtered = np.real(ifft(projection, axis=0))
		
		else: #normal filter 
			filter_size = 10
			filter_tab = np.zeros((2*filter_size+1))
			for k in xrange(-filter_size,filter_size):
				if(k%2!=0):
					filter_tab[k+filter_size] = -4.0 / (np.pi**2 * k**2)  
			filter_tab[filter_size]=1
			
			radon_filtered = np.zeros((img.shape[0], img.shape[1]))
			for i in xrange(img.shape[1]):
				radon_filtered[:,i] = np.convolve(img[:,i],filter_tab, mode='same') 		

	

		# resize filtered image back to original size
		radon_filtered = radon_filtered[:radon_image.shape[0], :]
		
		
		
		reconstructed = np.zeros((output_size, output_size))
		mid_index = np.ceil(n / 2.0)

		x = output_size
		y = output_size
		[X, Y] = np.mgrid[0.0:x, 0.0:y]
		xpr = X - int(output_size) // 2
		ypr = Y - int(output_size) // 2

	 

		# reconstruct image by interpolation
		for i in xrange(len(theta)):
			t = xpr * np.sin(th[i]) - ypr * np.cos(th[i])
			
			a = np.floor(t)
			
			b = mid_index + a
			b0 = ((((b + 1 > 0) & (b + 1 < n)) * (b + 1)) - 1).astype(np.int)
			b1 = ((((b > 0) & (b < n)) * b) - 1).astype(np.int)
			reconstructed += (t - a) * radon_filtered[b0, i] + (a - t + 1) * radon_filtered[b1, i]

			#debug
			#print b0
			#print i
			#print b1
			#plt.subplot(221)
			#plt.imshow(reconstructed, cmap=plt.cm.Greys_r)
			#plt.subplot(222)
			#plt.imshow((t - a) * radon_filtered[b0, i], cmap=plt.cm.Greys_r)
			#plt.subplot(223)
			#plt.imshow((a - t + 1) * radon_filtered[b1, i], cmap=plt.cm.Greys_r)
			#plt.show()

		h, w = reconstructed.shape
		dh, dw = h // 2, w // 2
		
		if not self.__firstGen:
			rotated = _warp_fast(reconstructed, np.linalg.inv(self.__build_rotation(90, dw, dh)))
  			#rotated = warp(reconstructed, np.linalg.inv(self.__build_rotation(-90, dw, dh)))
  			result = self.normalize_array(rotated * np.pi / (2 * len(th)) )
  		else:
  			result = self.normalize_array(reconstructed * np.pi / (2 * len(th)) )
			return result
			


		#print("A %d %d") % (result.shape[0], result.shape[1])
		
		if(self.__firstGen==0):
			scale = 1/self.__detSize * (self.__emmiterDistance + output_size+self.__detectorsDistance)/(self.__emmiterDistance + output_size/2)
			#print("scale %f") % (scale)
			margin = (output_size-output_size*scale)/2
			if(margin != 0):
				result = result[margin:-margin , margin:-margin]
			#print("B %d %d") % (result.shape[0], result.shape[1])
			result = rescale(result, (1/scale, 1/scale))
			#print("C %d %d") % (result.shape[0], result.shape[1])
			result = result[0:output_size, 0:output_size]
					
		return result
def radon_real_geom(image, theta=None, circle=True, noise=1):
    def build_rotation(theta):
        T = np.deg2rad(theta)
        R = np.array([[np.cos(T), np.sin(T), 0], [-np.sin(T),
                                                  np.cos(T), 0], [0, 0, 1]])
        return shift1.dot(R).dot(shift0)

    if image.ndim != 2:
        raise ValueError('The input image must be 2-D!')
    if theta is None:
        theta = np.arange(180)
    else:
        # Pad the image so when it's rotated, nothing relevant gets cut out
        diagonal = np.sqrt(2) * max(image.shape)
        pad = [int(np.ceil(diagonal - s)) for s in image.shape]
        new_center = [(s + p) // 2 for s, p in zip(image.shape, pad)]
        old_center = [s // 2 for s in image.shape]
        pad_before = [nc - oc for oc, nc in zip(old_center, new_center)]
        pad_width = [(pb, p - pb) for pb, p in zip(pad_before, pad)]
        padded_image = np.pad(image,
                              pad_width,
                              mode='constant',
                              constant_values=0)
    # padded_image should be square
    assert padded_image.shape[0] == padded_image.shape[1]
    radon_image = np.zeros((padded_image.shape[0], len(theta)))
    # For later comparison
    radon_image_unaltered = np.zeros((2 * padded_image.shape[0], len(theta)))
    # Upscale padded image with nearest neighbour filtering
    padded_image = np.array(
        Image.fromarray(padded_image).resize(
            (2 * padded_image.shape[0], 2 * padded_image.shape[1])))
    center = padded_image.shape[0] // 2

    shift0 = np.array([[1, 0, -center], [0, 1, -center], [0, 0, 1]])
    shift1 = np.array([[1, 0, center], [0, 1, center], [0, 0, 1]])

    for i in range(len(theta)):
        rotated = _warp_fast(padded_image, build_rotation(theta[i]))
        measurement = rotated.sum(0)

        # Coordinates of the projection pixels
        xp = np.arange(0, np.shape(measurement)[0])
        xp = xp - np.shape(measurement)[0] / 2 + 0.5
        # Translate and scale coordinates
        xr = (xp - np.sin(np.pi * theta[i] / 180) * np.shape(image)[0] /
              2) / np.cos(np.pi * theta[i] / 180)
        # Get values at new coordinates
        f = interpolate.interp1d(xr,
                                 measurement,
                                 bounds_error=False,
                                 fill_value=0)
        measurement_new = f(xp)
        # Downscale measurement_new to correct size
        measurement_new = np.reshape(measurement_new,
                                     (1, np.shape(measurement_new)[0]))
        measurement_new = np.array(
            Image.fromarray(measurement_new).resize(
                (int(np.shape(measurement_new)[1] / 2), 1),
                resample=Image.BILINEAR))
        # For comparison
        radon_image_unaltered[:, i] = measurement
        radon_image[:, i] = measurement_new
    if noise == 1:
        # Add 5% measurement noise
        noise = np.random.normal(1,
                                 0.05,
                                 size=(radon_image.shape[0],
                                       radon_image.shape[1]))
        radon_image = radon_image * noise

    # Visualisation
    #radon_image_unaltered = np.array(Image.fromarray(radon_image_unaltered).resize((13, 272), resample=Image.BILINEAR))
    #plt.figure()
    #plt.subplot(2, 1, 1)
    #plt.imshow(np.transpose(radon_image_unaltered))
    #plt.subplot(2, 1, 2)
    #plt.imshow(np.transpose(radon_image))
    return radon_image
    def perform(self, node, inputs, out_storage):
        x, rot, shear, scale, trans, oshape = inputs
        #foobar.append_ndarray_signature(x, 'AffineImageWarp x')

        aff = AffineTransform(rotation=rot,
                              shear=shear,
                              scale=scale,
                              translation=trans)

        if str(x.dtype) != node.inputs[0].dtype:
            raise TypeError("Wrong dtype argument to AffineImageWarp", x.dtype)

        if np.any(x < 0):
            raise ValueError('X should be positive')

        if np.any(x > 1.0):
            raise ValueError('X should be less than 1')

        N, C, H, W = x.shape
        rows, cols = oshape

        rval = out_storage[0][0]
        rval_shape = (N, C, rows, cols)

        if ((rval is None) or (rval.dtype != x.dtype)
                or rval.shape != rval_shape):
            rval3 = np.empty((N * C, rows, cols), dtype=x.dtype)
            bg_check = True
        else:
            rval3 = rval.reshape((N * C, rows, cols))
            bg_check = False

        xx = x.reshape(N * C, H, W)

        # -- a small exactly-representable float for out-of-bounds pixels
        oob = -1.0 / 2**16
        order = 1  # TODO: TRY ORDER=2 (WHY DOES RANGE GET LARGER?)

        tform = np.linalg.inv(aff._matrix)

        for i in xrange(N * C):
            if bg_check and i == 0:
                rval3[i] = _warp_fast(xx[i],
                                      tform,
                                      output_shape=oshape,
                                      order=order,
                                      cval=oob)
                oob_ratio = np.mean(rval3[i] == oob)
                if oob_ratio > 0.5:
                    raise InvalidDescription('too much background', oob_ratio)
                rval3[i] = np.maximum(0, rval3[i])
            else:
                rval3[i] = _warp_fast(xx[i],
                                      np.linalg.inv(aff._matrix),
                                      output_shape=oshape,
                                      order=order,
                                      cval=0)

            if 0 and i == 0:
                print 'Debugprint from AffineImageWarp...'
                for sym in 'rot', 'shear', 'scale', 'trans', 'oshape':
                    print sym, ':', locals()[sym]
                import matplotlib.pyplot as pl
                pl.subplot(2, 1, 1)
                pl.imshow(xx[i], cmap=pl.cm.gray)
                pl.subplot(2, 1, 2)
                pl.imshow(rval3[i], cmap=pl.cm.gray)
                pl.show()
                time.sleep(2)  # -- give some time to ctrl-C

        if np.any(rval3 > 1.001) or np.any(rval3 < 0.0):
            min3 = np.min(rval3)
            max3 = np.max(rval3)
            raise ValueError('interpolated pixel values out of range',
                             (min3, max3))

        out_storage[0][0] = rval3.reshape(rval_shape)