def test_load_file_from_stream(self): img_ref = image.load(tif_path) with open(tif_path, 'rb') as f: p = io.BytesIO(f.read()) img = image.load(p) self.assertIsInstance(img, FileImage) self.assertEqual(img.center, img_ref.center)
def test_load_dicom_from_stream(self): img_ref = image.load(dcm_path) with open(dcm_path, 'rb') as f: p = io.BytesIO(f.read()) img = image.load(p) self.assertIsInstance(img, DicomImage) self.assertEqual(img.dpi, img_ref.dpi)
def file_should_be_processed(self, filepath): """Decision of whether file should be run. Returns boolean.""" try: image.load(filepath) return True except: return False
def test_gamma(self): array = np.arange(49).reshape((7,7)) ref_img = image.load(array, dpi=1) comp_img = image.load(array, dpi=1) comp_img.roll(amount=1) g_map = ref_img.gamma(comp_img) num_passing_pixels = np.nansum(g_map < 1) num_calced_pixels = np.nansum(g_map >= 0) pass_pct = num_passing_pixels / num_calced_pixels * 100 average_gamma = np.nanmean(g_map) expected_pass_pct = 86 expected_avg_gamma = 0.87 self.assertAlmostEqual(pass_pct, expected_pass_pct, delta=1) self.assertAlmostEqual(average_gamma, expected_avg_gamma, delta=0.02)
def identify_images(zip_file): """Interactively identify images from a folder, writing the labels to an array for later training""" with TemporaryZipDirectory(zip_file) as zfiles: filepaths = get_files(zfiles, is_dicom) labels = np.zeros(len(filepaths)) split_val = 25 length = len(filepaths) rounds = int(math.ceil(length / split_val)) for n in range(rounds): fig, axes = plt.subplots(5, 5, figsize=(10, 10)) for axis, (idx, fp) in zip(axes.flatten(), enumerate(filepaths[split_val*n:split_val*(n+1)])): img = load(fp) plt.sca(axis) plt.imshow(img, cmap=plt.cm.Greys) plt.axis('off') plt.title(idx+split_val*n) plt.show() not_done = True while not_done: label = input("Input the HU indices as a number or range. E.g. '66' or '25-47'. Type 'done' when finished:") if label == 'done': not_done = False else: items = label.split('-') if len(items) > 1: labels[int(items[0]):int(items[1])] = 1 else: labels[int(items[0])] = 1 scaled_features = np.zeros((len(filepaths), 10000), dtype=np.float32) for idx, fp in enumerate(filepaths): scaled_features[idx, :] = process_image(fp) dir2write = osp.dirname(zip_file) np.save(osp.join(dir2write, 'images_' + osp.splitext(osp.basename(zip_file))[0]), scaled_features) np.save(osp.join(dir2write, 'labels_' + osp.splitext(osp.basename(zip_file))[0]), labels) os.remove(zip_file)
def _find_bb(img, rad_field_bounding_box): """Find the BB within the radiation field. Iteratively searches for a circle-like object by lowering a low-pass threshold value until found. Returns ------- Point The weighted-pixel value location of the BB. """ # get initial starting conditions hmin, hmax = np.percentile(img.array, [5, 99.9]) spread = hmax - hmin max_thresh = hmax lower_thresh = hmax - spread / 1.5 # search for the BB by iteratively lowering the low-pass threshold value until the BB is found. found = False iteration = 0 while not found: try: binary_arr = np.logical_and((max_thresh > img), (img >= lower_thresh)) labeled_arr, num_roi = ndimage.measurements.label(binary_arr) roi_sizes, bin_edges = np.histogram(labeled_arr, bins=num_roi + 1) if num_roi != 3: # if not background, field, and 2 BBs raise ValueError bw_bb_img1 = np.where(labeled_arr == np.argsort(roi_sizes)[-3], 1, 0) bw_bb_img1 = ndimage.binary_fill_holes(bw_bb_img1).astype(int) bb_regionprops1 = measure.regionprops(bw_bb_img1)[0] bw_bb_img2 = np.where(labeled_arr == np.argsort(roi_sizes)[-4], 1, 0) bw_bb_img2 = ndimage.binary_fill_holes(bw_bb_img2).astype(int) bb_regionprops2 = measure.regionprops(bw_bb_img2)[0] if not is_round(bb_regionprops1) and not is_round(bb_regionprops2): raise ValueError if not is_modest_size(bw_bb_img1, rad_field_bounding_box) and not is_modest_size(bw_bb_img2, rad_field_bounding_box): raise ValueError if not is_symmetric(bw_bb_img1) and not is_symmetric(bw_bb_img2): raise ValueError except (IndexError, ValueError): max_thresh -= 0.05 * spread if max_thresh < hmin or iteration > 50: raise ValueError("Unable to locate the two BBs. Make sure the BBs are located within the field away from field edges and that there is no significant noise or artifact in the image.") else: found = True iteration += 1 # determine the center of mass of the BB inv_img = image.load(img.array) # we invert so BB intensity increases w/ attenuation inv_img.check_inversion_by_histogram(percentiles=(99.99, 50, 0.01)) bb_rprops1 = measure.regionprops(bw_bb_img1, intensity_image=inv_img)[0] bb_rprops2 = measure.regionprops(bw_bb_img2, intensity_image=inv_img)[0] return [[[bb_rprops1.weighted_centroid[1], bb_rprops1.weighted_centroid[0]], bw_bb_img1], [[bb_rprops2.weighted_centroid[1], bb_rprops2.weighted_centroid[0]], bw_bb_img2]]
def _find_bb(img, bb_box): """Find the BB within the radiation field. Iteratively searches for a circle-like object by lowering a low-pass threshold value until found. Returns ------- Point The weighted-pixel value location of the BB. """ # get initial starting conditions hmin, hmax = np.percentile(img.array, [5, 99.9]) spread = hmax - hmin max_thresh = hmax lower_thresh = hmax - spread / 1.5 # search for the BB by iteratively lowering the low-pass threshold value until the BB is found. found = False iteration = 0 while not found: try: binary_arr = np.logical_and((max_thresh > img), (img >= lower_thresh)) labeled_arr, num_roi = ndimage.measurements.label(binary_arr) roi_sizes, bin_edges = np.histogram(labeled_arr, bins=num_roi + 1) bw_bb_img = np.where(labeled_arr == np.argsort(roi_sizes)[-3], 1, 0) bw_bb_img = ndimage.binary_fill_holes(bw_bb_img).astype( int) # fill holes for low energy beams like 2.5MV bb_regionprops = measure.regionprops(bw_bb_img)[0] if not is_round(bb_regionprops): raise ValueError if not is_modest_size(bw_bb_img, bb_box): raise ValueError if not is_symmetric(bw_bb_img): raise ValueError except (IndexError, ValueError): max_thresh -= 0.05 * spread if max_thresh < hmin: raise ValueError( "Unable to locate the BB. Make sure the field edges do not obscure the BB and that there is no artifacts in the images." ) else: found = True if iteration > 100: # Allow only 100 iterations, then abort (addition) raise ValueError( "Unable to locate the BB. It is possible that your image does not contain a BB." ) iteration += 1 # determine the center of mass of the BB inv_img = image.load(img.array) # we invert so BB intensity increases w/ attenuation inv_img.check_inversion_by_histogram(percentiles=(99.99, 50, 0.01)) bb_rprops = measure.regionprops(bw_bb_img, intensity_image=inv_img)[0] # Added output to show BB contour! return [[bb_rprops.weighted_centroid[1], bb_rprops.weighted_centroid[0]], bw_bb_img]
def __init__(self, path: str): """ Parameters ---------- path : str The path to the image. """ self.image = image.load(path) self.symmetry: dict = {} self.flatness: dict = {} self.positions: dict = {} self._is_analyzed: bool = False self.image.check_inversion_by_histogram()
def _check_inversion(self): """Check the inversion by using the histogram of the phantom region""" roi = self._phantom_ski_region_calc() phantom_array = self.image.array[roi.bbox[0]:roi.bbox[2], roi.bbox[1]:roi.bbox[3]] phantom_sub_image = image.load(phantom_array) phantom_sub_image.crop(int(phantom_sub_image.shape[0]*0.1)) p5 = np.percentile(phantom_sub_image, 0.5) p50 = np.percentile(phantom_sub_image, 50) p95 = np.percentile(phantom_sub_image, 99.5) dist_to_5 = abs(p50 - p5) dist_to_95 = abs(p50 - p95) if dist_to_5 > dist_to_95: self.image.invert()
def __init__(self, filepath: str): """ Parameters ---------- filepath : str Path to the image file. """ self.image = image.load(filepath) self.image.invert() self.image.ground() self.image.normalize() self._angle_override = None self._size_override = None self._center_override = None self._high_contrast_threshold = None self._low_contrast_threshold = None self.mtf = None
def identify_images(zip_file): """Interactively identify images from a folder, writing the labels to an array for later training""" with TemporaryZipDirectory(zip_file) as zfiles: filepaths = get_files(zfiles, is_dicom) labels = np.zeros(len(filepaths)) split_val = 25 length = len(filepaths) rounds = int(math.ceil(length / split_val)) for n in range(rounds): fig, axes = plt.subplots(5, 5, figsize=(10, 10)) for axis, (idx, fp) in zip( axes.flatten(), enumerate(filepaths[split_val * n:split_val * (n + 1)])): img = load(fp) plt.sca(axis) plt.imshow(img, cmap=plt.cm.Greys) plt.axis('off') plt.title(idx + split_val * n) plt.show() not_done = True while not_done: label = input( "Input the HU indices as a number or range. E.g. '66' or '25-47'. Type 'done' when finished:" ) if label == 'done': not_done = False else: items = label.split('-') if len(items) > 1: labels[int(items[0]):int(items[1])] = 1 else: labels[int(items[0])] = 1 scaled_features = np.zeros((len(filepaths), 10000), dtype=np.float32) for idx, fp in enumerate(filepaths): scaled_features[idx, :] = process_image(fp) dir2write = osp.dirname(zip_file) np.save( osp.join(dir2write, 'images_' + osp.splitext(osp.basename(zip_file))[0]), scaled_features) np.save( osp.join(dir2write, 'labels_' + osp.splitext(osp.basename(zip_file))[0]), labels) os.remove(zip_file)
def test_nonsense(self): with self.assertRaises(TypeError): image.load('blahblah')
def setUp(self): self.img = image.load(tif_path) self.dcm = image.load(dcm_path) array = np.arange(42).reshape(6, 7) self.arr = image.load(array)
def test_load_file(self): img = image.load(tif_path) self.assertIsInstance(img, FileImage)
def test_load_array(self): arr = np.arange(36).reshape(6, 6) img = image.load(arr) self.assertIsInstance(img, ArrayImage)
def setUpClass(cls): cls.dcm = image.load(dcm_path)
def test_load_dicom(self): img = image.load(dcm_path) self.assertIsInstance(img, DicomImage)
def setUpClass(cls): img = image.load(cls.image_file_location) cls.profile = cls.klass(cls.center_point, cls.radius, img.array) cls.profile.filter(size=0.01, kind='gaussian')
def setUpClass(cls): img = image.load(cls.image_file_location) cls.profile = cls.klass(cls.center_point, cls.radius, img.array)
def test_nonsense(self): with self.assertRaises(FileNotFoundError): image.load('blahblah')
def test_load_dicom_from_file_object(self): img_ref = image.load(dcm_path) with open(dcm_path, 'rb') as f: img = image.load(f) self.assertIsInstance(img, DicomImage) self.assertEqual(img.dpi, img_ref.dpi)
def test_load_file_from_file_object(self): img_ref = image.load(tif_path) with open(tif_path, 'rb') as f: img = image.load(f) self.assertIsInstance(img, FileImage) self.assertEqual(img.center, img_ref.center)