def test_masked_image_as_unmasked_fill_tuple(): m_img = MaskedImage(np.random.rand(3, 3, 3), copy=False) m_img.mask.pixels[0, 0, 0] = False img = m_img.as_unmasked(fill=(1, 2, 3)) assert(type(img) == Image) assert_allclose(m_img.pixels[0, 1:, 1:], img.pixels[0, 1:, 1:]) assert_allclose(img.pixels[:, 0, 0], (1, 2, 3))
def test_normalize_norm_zero_norm_exception(): pixels = np.zeros((3, 120, 120)) image = MaskedImage(pixels) with warnings.catch_warnings(): warnings.simplefilter("ignore") with raises(ValueError): image.normalize_norm(mode='per_channel')
def test_masked_image_as_unmasked_fill(): m_img = MaskedImage(np.random.rand(1, 3, 3), copy=False) m_img.mask.pixels[0, 0, 0] = False img = m_img.as_unmasked(fill=8) assert type(img) == Image assert_allclose(m_img.pixels[0, 1:, 1:], img.pixels[0, 1:, 1:]) assert_allclose(img.pixels[0, 0, 0], 8.0)
def test_as_greyscale_average(): ones = np.ones([3, 120, 120]) image = MaskedImage(ones) image.pixels[0] *= 0.5 new_image = image.as_greyscale(mode='average') assert (new_image.shape == image.shape) assert (new_image.n_channels == 1) assert_allclose(new_image.pixels[0], ones[0] * 0.83333333)
def test_2d_crop_with_mask(): pixels = np.ones((120, 120, 3)) mask = np.zeros_like(pixels[..., 0]) mask[10:100, 20:30] = 1 im = MaskedImage(pixels, mask=mask) cropped_im = im.cropped_copy([0, 0], [20, 60]) assert (cropped_im.shape == (20, 60)) assert (np.alltrue(cropped_im.shape))
def test_normalize_norm_default(): pixels = np.ones((120, 120, 3)) pixels[..., 0] = 0.5 pixels[..., 1] = 0.2345 image = MaskedImage(pixels) image.normalize_norm_inplace() assert_allclose(np.mean(image.pixels), 0, atol=1e-10) assert_allclose(np.linalg.norm(image.pixels), 1)
def test_as_greyscale_luminosity(): ones = np.ones([3, 120, 120]) image = MaskedImage(ones) image.pixels[0] *= 0.5 new_image = image.as_greyscale(mode='luminosity') assert (new_image.shape == image.shape) assert (new_image.n_channels == 1) assert_allclose(new_image.pixels[0], ones[0] * 0.850532)
def test_normalize_std_no_variance_exception(): pixels = np.ones((3, 120, 120)) pixels[0] = 0.5 pixels[1] = 0.2345 image = MaskedImage(pixels) with warnings.catch_warnings(): warnings.simplefilter("ignore") image.normalize_std(mode='per_channel')
def test_2d_crop_without_mask(): pixels = np.ones((120, 120, 3)) im = MaskedImage(pixels) cropped_im = im.cropped_copy([10, 50], [20, 60]) assert (cropped_im.shape == (10, 10)) assert (cropped_im.n_channels == 3) assert (np.alltrue(cropped_im.shape))
def test_normalize_norm_per_channel(): pixels = np.random.randn(120, 120, 3) pixels[..., 1] *= 7 pixels[..., 0] += -14 pixels[..., 2] /= 130 image = MaskedImage(pixels) image.normalize_norm_inplace(mode="per_channel") assert_allclose(np.mean(image.as_vector(keep_channels=True), axis=0), 0, atol=1e-10) assert_allclose(np.linalg.norm(image.as_vector(keep_channels=True), axis=0), 1)
def test_maskedimage_copy(): pixels = np.ones([1, 10, 10]) landmarks = PointCloud(np.ones([3, 2]), copy=False) im = MaskedImage(pixels, copy=False) im.landmarks['test'] = landmarks im_copy = im.copy() assert (not is_same_array(im.pixels, im_copy.pixels)) assert (not is_same_array(im_copy.landmarks['test'].points, im.landmarks['test'].points))
def rebuild_feature_image_with_centres(image, f_pixels, centres): if hasattr(image, 'mask'): mask = sample_mask_for_centres(image.mask.mask, centres) new_image = MaskedImage(f_pixels, mask=mask, copy=False) else: new_image = Image(f_pixels, copy=False) if image.has_landmarks: t = lm_centres_correction(centres) new_image.landmarks = t.apply(image.landmarks) return new_image
def test_normalize_norm_masked(): pixels = np.random.randn(120, 120, 3) pixels[..., 1] *= 7 pixels[..., 0] += -14 pixels[..., 2] /= 130 mask = np.zeros((120, 120)) mask[30:50, 20:30] = 1 image = MaskedImage(pixels, mask=mask) image.normalize_norm_inplace(mode="per_channel", limit_to_mask=True) assert_allclose(np.mean(image.as_vector(keep_channels=True), axis=0), 0, atol=1e-10) assert_allclose(np.linalg.norm(image.as_vector(keep_channels=True), axis=0), 1)
def test_normalize_std_masked_per_channel(): pixels = np.random.randn(3, 120, 120) pixels[0] *= 7 pixels[1] += -14 pixels[2] /= 130 image = MaskedImage(pixels) new_image = image.normalize_std(mode='per_channel') assert_allclose( np.mean(new_image.as_vector(keep_channels=True), axis=1), 0, atol=1e-10) assert_allclose( np.std(new_image.as_vector(keep_channels=True), axis=1), 1)
def test_normalize_norm_masked_per_channel(): pixels = np.random.randn(3, 120, 120) pixels[1] *= 7 pixels[0] += -14 pixels[2] /= 130 image = MaskedImage(pixels) with warnings.catch_warnings(): warnings.simplefilter("ignore") new_image = image.normalize_norm(mode="per_channel") assert_allclose(np.mean(new_image.as_vector(keep_channels=True), axis=1), 0, atol=1e-10) assert_allclose(np.linalg.norm(new_image.as_vector(keep_channels=True), axis=1), 1)
def test_normalize_norm_masked_per_channel(): pixels = np.random.randn(3, 120, 120) pixels[1] *= 7 pixels[0] += -14 pixels[2] /= 130 image = MaskedImage(pixels) image.normalize_norm_inplace(mode='per_channel') assert_allclose( np.mean(image.as_vector(keep_channels=True), axis=1), 0, atol=1e-10) assert_allclose( np.linalg.norm(image.as_vector(keep_channels=True), axis=1), 1)
def test_normalize_norm_masked(): pixels = np.random.randn(3, 120, 120) pixels[1] *= 7 pixels[0] += -14 pixels[2] /= 130 mask = np.zeros((120, 120)) mask[30:50, 20:30] = 1 image = MaskedImage(pixels, mask=mask) with warnings.catch_warnings(): warnings.simplefilter("ignore") new_image = image.normalize_norm(mode="per_channel", limit_to_mask=True) assert_allclose(np.mean(new_image.as_vector(keep_channels=True), axis=1), 0, atol=1e-10) assert_allclose(np.linalg.norm(new_image.as_vector(keep_channels=True), axis=1), 1)
def test_normalize_std_masked(): pixels = np.random.randn(3, 120, 120) pixels[1] *= 7 pixels[0] += -14 pixels[2] /= 130 mask = np.zeros((120, 120)) mask[30:50, 20:30] = 1 image = MaskedImage(pixels, mask=mask) image.normalize_std_inplace(mode='per_channel', limit_to_mask=True) assert_allclose( np.mean(image.as_vector(keep_channels=True), axis=1), 0, atol=1e-10) assert_allclose( np.std(image.as_vector(keep_channels=True), axis=1), 1)
def test_dilate(): img = MaskedImage.init_blank((10, 10)) img = img.erode(n_pixels=3) img2 = img.dilate() assert(img2.mask.n_true() == 32) img3 = img.dilate(n_pixels=3) assert(img3.mask.n_true() == 76)
def build_patch_reference_frame(landmarks, boundary=3, group='source', patch_shape=(17, 17)): r""" Builds a patch-based reference frame from a particular set of landmarks. Parameters ---------- landmarks : `menpo.shape.PointCloud` The landmarks that will be used to build the reference frame. boundary : `int`, optional The number of pixels to be left as a safe margin on the boundaries of the reference frame (has potential effects on the gradient computation). group : `str`, optional Group that will be assigned to the provided set of landmarks on the reference frame. patch_shape : (`int`, `int`), optional The shape of the patches. Returns ------- patch_based_reference_frame : `menpo.image.MaskedImage` The patch-based reference frame. """ boundary = np.max(patch_shape) + boundary reference_frame = MaskedImage.init_from_pointcloud( landmarks, group=group, boundary=boundary, constrain_mask=False) # mask reference frame return reference_frame.constrain_mask_to_patches_around_landmarks( patch_shape, group=group)
def build_reference_frame(landmarks, boundary=3, group='source'): r""" Builds a reference frame from a particular set of landmarks. Parameters ---------- landmarks : `menpo.shape.PointCloud` The landmarks that will be used to build the reference frame. boundary : `int`, optional The number of pixels to be left as a safe margin on the boundaries of the reference frame (has potential effects on the gradient computation). group : `str`, optional Group that will be assigned to the provided set of landmarks on the reference frame. Returns ------- reference_frame : `manpo.image.MaskedImage` The reference frame. """ if not isinstance(landmarks, TriMesh): warnings.warn('The reference shape passed is not a TriMesh or ' 'subclass and therefore the reference frame (mask) will ' 'be calculated via a Delaunay triangulation. This may ' 'cause small triangles and thus suboptimal warps.', MenpoFitModelBuilderWarning) return MaskedImage.init_from_pointcloud(landmarks, boundary=boundary, group=group, constrain_mask=True)
def test_warp_to_mask_masked_image_all_true(): img = MaskedImage.init_blank((10, 10), fill=2.5) template_mask = BooleanImage.init_blank((10, 10), fill=False) template_mask.pixels[:, :5, :5] = True t = Affine.init_identity(2) warped_img = img.warp_to_mask(template_mask, t) assert(type(warped_img) == MaskedImage)
def test_init_from_rolled_channels_masked(): p = np.empty([50, 60, 3]) example_mask = BooleanImage.init_blank((50, 60), fill=False) example_mask.pixels[0, :6, :6] = True im = MaskedImage.init_from_rolled_channels(p, mask=example_mask) assert im.n_channels == 3 assert im.height == 50 assert im.width == 60 assert im.mask.n_true() == 36
def test_constrain_mask_to_patches_around_landmarks_even(): img = MaskedImage.init_blank((10, 10)) img.landmarks['box'] = PointCloud(np.array([[0., 0.], [5., 0.], [5., 5.], [0., 5.]])) new_img = img.constrain_mask_to_patches_around_landmarks((2,2), group='box') assert(new_img.mask.n_true() == 9) assert_allclose(new_img.mask.pixels[:, 0, 0], True) assert_allclose(new_img.mask.pixels[:, 4:6, 0], True) assert_allclose(new_img.mask.pixels[:, 0, 4:6], True) assert_allclose(new_img.mask.pixels[:, 4:6, 4:6], True)
def test_constrain_mask_to_patches_around_landmarks_odd(): img = MaskedImage.init_blank((10, 10)) img.landmarks['box'] = PointCloud(np.array([[0., 0.], [5., 0.], [5., 5.], [0., 5.]])) new_img = img.constrain_mask_to_patches_around_landmarks((3,3), group='box') assert(new_img.mask.n_true() == 25) assert_allclose(new_img.mask.pixels[:, :2, :2], True) assert_allclose(new_img.mask.pixels[:, 4:7, :2], True) assert_allclose(new_img.mask.pixels[:, :2, 4:7], True) assert_allclose(new_img.mask.pixels[:, 4:7, 4:7], True)
def _build_reference_frame(landmarks, boundary=3, group='source'): # translate landmarks to the origin minimum = landmarks.bounds(boundary=boundary)[0] landmarks = Translation(-minimum).apply(landmarks) resolution = landmarks.range(boundary=boundary) reference_frame = MaskedImage.blank(resolution) reference_frame.landmarks[group] = landmarks return reference_frame
def test_constrain_mask_to_landmarks_convex_hull(): img = MaskedImage.init_blank((10, 10)) img.landmarks['box'] = PointCloud(np.array([[0., 0.], [5., 0.], [5., 5.], [0., 5.]])) img.constrain_mask_to_landmarks(group='box', point_in_pointcloud='convex_hull') example_mask = BooleanImage.init_blank((10, 10), fill=False) example_mask.pixels[0, :6, 1:6] = True assert(img.mask.n_true() == 30) assert_allclose(img.mask.pixels, example_mask.pixels)
def test_constrain_mask_to_landmarks_pwa(): img = MaskedImage.init_blank((10, 10)) img.landmarks['box'] = PointCloud(np.array([[0.0, 0.0], [5.0, 0.0], [5.0, 5.0], [0.0, 5.0]])) img.constrain_mask_to_landmarks(group='box') example_mask = BooleanImage.init_blank((10, 10), fill=False) example_mask.pixels[0, :6, :6] = True assert(img.mask.n_true() == 36) assert_allclose(img.mask.pixels, example_mask.pixels)
def test_set_boundary_pixels(): mask = np.ones((10, 10), dtype=np.bool) img = MaskedImage.init_blank((10, 10), mask=mask, fill=0., n_channels=1) new_img = img.set_boundary_pixels(value=2.) assert(new_img.mask.n_true() == 100) assert(~np.allclose(img.pixels, new_img.pixels)) assert_allclose(new_img.pixels[0, 1:-1, 1:-1], 0.) assert_allclose(new_img.pixels[0, :, 0], 2.) assert_allclose(new_img.pixels[0, 0, :], 2.) assert_allclose(new_img.pixels[0, :, -1], 2.) assert_allclose(new_img.pixels[0, -1, :], 2.)
def test_rescale_pixels_only_masked(): img = MaskedImage.init_blank((10, 10), n_channels=1, fill=1) img.pixels[0, 0, 0] = 0 img.pixels[0, 6:, 6:] = 2 img.mask.pixels[:, 6:, 6:] = False img_rescaled = img.rescale_pixels(0, 100) assert np.min(img_rescaled.pixels) == 0 assert np.max(img_rescaled.pixels) == 100 assert img_rescaled.pixels[0, 0, 0] == 0 assert img_rescaled.pixels[0, 1, 1] == 100 assert np.all(img_rescaled.mask.pixels == img.mask.pixels)
def test_normalize_norm_masked(): pixels = np.random.randn(3, 120, 120) pixels[1] *= 7 pixels[0] += -14 pixels[2] /= 130 mask = np.zeros((120, 120)) mask[30:50, 20:30] = 1 image = MaskedImage(pixels, mask=mask) image.normalize_norm_inplace(mode='per_channel', limit_to_mask=True) assert_allclose(np.mean(image.as_vector(keep_channels=True), axis=1), 0, atol=1e-10) assert_allclose( np.linalg.norm(image.as_vector(keep_channels=True), axis=1), 1)
def imageio_to_menpo(imio_reader, index): pixels = imio_reader.get_data(index) pixels = channels_to_front(pixels) if pixels.shape[0] == 4: # If normalize is False, then we return the alpha as an extra # channel, which can be useful if the alpha channel has semantic # meanings! if normalize: p = normalize_pixels_range(pixels[:3]) return MaskedImage(p, mask=pixels[-1].astype(np.bool), copy=False) else: return Image(pixels, copy=False) # Assumed not to have an Alpha channel if normalize: return Image(normalize_pixels_range(pixels), copy=False) else: return Image(pixels, copy=False)
def test_hog_channels_zhuramanan(): n_cases = 3 cell_size = np.random.randint(2, 10, [n_cases]) channels = np.random.randint(1, 4, [n_cases]) for i in range(n_cases): image = MaskedImage(np.random.randn(channels[i], 40, 40)) win_width = np.random.randint(3 * cell_size[i], 40, 1) win_height = np.random.randint(3 * cell_size[i], 40, 1) hog_img = hog(image, mode='dense', algorithm='zhuramanan', cell_size=cell_size[i], window_height=win_height[0], window_width=win_width[0], window_unit='pixels', window_step_vertical=3, window_step_horizontal=3, window_step_unit='pixels', padding=True, verbose=True) length_per_block = 31 n_blocks_horizontal = np.floor((win_width[0] / cell_size[i]) + 0.5) - 2 n_blocks_vertical = np.floor((win_height[0] / cell_size[i]) + 0.5) - 2 n_channels = n_blocks_horizontal * n_blocks_vertical * length_per_block assert_allclose(hog_img.n_channels, n_channels)
def test_imagewindowiterator_hog_padding(): n_cases = 5 image_width = np.random.randint(50, 250, [n_cases, 1]) image_height = np.random.randint(50, 250, [n_cases, 1]) window_step_horizontal = np.random.randint(1, 10, [n_cases, 1]) window_step_vertical = np.random.randint(1, 10, [n_cases, 1]) for i in range(n_cases): image = MaskedImage( np.random.randn(image_height[i, 0], image_width[i, 0], 1)) hog = image.features.hog( mode='dense', window_step_vertical=window_step_vertical[i, 0], window_step_horizontal=window_step_horizontal[i, 0], window_step_unit='pixels', padding=True) n_windows_horizontal = len( range(0, image_width[i, 0], window_step_horizontal[i, 0])) n_windows_vertical = len( range(0, image_height[i, 0], window_step_vertical[i, 0])) assert_allclose(hog.shape, (n_windows_vertical, n_windows_horizontal))
def test_windowiterator_lbp_padding(): n_cases = 5 image_width = np.random.randint(50, 250, [n_cases, 1]) image_height = np.random.randint(50, 250, [n_cases, 1]) window_step_horizontal = np.random.randint(1, 10, [n_cases, 1]) window_step_vertical = np.random.randint(1, 10, [n_cases, 1]) for i in range(n_cases): image = MaskedImage( np.random.randn(1, image_height[i, 0], image_width[i, 0])) lbp_img = lbp(image, window_step_vertical=window_step_vertical[i, 0], window_step_horizontal=window_step_horizontal[i, 0], window_step_unit='pixels', padding=True) n_windows_horizontal = len( range(0, image_width[i, 0], window_step_horizontal[i, 0])) n_windows_vertical = len( range(0, image_height[i, 0], window_step_vertical[i, 0])) assert_allclose(lbp_img.shape, (n_windows_vertical, n_windows_horizontal))
def test_dsift_channels(): from menpo.feature import dsift n_cases = 3 num_bins_horizontal = np.random.randint(1, 3, [n_cases, 1]) num_bins_vertical = np.random.randint(1, 3, [n_cases, 1]) num_or_bins = np.random.randint(7, 9, [n_cases, 1]) cell_size_horizontal = np.random.randint(1, 10, [n_cases, 1]) cell_size_vertical = np.random.randint(1, 10, [n_cases, 1]) channels = np.random.randint(1, 4, [n_cases]) for i in range(n_cases): image = MaskedImage(np.random.randn(channels[i], 40, 40)) dsift_img = dsift(image, window_step_horizontal=1, window_step_vertical=1, num_bins_horizontal=num_bins_horizontal[i, 0], num_bins_vertical=num_bins_vertical[i, 0], num_or_bins=num_or_bins[i, 0], cell_size_horizontal=cell_size_horizontal[i, 0], cell_size_vertical=cell_size_vertical[i, 0]) n_channels = (num_bins_horizontal[i, 0] * num_bins_vertical[i, 0] * num_or_bins[i, 0]) assert_allclose(dsift_img.n_channels, n_channels)
def rasterize_mesh(self, mesh): r"""Rasterize a mesh to an image. Parameters ---------- mesh : object implementing the Rasterizable interface. Returns ------- rgb_image : 3 channel MaskedImage of shape (width, height) The result of the rasterization. Mask is true iff the pixel was rendered to by OpenGL. """ self._set_active_program_by_mesh_type(mesh) per_vertex_f3v = np.zeros(mesh.points.shape, dtype=np.float32) rgb_pixels, _, mask = self._rasterize(mesh, per_vertex_f3v, fetch_f3v=False) image = MaskedImage.init_from_channels_at_back(rgb_pixels, mask=mask) image.landmarks = self.model_to_image_transform.apply(mesh.landmarks) return image
def steepest_descent_images(self, image, dW_dp, forward=None): # compute gradient # gradient: height x width x n_channels gradient_img = self._calculate_gradients(image, forward=forward) # reshape gradient # gradient: n_pixels x (n_channels x n_dims) gradient = gradient_img.as_vector(keep_channels=True) # reshape gradient # gradient: n_pixels x n_channels x n_dims gradient = np.reshape(gradient, (-1, image.n_channels, image.n_dims)) # compute steepest descent images # gradient: n_pixels x n_channels x x n_dims # dW_dp: n_pixels x x n_params x n_dims # sdi: n_pixels x n_channels x n_params sdi = np.sum(dW_dp[:, None, :, :] * gradient[:, :, None, :], axis=3) # make sdi images # sdi_img: shape x n_channels x n_params sdi_img_channels = image.n_channels * dW_dp.shape[1] sdi_img = MaskedImage.blank(gradient_img.shape, n_channels=sdi_img_channels, mask=gradient_img.mask) sdi_img.from_vector_inplace(sdi.flatten()) # compute FFT over each channel, parameter and dimension # fft_sdi: height x width x n_channels x n_params fft_axes = range(image.n_dims) fft_sdi = fftshift(fftn(sdi_img.pixels, axes=fft_axes), axes=fft_axes) # ToDo: Note that, fft_sdi is rectangular, i.e. is not define in # terms of the mask pixels, but in terms of the whole image. # Selecting mask pixels once the fft has been computed makes no # sense because they have lost their original spatial meaning. # reshape steepest descent images # sdi: (height x width x n_channels) x n_params return np.reshape(fft_sdi, (-1, dW_dp.shape[1]))
def create_feature_space(feature_matrix, example_image, feature_space_name, subject_id, out_path='/vol/atlas/homes/pts08'): feature_space_images = [] N = feature_matrix.shape[0] for i, n in enumerate(feature_matrix): new_im = MaskedImage.blank(example_image.shape, mask=example_image.mask, n_channels=n.shape[1]) new_im.from_vector_inplace(n.flatten()) new_im.landmarks = example_image.landmarks feature_space_images.append(new_im) print_replace_line('Image {0} of {1}'.format(i + 1, N)) out_file_name = 'frgc_spring2003_68_{0}_{1}.pkl'.format( subject_id, feature_space_name) out_file_path = os.path.join(out_path, out_file_name) with open(out_file_path, 'wb') as f: cPickle.dump(feature_space_images, f, protocol=2) return feature_space_images
def svs_image(self, xr=None, yr=None): w = len(xr) h = len(yr) img = MaskedImage.init_blank((w, h)) for i, x in enumerate(xr): for j, y in enumerate(yr): pix = self.svs.decision_function([[x, y]])[0] # pix = 1 if pix > 1 else pix # pix = 0 if pix < 0 else pix img.pixels[0, i, j] = pix minp = np.min(img.pixels) maxp = np.max(img.pixels) img.pixels = (img.pixels - minp) / (maxp-minp) reject_level = img.pixels[0, 0, 0] + 0.05 for i, x in enumerate(xr): for j, y in enumerate(yr): if img.pixels[0, i, j] <= reject_level: img.pixels[0, i, j] = 0 return img
def test_hog_channels_dalaltriggs(): n_cases = 3 cell_size = np.random.randint(1, 10, [n_cases, 1]) block_size = np.random.randint(1, 3, [n_cases, 1]) num_bins = np.random.randint(7, 9, [n_cases, 1]) channels = np.random.randint(1, 4, [n_cases, 1]) for i in range(n_cases): image = MaskedImage(np.random.randn(channels[i, 0], 40, 40)) block_size_pixels = cell_size[i, 0] * block_size[i, 0] window_width = np.random.randint(block_size_pixels, 40, 1) window_height = np.random.randint(block_size_pixels, 40, 1) hog_img = hog(image, mode='dense', algorithm='dalaltriggs', cell_size=cell_size[i, 0], block_size=block_size[i, 0], num_bins=num_bins[i, 0], window_height=window_height[0], window_width=window_width[0], window_unit='pixels', window_step_vertical=3, window_step_horizontal=3, window_step_unit='pixels', padding=True) length_per_block = block_size[i, 0] * block_size[i, 0] * num_bins[i, 0] n_blocks_horizontal = len(range(block_size_pixels - 1, window_width[0], cell_size[i, 0])) n_blocks_vertical = len(range(block_size_pixels - 1, window_height[0], cell_size[i, 0])) n_channels = n_blocks_horizontal * n_blocks_vertical * length_per_block assert_allclose(hog_img.n_channels, n_channels)
def build(self): r""" Read the image using PIL and then use the :map:`Image` constructor to create a class. """ import PIL.Image as PILImage self._pil_image = PILImage.open(self.filepath) mode = self._pil_image.mode if mode == 'RGBA': # If normalise is False, then we return the alpha as an extra # channel, which can be useful if the alpha channel has semantic # meanings! if self.normalise: alpha = np.array(self._pil_image)[..., 3].astype(np.bool) image_pixels = self._pil_to_numpy(True, convert='RGB') image = MaskedImage(image_pixels, mask=alpha, copy=False) else: # With no normalisation we just return the pixels image = Image(self._pil_to_numpy(False), copy=False) elif mode in ['L', 'I', 'RGB']: # Greyscale, Integer and RGB images image = Image(self._pil_to_numpy(self.normalise), copy=False) elif mode == '1': # Can't normalise a binary image image = BooleanImage(self._pil_to_numpy(False), copy=False) elif mode == 'P': # Convert pallete images to RGB image = Image(self._pil_to_numpy(self.normalise, convert='RGB')) elif mode == 'F': # Floating point images # Don't normalise as we don't know the scale image = Image(self._pil_to_numpy(False), copy=False) else: raise ValueError('Unexpected mode for PIL: {}'.format(mode)) return image
def build(self): import imageio pixels = imageio.imread(self.filepath) pixels = channels_to_front(pixels) transparent_types = {'.png'} filepath = Path(self.filepath) if pixels.shape[0] == 4 and filepath.suffix in transparent_types: # If normalise is False, then we return the alpha as an extra # channel, which can be useful if the alpha channel has semantic # meanings! if self.normalise: p = normalise_pixels_range(pixels[:3]) return MaskedImage(p, mask=pixels[-1].astype(np.bool), copy=False) else: return Image(pixels, copy=False) # Assumed not to have an Alpha channel if self.normalise: return Image(normalise_pixels_range(pixels), copy=False) else: return Image(pixels, copy=False)
def test_rescale_negative_single_num(): image = MaskedImage(np.random.randn(120, 120, 3)) image.rescale(-0.5)
def test_rescale_negative(): image = MaskedImage(np.random.randn(120, 120, 3)) image.rescale([0.5, -0.5])
def test_masked_image_as_unmasked(): m_img = MaskedImage(np.random.rand(1, 3, 3), copy=False) img = m_img.as_unmasked() assert type(img) == Image assert_allclose(m_img.pixels, img.pixels)
def test_resize(): image = MaskedImage(np.random.randn(120, 120, 3)) new_size = (250, 250) new_image = image.resize(new_size) assert_allclose(new_image.shape, new_size)
def test_as_greyscale_average(): image = MaskedImage(np.ones([120, 120, 3])) new_image = image.as_greyscale(mode='average') assert (new_image.shape == image.shape) assert (new_image.n_channels == 1)
def test_as_greyscale_luminosity(): image = MaskedImage(np.ones([120, 120, 3])) new_image = image.as_greyscale(mode='luminosity') assert (new_image.shape == image.shape) assert (new_image.n_channels == 1)
def test_as_greyscale_channels(): image = MaskedImage(np.random.randn(120, 120, 3)) new_image = image.as_greyscale(mode='channel', channel=0) assert (new_image.shape == image.shape) assert (new_image.n_channels == 1) assert_allclose(new_image.pixels[..., 0], image.pixels[..., 0])
def test_constrain_mask_to_landmarks_unknown_key(): img = MaskedImage.init_blank((10, 10)) img.landmarks['box'] = PointCloud(np.array([[0., 0., 0.]])) img.constrain_mask_to_landmarks(point_in_pointcloud='unknown')
def test_as_pil_image_bad_range(): im = MaskedImage(np.random.randn(120, 120, 1)) im.as_PILImage()
def _rasterize_texture_with_interp(self, points, trilist, texture, tcoords, normals=None, per_vertex_f3v=None): r"""Rasterizes a textured mesh along with it's interpolant data through OpenGL. Parameters ---------- r : object Any object with fields named 'points', 'trilist', 'texture' and 'tcoords' specifying the data that will be used to render. Such objects are handed out by the _rasterize_generate_textured_mesh method on Rasterizable subclasses normals : ndarray, shape (n_points, 3) A matrix specifying custom per-vertex normals to be used. If omitted, the normals will be calculated from the triangulation of triangle normals. per_vertex_f3v : ndarray, shape (n_points, 3), optional A matrix specifying arbitrary 3 floating point numbers per vertex. This data will be linearly interpolated across triangles and returned in the f3v image. If none, the shape information is used Returns ------- image : MaskedImage The rasterized image returned from OpenGL. Note that the behavior of the rasterization is governed by the projection, rotation and view matrices that may be set on this class, as well as the width and height of the rasterization, which is determined on the creation of this class. The mask is True if a triangle is visible at that pixel in the output, and False if not. f3v_image : MaskedImage The rasterized image returned from OpenGL. Note that the behavior of the rasterization is governed by the projection, rotation and view matrices that may be set on this class, as well as the width and height of the rasterization, which is determined on the creation of this class. """ # make a call out to the CyRasterizer _rasterize method # first, roll the axes to get things to the way OpenGL expects them texture = np.rollaxis(texture, 0, len(texture.shape)) rgb_pixels, f3v_pixels, mask = self._rasterize( points, trilist, texture, tcoords, normals=normals, per_vertex_f3v=per_vertex_f3v) # roll back the results so things are as Menpo expects return (MaskedImage(np.array(np.rollaxis(rgb_pixels, -1), dtype=np.float), mask=mask), MaskedImage(np.array(np.rollaxis(f3v_pixels, -1), dtype=np.float), mask=mask))
def test_as_pil_image_3channels(): im = MaskedImage(np.ones((120, 120, 3))) new_im = im.as_PILImage() assert_allclose( np.asarray(new_im.getdata()).reshape(im.pixels.shape), (im.pixels * 255).astype(np.uint8))
def test_init_from_rolled_channels(): p = np.empty([50, 60, 3]) im = MaskedImage.init_from_rolled_channels(p) assert im.n_channels == 3 assert im.height == 50 assert im.width == 60
def test_erode(): img = MaskedImage.init_blank((10, 10)) img2 = img.erode() assert (img2.mask.n_true() == 64) img3 = img.erode(n_pixels=3) assert (img3.mask.n_true() == 16)
def pillow_importer(filepath, asset=None, normalize=True, **kwargs): r""" Imports an image using PIL/pillow. Different image modes cause different importing strategies. RGB, L, I: Imported as either `float` or `uint8` depending on normalisation flag. RGBA: Imported as :map:`MaskedImage` if normalize is ``True`` else imported as a 4 channel `uint8` image. 1: Imported as a :map:`BooleanImage`. Normalisation is ignored. F: Imported as a floating point image. Normalisation is ignored. Parameters ---------- filepath : `Path` Absolute filepath of image asset : `object`, optional An optional asset that may help with loading. This is unused for this implementation. normalize : `bool`, optional If ``True``, normalize between 0.0 and 1.0 and convert to float. If ``False`` just pass whatever PIL imports back (according to types rules outlined in constructor). \**kwargs : `dict`, optional Any other keyword arguments. Returns ------- image : :map:`Image` or subclass The imported image. """ import PIL.Image as PILImage if isinstance(filepath, Path): filepath = str(filepath) pil_image = PILImage.open(filepath) mode = pil_image.mode if mode == 'RGBA': # If normalize is False, then we return the alpha as an extra # channel, which can be useful if the alpha channel has semantic # meanings! if normalize: alpha = np.array(pil_image)[..., 3].astype(np.bool) image_pixels = _pil_to_numpy(pil_image, True, convert='RGB') image = MaskedImage(image_pixels, mask=alpha, copy=False) else: # With no normalisation we just return the pixels image = Image(_pil_to_numpy(pil_image, False), copy=False) elif mode in ['L', 'I', 'RGB']: # Greyscale, Integer and RGB images image = Image(_pil_to_numpy(pil_image, normalize), copy=False) elif mode == '1': # Convert to 'L' type (http://stackoverflow.com/a/4114122/1716869). # Can't normalize a binary image image = BooleanImage(_pil_to_numpy(pil_image, False, convert='L'), copy=True) elif mode == 'P': # Convert pallete images to RGB image = Image(_pil_to_numpy(pil_image, normalize, convert='RGB')) elif mode == 'F': # Floating point images # Don't normalize as we don't know the scale image = Image(_pil_to_numpy(pil_image, False), copy=False) else: raise ValueError('Unexpected mode for PIL: {}'.format(mode)) return image
def test_as_greyscale_channels_no_index(): image = MaskedImage(np.ones([120, 120, 3])) new_image = image.as_greyscale(mode='channel') assert (new_image.shape == image.shape) assert (new_image.n_channels == 1)
def test_rescale_boundaries_interpolation(): image = MaskedImage(np.random.randn(60, 60, 3)) for i in [x * 0.1 for x in range(1, 31)]: image_rescaled = image.rescale(i) assert_allclose(image_rescaled.mask.proportion_true(), 1.0)
def test_constrain_mask_to_landmarks_non_2d(): img = MaskedImage.init_blank((10, 10, 10)) img.landmarks['box'] = PointCloud(np.array([[0., 0., 0.]])) img.constrain_mask_to_landmarks()