def test_mask_crop(): passing = True # read in an image with a black border present f_in = Path(__file__).parent / "resources" / "images" / "c3574.png" f_in = str(f_in.resolve()) img_np, _, _ = read_file(f_in) # test first crop_img method cropped_img, size_changes = crop_img_borders(img_np) if not cropped_img.shape == (1024, 984): print("crop_img_borders returned wrong shape", cropped_img.shape) passing = False # test second crop_img method cropped_img, size_changes = crop_img_borders_by_edginess(img_np) if not cropped_img.shape == (1022, 984): passing = False # test uncrop with params method img_np_uncropped, _ = reverse_size_changes_to_img(cropped_img, [1.0, 1.0], size_changes) if not img_np_uncropped.shape == (1024, 1024): print("uncropped shape not as expected", img_np_uncropped.shape) passing = False # test set non-mask as constant mask_np = np.zeros(img_np.shape) mask_np[500:600, 500:600] = 1 masked_img = set_non_mask_constant(img_np, mask_np) # verify masked image is correct size if not masked_img.shape == img_np.shape: print("masked image has wrong shape", masked_img.shape) passing = False # verify pixels we reset are zero now and were not in original test_patch_masked = masked_img[0:450, 0:450] test_patch_unmasked = img_np[0:450, 0:450] if not np.all(test_patch_masked == 0): print("mask not applied correctly") passing = False if np.all(test_patch_unmasked == 0): print("orig image was already zero in test patch") passing = False assert passing
def test_cxrstandardization(): # read in and standardize an image # first get the file path relative to current location f_in = Path(__file__).parent / "resources" / "images" / "c0002.mha" f_in = str(f_in.resolve()) # read in the image img_np, spacing, pydata = read_file(f_in) # load the standardization algorithm cxrstandardize_algorithm = opencxr.load(opencxr.algorithms.cxr_standardize) # run the standardization algorithm on the test image # this will return the new image, the new spacing, and a dict of size changes carried out # these size changes can be easily applied to other images, see further code below final_norm_img, new_spacing, size_changes = cxrstandardize_algorithm.run( img_np, spacing) # set up an output location and write the output image there f_out = Path( __file__).parent / "resources" / "tmp_test_outputs" / "c0002_norm.mha" f_out = str(f_out.resolve()) write_file(f_out, final_norm_img, new_spacing) # Next we test whether the size_changes information that was provided is correct # run apply_size_changes_to_img and verify that the output sizes are the same as the ones that came from standardization algorithm img_resized_to_test, new_spacing_to_test = apply_size_changes_to_img( img_np, spacing, size_changes) resized_img_worked = final_norm_img.shape == img_resized_to_test.shape resized_spacing_worked = new_spacing == new_spacing_to_test passed = (final_norm_img.shape == (1024, 1024) and not np.max(final_norm_img) == 0 and (final_norm_img.shape == img_resized_to_test.shape) and (new_spacing == new_spacing_to_test)) if passed: print("CXR Standardization test completed successfully") else: print("CXR Standardization test failed") assert passed
def test_rotate_flip_invert(): passing = True f_in = Path(__file__).parent / "resources" / "images" / "c0005.mha" f_in = str(f_in.resolve()) img_np, spacing, _ = read_file(f_in) rot90 = rotate_img(img_np, 90) rot180 = rotate_img(img_np, 180) rot270 = rotate_img(img_np, 270) rot360 = rotate_img(img_np, 360) flipyx = flip_y(flip_x(img_np)) flipxyrot90 = flip_x(flip_y(rot90)) # compare images we expect to be the same diff_img = img_np.astype(float) - rot360.astype(float) avg_pixel_diff = np.sum( np.abs(diff_img)) / (img_np.shape[0] * img_np.shape[1]) if not avg_pixel_diff < 20: print("rot360 not the same as orig", avg_pixel_diff) passing = False diff_img = flipyx.astype(float) - rot180.astype(float) avg_pixel_diff = np.sum( np.abs(diff_img)) / (img_np.shape[0] * img_np.shape[1]) if not avg_pixel_diff < 20: print("flipyx not same as rot180", avg_pixel_diff) passing = False diff_img = flipxyrot90.astype(float) - rot270.astype(float) avg_pixel_diff = np.sum( np.abs(diff_img)) / (img_np.shape[0] * img_np.shape[1]) if not avg_pixel_diff < 20: print("flipxyrot90 not same as rot270", avg_pixel_diff) passing = False assert passing
def test_lung_seg(): # Load the algorithm lungseg_algorithm = opencxr.load(opencxr.algorithms.lung_seg) # read an image from disk f_in = Path(__file__).parent / "resources" / "images" / "c0005.mha" f_in = str(f_in.resolve()) img_np, spacing, pydata = read_file(f_in) # run the lung segmentation algorithm on the image (note: in the wild it may be best to perform cxr standardization first) # this will return the segmentation map image seg_map = lungseg_algorithm.run(img_np) # write the output segmentation to disk f_out = (Path(__file__).parent / "resources" / "tmp_test_outputs" / "c0005_lungseg.mha") f_out = str(f_out.resolve()) write_file(f_out, seg_map, spacing) passed = seg_map.shape == img_np.shape and not np.max(seg_map) == 0 if passed: print("Lung Segmentation test completed successfully") else: print("Lung Segmentation results not as expected") assert passed
def test_file_io(): # read files of type dicom, png (8 and 16 bit), mha f_in_dcm = Path(__file__).parent / "resources" / "images" / "c0004.dcm" f_in_dcm = str(f_in_dcm.resolve()) img_np_dcm, spacing_dcm, tags = read_file(f_in_dcm) f_in_png_8 = Path( __file__).parent / "resources" / "images" / "c0001_8bit.png" f_in_png_8 = str(f_in_png_8.resolve()) img_np_png_8, _, _ = read_file(f_in_png_8) f_in_png_16 = Path( __file__).parent / "resources" / "images" / "c0002_16bit.png" f_in_png_16 = str(f_in_png_16.resolve()) img_np_png_16, _, _ = read_file(f_in_png_16) f_in_mha = Path(__file__).parent / "resources" / "images" / "c0003.mha" f_in_mha = str(f_in_mha.resolve()) img_np_mha, spacing_mha, _ = read_file(f_in_mha) # verify the appropriate information is not empty passing = True if not img_np_dcm.shape == (2992, 2991): print("dcm wrong shape", img_np_dcm.shape) passing = False if not np.array_equal(spacing_dcm, np.asarray([0.143, 0.143, 1.0])): print("dcm wrong spacing", spacing_dcm) passing = False if (not tags["StudyInstanceUID"].value == "9999.324256108382831452380358921215687044879"): print("dcm tags wrong study UID", tags["StudyInstanceUID"].value) passing = False if not img_np_png_8.shape == (1024, 1024): print("png 8 bit wrong shape", img_np_png_8.shape) passing = False if not img_np_png_16.shape == (3000, 2967): print("png 16 bit wrong shape", img_np_png_16.shape) passing = False if not img_np_mha.shape == (2834, 2851): print("mha wrong shape", img_np_mha.shape) passing = False if not np.array_equal(spacing_mha, np.asarray([0.148, 0.148])): print("mha wrong spacing", spacing_mha) passing = False # write files of type mha, png (uint8) and png (uint16) f_out = Path( __file__).parent / "resources" / "tmp_test_outputs" / "writing_mha.mha" f_out = str(f_out.resolve()) write_file(f_out, img_np_mha, spacing_mha) if not os.path.isfile(f_out): print("Failed to write file at ", f_out) passing = False f_out = (Path(__file__).parent / "resources" / "tmp_test_outputs" / "writing_png_8bit.png") f_out = str(f_out.resolve()) write_file(f_out, img_np_png_8, [1.0, 1.0]) if not os.path.isfile(f_out): print("Failed to write file at ", f_out) passing = False f_out = (Path(__file__).parent / "resources" / "tmp_test_outputs" / "writing_png_16bit.png") f_out = str(f_out.resolve()) write_file(f_out, img_np_png_16, [1.0, 1.0]) if not os.path.isfile(f_out): print("Failed to write file at ", f_out) passing = False assert passing
def test_imagesorter(): # Load the algorithm img_sorter_algorithm = opencxr.load(opencxr.algorithms.image_sorter) # read in a test image # note that the image sorter is designed to run on raw data so it performs better without prior image normalization/standardization f_in = Path(__file__).parent / "resources" / "images" / "c0004.mha" f_in = str(f_in.resolve()) img_np, spacing, pydata = read_file(f_in) # get the output from the image sorter # the output is a dict something like the one shown below. # The first four keys give classifications for Type, Rotation, Inversion, Lateral_Flip. # The second four keys provide probabilities of all possible classes for users that might need this # {'Type': 'PA', # 'Rotation': '0', # 'Inversion': 'No', # 'Lateral_Flip': 'No', # 'Type_Probs_PA_AP_lateral_notCXR': [0.99999976, 2.5101654e-08, 2.4382584e-07, 1.0590604e-08], # 'Rotation_Probs_0_90_180_270': [0.9999999, 2.7740466e-08, 2.2800064e-08, 3.7591672e-08], # 'Inversion_Probs_No_Yes': [0.9999968589511354, 3.1410489e-06], # 'Lateral_Flip_Probs_No_Yes': [0.9999986753330177, 1.324667e-06]} # Possible values for the first 4 keys listed here are as follows: # Type: ['PA', 'AP', 'lateral', 'notCXR'] # Rotation: ['0', '90', '180', '270'] # Inversion: ['No', 'Yes'] # Lateral_Flip: ['No', 'Yes'] result = img_sorter_algorithm.run(img_np) expected_result = { "Type": "PA", "Rotation": "0", "Inversion": "No", "Lateral_Flip": "No", "Type_Probs_PA_AP_lateral_notCXR": [ 0.99999976, 2.5101654e-08, 2.4382584e-07, 1.0590604e-08, ], "Rotation_Probs_0_90_180_270": [ 0.9999999, 2.7740466e-08, 2.2800064e-08, 3.7591672e-08, ], "Inversion_Probs_No_Yes": [0.9999968589511354, 3.1410489e-06], "Lateral_Flip_Probs_No_Yes": [0.9999986753330177, 1.324667e-06], } first_four_keys_passed = False if (result["Type"] == expected_result["Type"] and result["Rotation"] == expected_result["Rotation"] and result["Inversion"] == expected_result["Inversion"] and result["Lateral_Flip"] == expected_result["Lateral_Flip"]): first_four_keys_passed = True else: print("Failed to match first four keys checked", result, expected_result) last_four_keys_passed = False if (np.array_equal( np.round(np.asarray(result["Type_Probs_PA_AP_lateral_notCXR"]), 3), np.round( np.asarray(expected_result["Type_Probs_PA_AP_lateral_notCXR"]), 3), ) and np.array_equal( np.round(np.asarray(result["Rotation_Probs_0_90_180_270"]), 3), np.round( np.asarray(expected_result["Rotation_Probs_0_90_180_270"]), 3), ) and np.array_equal( np.round(np.asarray(result["Inversion_Probs_No_Yes"]), 3), np.round(np.asarray(expected_result["Inversion_Probs_No_Yes"]), 3), ) and np.array_equal( np.round(np.asarray(result["Lateral_Flip_Probs_No_Yes"]), 3), np.round(np.asarray(expected_result["Lateral_Flip_Probs_No_Yes"]), 3), )): last_four_keys_passed = True else: print("Failed to match last four keys checked", result, expected_result) passed = first_four_keys_passed and last_four_keys_passed if passed: print("Image Sorter test completed successfully") else: print("Image Sorter results not as expected") assert passed