def output(
        self,
        classes,
        classes_refl,
        rot,
        shifts=None,
        coefs=None,
    ):
        """
        Return class averages.

        :param classes: class indices (refering to src). (n_img, n_nbor)
        :param classes_refl: Bool representing whether to reflect image in `classes`
        :param rot: Array of in-plane rotation angles (Radians) of image in `classes`
        :param shifts: Optional array of shifts for image in `classes`.
        :coefs: Optional Fourier bessel coefs (avoids recomputing).
        :return: Stack of Synthetic Class Average images as Image instance.
        """

        logger.info(f"Select {self.n_classes} Classes from Nearest Neighbors")
        # generate indices for random sample (can do something smart with corr later).
        # For testing just take the first n_classes so it matches earlier plots for manual comparison
        # This is assumed to be reasonably random.
        selection = np.arange(self.n_classes)

        imgs = self.src.images(0, self.src.n)
        fb_avgs = np.empty((self.n_classes, self.fb_basis.count),
                           dtype=self.src.dtype)

        for i in tqdm(range(self.n_classes)):
            j = selection[i]
            # Get the neighbors
            neighbors_ids = classes[j]

            # Get coefs in Fourier Bessel Basis if not provided as an argument.
            if coefs is None:
                neighbors_imgs = Image(imgs[neighbors_ids])
                if shifts is not None:
                    neighbors_imgs.shift(shifts[i])
                neighbors_coefs = self.fb_basis.evaluate_t(neighbors_imgs)
            else:
                neighbors_coefs = coefs[neighbors_ids]
                if shifts is not None:
                    neighbors_coefs = self.fb_basis.shift(
                        neighbors_coefs, shifts[i])

            # Rotate in Fourier Bessel
            neighbors_coefs = self.fb_basis.rotate(neighbors_coefs, rot[j],
                                                   classes_refl[j])

            # Averaging in FB
            fb_avgs[i] = np.mean(neighbors_coefs, axis=0)

        # Now we convert the averaged images from FB to Cartesian.
        return ArrayImageSource(self.fb_basis.evaluate(fb_avgs))
Beispiel #2
0
class ImageTestCase(TestCase):
    def setUp(self):
        # numpy array for top-level functions that directly expect it
        self.im_np = misc.face(
            gray=True).astype('float64')[:768, :768][:, :, np.newaxis]
        # Independent Image object for testing Image methods
        self.im = Image(misc.face(gray=True).astype('float64')[:768, :768])

    def tearDown(self):
        pass

    def testImShift(self):
        # Ensure that the two separate im_translate functions we have return the same thing

        # A single shift applied to all images
        shifts = np.array([100, 200])

        im = self.im.shift(shifts)

        im1 = _im_translate(self.im_np, shifts.reshape(1, 2))
        # Note the difference in the concept of shifts for _im_translate2 - negative sign/transpose
        im2 = _im_translate2(self.im_np, -shifts.reshape(2, 1))
        # Pure numpy 'shifting'
        # 'Shifting' an Image corresponds to a 'roll' of a numpy array - again, note the negated signs and the axes
        im3 = np.roll(self.im.asnumpy()[:, :, 0], -shifts, axis=(0, 1))

        self.assertTrue(np.allclose(im.asnumpy(), im1))
        self.assertTrue(np.allclose(im1, im2))
        self.assertTrue(np.allclose(im1[:, :, 0], im3))

    def testArrayImageSource(self):
        # An Image can be wrapped in an ArrayImageSource when we need to deal with ImageSource objects.
        src = ArrayImageSource(self.im)
        im = src.images(start=0, num=np.inf)
        self.assertTrue(np.allclose(im.asnumpy(), self.im_np))
Beispiel #3
0
class ImageTestCase(TestCase):
    def setUp(self):
        # numpy array for top-level functions that directly expect it
        self.im_np = misc.face(gray=True).astype(
            np.float64)[np.newaxis, :768, :768]
        # Independent Image object for testing Image methods
        self.im = Image(misc.face(gray=True).astype(np.float64)[:768, :768])
        # Construct a simple stack of Images
        self.n = 3
        self.ims_np = np.empty((3, *self.im_np.shape[1:]),
                               dtype=self.im_np.dtype)
        for i in range(self.n):
            self.ims_np[i] = self.im_np * (i + 1) / float(self.n)
        # Independent Image stack object for testing Image methods
        self.ims = Image(self.ims_np)

    def tearDown(self):
        pass

    def testImShift(self):
        # Ensure that the two separate im_translate functions we have return the same thing

        # A single shift applied to all images
        shifts = np.array([100, 200])

        im = self.im.shift(shifts)

        im1 = self.im._im_translate(shifts)
        # Note the difference in the concept of shifts for _im_translate2 - negative sign
        im2 = _im_translate2(self.im_np, -shifts)

        # Pure numpy 'shifting'
        # 'Shifting' an Image corresponds to a 'roll' of a numpy array - again, note the negated signs and the axes
        im3 = np.roll(self.im.asnumpy()[0], -shifts, axis=(0, 1))

        self.assertTrue(np.allclose(im.asnumpy(), im1.asnumpy()))
        self.assertTrue(np.allclose(im1.asnumpy(), im2.asnumpy()))
        self.assertTrue(np.allclose(im1.asnumpy()[0, :, :], im3))

    def testArrayImageSource(self):
        # An Image can be wrapped in an ArrayImageSource when we need to deal with ImageSource objects.
        src = ArrayImageSource(self.im)
        im = src.images(start=0, num=np.inf)
        self.assertTrue(np.allclose(im.asnumpy(), self.im_np))

    def testImageSqrt(self):
        self.assertTrue(
            np.allclose(self.im.sqrt().asnumpy(), np.sqrt(self.im_np)))

        self.assertTrue(
            np.allclose(self.ims.sqrt().asnumpy(), np.sqrt(self.ims_np)))

    def testImageTranspose(self):
        self.assertTrue(
            np.allclose(self.im.flip_axes().asnumpy(),
                        np.transpose(self.im_np, (0, 2, 1))))

        # This is equivalent to checking np.tranpose(..., (0, 2, 1))
        for i in range(self.ims_np.shape[0]):

            self.assertTrue(
                np.allclose(self.ims.flip_axes()[i], self.ims_np[i].T))

            # Check against the contruction.
            self.assertTrue(
                np.allclose(self.ims.flip_axes()[i],
                            self.im_np[0].T * (i + 1) / float(self.n)))
Beispiel #4
0
im = Image(img_data, dtype=np.float64)

# %%
# Plot the Image Stack
# --------------------

# Plot the Image stack
im.show()

# %%
# Apply a Uniform Shift
# ---------------------

# Apply a single shift to each image.
shifts = np.array([100, 30])
im.shift(shifts).show()

# %%
# Apply Image-wise Shifts
# -----------------------

# Or apply shifts corresponding to to each image.
shifts = np.array([[300 * i, 100 * i] for i in range(1, im.n_images + 1)])
im.shift(shifts).show()

# %%
# Downsampling
# ------------

im.downsample(80).show()