def test_get_rgb_image(): """Test conversion of true RGB from multispectral image""" testing.needs_internet() hsi_file = testing.get_remote_file(TEST_HSI_FILENAME) hsi = SpectralArray(np.load(hsi_file), dtype=np.float32) rgb_file = testing.get_remote_file(TEST_RGB_FILENAME) rgb = (imageio.imread(rgb_file) / 255.0).astype(np.float64) grey_file = testing.get_remote_file(TEST_GREY_FILENAME) grey = (imageio.imread(grey_file) / 255.0).astype(np.float64)[..., np.newaxis] assert np.allclose(rgb, hsi.get_rgb(), atol=0.01) # Test 1D real spectrum conversion for x, y in zip([0, 10, 20], [10, 100, 200]): spectrum = hsi[x, y, :] rgb_point = rgb[x, y, :] assert np.allclose(rgb_point, spectrum.get_rgb(), atol=0.01) # Calculate black and white from rgb grey_from_hsi = hsi.get_grey(weighted=True) grey_from_rgb = SpectralArray(rgb, dtype=np.float32).get_grey(weighted=True) grey_from_grey = SpectralArray(grey, dtype=np.float32).get_grey(weighted=True) assert np.allclose(grey, grey_from_grey, atol=0.01) assert np.allclose(grey, grey_from_rgb, atol=0.01) assert np.allclose(grey, grey_from_hsi, atol=0.01) return
def test_get_edges(): """This only tests for failure, not for correct edge detection...""" testing.needs_internet() im_file = testing.get_remote_file(TEST_GREY_FILENAME) im = imageio.imread(im_file) methods = ["scharr", "sobel", "dog", "log", "gradient"] for method in methods: edge = images.get_edges(im, method=method) # Test kwargs options for DOG, LOG edge = images.get_edges(im, method='log', sigma=4) edge = images.get_edges(im, method='dog', sigma=4) # Color input im_file = testing.get_remote_file(TEST_RGB_FILENAME) im = imageio.imread(im_file) with raises(ValueError) as cm: images.get_gradients(im, method='scharr') assert "Gradient calculation only works on 2D images right now. " \ "For multi-dimensional arrays, use numpy's gradient() instead." == str(cm.value) return
def create_test_camera(): """Download the Raytracer test camera, if not already present.""" testing.needs_internet() for ext in [".png", ".json"]: testing.get_remote_file("cameras/RayTracerSmall/Calibration/cal_img" + ext) testing.get_remote_file("cameras/RayTracerSmall/Images/example_img" + ext) return
def create_test_lytro_camera_small(): """Download the Lytro test camera, if not already present.""" testing.needs_internet() for file in ["MOD_0001", "MOD_0016", "MOD_0033"]: testing.get_remote_file("cameras/LytroIllumSmall/Calibration/" + file + ".bsdf") testing.get_remote_file("cameras/LytroIllumSmall/Images/IIIT.bsdf") return
def create_test_camera() -> Tuple[Path, UUID]: """ Helper function to create a test camera folder structure with images. """ testing.needs_internet() # Get a temporary folder path, id = testing.get_tmp_folder() try: # Create folder structure for folder in FOLDERS: try: (path / folder).mkdir() except FileExistsError: pass img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imageio.imread(img_file) # Mosaic img = mosaic(img) # Save test image, rotated image and BW image imageio.imsave(path / FILES[0], img) imageio.imsave(path / FILES[1], np.flipud(img)) imageio.imsave(path / FILES[2], (255 * img).astype(np.uint8)) imageio.imsave(path / FILES[3], img) imageio.imsave(path / FILES[4], np.flipud(img)) imageio.imsave(path / FILES[5], (255 * img).astype(np.uint8)) except: delete_test_camera(path, id) return path, id
def test_abstract_camera_load_sensor_image(): try: # Create camera folder structure path, id = create_test_camera() # Create a mock patch to test abstract base class ABC_PATCH.start() test_camera = AbstractCamera(path) img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) test_camera.load_sensor_image(0) test_camera.load_sensor_image(1) # Check that images have been read correctly assert test_camera._sensorImages[0].is_loaded() is True assert test_camera._sensorImages[1].is_loaded() is True assert test_camera._sensorImages[2].is_loaded() is False assert np.array_equal(img, test_camera.get_sensor_image(0)) assert np.array_equal(np.flipud(img), test_camera.get_sensor_image(1)) with raises(ValueError) as cm: test_camera.load_sensor_image(3) assert (f"There is no Sensor image with number '3'.") == str(cm.value) ABC_PATCH.stop() finally: # Always clean up delete_test_camera(path, id) return
def test_abstract_camera_load_sensor_image_from_path(): try: # Create camera folder structure path, id = create_test_camera() # Create a mock patch to test abstract base class ABC_PATCH.start() test_camera = AbstractCamera(path) img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) assert len(test_camera._sensorImages) == 3 test_camera.load_sensor_image_from_path(path=img_file) assert len(test_camera._sensorImages) == 4 # Check that images have been read correctly assert np.array_equal(img, test_camera.get_sensor_image(3)) ABC_PATCH.stop() finally: # Always clean up delete_test_camera(path, id) return
def test_rgb_camera(): testing.needs_internet() try: # Create camera folder structure path, id = create_test_camera() test_camera = RgbCamera(path, bayer_pattern=PATTERN) img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imageio.imread(img_file) img = mosaic(img) img = demosaic.get_demosaiced(img, pattern=PATTERN, method='malvar2004') img = np.clip(img, 0, 255) / 255.0 assert test_camera._bayerPattern == PATTERN test_camera.load_sensor_image(0) test_camera.decode_sensor_image(0) tmp = test_camera.get_decoded_image(0) # Test that demosaiced image is close to original assert img.shape == tmp.shape assert np.allclose(img, tmp, atol=0.05) finally: # Always clean up delete_test_camera(path, id) return
def test_from_mat(): testing.needs_internet() # Get a temporary folder path, id = testing.get_tmp_folder() try: path = path / "test_hsi.mat" hsi_file = testing.get_remote_file(TEST_HSI_FILENAME) hsi = np.load(hsi_file) mdict = dict(data=hsi) scipy.io.savemat(path, mdict) # Try loading with and without key for key in [None, 'data']: tmp = SpectralImage.from_mat_file(path=path, key=key) assert np.allclose(hsi, tmp) finally: # Cleanup temporary folder testing.remove_tmp_folder(id) return
def test_abstract_camera_load_sensor_image_all(): try: # Create camera folder structure path, id = create_test_camera() # Create a mock patch to test abstract base class ABC_PATCH.start() test_camera = AbstractCamera(path) img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) test_camera.load_sensor_image("all") # Check that images have been read correctly assert test_camera._sensorImages[0].is_loaded() is True assert test_camera._sensorImages[1].is_loaded() is True assert test_camera._sensorImages[2].is_loaded() is True assert np.array_equal(img, test_camera.get_sensor_image(0)) assert np.array_equal(np.flipud(img), test_camera.get_sensor_image(1)) assert np.array_equal((rgb2gray(img) * 255).astype(np.uint8), test_camera.get_sensor_image(2)) ABC_PATCH.stop() finally: # Always clean up delete_test_camera(path, id) return
def test_from_file_collection(): testing.needs_internet() for i in range(1, 32): fname = TEST_FILE_COLLECTION + f"balloons_ms_{i:02d}.png" testing.get_remote_file(fname) # Read from file collection path = testing.appdata_dir(APPNAME) / TEST_FILE_COLLECTION tmp = SpectralImage.from_file_collection(path=path) hsi_file = testing.get_remote_file(TEST_HSI_FILENAME) hsi = np.load(hsi_file) assert np.allclose(hsi, tmp) return
def test_from_file(): """Test from_file() classmethod. Read RGB image.""" testing.needs_internet() rgb_file = testing.get_remote_file(TEST_RGB_FILENAME) rgb = (imageio.imread(rgb_file) / 255.0).astype(np.float32) tmp = SpectralImage.from_file(rgb_file, format='PNG', dtype=np.float32) assert np.allclose(rgb, tmp) grey_file = testing.get_remote_file(TEST_GREY_FILENAME) grey = (imageio.imread(grey_file) / 255.0).astype(np.float32) assert grey.ndim == 2 tmp = SpectralImage.from_file(grey_file, format='PNG', dtype=np.float32) assert tmp.ndim == 3 return
def test_sensor_image_init(): img_file = testing.get_remote_file(TEST_IMG_FILENAME) test_sensor_image = SensorImage(img_file) assert test_sensor_image.imagePath == img_file assert test_sensor_image._SensorImage__image is None assert test_sensor_image.is_loaded() is False assert test_sensor_image.is_decoded() is False assert test_sensor_image._SensorImage__metadata is None return
def test_plot_fft(): # Check Color img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imageio.imread(img_file) # Crop image to (256,512) to increase fft speed img = img[:256, :512, :] assert plots.plot_fft(img) is None # Check odd shape img_odd_x = img[:-1, :] assert plots.plot_fft(img_odd_x) is None img_odd_y = img[:, :-1] assert plots.plot_fft(img_odd_y) is None img_odd_xy = img[:-1, :-1] assert plots.plot_fft(img_odd_xy) is None # Check BW img = rgb2gray(img) assert plots.plot_fft(img) is None # Check BW squeeze img = np.squeeze(img) assert plots.plot_fft(img) is None # Check shape error with raises(ValueError) as cm: plots.plot_fft(np.ones((100, 100, 100, 3))) # Check options assert plots.plot_fft(img, implementation='scipy') is None assert plots.plot_fft(img, implementation='numpy') is None assert plots.plot_fft(img, window='hann') is None assert plots.plot_fft(img, interpolation=None) is None assert plots.plot_fft(img, cmap='viridis') is None assert plots.plot_fft(img, vmin=2.0, vmax=5) is None assert plots.plot_fft(img, rescale=False) is None assert plots.plot_fft(img, shift=False) is None assert plots.plot_fft(img, plt_show=False) is None # Test error handling with raises(ValueError) as cm: plots.plot_fft(img, implementation='nonsense') assert ("The implementation 'nonsense' is not one of the " "supported implementations, ['numpy', 'scipy', 'fftw'].") == str( cm.value) return
def test_sensor_image_get_metadata(): img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) test_sensor_image = SensorImage(img_file) with raises(RuntimeError) as cm: test_sensor_image.get_metadata() assert ("The image is not loaded yet. " "Load the image with 'load()' first.") == str(cm.value) test_sensor_image.load() assert np.array_equal(test_sensor_image.get_metadata(), img._meta) return
def create_test_lytro_camera(): """Download the Lytro test camera, if not already present.""" testing.needs_internet() for file in ["MOD_0033"]: testing.get_remote_file("cameras/LytroIllum/Calibration/" + file + ".RAW") testing.get_remote_file("cameras/LytroIllum/Calibration/" + file + ".TXT") testing.get_remote_file("cameras/LytroIllum/Images/IIIT.LFR") return
def test_sensor_image_load(): img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) test_sensor_image = SensorImage(img_file) assert test_sensor_image.is_loaded() is False assert test_sensor_image.is_decoded() is False test_sensor_image.load() assert test_sensor_image.is_loaded() is True assert test_sensor_image.is_decoded() is False assert np.array_equal(test_sensor_image._SensorImage__image, img) assert test_sensor_image._SensorImage__metadata is not None return
def test_sensor_image_set_decoded(): img_file = testing.get_remote_file(TEST_IMG_FILENAME) test_sensor_image = SensorImage(img_file) with raises(ValueError) as cm: test_sensor_image.set_decoded("nonsense") assert "The passed value 'nonsense' is not of type Bool" == str(cm.value) with raises(ValueError) as cm: test_sensor_image.set_decoded(3) assert "The passed value '3' is not of type Bool" == str(cm.value) assert test_sensor_image.is_decoded() is False test_sensor_image.set_decoded(True) assert test_sensor_image.is_decoded() is True return
def test_band_info_envi(): """Test ``from_envi`` class method. """ testing.needs_internet() envi_file = testing.get_remote_file(TEST_ENVI_HDR) d = SpectralArray.read_envi_header(envi_file) band_info = BandInfo.from_envi_header(d) centers_exp = np.asarray([400.6, 450.3, 500, 551.7, 600.666, 760.9]) bandwiths_exp = np.asarray([1.1, 1.2, 1.3, 1.4, 1.5, 1.6]) assert 6 == band_info.num_channels assert band_info.type is None assert band_info.centers_std is None assert band_info.bandwidths_std is None assert np.array_equal(centers_exp, band_info.centers) assert np.array_equal(bandwiths_exp, band_info.bandwidths) return
def create_test_camera() -> Tuple[Path, UUID]: """ Helper function to create a test camera folder structure with images. """ testing.needs_internet() # Get a temporary folder path, id = testing.get_tmp_folder() try: # Create folder structure for folder in FOLDERS: try: (path / folder).mkdir() except FileExistsError: pass img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) # Save test image imsave(path / FILES[0], img) # Create greyscale whiteimages whiteimg_1 = (255 * np.ones( (img.shape[0], img.shape[1]))).astype(np.uint8) whiteimg_2 = (127 * np.ones( (img.shape[0], img.shape[1]))).astype(np.uint8) # Save whiteimages imsave(path / FILES[1], whiteimg_1) imsave(path / FILES[2], whiteimg_2) except: delete_test_camera(path, id) return path, id
def test_abstract_camera_decoded_image(): try: # Create camera folder structure path, id = create_test_camera() # Create a mock patch to test abstract base class ABC_PATCH.start() test_camera = AbstractCamera(path) img_file = testing.get_remote_file(TEST_IMG_FILENAME) img = imread(img_file) # Load image test_camera.load_sensor_image(0) assert test_camera._sensorImages[0].is_loaded() is True assert test_camera._sensorImages[0].is_decoded() is False # Decode image test_camera._add_decoded_image(img, 0) assert test_camera._sensorImages[0].is_decoded() is True assert np.array_equal(img, test_camera.get_decoded_image(0)) with raises(ValueError) as cm: test_camera.get_decoded_image(1) assert f"Image number 1 is not decoded yet." == str(cm.value) with raises(ValueError) as cm: test_camera.get_decoded_image(4) assert (f"There is no Sensor image with number '4'.") == str(cm.value) ABC_PATCH.stop() finally: # Always clean up delete_test_camera(path, id) return