def test_lbp_values(): image = MaskedImage([[0., 6., 0.], [5., 18., 13.], [0., 20., 0.]]) lbp = image.features.lbp(radius=1, samples=4, mapping_type='none', padding=False) assert_allclose(lbp.pixels, 8.) image = MaskedImage([[0., 6., 0.], [5., 25., 13.], [0., 20., 0.]]) lbp = image.features.lbp(radius=1, samples=4, mapping_type='riu2', padding=False) assert_allclose(lbp.pixels, 0.) image = MaskedImage([[0., 6., 0.], [5., 13., 13.], [0., 20., 0.]]) lbp = image.features.lbp(radius=1, samples=4, mapping_type='u2', padding=False) assert_allclose(lbp.pixels, 8.) image = MaskedImage([[0., 6., 0.], [5., 6., 13.], [0., 20., 0.]]) lbp = image.features.lbp(radius=1, samples=4, mapping_type='ri', padding=False) assert_allclose(lbp.pixels, 4.)
def test_es_values(): image = MaskedImage([[1, 2], [2, 1]]) es = image.features.es() k = 1 / (2 * (2**0.5)) res = np.array([[[k, k], [-k, k]], [[k, -k], [-k, -k]]]) assert_allclose(es.pixels, res) image = MaskedImage([[0, 0], [0, 0]]) es = image.features.es() res = np.array([[[np.nan, np.nan], [np.nan, np.nan]], [[np.nan, np.nan], [np.nan, np.nan]]]) assert_allclose(es.pixels, res)
def _rasterize_texture_with_interp(self, points, trilist, texture, tcoords, 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 per_vertex_f3v: ndarray, shape (n_points, 3) 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, 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 rasterize_barycentric_coordinate_images(mesh, image_shape): h, w = image_shape yx, bcoords, tri_indices = rasterize_barycentric_coordinates( mesh, image_shape) tri_indices_img = np.zeros((1, h, w), dtype=int) bcoords_img = np.zeros((3, h, w)) mask = np.zeros((h, w), dtype=np.bool) mask[yx[:, 0], yx[:, 1]] = True tri_indices_img[:, yx[:, 0], yx[:, 1]] = tri_indices bcoords_img[:, yx[:, 0], yx[:, 1]] = bcoords.T mask = BooleanImage(mask) return (MaskedImage(bcoords_img, mask=mask.copy(), copy=False), MaskedImage(tri_indices_img, mask=mask.copy(), copy=False))
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_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_create_MaskedImage_copy_true_mask_BooleanImage(): pixels = np.ones((100, 100, 1)) mask = np.ones((100, 100), dtype=np.bool) mask_image = BooleanImage(mask, copy=False) image = MaskedImage(pixels, mask=mask_image, copy=True) assert (not is_same_array(image.pixels, pixels)) assert (not is_same_array(image.mask.pixels, mask))
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 = 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 self.normalise: return Image(normalize_pixels_range(pixels), copy=False) else: return Image(pixels, copy=False)
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 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_windowiterator_hog_no_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]) window_width = np.random.randint(3, 20, [n_cases, 1]) window_height = np.random.randint(3, 20, [n_cases, 1]) for i in range(n_cases): image = MaskedImage( np.random.randn(1, image_height[i, 0], image_width[i, 0])) hog_img = hog(image, mode='dense', cell_size=3, block_size=1, window_height=window_height[i, 0], window_width=window_width[i, 0], window_unit='pixels', window_step_vertical=window_step_vertical[i, 0], window_step_horizontal=window_step_horizontal[i, 0], window_step_unit='pixels', padding=False) n_windows_horizontal = len( range(window_width[i, 0] - 1, image_width[i, 0], window_step_horizontal[i, 0])) n_windows_vertical = len( range(window_height[i, 0] - 1, image_height[i, 0], window_step_vertical[i, 0])) assert_allclose(hog_img.shape, (n_windows_vertical, n_windows_horizontal))
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_imagewindowiterator_lbp_no_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]) radius = np.random.randint(3, 5, [n_cases, 1]) for i in range(n_cases): image = MaskedImage( np.random.randn(image_height[i, 0], image_width[i, 0], 1)) lbp = image.features.lbp( radius=radius[i, 0], samples=8, window_step_vertical=window_step_vertical[i, 0], window_step_horizontal=window_step_horizontal[i, 0], window_step_unit='pixels', padding=False) window_size = 2 * radius[i, 0] + 1 n_windows_horizontal = len( range(window_size - 1, image_width[i, 0], window_step_horizontal[i, 0])) n_windows_vertical = len( range(window_size - 1, image_height[i, 0], window_step_vertical[i, 0])) assert_allclose(lbp.shape, (n_windows_vertical, n_windows_horizontal))
def build(self): r""" Read the image using PIL and then use the :map:`Image` constructor to create a class. """ self._pil_image = PILImage.open(self.filepath) mode = self._pil_image.mode if mode == 'RGBA': # RGB with Alpha Channel # If we normalise it then we convert to floating point # and set the alpha channel to the mask 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) else: # With no normalisation we just return the pixels image = Image(self._pil_to_numpy(False)) elif mode in ['L', 'I', 'RGB']: # Greyscale, Integer and RGB images image = Image(self._pil_to_numpy(self.normalise)) elif mode == '1': # Can't normalise a binary image image = BooleanImage(self._pil_to_numpy(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)) else: raise ValueError('Unexpected mode for PIL: {}'.format(mode)) return image
def test_hog_channels_zhuramanan(): n_cases = 3 cell_size = np.random.randint(2, 10, [n_cases, 1]) channels = np.random.randint(1, 4, [n_cases, 1]) for i in range(n_cases): image = MaskedImage(np.random.randn(40, 40, channels[i, 0])) window_width = np.random.randint(3 * cell_size[i, 0], 40, 1) window_height = np.random.randint(3 * cell_size[i, 0], 40, 1) hog = image.features.hog(mode='dense', algorithm='zhuramanan', cell_size=cell_size[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 = 31 n_blocks_horizontal = round( np.float(window_width[0]) / np.float(cell_size[i, 0])) - 2 n_blocks_vertical = round( np.float(window_height[0]) / np.float(cell_size[i, 0])) - 2 n_channels = n_blocks_horizontal * n_blocks_vertical * length_per_block assert_allclose(hog.n_channels, n_channels)
def test_dsift_channels(): try: from menpo.feature import dsift except ImportError: skip("Cyvlfeat must be installed to run this unit test") 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 build(self): import re with open(self.filepath, 'r') as f: # Currently these are unused, but they are in the format # Could possibly store as metadata? # Assume first result for regexes re_rows = re.compile(u'([0-9]+) rows') n_rows = int(re_rows.findall(f.readline())[0]) re_cols = re.compile(u'([0-9]+) columns') n_cols = int(re_cols.findall(f.readline())[0]) # This also loads the mask # >>> image_data[:, 0] image_data = np.loadtxt(self.filepath, skiprows=3, unpack=True) # Replace the lowest value with nan so that we can render properly data_view = image_data[:, 1:] corrupt_value = np.min(data_view) data_view[np.any(np.isclose(data_view, corrupt_value), axis=1)] = np.nan return MaskedImage(np.rollaxis( np.reshape(data_view, [n_rows, n_cols, 3]), -1), np.reshape(image_data[:, 0], [n_rows, n_cols]).astype(np.bool), copy=False)
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 test_es_channels(): n_cases = 3 channels = np.random.randint(1, 10, [n_cases, 1]) for i in range(n_cases): image = MaskedImage(np.random.randn(40, 40, channels[i, 0])) es = image.features.es() assert_allclose(es.shape, image.shape) assert_allclose(es.n_channels, 2 * channels[i, 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_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_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.crop([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_igo_values(): image = MaskedImage([[1, 2], [2, 1]]) igo = image.features.igo() res = np.array( [[[math.cos(math.radians(45)), math.sin(math.radians(45))], [math.cos(math.radians(90 + 45)), math.sin(math.radians(90 + 45))]], [[math.cos(math.radians(-45)), math.sin(math.radians(-45))], [math.cos(math.radians(180 + 45)), math.sin(math.radians(180 + 45))]]]) assert_allclose(igo.pixels, res) image = MaskedImage([[0, 0], [0, 0]]) igo = image.features.igo() res = np.array([[[1., 0.], [1., 0.]], [[1., 0.], [1., 0.]]]) assert_allclose(igo.pixels, res)
def build(self): r""" Read the image using PIL and then use the :class:`menpo.image.base.MaskedImage` constructor to create a class. Normalise between 0 and 1.0 """ self._pil_image = PILImage.open(self.filepath) image_pixels = np.array(self._pil_image, dtype=np.float) / 255.0 return MaskedImage(image_pixels)
def test_2d_crop_without_mask(): pixels = np.ones((120, 120, 3)) im = MaskedImage(pixels) cropped_im = im.crop([10, 50], [20, 60]) assert (cropped_im.shape == (10, 10)) assert (cropped_im.n_channels == 3) assert (np.alltrue(cropped_im.shape))
def horn_brooks(intensity_image, initial_estimate, normal_model, light_vector, n_iters=100, c_lambda=0.001, mapping_object=IdentityMapper()): """ M. Brooks and B. Horn Shape and Source from Shading 1985 """ from scipy.signal import convolve2d # Ensure the light is a unit vector light_vector = normalise_vector(light_vector) # Equation (1): Should never be < 0 if image is properly scaled theta_vec = np.arccos(intensity_image.as_vector()) theta_image = intensity_image.from_vector(theta_vec) n_im = estimate_normals_from_intensity(initial_estimate, theta_image) average_kernel = np.array([[0.0, 0.25, 0.0], [0.25, 0.0, 0.25], [0.0, 0.25, 0.0]]) scale_constant = (1.0 / 4.0 * c_lambda) n_vec = n_im.as_vector(keep_channels=True) I_vec = intensity_image.as_vector() for i in xrange(n_iters): n_dot_s = np.sum(n_vec * light_vector, axis=1) # Calculate the average normal neighbourhood n_im.from_vector_inplace(n_vec) n_xs = convolve2d(n_im.pixels[:, :, 0], average_kernel, mode='same') n_ys = convolve2d(n_im.pixels[:, :, 1], average_kernel, mode='same') n_zs = convolve2d(n_im.pixels[:, :, 2], average_kernel, mode='same') n_bar = np.concatenate([n_xs[..., None], n_ys[..., None], n_zs[..., None]], axis=-1) n_bar = MaskedImage(n_bar, mask=n_im.mask).as_vector( keep_channels=True) rho = scale_constant * (I_vec - n_dot_s) m = n_bar + np.dot(rho[..., None], light_vector[..., None].T) n_im.from_vector_inplace(normalise_vector(m)) v0 = mapping_object.logmap(n_im) # Vector of best-fit parameters vprime = normal_model.reconstruct(v0) nprime = mapping_object.expmap(vprime) nprime = normalise_image(nprime) n_vec = nprime.as_vector(keep_channels=True) n_im.from_vector_inplace(n_vec) return normalise_image(n_im)
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_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))