def run(self, workspace): image = workspace.image_set.get_image(self.image_name.value, must_be_grayscale=True) orig_pixels = image.pixel_data if image.has_mask: mask = image.mask else: mask = np.ones(orig_pixels.shape, bool) if self.method == M_SOBEL: if self.direction == E_ALL: output_pixels = sobel(orig_pixels, mask) elif self.direction == E_HORIZONTAL: output_pixels = hsobel(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vsobel(orig_pixels, mask) else: raise NotImplementedError( "Unimplemented direction for Sobel: %s", self.direction.value) elif self.method == M_LOG: sigma = self.get_sigma() size = int(sigma * 4) + 1 output_pixels = laplacian_of_gaussian(orig_pixels, mask, size, sigma) elif self.method == M_PREWITT: if self.direction == E_ALL: output_pixels = prewitt(orig_pixels) elif self.direction == E_HORIZONTAL: output_pixels = hprewitt(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vprewitt(orig_pixels, mask) else: raise NotImplementedError( "Unimplemented direction for Prewitt: %s", self.direction.value) elif self.method == M_CANNY: high_threshold = self.manual_threshold.value low_threshold = self.low_threshold.value if (self.wants_automatic_low_threshold.value or self.wants_automatic_threshold.value): sobel_image = sobel(orig_pixels, mask) low, high = otsu3(sobel_image[mask]) if self.wants_automatic_low_threshold.value: low_threshold = low * self.threshold_adjustment_factor.value if self.wants_automatic_threshold.value: high_threshold = high * self.threshold_adjustment_factor.value output_pixels = canny(orig_pixels, mask, self.get_sigma(), low_threshold, high_threshold) elif self.method == M_ROBERTS: output_pixels = roberts(orig_pixels, mask) else: raise NotImplementedError( "Unimplemented edge detection method: %s" % self.method.value) output_image = cpi.Image(output_pixels, parent_image=image) workspace.image_set.add(self.output_image_name.value, output_image) if self.show_window: workspace.display_data.orig_pixels = orig_pixels workspace.display_data.output_pixels = output_pixels
def run(self, workspace): image = workspace.image_set.get_image(self.image_name.value, must_be_grayscale=True) orig_pixels = image.pixel_data if image.has_mask: mask = image.mask else: mask = np.ones(orig_pixels.shape, bool) if self.method == M_SOBEL: if self.direction == E_ALL: output_pixels = sobel(orig_pixels, mask) elif self.direction == E_HORIZONTAL: output_pixels = hsobel(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vsobel(orig_pixels, mask) else: raise NotImplementedError("Unimplemented direction for Sobel: %s", self.direction.value) elif self.method == M_LOG: sigma = self.get_sigma() size = int(sigma * 4) + 1 output_pixels = laplacian_of_gaussian(orig_pixels, mask, size, sigma) elif self.method == M_PREWITT: if self.direction == E_ALL: output_pixels = prewitt(orig_pixels) elif self.direction == E_HORIZONTAL: output_pixels = hprewitt(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vprewitt(orig_pixels, mask) else: raise NotImplementedError("Unimplemented direction for Prewitt: %s", self.direction.value) elif self.method == M_CANNY: high_threshold = self.manual_threshold.value low_threshold = self.low_threshold.value if (self.wants_automatic_low_threshold.value or self.wants_automatic_threshold.value): sobel_image = sobel(orig_pixels, mask) low, high = otsu3(sobel_image[mask]) if self.wants_automatic_low_threshold.value: low_threshold = low * self.threshold_adjustment_factor.value if self.wants_automatic_threshold.value: high_threshold = high * self.threshold_adjustment_factor.value output_pixels = canny(orig_pixels, mask, self.get_sigma(), low_threshold, high_threshold) elif self.method == M_ROBERTS: output_pixels = roberts(orig_pixels, mask) elif self.method == M_KIRSCH: output_pixels = kirsch(orig_pixels) else: raise NotImplementedError("Unimplemented edge detection method: %s" % self.method.value) output_image = cpi.Image(output_pixels, parent_image=image) workspace.image_set.add(self.output_image_name.value, output_image) if self.show_window: workspace.display_data.orig_pixels = orig_pixels workspace.display_data.output_pixels = output_pixels
def bg_compensate(img, sigma, splinepoints, scale): """Reads file, subtracts background. Returns [compensated image, background].""" from PIL import Image import pylab from matplotlib.image import pil_to_array from centrosome.filter import canny import matplotlib img = Image.open(img) if img.mode == "I;16": # 16-bit image # deal with the endianness explicitly... I'm not sure # why PIL doesn't get this right. imgdata = np.fromstring(img.tostring(), np.uint8) imgdata.shape = (int(imgdata.shape[0] / 2), 2) imgdata = imgdata.astype(np.uint16) hi, lo = (0, 1) if img.tag.prefix == "MM" else (1, 0) imgdata = imgdata[:, hi] * 256 + imgdata[:, lo] img_size = list(img.size) img_size.reverse() new_img = imgdata.reshape(img_size) # The magic # for maximum sample value is 281 if 281 in img.tag: img = new_img.astype(np.float32) / img.tag[281][0] elif np.max(new_img) < 4096: img = new_img.astype(np.float32) / 4095.0 else: img = new_img.astype(np.float32) / 65535.0 else: img = pil_to_array(img) pylab.subplot(1, 3, 1).imshow(img, cmap=matplotlib.cm.Greys_r) pylab.show() if len(img.shape) > 2: raise ValueError("Image must be grayscale") ## Create mask that will fix problem when image has black areas outside of well edges = canny(img, np.ones(img.shape, bool), 2, 0.1, 0.3) ci = np.cumsum(edges, 0) cj = np.cumsum(edges, 1) i, j = np.mgrid[0 : img.shape[0], 0 : img.shape[1]] mask = ci > 0 mask = mask & (cj > 0) mask[1:, :] &= ci[0:-1, :] < ci[-1, j[0:-1, :]] mask[:, 1:] &= cj[:, 0:-1] < cj[i[:, 0:-1], -1] import time t0 = time.process_time() bg = backgr(img, mask, MODE_AUTO, sigma, splinepoints=splinepoints, scale=scale) print("Executed in %f sec" % (time.process_time() - t0)) bg[~mask] = img[~mask] pylab.subplot(1, 3, 2).imshow(img - bg, cmap=matplotlib.cm.Greys_r) pylab.subplot(1, 3, 3).imshow(bg, cmap=matplotlib.cm.Greys_r) pylab.show()
def bg_compensate(img, sigma, splinepoints, scale): '''Reads file, subtracts background. Returns [compensated image, background].''' from PIL import Image import pylab from matplotlib.image import pil_to_array from centrosome.filter import canny import matplotlib img = Image.open(img) if img.mode=='I;16': # 16-bit image # deal with the endianness explicitly... I'm not sure # why PIL doesn't get this right. imgdata = np.fromstring(img.tostring(),np.uint8) imgdata.shape=(int(imgdata.shape[0]/2),2) imgdata = imgdata.astype(np.uint16) hi,lo = (0,1) if img.tag.prefix == 'MM' else (1,0) imgdata = imgdata[:,hi]*256 + imgdata[:,lo] img_size = list(img.size) img_size.reverse() new_img = imgdata.reshape(img_size) # The magic # for maximum sample value is 281 if img.tag.has_key(281): img = new_img.astype(np.float32) / img.tag[281][0] elif np.max(new_img) < 4096: img = new_img.astype(np.float32) / 4095. else: img = new_img.astype(np.float32) / 65535. else: img = pil_to_array(img) pylab.subplot(1,3,1).imshow(img, cmap=matplotlib.cm.Greys_r) pylab.show() if len(img.shape)>2: raise ValueError('Image must be grayscale') ## Create mask that will fix problem when image has black areas outside of well edges = canny(img, np.ones(img.shape, bool), 2, .1, .3) ci = np.cumsum(edges, 0) cj = np.cumsum(edges, 1) i,j = np.mgrid[0:img.shape[0], 0:img.shape[1]] mask = ci > 0 mask = mask & (cj > 0) mask[1:,:] &= (ci[0:-1,:] < ci[-1,j[0:-1,:]]) mask[:,1:] &= (cj[:,0:-1] < cj[i[:,0:-1],-1]) import time t0 = time.clock() bg = backgr(img, mask, MODE_AUTO, sigma, splinepoints=splinepoints, scale=scale) print ("Executed in %f sec" % (time.clock() - t0)) bg[~mask] = img[~mask] pylab.subplot(1,3,2).imshow(img - bg, cmap=matplotlib.cm.Greys_r) pylab.subplot(1,3,3).imshow(bg, cmap=matplotlib.cm.Greys_r) pylab.show()
def test_06_01_canny(self): '''Test the canny method''' i, j = np.mgrid[-20:20, -20:20] image = np.logical_and(i > j, i ** 2 + j ** 2 < 300).astype(np.float32) np.random.seed(0) image = image * .5 + np.random.uniform(size=image.shape) * .3 image = np.ascontiguousarray(image, np.float32) workspace, module = self.make_workspace(image) module.method.value = F.M_CANNY module.wants_automatic_threshold.value = True module.wants_automatic_low_threshold.value = True module.wants_automatic_sigma.value = True module.run(workspace) output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME) t1, t2 = otsu3(FIL.sobel(image)) result = FIL.canny(image, np.ones(image.shape, bool), 1.0, t1, t2) self.assertTrue(np.all(output.pixel_data == result))
def test_06_01_canny(self): '''Test the canny method''' i, j = np.mgrid[-20:20, -20:20] image = np.logical_and(i > j, i**2 + j**2 < 300).astype(np.float32) np.random.seed(0) image = image * .5 + np.random.uniform(size=image.shape) * .3 image = np.ascontiguousarray(image, np.float32) workspace, module = self.make_workspace(image) module.method.value = F.M_CANNY module.wants_automatic_threshold.value = True module.wants_automatic_low_threshold.value = True module.wants_automatic_sigma.value = True module.run(workspace) output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME) t1, t2 = otsu3(FIL.sobel(image)) result = FIL.canny(image, np.ones(image.shape, bool), 1.0, t1, t2) self.assertTrue(np.all(output.pixel_data == result))
def test_01_02_circle_with_noise(self): '''Test that the Canny filter finds the circle outlines in a noisy image''' np.random.seed(0) i, j = np.mgrid[-200:200, -200:200].astype(float) / 200 c = np.abs(np.sqrt(i * i + j * j) - .5) < .02 cf = c.astype(float) * .5 + np.random.uniform(size=c.shape) * .5 result = F.canny(cf, np.ones(c.shape, bool), 4, .1, .2) # # erode and dilate the circle to get rings that should contain the # outlines # cd = binary_dilation(c, iterations=4) ce = binary_erosion(c, iterations=4) cde = np.logical_and(cd, np.logical_not(ce)) self.assertTrue(np.all(cde[result])) point_count = np.sum(result) self.assertTrue(point_count > 1200) self.assertTrue(point_count < 1600)
def test_01_01_circle(self): '''Test that the Canny filter finds the outlines of a circle''' i, j = np.mgrid[-200:200, -200:200].astype(float) / 200 c = np.abs(np.sqrt(i * i + j * j) - .5) < .02 result = F.canny(c.astype(float), np.ones(c.shape, bool), 4, 0, 0) # # erode and dilate the circle to get rings that should contain the # outlines # cd = binary_dilation(c, iterations=3) ce = binary_erosion(c, iterations=3) cde = np.logical_and(cd, np.logical_not(ce)) self.assertTrue(np.all(cde[result])) # # The circle has a radius of 100. There are two rings here, one # for the inside edge and one for the outside. So that's 100 * 2 * 2 * 3 # for those places where pi is still 3. The edge contains both pixels # if there's a tie, so we bump the count a little. # point_count = np.sum(result) self.assertTrue(point_count > 1200) self.assertTrue(point_count < 1600)
def test_00_01_zeros_mask(self): '''Test that the Canny filter finds no points in a masked image''' result = F.canny(np.random.uniform(size=(20, 20)), np.zeros((20, 20), bool), 4, 0, 0) self.assertFalse(np.any(result))
def test_00_00_zeros(self): '''Test that the Canny filter finds no points for a blank field''' result = F.canny(np.zeros((20, 20)), np.ones((20, 20), bool), 4, 0, 0) self.assertFalse(np.any(result))