def test_square_image(): im = np.zeros((50, 50)).astype(float) im[:25, :25] = 1. # Moravec results = peak_local_max(corner_moravec(im), min_distance=10, threshold_rel=0) # interest points along edge assert len(results) == 57 # Harris results = peak_local_max(corner_harris(im, method='k'), min_distance=10, threshold_rel=0) # interest at corner assert len(results) == 1 results = peak_local_max(corner_harris(im, method='eps'), min_distance=10, threshold_rel=0) # interest at corner assert len(results) == 1 # Shi-Tomasi results = peak_local_max(corner_shi_tomasi(im), min_distance=10, threshold_rel=0) # interest at corner assert len(results) == 1
def average_hough_detections(self, hough_radii, hough_res, num_best=5): """ Smooths `num_best` hough detections with Gaussian and computes weighted average across the `num_best` hough detections to get more precise center_x, center_y and radius of circle """ centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): # For each radius, extract two circles h_smooth = skifilt.gaussian_filter(h, sigma=4) num_peaks = 1 peaks = skif.peak_local_max(h, min_distance=40, num_peaks=num_peaks) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) h_sum = np.sum([skifilt.gaussian_filter(x, sigma=2) for x in hough_res[np.argsort(accums)[::-1][:num_best]]], axis=0) peaks = skif.peak_local_max(h_sum, min_distance=40, num_peaks=num_peaks) center_x, center_y = peaks[0] max_sel = [np.max(x.ravel()) for x in hough_res[np.argsort(accums)[::-1][:num_best]]] radii_sel = [radii[i] for i in np.argsort(accums)[::-1][:num_best]] radius = sum([m * r for m, r in zip(max_sel, radii_sel)]) / float(sum(max_sel)) return center_x, center_y, int(radius)
def find_peaks(img, npeaks=float("inf")): threshold = lambda x: 10.0 ** (-x) log_th = __MIN_THRESHOLD peaks = peak_local_max(img, threshold_rel=threshold(log_th)) while len(peaks) > npeaks and log_th > __MAX_THRESHOLD: log_th -= 0.05 peaks = peak_local_max(img, threshold_rel=threshold(log_th)) return peaks
def get_local_maxima(im_array, min_distance, threshold_rel): """Return the local maxima.""" img = peak_local_max(im_array, indices=False, min_distance=min_distance, threshold_rel=threshold_rel) coords = peak_local_max(im_array, indices=True, min_distance=min_distance, threshold_rel=threshold_rel) return img, coords
def test_squared_dot(): im = np.zeros((50, 50)) im[4:8, 4:8] = 1 im = img_as_float(im) # Moravec fails # Harris results = peak_local_max(corner_harris(im)) assert (results == np.array([[6, 6]])).all() # Shi-Tomasi results = peak_local_max(corner_shi_tomasi(im)) assert (results == np.array([[6, 6]])).all()
def find_n_local_minima(image, n=0): """Takes a 3D image and creates a local minimum mask, and n minima mask """ # Invert image so we are searching for maximas im_inv = np.invert(image) # Find peaks in each of r,g,b minimaR = peak_local_max(im_inv[:,:,0]) minimaG = peak_local_max(im_inv[:,:,1]) minimaB = peak_local_max(im_inv[:,:,2]) # each of the minima will have an array of shape (n, 2) # where n is the number of minima # get 2D dimensions of the image y, x, z = image.shape zR = np.zeros((y, x)) zG = np.zeros((y, x)) zB = np.zeros((y, x)) nMinima = np.zeros((y, x)) # Make zR, zG, zB an accumulator space for the minima points zR[minimaR[:,0], minimaR[:,1]] = 1 zG[minimaG[:,0], minimaG[:,1]] = 1 zB[minimaB[:,0], minimaB[:,1]] = 1 # Find where peaks in rgb overlap minima = zR * zG * zB if n != 0: i, j = np.nonzero(minima) # making sure the number of minima is not exceeded if n > np.sum(minima): n = np.sum(minima) ix = np.random.choice(len(i), n, replace=False) nMinima[i[ix], j[ix]] = 1 # Label the masked image labelled = label(nMinima) #Make an nMinima shape of the image markers = np.zeros(image.shape) for i in range(z): markers[:,:,i] = labelled return minima, markers else: return minima
def detect_Hough(data): image = data.copy() edges = canny(image, sigma=10, low_threshold=60, high_threshold=90) # Detect circles between 80% and 100% of image semi-diagonal lx, ly = data.shape sizex, sizey = lx/2., ly/2. max_r = numpy.sqrt(sizex**2 + sizey**2) hough_radii = numpy.linspace(0.5*max_r, 0.9 * max_r, 20) hough_res = hough_circle(edges, hough_radii) centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): # For each radius, extract two circles num_peaks = 2 peaks = peak_local_max(h, num_peaks=num_peaks) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) # Use the most prominent circle idx = numpy.argsort(accums)[::-1][:1] center_x, center_y = centers[idx] radius = radii[idx] return center_x, center_y, radius
def LargestWatershedRegion(shapes,dims,skipBias): L=len(shapes)-skipBias shapes=shapes.reshape((-1,) + dims[1:]) D=len(dims) num_peaks=4 # structure=np.ones(tuple(3*np.ones((np.ndim(shapes)-1,1)))) for ll in range(L): temp=shapes[ll] local_maxi = peak_local_max(gaussian_filter(temp,[1]*(D-1)), exclude_border=False, indices=False, num_peaks=num_peaks) markers,junk = label(local_maxi) nonzero_mask=temp>0 if np.sum(nonzero_mask)>(3**3)*num_peaks: labels = watershed(-temp, markers, mask=nonzero_mask) #watershed regions ind = 1 temp2 = np.copy(temp) temp2[labels!=1]=0 total_intensity = sum(temp2.reshape(-1,)) for kk in range(2,labels.max()+1): temp2 = np.copy(temp) temp2[labels!=kk]=0 total_intensity2 = sum(temp2.reshape(-1,)) if total_intensity2>total_intensity: ind = kk total_intensity=total_intensity2 temp[labels!=ind]=0 shapes[ll]=temp shapes=shapes.reshape((len(shapes),-1)) return shapes
def test_circles2(): data = np.memmap("E:\\guts_tracking\\data\\fish202_aligned_masked_8bit_150x200x440.raw", dtype='uint8', shape=(440,200,150)).copy() i = 157 hough_radii = np.arange(10, 100, 10) edges = feature.canny(data[i], sigma=3.0, low_threshold=0.4, high_threshold=0.8) hough_res = hough_circle(edges, hough_radii) centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): peaks = feature.peak_local_max(h) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * len(peaks)) image = ski.color.gray2rgb(data[i]) for idx in np.argsort(accums)[::-1][:5]: center_x, center_y = centers[idx] radius = radii[idx] cx, cy = circle_perimeter(center_y, center_x, radius) if max(cx) < 150 and max(cy) < 200: image[cy, cx] = (220, 20, 20) plt.imshow(image, cmap='gray') plt.show()
def animate(i): print 'Frame %d' % i plt.title('Frame %d' % i) image = data[i] hough_radii = np.arange(10, 100, 10) edges = feature.canny(data[i], sigma=3.0, low_threshold=0.4, high_threshold=0.8) hough_res = hough_circle(edges, hough_radii) centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): peaks = feature.peak_local_max(h) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * len(peaks)) image = ski.color.gray2rgb(data[i]) for idx in np.argsort(accums)[::-1][:5]: center_x, center_y = centers[idx] radius = radii[idx] cx, cy = circle_perimeter(center_y, center_x, radius) if max(cx) < 150 and max(cy) < 200: image[cy, cx] = (220, 20, 20) im.set_data(image) return im,
def test_template(): size = 100 # Float prefactors ensure that image range is between 0 and 1 image = np.full((400, 400), 0.5) target = 0.1 * (np.tri(size) + np.tri(size)[::-1]) target_positions = [(50, 50), (200, 200)] for x, y in target_positions: image[x:x + size, y:y + size] = target np.random.seed(1) image += 0.1 * np.random.uniform(size=(400, 400)) result = match_template(image, target) delta = 5 positions = peak_local_max(result, min_distance=delta) if len(positions) > 2: # Keep the two maximum peaks. intensities = result[tuple(positions.T)] i_maxsort = np.argsort(intensities)[::-1] positions = positions[i_maxsort][:2] # Sort so that order matches `target_positions`. positions = positions[np.argsort(positions[:, 0])] for xy_target, xy in zip(target_positions, positions): assert_almost_equal(xy, xy_target)
def watershed_segmentation(rgb_img, mask, distance=10): """Uses the watershed algorithm to detect boundary of objects. Needs a marker file which specifies area which is object (white), background (grey), unknown area (black). Inputs: rgb_img = image to perform watershed on needs to be 3D (i.e. np.shape = x,y,z not np.shape = x,y) mask = binary image, single channel, object in white and background black distance = min_distance of local maximum Returns: analysis_images = list of output images :param rgb_img: numpy.ndarray :param mask: numpy.ndarray :param distance: int :return analysis_images: list """ params.device += 1 # # Will be depricating opencv version 2 # if cv2.__version__[0] == '2': # dist_transform = cv2.distanceTransform(mask, cv2.cv.CV_DIST_L2, maskSize=0) # else: dist_transform = cv2.distanceTransformWithLabels(mask, cv2.DIST_L2, maskSize=0)[0] localMax = peak_local_max(dist_transform, indices=False, min_distance=distance, labels=mask) markers = ndi.label(localMax, structure=np.ones((3, 3)))[0] dist_transform1 = -dist_transform labels = watershed(dist_transform1, markers, mask=mask) img1 = np.copy(rgb_img) for x in np.unique(labels): rand_color = color_palette(len(np.unique(labels))) img1[labels == x] = rand_color[x] img2 = apply_mask(img1, mask, 'black') joined = np.concatenate((img2, rgb_img), axis=1) estimated_object_count = len(np.unique(markers)) - 1 analysis_image = [] analysis_image.append(joined) if params.debug == 'print': print_image(dist_transform, os.path.join(params.debug_outdir, str(params.device) + '_watershed_dist_img.png')) print_image(joined, os.path.join(params.debug_outdir, str(params.device) + '_watershed_img.png')) elif params.debug == 'plot': plot_image(dist_transform, cmap='gray') plot_image(joined) outputs.add_observation(variable='estimated_object_count', trait='estimated object count', method='plantcv.plantcv.watershed', scale='none', datatype=int, value=estimated_object_count, label='none') # Store images outputs.images.append(analysis_image) return analysis_image
def findBraggs(A, min_distance=2, threshold_rel=0.5, norm='linear', rspace=True, zero_center=True): ''' find Bragg peaks of topo image A using peak_local_max, will plot modulus of FT of A with result points NOTE: PLEASE REMOVE NON-BRAGG PEAKS MANUALLY BY 'Bragg = np.delete(coords, [indices], axis=0)' Parameters: min_distance - peaks are separated by at least min_distance in pixel; threshold_rel - minimum intensity of peaks, calculated as max(image) * threshold_rel norm: 'linear' or 'log', scale of display rspace: True - real space; False - reciprocal space zero_center - whether or not zero the DC point of Fourier transform ''' if rspace: ft = np.fft.fft2(A) if zero_center: ft[0,0] = 0 F = np.absolute(np.fft.fftshift(ft)) else: F = np.copy(A) cnorm = mpl.colors.Normalize(vmin=F.min(), vmax=F.max()) if norm is 'log': cnorm = mpl.colors.LogNorm(vmin=F.mean(), vmax=F.max()) coords = peak_local_max(F, min_distance=min_distance, threshold_rel=threshold_rel) coords = np.fliplr(coords) plt.imshow(F, cmap=plt.cm.gray, origin='lower', norm=cnorm, aspect=1) plt.plot(coords[:, 0], coords[:, 1], 'r.') plt.gca().set_aspect(1) plt.axis('tight') print('#:\t[x y]') for ix, iy in enumerate(coords): print(ix, end='\t') print(iy) return coords
def segment_out_cells(base): # TODO: try using OTSU for GFP thresholding sel_elem = disk(2) gfp_collector = np.sum(base, axis=0) gfp_clustering_markers = np.zeros(gfp_collector.shape, dtype=np.uint8) # random walker segment gfp_clustering_markers[gfp_collector > np.mean(gfp_collector) * 2] = 2 gfp_clustering_markers[gfp_collector < np.mean(gfp_collector) * 0.20] = 1 labels = random_walker(gfp_collector, gfp_clustering_markers, beta=10, mode='bf') # round up the labels and set the background to 0 from 1 labels = closing(labels, sel_elem) labels -= 1 # prepare distances for the watershed distance = ndi.distance_transform_edt(labels) local_maxi = peak_local_max(distance, indices=False, # we want the image mask, not peak position min_distance=10, # about half of a bud with our size threshold_abs=10, # allows to clear the noise labels=labels) # we fuse the labels that are close together that escaped the min distance in local_maxi local_maxi = ndi.convolve(local_maxi, np.ones((5, 5)), mode='constant', cval=0.0) # finish the watershed expanded_maxi_markers = ndi.label(local_maxi, structure=np.ones((3, 3)))[0] segmented_cells_labels = watershed(-distance, expanded_maxi_markers, mask=labels) # log debugging data running_debug_frame.gfp_collector = gfp_collector running_debug_frame.gfp_clustering_markers = gfp_clustering_markers running_debug_frame.labels = labels running_debug_frame.segmented_cells_labels = segmented_cells_labels return gfp_collector, segmented_cells_labels
def label_nuclei(binary, min_size): '''Label, watershed and remove small objects''' distance = medial_axis(binary, return_distance=True)[1] distance_blured = gaussian_filter(distance, 5) local_maxi = peak_local_max(distance_blured, indices=False, labels=binary, min_distance = 30) markers = measure_label(local_maxi) # markers[~binary] = -1 # labels_rw = segmentation.random_walker(binary, markers) # labels_rw[labels_rw == -1] = 0 # labels_rw = segmentation.relabel_sequential(labels_rw) labels_ws = watershed(-distance, markers, mask=binary) labels_large = remove_small_objects(labels_ws,min_size) labels_clean_border = clear_border(labels_large) labels_from_one = relabel_sequential(labels_clean_border) # plt.imshow(ndimage.morphology.binary_dilation(markers)) # plt.show() return labels_from_one[0]
def local_maximum(data, dist=1): """Generate the local maxinum value in image.""" lmax = np.zeros(data.shape) p = skft.peak_local_max(data, dist).T p = (np.array(p[0]), np.array(p[1]), np.array(p[2])) lmax[p] = 1 return lmax
def test_subpix_dot(): img = np.zeros((50, 50)) img[25, 25] = 255 corner = peak_local_max(corner_harris(img), min_distance=10, threshold_rel=0, num_peaks=1) subpix = corner_subpix(img, corner) assert_array_equal(subpix[0], (25, 25))
def corner_peaks(image, min_distance=10, threshold_abs=0, threshold_rel=0.1, exclude_border=True, indices=True, num_peaks=np.inf, footprint=None, labels=None): """Find corners in corner measure response image. This differs from `skimage.feature.peak_local_max` in that it suppresses multiple connected peaks with the same accumulator value. Parameters ---------- See `skimage.feature.peak_local_max`. Returns ------- See `skimage.feature.peak_local_max`. Examples -------- >>> from skimage.feature import peak_local_max, corner_peaks >>> response = np.zeros((5, 5)) >>> response[2:4, 2:4] = 1 >>> response array([[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 1., 1., 0.], [ 0., 0., 1., 1., 0.], [ 0., 0., 0., 0., 0.]]) >>> peak_local_max(response, exclude_border=False) array([[2, 2], [2, 3], [3, 2], [3, 3]]) >>> corner_peaks(response, exclude_border=False) array([[2, 2]]) >>> corner_peaks(response, exclude_border=False, min_distance=0) array([[2, 2], [2, 3], [3, 2], [3, 3]]) """ peaks = peak_local_max(image, min_distance=min_distance, threshold_abs=threshold_abs, threshold_rel=threshold_rel, exclude_border=exclude_border, indices=False, num_peaks=num_peaks, footprint=footprint, labels=labels) if min_distance > 0: coords = np.transpose(peaks.nonzero()) for r, c in coords: if peaks[r, c]: peaks[r - min_distance:r + min_distance + 1, c - min_distance:c + min_distance + 1] = False peaks[r, c] = True if indices is True: return np.transpose(peaks.nonzero()) else: return peaks
def test_subpix(): img = np.zeros((50, 50)) img[:25,:25] = 255 img[25:,25:] = 255 corner = peak_local_max(corner_harris(img), num_peaks=1) subpix = corner_subpix(img, corner) assert_array_equal(subpix[0], (24.5, 24.5))
def stk_to_rois(stk, threshold, min_size, max_window=8, downscale_factor=2): thresholded_stk = stk > threshold thresholded_stk = remove_small_objects(thresholded_stk, min_size) distance = ndi.distance_transform_edt(thresholded_stk) cropped_stk = stk.copy() cropped_stk[np.logical_not(thresholded_stk)] = 0 combined_stk = cropped_stk + distance/distance.max() local_max = peak_local_max(combined_stk, indices=False, footprint=np.ones((max_window, max_window)), labels=thresholded_stk) markers = ndi.label(local_max)[0] labels = watershed(-combined_stk, markers, mask=thresholded_stk) new_markers = markers.copy() for i in set(labels.flatten()): if i == 0: continue if np.sum(labels==i) < min_size: new_markers[markers==i] = 0 labels = watershed(-combined_stk, new_markers, mask=thresholded_stk) labels_set = set(labels.flatten()) rois = [] for label in labels_set: if label == 0: continue if np.sum((labels==label).astype(int)) < min_size: continue nroi = np.zeros((stk.shape[0], stk.shape[1])) cx,cy = np.where(labels==label) cx,cy = int(cx.mean()), int(cy.mean()) x,y = np.ogrid[0:nroi.shape[0], 0:nroi.shape[1]] r = 4 mask = (cx-x)**2 + (cy-y)**2 <= r*r nroi[mask] = 1 #nroi[labels==label] = 1 rois.append(zoom(nroi, downscale_factor, order=0)) rois = np.array(rois) return rois, thresholded_stk, labels
def waterShed(blob, shape): img = np.zeros(shape, np.uint16) img[zip(*blob)] = 99999 D = ndimage.distance_transform_edt(img) mindist = 7 labels = [1,2,3,4] while len(np.unique(labels)) > 3: mindist += 1 localMax = peak_local_max(D, indices=False, min_distance=mindist, labels=img) markers = ndimage.label(localMax, structure=np.ones((3,3)))[0] labels = watershed(-D, markers, mask=img) subBlobs = [] for label in np.unique(labels): if label == 0: continue ww = np.where(labels==label) bb = zip(ww[0], ww[1]) subBlobs.append(bb) # code.interact(local=locals()) try: return subBlobs, zip(np.where(localMax==True)[0],np.where(localMax==True)[1])[0] except IndexError: return subBlobs, 0
def segment(image, thresh): #preprocess image gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #perform euclidean distance transform distances = ndimage.distance_transform_edt(thresh) localMax = peak_local_max(distances, indices = False, min_distance = 3, labels = thresh) #perform connected component analysis on local peaks markers = ndimage.label(localMax, structure = np.ones((3, 3)))[0] labels = watershed(-distances, markers, mask = thresh) #loop over labels returned from watershed to mark them for label in np.unique(labels): if label == 0: continue mask = np.zeros(gray.shape, dtype="uint8") mask[labels == label] = 255 #find contours in mask and choose biggest contour by area contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] contour = max(contours, key = cv2.contourArea) #draw circle around max size contour ((x, y), r) = cv2.minEnclosingCircle(contour) cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2) #show final image cv2.imshow("Output", image) return len(np.unique(labels) - 1)
def segmentationize(imageSe): """ Divides coherent forms of an image in smaller groups of type integer. """ # create an matrix of distances to the next sourrounding area distance = ndimage.distance_transform_edt(imageSe, sampling=3) erosed = ndimage.binary_erosion(imageSe, iterations=8).astype(imageSe.dtype) distanceE = ndimage.distance_transform_edt(erosed, sampling=3) distance += (2 * distanceE) labels, num = label(imageSe, background=0, return_num='True') sizes_image = ndimage.sum(imageSe, labels, range(num)) sizes_image = np.sort(sizes_image, axis=None) pos = int(0.4 * num) areal = int(sizes_image[pos] ** 0.5) if areal <= 10: areal = 10 elif (areal % 2) != 0: areal += 1 footer = circarea(areal) # draw circle area # find the positions of the maxima from the distances local_maxi = peak_local_max(distance, indices=False, footprint=footer, labels=imageSe) markers = label(local_maxi) # watershed algorithm starts at the maxima and returns labels of particles simplefilter("ignore", FutureWarning) # avoid warning in watershed method labels_ws = watershed(-distance, markers, mask=imageSe) simplefilter("default", FutureWarning) return labels, labels_ws, local_maxi
def process(self, im): (width, height, _) = im.image.shape img_adapted = im.prep(self.transform) if width > self.max_resized or height > self.max_resized: scale_height = self.max_resized / height scale_width = self.max_resized / width scale = min(scale_height, scale_width) img_adapted = resize(img_adapted, (int(width * scale), int(height * scale))) edges = canny(img_adapted, sigma=self.sigma) # Detect two radii # Calculate image diameter shape = im.image.shape diam = math.sqrt(shape[0] ** 2 + shape[1] ** 2) radii = np.arange(diam / 3, diam * 0.8, 2) hough_res = hough_circle(edges, radii) accums = [] for radius, h in zip(radii, hough_res): # For each radius, extract two circles peaks = peak_local_max(h, num_peaks=1, min_distance=1) if len(peaks) > 0: accums.extend(h[peaks[:, 0], peaks[:, 1]]) if len(accums) == 0: # TODO: fix, should not happen return [0] idx = np.argmax(accums) return [accums[idx]]
def hugh_circle_detection(image): # Load picture and detect edges edges = canny(image, sigma=3, low_threshold=10, high_threshold=50) fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(5, 2)) # Detect two radii hough_radii = np.arange(15, 30, 2) hough_res = hough_circle(edges, hough_radii) centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): # For each radius, extract two circles num_peaks = 2 peaks = peak_local_max(h, num_peaks=num_peaks) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) # Draw the most prominent 5 circles image = color.gray2rgb(image) for idx in np.argsort(accums)[::-1][:5]: center_x, center_y = centers[idx] radius = radii[idx] cx, cy = circle_perimeter(center_y, center_x, radius) image[cy, cx] = (220, 20, 20) ax.imshow(image, cmap=plt.cm.gray) plt.show()
def run(self, im, skin_thresh=[-1,1], n_peaks=3): ''' im : color image ''' im_skin = rgb2lab(im.astype(np.int16))[:,:,2] self.im_skin = im_skin # im_skin = skimage.exposure.equalize_hist(im_skin) # im_skin = skimage.exposure.rescale_intensity(im_skin, out_range=[0,1]) im_skin *= im_skin > skin_thresh[0] im_skin *= im_skin < skin_thresh[1] skin_match_c = nd.correlate(-im_skin, self.hand_template) self.skin_match = skin_match_c # Display Predictions - Color Based matching optima = peak_local_max(skin_match_c, min_distance=20, num_peaks=n_peaks, exclude_border=False) # Visualize if len(optima) > 0: optima_values = skin_match_c[optima[:,0], optima[:,1]] optima_thresh = np.max(optima_values) / 2 optima = optima.tolist() for i,o in enumerate(optima): if optima_values[i] < optima_thresh: optima.pop(i) break self.markers = optima return self.markers
def run(self, im, skin_thresh=[-1,1], n_peaks=3): ''' im : color image ''' im_skin = im self.im_skin = im_skin skin_match_c = match_template(im_skin, self.template, pad_input=True)*(im>0) self.skin_match = skin_match_c # cv2.matchTemplate(im_skin, self.template, cv2.cv.CV_TM_SQDIFF_NORMED) # imshow(cv2.matchTemplate(im_skin.astype(np.float32), self.template.astype(np.float32), cv2.cv.CV_TM_CCOEFF_NORMED)) # Display Predictions - Color Based matching optima = peak_local_max(skin_match_c, min_distance=20, num_peaks=n_peaks, exclude_border=False) # Visualize if len(optima) > 0: optima_values = skin_match_c[optima[:,0], optima[:,1]] optima_thresh = np.max(optima_values) / 2 optima = optima.tolist() for i,o in enumerate(optima): if optima_values[i] < optima_thresh: optima.pop(i) break self.markers = optima return self.markers
def blackout_outside(self, img, sigma=3): img_g = skic.rgb2gray(img) edges = skif.canny(img_g, sigma=sigma) hough_radii = np.arange(180, 210, 2) hough_res = skit.hough_circle(edges, hough_radii) centers = [] accums = [] radii = [] for radius, h in zip(hough_radii, hough_res): # For each radius, extract two circles num_peaks = 1 peaks = skif.peak_local_max(h, min_distance=40, num_peaks=num_peaks) if peaks != []: centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) # print radius, np.max(h.ravel()), len(peaks) if accums == [] and sigma==3: return self.blackout_outside(img, sigma=3) # Draw the most prominent 5 circles image = (img.copy() / 4.0).astype(np.uint8) cx, cy = skid.circle(*self.average_hough_detections(hough_radii, hough_res)) image[cy, cx] = img[cy, cx] return image
def black_background(image, kernel): shifted = cv2.pyrMeanShiftFiltering(image, 10, 39) gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] D = ndimage.distance_transform_edt(thresh) localMax = peak_local_max(D, indices=False, min_distance=10, labels=thresh) # perform a connected component analysis on the local peaks, # using 8-connectivity, then appy the Watershed algorithm markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0] labels = watershed(-D, markers, mask=thresh) # create a mask mask2 = np.zeros(gray.shape, dtype="uint8") # loop over the unique labels returned by the Watershed algorithm for for label in np.unique(labels): # if the label is zero, we are examining the 'background' so simply ignore it if label == 0: continue # otherwise, allocate memory for the label region and draw # it on the mask mask2[labels == label] = 255 return mask2
def find_storms(z): thresh_z = 20 #min z value for finding peaks min_distance = 5 #minimum distance between peaks #find peaks, using local maxima peaks = feature.peak_local_max(z, threshold_abs=thresh_z, min_distance=min_distance, indices=False) #uniquely label each peak markers, num_markers = ndimage.label(peaks) #use watershed algorithm to split image into basins, starting at markers labels = watershed(-z, markers, mask=z>thresh_z/2) #compute region properties props = measure.regionprops(labels, z) props = filter_storms(props) storms = [] for p in props: s = {} s['x'], s['y'] = p.centroid s['centroid'] = p.centroid[::-1] s['max_intensity'] = p.max_intensity s['majlen'] = p.major_axis_length s['minlen'] = p.minor_axis_length s['angle'] = 180 - np.rad2deg(p.orientation) s['area'] = p.area storms.append(s) return storms
def act(self, obs, info): """Run inference and return best action given visual observations.""" del info act = {'camera_config': self.camera_config, 'primitive': None} if not obs: return act # Get heightmap from RGB-D images. colormap, heightmap = self.get_heightmap(obs, self.camera_config) # Concatenate color with depth images. input_image = np.concatenate( (colormap, heightmap[Ellipsis, None], heightmap[Ellipsis, None], heightmap[Ellipsis, None]), axis=2) # Get top-k pixels from pick and place heatmaps. k = 100 pick_heatmap = self.pick_model.forward(input_image, apply_softmax=True).squeeze() place_heatmap = self.place_model.forward(input_image, apply_softmax=True).squeeze() descriptors = np.float32(self.match_model.forward(input_image)) # V4 pick_heatmap = cv2.GaussianBlur(pick_heatmap, (49, 49), 0) place_heatmap = cv2.GaussianBlur(place_heatmap, (49, 49), 0) pick_topk = np.int32( np.unravel_index( np.argsort(pick_heatmap.reshape(-1))[-k:], pick_heatmap.shape)).T pick_pixel = pick_topk[-1, :] from skimage.feature import peak_local_max # pylint: disable=g-import-not-at-top place_peaks = peak_local_max(place_heatmap, num_peaks=1) distances = np.ones((place_peaks.shape[0], self.num_rotations)) * 10 pick_descriptor = descriptors[0, pick_pixel[0], pick_pixel[1], :].reshape(1, -1) for i in range(place_peaks.shape[0]): peak = place_peaks[i, :] place_descriptors = descriptors[:, peak[0], peak[1], :] distances[i, :] = np.linalg.norm(place_descriptors - pick_descriptor, axis=1) ibest = np.unravel_index(np.argmin(distances), shape=distances.shape) p0_pixel = pick_pixel p0_theta = 0 p1_pixel = place_peaks[ibest[0], :] p1_theta = ibest[1] * (2 * np.pi / self.num_rotations) # # V3 # pick_heatmap = cv2.GaussianBlur(pick_heatmap, (49, 49), 0) # place_heatmap = cv2.GaussianBlur(place_heatmap, (49, 49), 0) # pick_topk = np.int32( # np.unravel_index( # np.argsort(pick_heatmap.reshape(-1))[-k:], pick_heatmap.shape)).T # place_topk = np.int32( # np.unravel_index( # np.argsort(place_heatmap.reshape(-1))[-k:], # place_heatmap.shape)).T # pick_pixel = pick_topk[-1, :] # place_pixel = place_topk[-1, :] # pick_descriptor = descriptors[0, pick_pixel[0], # pick_pixel[1], :].reshape(1, -1) # place_descriptor = descriptors[:, place_pixel[0], place_pixel[1], :] # distances = np.linalg.norm(place_descriptor - pick_descriptor, axis=1) # irotation = np.argmin(distances) # p0_pixel = pick_pixel # p0_theta = 0 # p1_pixel = place_pixel # p1_theta = irotation * (2 * np.pi / self.num_rotations) # # V2 # pick_topk = np.int32( # np.unravel_index( # np.argsort(pick_heatmap.reshape(-1))[-k:], pick_heatmap.shape)).T # place_topk = np.int32( # np.unravel_index( # np.argsort(place_heatmap.reshape(-1))[-k:], # place_heatmap.shape)).T # pick_pixel = pick_topk[-1, :] # pick_descriptor = descriptors[0, pick_pixel[0], # pick_pixel[1], :].reshape(1, 1, 1, -1) # distances = np.linalg.norm(descriptors - pick_descriptor, axis=3) # distances = np.transpose(distances, [1, 2, 0]) # max_distance = int(np.round(np.max(distances))) # for i in range(self.num_rotations): # distances[:, :, i] = cv2.circle(distances[:, :, i], # (pick_pixel[1], pick_pixel[0]), 50, # max_distance, -1) # ibest = np.unravel_index(np.argmin(distances), shape=distances.shape) # p0_pixel = pick_pixel # p0_theta = 0 # p1_pixel = ibest[:2] # p1_theta = ibest[2] * (2 * np.pi / self.num_rotations) # # V1 # pick_topk = np.int32( # np.unravel_index( # np.argsort(pick_heatmap.reshape(-1))[-k:], pick_heatmap.shape)).T # place_topk = np.int32( # np.unravel_index( # np.argsort(place_heatmap.reshape(-1))[-k:], # place_heatmap.shape)).T # distances = np.zeros((k, k, self.num_rotations)) # for ipick in range(k): # pick_descriptor = descriptors[0, pick_topk[ipick, 0], # pick_topk[ipick, 1], :].reshape(1, -1) # for iplace in range(k): # place_descriptors = descriptors[:, place_topk[iplace, 0], # place_topk[iplace, 1], :] # distances[ipick, iplace, :] = np.linalg.norm( # place_descriptors - pick_descriptor, axis=1) # ibest = np.unravel_index(np.argmin(distances), shape=distances.shape) # p0_pixel = pick_topk[ibest[0], :] # p0_theta = 0 # p1_pixel = place_topk[ibest[1], :] # p1_theta = ibest[2] * (2 * np.pi / self.num_rotations) # Pixels to end effector poses. p0_position = utils.pix_to_xyz(p0_pixel, heightmap, self.bounds, self.pixel_size) p1_position = utils.pix_to_xyz(p1_pixel, heightmap, self.bounds, self.pixel_size) p0_rotation = utils.eulerXYZ_to_quatXYZW((0, 0, -p0_theta)) p1_rotation = utils.eulerXYZ_to_quatXYZW((0, 0, -p1_theta)) act['primitive'] = 'pick_place' if self.task == 'sweeping': act['primitive'] = 'sweep' elif self.task == 'pushing': act['primitive'] = 'push' params = { 'pose0': (p0_position, p0_rotation), 'pose1': (p1_position, p1_rotation) } act['params'] = params return act
# make marker array for labelling markers = np.zeros_like(yellow_channel_greyscalef) markers[yellow_channel_greyscalef < 1] = 1 markers[yellow_channel_greyscalef > 30] = 2 # nope elevation_map = sobel(yellow_channel_greyscalef) ws = watershed(elevation_map, markers) from skimage.feature import peak_local_max distance = distance_transform_edt(yellow_channel_greyscalef) # insanely slow....90p[]\] local_maxi = peak_local_max(-distance, indices=False, footprint=np.ones( (3, 3))) #, labels=yellow_channel_greyscalef) # also doesn't work..... markers = ndimage.label(local_maxi)[0] labels = watershed(-distance, markers, mask=image) # the larger you make sigma, the more blurred it gets ycf = ndimage.gaussian_filter(yellow_channel_greyscale2, 1) bin_image = np.zeros_like(ycf) bin_image[ycf > 12] = 1 # think that will be ok.... labelled = measure.label(bin_image) labels = skimage.morphology.remove_small_objects(labelled, 30)
xx, yy = np.mgrid[xmin:xmax:dx, ymin:ymax:dy] positions = np.vstack([xx.ravel(), yy.ravel()]) #kernel = st.gaussian_kde(Y.T, bw_method = 'silverman'); kernel = st.gaussian_kde(Y.T, bw_method=0.25) Y_xy = kernel(positions) Y_xy = np.reshape(Y_xy, xx.shape) fplt.plot_array(Y_xy) #watershed it from scipy import ndimage as ndi from skimage.morphology import watershed from skimage.feature import peak_local_max local_maxi = peak_local_max(Y_xy, indices=False, footprint=np.ones((7, 7))) markers = ndi.label(local_maxi)[0] labels = watershed(-Y_xy, markers) #, mask=image) #classify points Y_idx = np.array(np.round( (Y - [xmin, ymin]) / [xmax - xmin, ymax - ymin] * (npts - 1)), dtype=int) Y_idx[Y_idx < 0] = 0 Y_idx[Y_idx > npts - 1] = npts - 1 Y_class = labels[Y_idx[:, 0], Y_idx[:, 1]] cmap = 'jet' fig = plt.figure(1) plt.clf()
def seeds(args): """ %prog seeds [pngfile|jpgfile] Extract seed metrics from [pngfile|jpgfile]. Use --rows and --cols to crop image. """ p = OptionParser(seeds.__doc__) p.set_outfile() opts, args, iopts = add_seeds_options(p, args) if len(args) != 1: sys.exit(not p.print_help()) pngfile, = args pf = opts.prefix or op.basename(pngfile).rsplit(".", 1)[0] sigma, kernel = opts.sigma, opts.kernel rows, cols = opts.rows, opts.cols labelrows, labelcols = opts.labelrows, opts.labelcols ff = opts.filter calib = opts.calibrate outdir = opts.outdir if outdir != '.': mkdir(outdir) if calib: calib = json.load(must_open(calib)) pixel_cm_ratio, tr = calib["PixelCMratio"], calib["RGBtransform"] tr = np.array(tr) pngfile = convert_background(pngfile) resizefile, mainfile, labelfile, exif = \ convert_image(pngfile, pf, outdir=outdir, rotate=opts.rotate, rows=rows, cols=cols, labelrows=labelrows, labelcols=labelcols) oimg = load_image(resizefile) img = load_image(mainfile) fig, (ax1, ax2, ax3, ax4) = plt.subplots(ncols=4, nrows=1, figsize=(iopts.w, iopts.h)) # Edge detection img_gray = rgb2gray(img) logging.debug("Running {0} edge detection ...".format(ff)) if ff == "canny": edges = canny(img_gray, sigma=opts.sigma) elif ff == "roberts": edges = roberts(img_gray) elif ff == "sobel": edges = sobel(img_gray) edges = clear_border(edges, buffer_size=opts.border) selem = disk(kernel) closed = closing(edges, selem) if kernel else edges filled = binary_fill_holes(closed) # Watershed algorithm if opts.watershed: distance = distance_transform_edt(filled) local_maxi = peak_local_max(distance, threshold_rel=.05, indices=False) coordinates = peak_local_max(distance, threshold_rel=.05) markers, nmarkers = label(local_maxi, return_num=True) logging.debug("Identified {0} watershed markers".format(nmarkers)) labels = watershed(closed, markers, mask=filled) else: labels = label(filled) # Object size filtering w, h = img_gray.shape canvas_size = w * h min_size = int(round(canvas_size * opts.minsize / 100)) max_size = int(round(canvas_size * opts.maxsize / 100)) logging.debug("Find objects with pixels between {0} ({1}%) and {2} ({3}%)"\ .format(min_size, opts.minsize, max_size, opts.maxsize)) # Plotting ax1.set_title('Original picture') ax1.imshow(oimg) params = "{0}, $\sigma$={1}, $k$={2}".format(ff, sigma, kernel) if opts.watershed: params += ", watershed" ax2.set_title('Edge detection\n({0})'.format(params)) closed = gray2rgb(closed) ax2_img = labels if opts.edges: ax2_img = closed elif opts.watershed: ax2.plot(coordinates[:, 1], coordinates[:, 0], 'g.') ax2.imshow(ax2_img, cmap=iopts.cmap) ax3.set_title('Object detection') ax3.imshow(img) filename = op.basename(pngfile) if labelfile: accession = extract_label(labelfile) else: accession = pf # Calculate region properties rp = regionprops(labels) rp = [x for x in rp if min_size <= x.area <= max_size] nb_labels = len(rp) logging.debug("A total of {0} objects identified.".format(nb_labels)) objects = [] for i, props in enumerate(rp): i += 1 if i > opts.count: break y0, x0 = props.centroid orientation = props.orientation major, minor = props.major_axis_length, props.minor_axis_length major_dx = cos(orientation) * major / 2 major_dy = sin(orientation) * major / 2 minor_dx = sin(orientation) * minor / 2 minor_dy = cos(orientation) * minor / 2 ax2.plot((x0 - major_dx, x0 + major_dx), (y0 + major_dy, y0 - major_dy), 'r-') ax2.plot((x0 - minor_dx, x0 + minor_dx), (y0 - minor_dy, y0 + minor_dy), 'r-') npixels = int(props.area) # Sample the center of the blob for color d = min(int(round(minor / 2 * .35)) + 1, 50) x0d, y0d = int(round(x0)), int(round(y0)) square = img[(y0d - d):(y0d + d), (x0d - d):(x0d + d)] pixels = [] for row in square: pixels.extend(row) logging.debug("Seed #{0}: {1} pixels ({2} sampled) - {3:.2f}%".\ format(i, npixels, len(pixels), 100. * npixels / canvas_size)) rgb = pixel_stats(pixels) objects.append(Seed(filename, accession, i, rgb, props, exif)) minr, minc, maxr, maxc = props.bbox rect = Rectangle((minc, minr), maxc - minc, maxr - minr, fill=False, ec='w', lw=1) ax3.add_patch(rect) mc, mr = (minc + maxc) / 2, (minr + maxr) / 2 ax3.text(mc, mr, "{0}".format(i), color='w', ha="center", va="center", size=6) for ax in (ax2, ax3): ax.set_xlim(0, h) ax.set_ylim(w, 0) # Output identified seed stats ax4.text(.1, .92, "File: {0}".format(latex(filename)), color='g') ax4.text(.1, .86, "Label: {0}".format(latex(accession)), color='m') yy = .8 fw = must_open(opts.outfile, "w") if not opts.noheader: print(Seed.header(calibrate=calib), file=fw) for o in objects: if calib: o.calibrate(pixel_cm_ratio, tr) print(o, file=fw) i = o.seedno if i > 7: continue ax4.text(.01, yy, str(i), va="center", bbox=dict(fc='none', ec='k')) ax4.text(.1, yy, o.pixeltag, va="center") yy -= .04 ax4.add_patch( Rectangle((.1, yy - .025), .12, .05, lw=0, fc=rgb_to_hex(o.rgb))) ax4.text(.27, yy, o.hashtag, va="center") yy -= .06 ax4.text(.1, yy, "(A total of {0} objects displayed)".format(nb_labels), color="darkslategray") normalize_axes(ax4) for ax in (ax1, ax2, ax3): xticklabels = [int(x) for x in ax.get_xticks()] yticklabels = [int(x) for x in ax.get_yticks()] ax.set_xticklabels(xticklabels, family='Helvetica', size=8) ax.set_yticklabels(yticklabels, family='Helvetica', size=8) image_name = op.join(outdir, pf + "." + iopts.format) savefig(image_name, dpi=iopts.dpi, iopts=iopts) return objects
def __proposal_old(img_preprocessed, min_dim, max_dim): """ This algorithm depends on Hough circle detection using skii-image Which turned out to be crap :param img_preprocessed: :param min_dim: :param max_dim: :return: """ img = img_preprocessed img_edge = canny(img * 255, sigma=3, low_threshold=10, high_threshold=50) centers = [] accums = [] radii = [] regions = [] # detect all radii within the range min_radius = int(min_dim / 2) max_radius = int(max_dim / 2) hough_radii = np.arange(start=min_radius, stop=max_radius, step=1) hough_res = hough_circle(img_edge, hough_radii) for radius, h in zip(hough_radii, hough_res): # for each radius, extract 2 circles num_peaks = 2 peaks = peak_local_max(h, num_peaks=num_peaks) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) # don't consider circles with accum value less than the threshold idx_sorted = np.argsort(accums)[::-1] accum_threshold = 0.3 for idx in idx_sorted: idx = int(idx) if accums[idx] < accum_threshold: continue center_y, center_x = centers[idx] radius = radii[idx] x1 = center_x - radius y1 = center_y - radius x2 = center_x + radius y2 = center_y + radius # we don't want to collect circles, but we want to collect regions # later on, we'll suppress these regions regions.append([x1, y1, x2, y2]) # suppress the regions to extract the strongest ones if len(regions) > 0: min_overlap = 3 overlap_thresh = 0.7 regions_weak, regions_strong = CNN.nms.suppression( boxes=regions, overlap_thresh=overlap_thresh, min_overlap=min_overlap) # create binary map using only the strong regions img_shape = img_preprocessed.shape map = np.zeros(shape=(img_shape[0], img_shape[1]), dtype=bool) for r in regions_strong: map[r[1]:r[3], r[0]:r[2]] = True else: regions_weak = [] regions_strong = [] map = [] return regions_weak, regions_strong, map
def extractWells(imagename): im = skimage.io.imread(imagename) edges = feature.canny(im) hough_radii = np.arange(130,131,2) hough_res = hough_circle(edges, hough_radii) peaks = peak_local_max(hough_res[0], num_peaks=30)#num_peaks gives the number of potential locations for wells; can be increased if oo few are found and decreased if wells are found in the wrong location plt.imshow(im, cmap=plt.cm.gray) outimages = [] outPoints = [] for [point, idx] in zip(peaks, range(len(peaks))): for pointTmp in peaks[:idx]: if (abs(point[0]-pointTmp[0]) < 200) and (abs(point[1]-pointTmp[1]) < 200): break else: plt.scatter(point[1], point[0]) plt.scatter(point[1]-130, point[0]-130, c='r', marker='+') plt.scatter(point[1]-130, point[0]+130, c='r', marker='+') plt.scatter(point[1]+130, point[0]-130, c='r', marker='+') plt.scatter(point[1]+130, point[0]+130, c='r', marker='+') plt.scatter(point[1]+130, point[0], c='r', marker='+') plt.scatter(point[1]-130, point[0], c='r', marker='+') plt.scatter(point[1], point[0]-130, c='r', marker='+') plt.scatter(point[1], point[0]+130, c='r', marker='+') outPoints.append(point) #outimages.append(im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) # Get Points with smalles x outPoints = sorted(outPoints, key=lambda x:x[1]) columns = [] for idx in xrange(6): columns.append(sorted(outPoints[idx*4:(idx+1)*4], key=lambda x:x[0])) imagedir = os.path.dirname(imagename) imageid = int(os.path.splitext(os.path.basename(imagename))[0]) with open('%s/debug/%03d.csv'%(imagedir, imageid), 'w') as outfile: for [point, idx] in zip(columns[0], range(4)): plt.annotate("0_%d" % (idx), (point[1], point[0])) #plt.scatter(point[1], point[0], c='r') outfile.write("0_%d: %d %d\n" % (idx, point[1], point[0])) #skimage.io.imsave('%s/0_%d/%03d.png'%(imagedir, idx, imageid), im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) for [point, idx] in zip(columns[1], range(4)): plt.annotate("1_%d" % (idx), (point[1], point[0])) #plt.scatter(point[1], point[0], c='y') outfile.write("1_%d: %d %d\n" % (idx, point[1], point[0])) #skimage.io.imsave('%s/1_%d/%03d.png'%(imagedir, idx, imageid), im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) for [point, idx] in zip(columns[2], range(4)): plt.annotate("2_%d" % (idx), (point[1], point[0])) #plt.scatter(point[1], point[0], c='g') outfile.write("2_%d: %d %d\n" % (idx, point[1], point[0])) #skimage.io.imsave('%s/2_%d/%03d.png'%(imagedir, idx, imageid), im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) for [point, idx] in zip(columns[3], range(4)): plt.annotate("3_%d" % (idx), (point[1], point[0])) #plt.scatter(point[1], point[0], c='r', marker='x') outfile.write("3_%d: %d %d\n" % (idx, point[1], point[0])) #skimage.io.imsave('%s/3_%d/%03d.png'%(imagedir, idx, imageid), im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) for [point, idx] in zip(columns[4], range(4)): plt.annotate("4_%d" % (idx), (point[1], point[0])) #plt.scatter(point[1], point[0], c='y', marker='x') outfile.write("4_%d: %d %d\n" % (idx, point[1], point[0])) #skimage.io.imsave('%s/4_%d/%03d.png'%(imagedir, idx, imageid), im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) for [point, idx] in zip(columns[5], range(4)): plt.annotate("5_%d" % (idx), (point[1], point[0])) #plt.scatter(point[1], point[0], c='g', marker='x') outfile.write("5_%d: %d %d\n" % (idx, point[1], point[0])) #skimage.io.imsave('%s/5_%d/%03d.png'%(imagedir, idx, imageid), im[point[0]-130:point[0]+130, point[1]-130:point[1]+130]) plt.savefig('%s/debug/%03d.png'%(imagedir, imageid)) return columns
##################################################################### # dividing nuclei in this sample. ##################################################################### # Segment nuclei # ============== # To separate overlapping nuclei, we resort to # :ref:`sphx_glr_auto_examples_segmentation_plot_watershed.py`. # To visualize the segmentation conveniently, we colour-code the labelled # regions using the `color.label2rgb` function, specifying the background # label with argument `bg_label=0`. distance = ndi.distance_transform_edt(cells) local_maxi = feature.peak_local_max(distance, indices=False, min_distance=7) markers = measure.label(local_maxi) segmented_cells = segmentation.watershed(-distance, markers, mask=cells) fig, ax = plt.subplots(ncols=2, figsize=(10, 5)) ax[0].imshow(cells, cmap='gray') ax[0].set_title('Overlapping nuclei') ax[0].axis('off') ax[1].imshow(color.label2rgb(segmented_cells, bg_label=0)) ax[1].set_title('Segmented nuclei') ax[1].axis('off') plt.show() #####################################################################
# load the image and perform pyramid mean shift filtering # to aid the thresholding step shifted = cv2.pyrMeanShiftFiltering(image, 21, 51) cv2.imshow("Shifted", shifted) # convert the mean shift image to grayscale, then apply # Otsu's thresholding gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] cv2.imshow("Threshold Image", thresh) # compute the exact Euclidean distance from every binary # pixel to the nearest zero pixel, then find peaks in this # distance map D = ndimage.distance_transform_edt(thresh) localMax = peak_local_max(D, indices=False, min_distance=20, labels=thresh) # perform a connected component analysis on the local peaks, # using 8-connectivity, then appy the Watershed algorithm markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0] labels = watershed(-D, markers, mask=thresh) print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1)) # loop over the unique labels returned by the Watershed # algorithm for label in np.unique(labels): # if the label is zero, we are examining the 'background' # so simply ignore it if label == 0: continue
async def controller(self, cancel_id, executor, job_is_cancelled, send_results): stddev_udf = StdDevUDF() roi = self.get_sd_roi() result_iter = UDFRunner([stddev_udf]).run_for_dataset_async( self.dataset, executor, roi=roi, cancel_id=cancel_id ) async for (sd_udf_results,) in result_iter: pass if job_is_cancelled(): raise JobCancelledError() sd_udf_results = consolidate_result(sd_udf_results) center = (self.parameters["cy"], self.parameters["cx"]) rad_in = self.parameters["ri"] rad_out = self.parameters["ro"] n_peaks = self.parameters["n_peaks"] min_dist = self.parameters["min_dist"] sstd = sd_udf_results['std'] sshape = sstd.shape if not (center is None or rad_in is None or rad_out is None): mask_out = 1*_make_circular_mask(center[1], center[0], sshape[1], sshape[0], rad_out) mask_in = 1*_make_circular_mask(center[1], center[0], sshape[1], sshape[0], rad_in) mask = mask_out - mask_in masked_sstd = sstd*mask else: masked_sstd = sstd coordinates = peak_local_max(masked_sstd, num_peaks=n_peaks, min_distance=min_dist) y = coordinates[..., 0] x = coordinates[..., 1] z = range(len(y)) mask = sparse.COO( shape=(len(y), ) + tuple(self.dataset.shape.sig), coords=(z, y, x), data=1 ) udf = ApplyMasksUDF( mask_factories=lambda: mask, mask_count=len(y), mask_dtype=np.uint8, use_sparse=True ) result_iter = UDFRunner([udf]).run_for_dataset_async( self.dataset, executor, cancel_id=cancel_id ) async for (udf_results,) in result_iter: pass if job_is_cancelled(): raise JobCancelledError() results = await run_blocking( self.get_udf_results, udf_results=udf_results, roi=roi, ) await send_results(results, True)
def separate_watershed( vdf_temp, min_distance=1, min_size=1, max_size=np.inf, max_number_of_grains=np.inf, marker_radius=1, threshold=False, exclude_border=False, plot_on=False, ): """Separate segments from one VDF image using edge-detection by the sobel transform and the watershed segmentation implemented in scikit-image. See [1,2] for examples from scikit-image. Parameters ---------- vdf_temp : np.array One VDF image. min_distance: int Minimum distance (in pixels) between markers for them to be considered separate markers for the watershed segmentation. min_size : float Grains with size (i.e. total number of pixels) below min_size are discarded. max_size : float Grains with size (i.e. total number of pixels) above max_size are discarded. max_number_of_grains : int Maximum number of grains included in the returned separated grains. If it is exceeded, those with highest peak intensities will be returned. marker_radius : float If 1 or larger, each marker for watershed is expanded to a disk of radius marker_radius. marker_radius should not exceed 2*min_distance. threshold : bool If True, a mask is calculated by thresholding the VDF image by the Li threshold method in scikit-image. If False (default), the mask is the boolean VDF image. exclude_border : int or True, optional If non-zero integer, peaks within a distance of exclude_border from the boarder will be discarded. If True, peaks at or closer than min_distance of the boarder, will be discarded. plot_on : bool If True, the VDF, the mask, the distance transform and the separated grains will be plotted in one figure window. Returns ------- sep : np.array Array containing segments from VDF images (i.e. separated grains). Shape: (image size x, image size y, number of grains) References ---------- [1] http://scikit-image.org/docs/dev/auto_examples/segmentation/ plot_watershed.html [2] http://scikit-image.org/docs/dev/auto_examples/xx_applications/ plot_coins_segmentation.html#sphx-glr-auto-examples-xx- applications-plot-coins-segmentation-py """ # Create a mask from the input VDF image. if threshold: th = threshold_li(vdf_temp) mask = np.zeros_like(vdf_temp) mask[vdf_temp > th] = True else: mask = vdf_temp.astype("bool") # Calculate the Eucledian distance from each point in the mask to the # nearest background point of value 0. distance = distance_transform_edt(mask) # If exclude_boarder is given, the edge of the distance is removed # by erosion. The distance image is used to find markers, and so the # erosion is done to avoid that markers are located at the edge # of the mask. if exclude_border > 0: distance_mask = binary_erosion(distance, structure=disk(exclude_border)) distance = distance * distance_mask.astype("bool") # Find the coordinates of the local maxima of the distance transform. local_maxi = peak_local_max( distance, indices=False, min_distance=1, num_peaks=max_number_of_grains, exclude_border=exclude_border, threshold_rel=None, ) maxi_coord1 = np.where(local_maxi) # Discard maxima that are found at pixels that are connected to a # smaller number of pixels than min_size. Used as markers, these would lead # to segments smaller than min_size and should therefore not be # considered when deciding which maxima to use as markers. if min_size > 1: labels_check = label(mask)[0] delete_indices = [] for i in np.arange(np.shape(maxi_coord1)[1]): index = np.transpose(maxi_coord1)[i] label_value = labels_check[index[0], index[1]] if len(labels_check[labels_check == label_value]) < min_size: delete_indices.append(i) local_maxi[index[0], index[1]] = False maxi_coord1 = np.delete(maxi_coord1, delete_indices, axis=1) # Cluster the maxima by DBSCAN based on min_distance. For each # cluster, only the maximum closest to the average maxima position is # used as a marker. if min_distance > 1 and np.shape(maxi_coord1)[1] > 1: clusters = DBSCAN( eps=min_distance, metric="euclidean", min_samples=1, ).fit(np.transpose(maxi_coord1)) local_maxi = np.zeros_like(local_maxi) for n in np.arange(clusters.labels_.max() + 1): maxi_coord1_n = np.transpose(maxi_coord1)[clusters.labels_ == n] com = np.average(maxi_coord1_n, axis=0).astype("int") index = distance_matrix([com], maxi_coord1_n).argmin() index = maxi_coord1_n[index] local_maxi[index[0], index[1]] = True # Use the resulting maxima as markers. Each marker should have a # unique label value. For each maximum, generate markers with the same # label value in a radius given by marker_radius centered at the # maximum position. This is done to make the segmentation more robust # to local changes in pixel values around the marker. markers = label(local_maxi)[0] if marker_radius >= 1: disk_mask = disk(marker_radius) for mm in np.arange(1, np.max(markers) + 1): im = np.zeros_like(markers) im[np.where(markers == mm)] = markers[np.where(markers == mm)] markers_temp = convolve2d(im, disk_mask, boundary="fill", mode="same", fillvalue=0) markers[np.where(markers_temp)] = mm markers = markers * mask # Find the edges of the VDF image using the Sobel transform. elevation = sobel(vdf_temp) # 'Flood' the elevation (i.e. edge) image from basins at the marker # positions. Find the locations where different basins meet, i.e. # the watershed lines (segment boundaries). Only search for segments # (labels) in the area defined by mask. labels = watershed(elevation, markers=markers, mask=mask) sep = np.zeros( (np.shape(vdf_temp)[0], np.shape(vdf_temp)[1], (np.max(labels))), dtype="int32") n, i = 1, 0 while (np.max(labels)) > n - 1: sep_temp = labels * (labels == n) / n sep_temp = np.nan_to_num(sep_temp) # Discard a segment if it is too small or too large, or else add # it to the list of separated segments. if (np.sum(sep_temp, axis=(0, 1)) < min_size) or np.sum( sep_temp, axis=(0, 1)) > max_size: sep = np.delete(sep, ((n - i) - 1), axis=2) i = i + 1 else: sep[:, :, (n - i) - 1] = sep_temp n = n + 1 # Put the intensity from the input VDF image into each segmented area. vdf_sep = np.broadcast_to(vdf_temp.T, np.shape(sep.T)) * (sep.T == 1) if plot_on: # pragma: no cover # If segments have been discarded, make new labels that do not # include the discarded segments. if np.max(labels) != (np.shape(sep)[2]) and (np.shape(sep)[2] != 0): labels = sep[:, :, 0] for i in range(1, np.shape(sep)[2]): labels = labels + sep[..., i] * (i + 1) # If no separated particles were found, set all elements in # labels to 0. elif np.shape(sep)[2] == 0: labels = np.zeros(np.shape(labels)) seps_img_sum = np.zeros_like(vdf_temp).astype("float64") for l, vdf in zip(np.arange(1, np.max(labels) + 1), vdf_sep): mask_l = np.zeros_like(labels).astype("bool") mask_l[np.where(labels == l)] = 1 seps_img_sum += vdf_temp * mask_l / np.max( vdf_temp[np.where(labels == l)]) seps_img_sum[np.where(labels == l)] += l maxi_coord = np.where(local_maxi) fig, axes = plt.subplots(2, 3, sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(vdf_temp, cmap=plt.cm.magma_r) ax[0].axis("off") ax[0].set_title("VDF") ax[1].imshow(mask, cmap=plt.cm.gray_r) ax[1].axis("off") ax[1].set_title("Mask") ax[2].imshow(distance, cmap=plt.cm.gray_r) ax[2].axis("off") ax[2].set_title("Distance and markers") ax[2].imshow(masked_where(markers == 0, markers), cmap=plt.cm.gist_rainbow) ax[2].plot(maxi_coord1[1], maxi_coord1[0], "k+") ax[2].plot(maxi_coord[1], maxi_coord[0], "gx") ax[3].imshow(elevation, cmap=plt.cm.magma_r) ax[3].axis("off") ax[3].set_title("Elevation") ax[4].imshow(labels, cmap=plt.cm.gnuplot2_r) ax[4].axis("off") ax[4].set_title("Labels") ax[5].imshow(seps_img_sum, cmap=plt.cm.magma_r) ax[5].axis("off") ax[5].set_title("Segments") return vdf_sep
def blob_log(image, min_sigma=1, max_sigma=50, num_sigma=10, thresholds=[.2], overlap=.5, log_scale=False, *, exclude_border=False): r"""Finds blobs in the given grayscale image. Blobs are found using the Laplacian of Gaussian (LoG) method [1]_. For each blob found, the method returns its coordinates and the standard deviation of the Gaussian kernel that detected the blob. Parameters ---------- image : 2D or 3D ndarray Input grayscale image, blobs are assumed to be light on dark background (white on black). min_sigma : scalar or sequence of scalars, optional the minimum standard deviation for Gaussian kernel. Keep this low to detect smaller blobs. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. max_sigma : scalar or sequence of scalars, optional The maximum standard deviation for Gaussian kernel. Keep this high to detect larger blobs. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. num_sigma : int, optional The number of intermediate values of standard deviations to consider between `min_sigma` and `max_sigma`. threshold : float, optional. The absolute lower bound for scale space maxima. Local maxima smaller than thresh are ignored. Reduce this to detect blobs with less intensities. overlap : float, optional A value between 0 and 1. If the area of two blobs overlaps by a fraction greater than `threshold`, the smaller blob is eliminated. log_scale : bool, optional If set intermediate values of standard deviations are interpolated using a logarithmic scale to the base `10`. If not, linear interpolation is used. exclude_border : int or bool, optional If nonzero int, `exclude_border` excludes blobs from within `exclude_border`-pixels of the border of the image. Returns ------- A : (n, image.ndim + sigma) ndarray A 2d array with each row representing 2 coordinate values for a 2D image, and 3 coordinate values for a 3D image, plus the sigma(s) used. When a single sigma is passed, outputs are: ``(r, c, sigma)`` or ``(p, r, c, sigma)`` where ``(r, c)`` or ``(p, r, c)`` are coordinates of the blob and ``sigma`` is the standard deviation of the Gaussian kernel which detected the blob. When an anisotropic gaussian is used (sigmas per dimension), the detected sigma is returned for each dimension. References ---------- .. [1] https://en.wikipedia.org/wiki/Blob_detection#The_Laplacian_of_Gaussian Examples -------- >>> from skimage import data, feature, exposure >>> img = data.coins() >>> img = exposure.equalize_hist(img) # improves detection >>> feature.blob_log(img, threshold = .3) array([[ 266. , 115. , 11.88888889], [ 263. , 302. , 17.33333333], [ 263. , 244. , 17.33333333], [ 260. , 174. , 17.33333333], [ 198. , 155. , 11.88888889], [ 198. , 103. , 11.88888889], [ 197. , 44. , 11.88888889], [ 194. , 276. , 17.33333333], [ 194. , 213. , 17.33333333], [ 185. , 344. , 17.33333333], [ 128. , 154. , 11.88888889], [ 127. , 102. , 11.88888889], [ 126. , 208. , 11.88888889], [ 126. , 46. , 11.88888889], [ 124. , 336. , 11.88888889], [ 121. , 272. , 17.33333333], [ 113. , 323. , 1. ]]) Notes ----- The radius of each blob is approximately :math:`\sqrt{2}\sigma` for a 2-D image and :math:`\sqrt{3}\sigma` for a 3-D image. """ image = img_as_float(image) # if both min and max sigma are scalar, function returns only one sigma scalar_sigma = ( True if np.isscalar(max_sigma) and np.isscalar(min_sigma) else False ) # Gaussian filter requires that sequence-type sigmas have same # dimensionality as image. This broadcasts scalar kernels if np.isscalar(max_sigma): max_sigma = np.full(image.ndim, max_sigma, dtype=float) if np.isscalar(min_sigma): min_sigma = np.full(image.ndim, min_sigma, dtype=float) # Convert sequence types to array min_sigma = np.asarray(min_sigma, dtype=float) max_sigma = np.asarray(max_sigma, dtype=float) if log_scale: start, stop = np.log10(min_sigma)[:, None], np.log10(max_sigma)[:, None] space = np.concatenate( [start, stop, np.full_like(start, num_sigma)], axis=1) sigma_list = np.stack([np.logspace(*s) for s in space], axis=1) else: scale = np.linspace(0, 1, num_sigma)[:, None] sigma_list = scale * (max_sigma - min_sigma) + min_sigma import time start = time.time() # computing gaussian laplace # average s**2 provides scale invariance gl_images = [-gaussian_laplace(image, s) * s ** 2 for s in np.mean(sigma_list, axis=1)] image_cube = np.stack(gl_images, axis=-1) print("LoG filter took {}s".format(round(time.time() - start, 2))) ret = list() times = list() for threshold in thresholds: start = time.time() local_maxima = peak_local_max(image_cube, threshold_abs=threshold, footprint=np.ones((3,) * (image.ndim + 1)), threshold_rel=0.0, exclude_border=exclude_border) # Catch no peaks if local_maxima.size == 0: ret.append(np.empty((0, 4))) continue # Convert local_maxima to float64 lm = local_maxima.astype(np.float64) # translate final column of lm, which contains the index of the # sigma that produced the maximum intensity value, into the sigma sigmas_of_peaks = sigma_list[local_maxima[:, -1]] if scalar_sigma: # select one sigma column, keeping dimension sigmas_of_peaks = sigmas_of_peaks[:, 0:1] # Remove sigma index and replace with sigmas lm = np.hstack([lm[:, :-1], sigmas_of_peaks]) ret.append(_prune_blobs(lm, overlap)) times.append(time.time() - start) print("Thresholds took on avg: {}s".format(round(np.average(np.array(times)),2))) return np.asarray(ret) # def blob_doh(image, min_sigma=1, max_sigma=30, num_sigma=10, threshold=0.01, # overlap=.5, log_scale=False): # """Finds blobs in the given grayscale image. # Blobs are found using the Determinant of Hessian method [1]_. For each blob # found, the method returns its coordinates and the standard deviation # of the Gaussian Kernel used for the Hessian matrix whose determinant # detected the blob. Determinant of Hessians is approximated using [2]_. # Parameters # ---------- # image : 2D ndarray # Input grayscale image.Blobs can either be light on dark or vice versa. # min_sigma : float, optional # The minimum standard deviation for Gaussian Kernel used to compute # Hessian matrix. Keep this low to detect smaller blobs. # max_sigma : float, optional # The maximum standard deviation for Gaussian Kernel used to compute # Hessian matrix. Keep this high to detect larger blobs. # num_sigma : int, optional # The number of intermediate values of standard deviations to consider # between `min_sigma` and `max_sigma`. # threshold : float, optional. # The absolute lower bound for scale space maxima. Local maxima smaller # than thresh are ignored. Reduce this to detect less prominent blobs. # overlap : float, optional # A value between 0 and 1. If the area of two blobs overlaps by a # fraction greater than `threshold`, the smaller blob is eliminated. # log_scale : bool, optional # If set intermediate values of standard deviations are interpolated # using a logarithmic scale to the base `10`. If not, linear # interpolation is used. # Returns # ------- # A : (n, 3) ndarray # A 2d array with each row representing 3 values, ``(y,x,sigma)`` # where ``(y,x)`` are coordinates of the blob and ``sigma`` is the # standard deviation of the Gaussian kernel of the Hessian Matrix whose # determinant detected the blob. # References # ---------- # .. [1] https://en.wikipedia.org/wiki/Blob_detection#The_determinant_of_the_Hessian # .. [2] Herbert Bay, Andreas Ess, Tinne Tuytelaars, Luc Van Gool, # "SURF: Speeded Up Robust Features" # ftp://ftp.vision.ee.ethz.ch/publications/articles/eth_biwi_00517.pdf # Examples # -------- # >>> from skimage import data, feature # >>> img = data.coins() # >>> feature.blob_doh(img) # array([[ 270. , 363. , 30. ], # [ 265. , 113. , 23.55555556], # [ 262. , 243. , 23.55555556], # [ 260. , 173. , 30. ], # [ 197. , 153. , 20.33333333], # [ 197. , 44. , 20.33333333], # [ 195. , 100. , 23.55555556], # [ 193. , 275. , 23.55555556], # [ 192. , 212. , 23.55555556], # [ 185. , 348. , 30. ], # [ 156. , 302. , 30. ], # [ 126. , 153. , 20.33333333], # [ 126. , 101. , 20.33333333], # [ 124. , 336. , 20.33333333], # [ 123. , 205. , 20.33333333], # [ 123. , 44. , 23.55555556], # [ 121. , 271. , 30. ]]) # Notes # ----- # The radius of each blob is approximately `sigma`. # Computation of Determinant of Hessians is independent of the standard # deviation. Therefore detecting larger blobs won't take more time. In # methods line :py:meth:`blob_dog` and :py:meth:`blob_log` the computation # of Gaussians for larger `sigma` takes more time. The downside is that # this method can't be used for detecting blobs of radius less than `3px` # due to the box filters used in the approximation of Hessian Determinant. # """ # assert_nD(image, 2) # image = img_as_float(image) # image = integral_image(image) # if log_scale: # start, stop = log(min_sigma, 10), log(max_sigma, 10) # sigma_list = np.logspace(start, stop, num_sigma) # else: # sigma_list = np.linspace(min_sigma, max_sigma, num_sigma) # hessian_images = [_hessian_matrix_det(image, s) for s in sigma_list] # image_cube = np.dstack(hessian_images) # local_maxima = peak_local_max(image_cube, threshold_abs=threshold, # footprint=np.ones((3,) * image_cube.ndim), # threshold_rel=0.0, # exclude_border=False) # # Catch no peaks # if local_maxima.size == 0: # return np.empty((0, 3)) # # Convert local_maxima to float64 # lm = local_maxima.astype(np.float64) # # Convert the last index to its corresponding scale value # lm[:, -1] = sigma_list[local_maxima[:, -1]] # return _prune_blobs(lm, overlap)
def blob_dog(image, min_sigma=1, max_sigma=50, sigma_ratio=1.6, threshold=2.0, overlap=.5, *, exclude_border=False): r"""Finds blobs in the given grayscale image. Blobs are found using the Difference of Gaussian (DoG) method [1]_. For each blob found, the method returns its coordinates and the standard deviation of the Gaussian kernel that detected the blob. Parameters ---------- image : 2D or 3D ndarray Input grayscale image, blobs are assumed to be light on dark background (white on black). min_sigma : scalar or sequence of scalars, optional The minimum standard deviation for Gaussian kernel. Keep this low to detect smaller blobs. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. max_sigma : scalar or sequence of scalars, optional The maximum standard deviation for Gaussian kernel. Keep this high to detect larger blobs. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. sigma_ratio : float, optional The ratio between the standard deviation of Gaussian Kernels used for computing the Difference of Gaussians threshold : float, optional. The absolute lower bound for scale space maxima. Local maxima smaller than thresh are ignored. Reduce this to detect blobs with less intensities. overlap : float, optional A value between 0 and 1. If the area of two blobs overlaps by a fraction greater than `threshold`, the smaller blob is eliminated. exclude_border : int or bool, optional If nonzero int, `exclude_border` excludes blobs from within `exclude_border`-pixels of the border of the image. Returns ------- A : (n, image.ndim + sigma) ndarray A 2d array with each row representing 2 coordinate values for a 2D image, and 3 coordinate values for a 3D image, plus the sigma(s) used. When a single sigma is passed, outputs are: ``(r, c, sigma)`` or ``(p, r, c, sigma)`` where ``(r, c)`` or ``(p, r, c)`` are coordinates of the blob and ``sigma`` is the standard deviation of the Gaussian kernel which detected the blob. When an anisotropic gaussian is used (sigmas per dimension), the detected sigma is returned for each dimension. References ---------- .. [1] https://en.wikipedia.org/wiki/Blob_detection#The_difference_of_Gaussians_approach Examples -------- >>> from skimage import data, feature >>> feature.blob_dog(data.coins(), threshold=.5, max_sigma=40) array([[ 267. , 359. , 16.777216], [ 267. , 115. , 10.48576 ], [ 263. , 302. , 16.777216], [ 263. , 245. , 16.777216], [ 261. , 173. , 16.777216], [ 260. , 46. , 16.777216], [ 198. , 155. , 10.48576 ], [ 196. , 43. , 10.48576 ], [ 195. , 102. , 16.777216], [ 194. , 277. , 16.777216], [ 193. , 213. , 16.777216], [ 185. , 347. , 16.777216], [ 128. , 154. , 10.48576 ], [ 127. , 102. , 10.48576 ], [ 125. , 208. , 10.48576 ], [ 125. , 45. , 16.777216], [ 124. , 337. , 10.48576 ], [ 120. , 272. , 16.777216], [ 58. , 100. , 10.48576 ], [ 54. , 276. , 10.48576 ], [ 54. , 42. , 16.777216], [ 52. , 216. , 16.777216], [ 52. , 155. , 16.777216], [ 45. , 336. , 16.777216]]) Notes ----- The radius of each blob is approximately :math:`\sqrt{2}\sigma` for a 2-D image and :math:`\sqrt{3}\sigma` for a 3-D image. """ image = img_as_float(image) # if both min and max sigma are scalar, function returns only one sigma scalar_sigma = np.isscalar(max_sigma) and np.isscalar(min_sigma) # Gaussian filter requires that sequence-type sigmas have same # dimensionality as image. This broadcasts scalar kernels if np.isscalar(max_sigma): max_sigma = np.full(image.ndim, max_sigma, dtype=float) if np.isscalar(min_sigma): min_sigma = np.full(image.ndim, min_sigma, dtype=float) # Convert sequence types to array min_sigma = np.asarray(min_sigma, dtype=float) max_sigma = np.asarray(max_sigma, dtype=float) # k such that min_sigma*(sigma_ratio**k) > max_sigma k = int(np.mean(np.log(max_sigma / min_sigma) / np.log(sigma_ratio) + 1)) # a geometric progression of standard deviations for gaussian kernels sigma_list = np.array([min_sigma * (sigma_ratio ** i) for i in range(k + 1)]) gaussian_images = [gaussian_filter(image, s) for s in sigma_list] # computing difference between two successive Gaussian blurred images # multiplying with average standard deviation provides scale invariance dog_images = [(gaussian_images[i] - gaussian_images[i + 1]) * np.mean(sigma_list[i]) for i in range(k)] image_cube = np.stack(dog_images, axis=-1) # local_maxima = get_local_maxima(image_cube, threshold) local_maxima = peak_local_max(image_cube, threshold_abs=threshold, footprint=np.ones((3,) * (image.ndim + 1)), threshold_rel=0.0, exclude_border=exclude_border) # Catch no peaks if local_maxima.size == 0: return np.empty((0, 3)) # Convert local_maxima to float64 lm = local_maxima.astype(np.float64) # translate final column of lm, which contains the index of the # sigma that produced the maximum intensity value, into the sigma sigmas_of_peaks = sigma_list[local_maxima[:, -1]] if scalar_sigma: # select one sigma column, keeping dimension sigmas_of_peaks = sigmas_of_peaks[:, 0:1] # Remove sigma index and replace with sigmas lm = np.hstack([lm[:, :-1], sigmas_of_peaks]) return _prune_blobs(lm, overlap)
b, g, r = cv2.split(data_array) # Sauvola binary_global = canny(r) fill_masks = ndi.binary_fill_holes(binary_global) cells_cleaned = morphology.remove_small_objects(fill_masks, 70) labeled_cells, num = ndi.label(cells_cleaned) print("Number of Cells detected: " + str(num)) # Now we want to separate the two objects in image # Generate the markers as local maxima of the distance to the background distance = ndi.distance_transform_edt(cells_cleaned) local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((100, 100)), labels=labeled_cells) markers = ndi.label(local_maxi)[0] labels = watershed(-distance, markers, mask=cells_cleaned) fig, axes = plt.subplots(ncols=4, figsize=(9, 3), sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(cells_cleaned, cmap=plt.cm.gray) ax[0].set_title('Overlapping objects') ax[1].imshow(-distance, cmap=plt.cm.gray) ax[1].set_title('Distances') ax[2].imshow(labels, cmap=plt.cm.nipy_spectral) ax[2].set_title('Separated objects') ax[3].imshow(r, cmap=plt.cm.gray) ax[3].set_title('Original')
if final_rect[i][j] != 0: final_rect[i][j] = 0 else: final_rect[i][j] = 1 #show image show_image(final_rect) #Exact euclidean distance transform. distance = ndimage.distance_transform_edt(final_rect) print distance.shape #np.savetxt("output_label.txt", distance, fmt = "%.3f") #Exact local maxima(tree's peak) binary_rect = np.array(final_rect) local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((55,55)),threshold_abs = 10, labels = binary_rect) print type(local_maxi) print local_maxi.shape show_image(local_maxi) #zengqiang peak? ba peak ju zai yi qi? markers = morphology.label(local_maxi) print type(markers) print markers.shape show_image(markers) #watershed start_ws = time.clock() #time when start watershed labels_ws = watershed(-distance, markers, mask=binary_rect) end_ws = time.clock() time_ws = end_ws - start_ws
def _compute_num_spots_per_threshold( self, img: np.ndarray) -> Tuple[np.ndarray, List[int]]: """Computes the number of detected spots for each threshold Parameters ---------- img : np.ndarray The image in which to count spots Returns ------- np.ndarray : thresholds List[int] : spot counts """ # thresholds to search over thresholds = np.linspace(img.min(), img.max(), num=100) # number of spots detected at each threshold spot_counts = [] # where we stop our threshold search stop_threshold = None if self.verbose and StarfishConfig().verbose: threshold_iter = tqdm(thresholds) print('Determining optimal threshold ...') else: threshold_iter = thresholds for stop_index, threshold in enumerate(threshold_iter): spots = peak_local_max(img, min_distance=self.min_distance, threshold_abs=threshold, exclude_border=False, indices=True, num_peaks=np.inf, footprint=None, labels=None) # stop spot finding when the number of detected spots falls below min_num_spots_detected if len(spots) <= self.min_num_spots_detected: stop_threshold = threshold if self.verbose: print( f'Stopping early at threshold={threshold}. Number of spots fell below: ' f'{self.min_num_spots_detected}') break else: spot_counts.append(len(spots)) if stop_threshold is None: stop_threshold = thresholds.max() if len(thresholds > 1): thresholds = thresholds[:stop_index] spot_counts = spot_counts[:stop_index] return thresholds, spot_counts
def get_img_nuclei(imgpath, reg_model): imgbase = os.path.basename(imgpath) img = read_image(imgpath) ## Normalization img_norm = reinhard(img) ## Regression mode img_reg = resize_image(img_norm, 512, 512) img_reg_scale = img_reg * (2 / 255.) - 1 reg, _, _ = tfmodels.bayesian_inference(reg_model, np.expand_dims(img_reg_scale, 0), samples=10) reg = np.squeeze(reg) # Comparison between image_max and im to find the coordinates of local maxima try: reg_max = peak_local_max(reg, min_distance=min_distance, threshold_abs=threshold_abs, indices=False) max_coord = peak_local_max(reg, min_distance=min_distance, threshold_abs=threshold_abs, indices=True) wshed = instances(reg, reg_max) except: print(imgpath, 'Failed watershed') return None if np.random.binomial(1, 0.2): reg_max = cv2.dilate(reg_max.astype(np.uint8), kernel=np.ones((3, 3), np.uint8), iterations=1) img_out = overlay(img_reg, reg_max.astype(np.bool)) cv2.imwrite(os.path.join(tiles_dir, imgbase), img_out) wshed = cv2.resize(wshed, dsize=(1000, 1000), interpolation=cv2.INTER_NEAREST) nuclei = [] for x, y in max_coord: x = int(x * ds_factor) y = int(y * ds_factor) label = wshed[x, y] bbox = get_box(x, y) if bbox is None: continue wsubimg = wshed[bbox[0]:bbox[1], bbox[2]:bbox[3]] subimg = img_norm[bbox[0]:bbox[1], bbox[2]:bbox[3], :] mask = wsubimg == label mask_area = mask.sum() if mask_area < area_threshold: continue mask = cv2.dilate(mask.astype(np.uint8), np.ones((5, 5), np.uint8), iterations=3) subimg = apply_mask(subimg, mask) # subimg = correct_angle(subimg, mask) nuclei.append(np.expand_dims(subimg, axis=0)) try: nuclei = np.concatenate(nuclei, axis=0) except: print('No nuclei found') return None return nuclei
def depth_callback(depth_message): global model global graph global prev_mp global ROBOT_Z global fx, cx, fy, cy with TimeIt('Crop'): depth = bridge.imgmsg_to_cv2(depth_message) # Crop a square out of the middle of the depth and resize it to 300*300 crop_size = 400 depth_crop = cv2.resize( depth[(480 - crop_size) // 2:(480 - crop_size) // 2 + crop_size, (640 - crop_size) // 2:(640 - crop_size) // 2 + crop_size], (300, 300)) # Replace nan with 0 for inpainting. depth_crop = depth_crop.copy() depth_nan = np.isnan(depth_crop).copy() depth_crop[depth_nan] = 0 with TimeIt('Inpaint'): # open cv inpainting does weird things at the border. depth_crop = cv2.copyMakeBorder(depth_crop, 1, 1, 1, 1, cv2.BORDER_DEFAULT) mask = (depth_crop == 0).astype(np.uint8) # Scale to keep as float, but has to be in bounds -1:1 to keep opencv happy. depth_scale = np.abs(depth_crop).max() depth_crop = depth_crop.astype( np.float32) / depth_scale # Has to be float32, 64 not supported. depth_crop = cv2.inpaint(depth_crop, mask, 1, cv2.INPAINT_NS) # Back to original size and value range. depth_crop = depth_crop[1:-1, 1:-1] depth_crop = depth_crop * depth_scale with TimeIt('Calculate Depth'): # Figure out roughly the depth in mm of the part between the grippers for collision avoidance. depth_center = depth_crop[100:141, 130:171].flatten() #变成1维 depth_center.sort() #按行排序,从小到大 depth_center = depth_center[:10].mean() * 1000.0 with TimeIt('Inference'): # Run it through the network. depth_crop = np.clip((depth_crop - depth_crop.mean()), -1, 1) with graph.as_default(): model = load_model(MODEL_FILE) pred_out = model.predict(depth_crop.reshape((1, 300, 300, 1))) points_out = pred_out[0].squeeze() #维度为1则降一维 points_out[depth_nan] = 0 with TimeIt('Trig'): # Calculate the angle map. cos_out = pred_out[1].squeeze() sin_out = pred_out[2].squeeze() ang_out = np.arctan2(sin_out, cos_out) / 2.0 width_out = pred_out[3].squeeze() * 150.0 # Scaled 0-150:0-1 with TimeIt('Filter'): # Filter the outputs. points_out = ndimage.filters.gaussian_filter(points_out, 5.0) # 卷积滤波 ang_out = ndimage.filters.gaussian_filter(ang_out, 2.0) with TimeIt('Control'): # Calculate the best pose from the camera intrinsics. maxes = None ALWAYS_MAX = False # Use ALWAYS_MAX = True for the open-loop solution. if ROBOT_Z > 0.34 or ALWAYS_MAX: # > 0.34 initialises the max tracking when the robot is reset. # Track the global max. max_pixel = np.array( np.unravel_index(np.argmax(points_out), points_out.shape)) prev_mp = max_pixel.astype(np.int) else: # Calculate a set of local maxes. Choose the one that is closes to the previous one. maxes = peak_local_max(points_out, min_distance=10, threshold_abs=0.1, num_peaks=3) if maxes.shape[0] == 0: return max_pixel = maxes[np.argmin(np.linalg.norm(maxes - prev_mp, axis=1))] # Keep a global copy for next iteration. prev_mp = (max_pixel * 0.25 + prev_mp * 0.75).astype(np.int) ang = ang_out[max_pixel[0], max_pixel[1]] width = width_out[max_pixel[0], max_pixel[1]] # Convert max_pixel back to uncropped/resized image coordinates in order to do the camera transform. max_pixel = ((np.array(max_pixel) / 300.0 * crop_size) + np.array([(480 - crop_size) // 2, (640 - crop_size) // 2])) max_pixel = np.round(max_pixel).astype(np.int) point_depth = depth[max_pixel[0], max_pixel[1]] # These magic numbers are my camera intrinsic parameters. x = (max_pixel[1] - cx) / (fx) * point_depth y = (max_pixel[0] - cy) / (fy) * point_depth z = point_depth if np.isnan(z): return with TimeIt('Draw'): # Draw grasp markers on the points_out and publish it. (for visualisation) grasp_img = np.zeros((300, 300, 3), dtype=np.uint8) grasp_img[:, :, 2] = (points_out * 255.0) grasp_img_plain = grasp_img.copy() rr, cc = circle(prev_mp[0], prev_mp[1], 5) grasp_img[rr, cc, 0] = 0 grasp_img[rr, cc, 1] = 255 grasp_img[rr, cc, 2] = 0 with TimeIt('Publish'): # Publish the output images (not used for control, only visualisation) grasp_img = bridge.cv2_to_imgmsg(grasp_img, 'bgr8') grasp_img.header = depth_message.header grasp_pub.publish(grasp_img) grasp_img_plain = bridge.cv2_to_imgmsg(grasp_img_plain, 'bgr8') grasp_img_plain.header = depth_message.header grasp_plain_pub.publish(grasp_img_plain) depth_pub.publish(bridge.cv2_to_imgmsg(depth_crop)) ang_pub.publish(bridge.cv2_to_imgmsg(ang_out)) # Output the best grasp pose relative to camera. cmd_msg = Float32MultiArray() cmd_msg.data = [x, y, z, ang, width, depth_center] cmd_pub.publish(cmd_msg)
# Loop through all tif files in input folder Images = (glob.glob(InputPath+"/*.tif")) for img in Images: # Read image I = io.imread(img) # Processing # Gaussian filter if IntensityBlurRad >= 1: I = 255*gaussian(I, sigma=IntensityBlurRad) # Adaptive threshold mask = threshold_adaptive(I, RadThr, offset = Thr).astype(np.uint8) # Binary watershed distance = ndimage.distance_transform_edt(mask) distance = gaussian(distance, sigma=DistanceBlurRad) local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)), labels=mask) markers = morphology.label(local_maxi) nuclei_labels = watershed(-distance, markers, mask=mask) nuclei_labels = nuclei_labels.astype(np.uint16) nuclei_labels = remove_small_objects(nuclei_labels, min_size=MinSize) nuclei_labels = skimage.segmentation.relabel_sequential(nuclei_labels)[0] nuclei_labels = nuclei_labels.astype(np.uint16) # Write label mask filename = os.path.basename(img) io.imsave(OutputPath+"/"+filename, nuclei_labels)
def froc_eval(g, t, sig, name, data_type): mask_folder = "..\\dataset\\" + data_type + "_cam\\mask" result_folder = "..\\results\\" + name + "\\" + data_type result_file_list = [] result_file_list += [ each for each in os.listdir(result_folder) if each.endswith('.tif') ] # result_file_list= [result_file_list[i] for i in [1,0,20,43,61,66,81,99,102,111,10,71]] # result_file_list= [result_file_list[i] for i in [1]] # if data_type=='valid': # result_file_list= [result_file_list[i] for i in [2,0,5,7,9,11,13,15,17]] # else: # result_file_list= [result_file_list[i] for i in np.arange(0,110,3)] EVALUATION_MASK_LEVEL = 5 # Image level at which the evaluation is done L0_RESOLUTION = 0.243 # pixel resolution at level 0 FROC_data = np.zeros((4, len(result_file_list)), dtype=np.object) FP_summary = np.zeros((2, len(result_file_list)), dtype=np.object) detection_summary = np.zeros((2, len(result_file_list)), dtype=np.object) caseNum = 0 for case in result_file_list: print( str(g) + ' ' + str(t) + ' ' + str(sig) + ' ' + 'Evaluating Performance on image:', case[0:-4]) sys.stdout.flush() # csvDIR = os.path.join(result_folder, case) # Probs, Xcorr, Ycorr = readCSVContent(csvDIR) result_img_folder = "..\\results\\" + name + "\\" + data_type r_n = os.path.join(result_img_folder, case[0:-4]) + '.tif' res_img = imread_gdal_mask_small(r_n, EVALUATION_MASK_LEVEL - 3) r = int(((2 * np.ceil(2 * sig) + 1) - 1) / 2) Probs, Xcorr, Ycorr = [], [], [] res_img = median_filter(res_img, 5) res_img = gaussian_filter(res_img, g) res_img[:r, :] = 0 res_img[-r:, :] = 0 res_img[:, -r:] = 0 res_img[:, :r] = 0 # res_0=res_img # # cont=1 # while cont: # ind=np.argmax(res_img,axis=None) # ind = np.unravel_index(ind, res_img.shape) # v=res_0[ind[0],ind[1]] # if v>t: # Probs.append(v) # Xcorr.append(ind[1]) # Ycorr.append(ind[0]) # rem=np.ones(np.shape(res_img),dtype=np.float32) # di=makeGaussian(sig) # rem[ind[0]-r:ind[0]-r+np.shape(di)[0],ind[1]-r:ind[1]-r+np.shape(di)[1]]=1-di # # res_img=res_img*rem # # else: # cont=0 tmp = peak_local_max(res_img, min_distance=int(sig), threshold_abs=t) Ycorr = list(tmp[:, 0]) Xcorr = list(tmp[:, 1]) Probs = list(res_img[Ycorr, Xcorr]) # plt.imshow(res_img) # plt.plot(Xcorr, Ycorr,'*') is_tumor = case[0:5] == 'tumor' if (is_tumor): maskDIR = os.path.join(mask_folder, case[0:-4]) + '_mask.tif' evaluation_mask = computeEvaluationMask(maskDIR, L0_RESOLUTION, EVALUATION_MASK_LEVEL) ITC_labels = computeITCList(evaluation_mask, L0_RESOLUTION, EVALUATION_MASK_LEVEL) # plt.figure() # plt.imshow(evaluation_mask) # plt.plot(Xcorr, Ycorr,'*') # a=fdfdfdfd else: evaluation_mask = 0 ITC_labels = [] # # a=fsddf # FROC_data[0][caseNum] = case FP_summary[0][caseNum] = case detection_summary[0][caseNum] = case FROC_data[1][caseNum], FROC_data[2][caseNum], FROC_data[3][ caseNum], detection_summary[1][caseNum], FP_summary[1][ caseNum] = compute_FP_TP_Probs(Ycorr, Xcorr, Probs, is_tumor, evaluation_mask, ITC_labels, EVALUATION_MASK_LEVEL) caseNum += 1 # Compute FROC curve total_FPs, total_sensitivity = computeFROC(FROC_data) # sfsdfd=fdfsdfsd # plot FROC curve # plotFROC(total_FPs, total_sensitivity) if len(total_FPs) > 2: results0 = griddata(total_FPs, total_sensitivity, [0.25, 0.5, 1, 2, 4, 8]) print(results0) results = np.array(results0) if np.sum(np.isnan(results)) <= 6: results[np.isnan(results)] = results[np.isnan(results) == 0][-1] else: results = np.ones(6) * np.nan print(results) froc = np.mean(results) print(froc) return results, froc
def __tutorial_hough_circle_detection_skiimage(img_path, min_dim=40, max_dim=60): """ This algorithm is crap, the one using opencv is much much better :param img_path: :param min_dim: :param max_dim: :return: """ # load picture and detect edges img = cv2.imread(img_path) img = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY) img_edges = canny(img, sigma=3, low_threshold=10, high_threshold=50) centers = [] accums = [] radii = [] # detect all radii within the range min_radius = int(min_dim / 2) max_radius = int(max_dim / 2) hough_radii = np.arange(start=min_radius, stop=max_radius, step=1) hough_res = hough_circle(img_edges, hough_radii) for radius, h in zip(hough_radii, hough_res): # for each radius, extract 2 circles num_peaks = 2 peaks = peak_local_max(h, num_peaks=num_peaks) centers.extend(peaks) accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) img_width = img.shape[1] img_height = img.shape[0] # get the sorted accumulated values # accums_sorted = np.asarray(accums) # accums_sorted = accums_sorted[idx_sorted] # don't consider circles with accum value less than the threshold accum_threshold = 0.3 idx_sorted = np.argsort(accums)[::-1] # draw the most prominent n circles, i.e those # with the highest n peaks img_color = color.gray2rgb(img) for idx in idx_sorted: if accums[idx] < accum_threshold: continue center_y, center_x = centers[idx] radius = radii[idx] cx, cy = circle_perimeter(center_x, center_y, radius) cx[cx > img_width - 1] = img_width - 1 cy[cy > img_height - 1] = img_height - 1 img_color[cy, cx] = (220, 20, 20) # save the result skimage.io.imsave("D://_Dataset//GTSDB//Test_Regions//_img2_.png", img_color)
def image_to_spots(self, data_image: xr.DataArray, **kwargs) -> PerImageSliceSpotResults: """measure attributes of spots detected by binarizing the image using the selected threshold Parameters ---------- data_image : xr.DataArray image containing spots to be detected kwargs : Additional keyword arguments to pass to skimage.feature.peak_local_max Returns ------- PerImageSliceSpotResults : includes a SpotAttributes DataFrame of metadata containing the coordinates, intensity and radius of each spot, as well as any extra information collected during spot finding. """ optimal_threshold, thresholds, spot_counts = self._compute_threshold( data_image) data_image_np = np.asarray(data_image) # identify each spot's size by binarizing and calculating regionprops masked_image = data_image_np[:, :] > optimal_threshold labels = label(masked_image)[0] spot_props = regionprops(np.squeeze(labels)) # mask spots whose areas are too small or too large for spot_prop in spot_props: if spot_prop.area < self.min_obj_area or spot_prop.area > self.max_obj_area: masked_image[0, spot_prop.coords[:, 0], spot_prop.coords[:, 1]] = 0 # store re-calculated regionprops and labels based on the area-masked image labels = label(masked_image)[0] if self.verbose: print('computing final spots ...') spot_coords = peak_local_max(data_image_np, min_distance=self.min_distance, threshold_abs=optimal_threshold, exclude_border=False, indices=True, num_peaks=np.inf, footprint=None, labels=labels, **kwargs) if data_image.ndim == 3: res = { Axes.X.value: spot_coords[:, 2], Axes.Y.value: spot_coords[:, 1], Axes.ZPLANE.value: spot_coords[:, 0], Features.SPOT_RADIUS: 1, Features.SPOT_ID: np.arange(spot_coords.shape[0]), Features.INTENSITY: data_image_np[spot_coords[:, 0], spot_coords[:, 1], spot_coords[:, 2]], } else: zlabel = int(data_image.coords[Axes.ZPLANE.value]) res = { Axes.X.value: spot_coords[:, 1], Axes.Y.value: spot_coords[:, 0], Axes.ZPLANE.value: zlabel, Features.SPOT_RADIUS: 1, Features.SPOT_ID: np.arange(spot_coords.shape[0]), Features.INTENSITY: data_image_np[spot_coords[:, 0], spot_coords[:, 1]], } extras: Mapping[str, Any] = { "threshold": optimal_threshold, "thresholds": thresholds, "spot_counts": spot_counts } return PerImageSliceSpotResults(spot_attrs=SpotAttributes( pd.DataFrame(res)), extras=extras)
def fitter(fname, data, bounds, xaxis, yaxis, rp, binning, angle=0): (xmin, xmax, ymin, ymax) = bounds (width, height) = (xmax - xmin, ymax - ymin) if fname == "Gaussian": guess = [0, 0.5, rp["xc"], rp["yc"], 0.2*width, 0.2*height] upper_bounds = [defaults.max_od, defaults.max_od, xmax, ymax, width, height] lower_bounds = [-defaults.max_od, 0, xmin, ymin, 0, 0] res = least_squares(gauss_fit, guess, args=([xaxis, yaxis], angle, data), bounds=(lower_bounds, upper_bounds)) if not res.success: print("Warning: fit did not converge.") fits = { "f": fname, "offset": res.x[0], "peak": res.x[1], "xc": res.x[2], "yc": res.x[3], "sigx": res.x[4], "sigy": res.x[5], "gradx": 0.0, "grady": 0.0, "angle": angle } fitted = gauss_fit(res.x, [xaxis, yaxis], angle, 0) fitted = np.reshape(fitted, (height, width)) fitted_x = np.sum(fitted, axis=0) * defaults.od_to_number * binning**2.0 / height fitted_y = np.sum(fitted, axis=1) * defaults.od_to_number * binning**2.0 / width return (fits, fitted_x, fitted_y) if fname == "Gaussian w/ Gradient": od_no_bg = subtract_gradient(data) blur = ndimage.gaussian_filter(od_no_bg,5,mode='constant') # plt.figure() # plt.imshow(blur) # plt.show() upper_bounds = [defaults.max_od, defaults.max_od, xmax, ymax, width, height, 0.000375, 0.000375] lower_bounds = [-defaults.max_od, 0, xmin, ymin, 0, 0, -0.000375, -0.000375] guess = [0, 0.5, rp["xc"], rp["yc"], 0.2*width, 0.2*height, 0.0, 0.0] pks=peak_local_max(blur, min_distance=20,exclude_border=2, num_peaks=3) guesses = [guess] for pk in pks: yc = pk[0] xc = pk[1] peak = data[yc, xc] offset = np.mean(data) if peak > 0: (sigx, sigy) = 15, 15 guess = [offset, peak, xmin+xc, ymin+yc, sigx, sigy, 0.0, 0.0] guesses.append(guess) best_fit = None best_guess = np.inf for guess in guesses: print(upper_bounds) print(lower_bounds) print(guess) try: res = least_squares(gauss_grad_fit, guess, args=([xaxis, yaxis], angle, data), bounds=(lower_bounds, upper_bounds)) print(res.cost) print(res.x) if not res.success: print("Warning: fit did not converge.") elif res.cost < best_guess: best_guess = res.cost best_fit = res except ValueError as e: print(e) res = best_fit # Try to get rid of big Gaussians fit when there's no signal # if res.x[4] > 0.5 * width and res.x[5] > 0.5 * height and res.x[1] < 0.02: # res.x[1] = 0 fits = { "f": fname, "offset": res.x[0], "peak": res.x[1], "xc": res.x[2], "yc": res.x[3], "sigx": res.x[4], "sigy": res.x[5], "gradx": res.x[6], "grady": res.x[7], "angle": angle } fitted = gauss_grad_fit(res.x, [xaxis, yaxis], angle, 0) fitted = np.reshape(fitted, (height, width)) fitted_x = np.sum(fitted, axis=0) * defaults.od_to_number * binning**2.0 / height fitted_y = np.sum(fitted, axis=1) * defaults.od_to_number * binning**2.0 / width return (fits, fitted_x, fitted_y) # if fname == "Gaussian w/ Gradient": # od_no_bg = subtract_gradient(data) # blur = ndimage.gaussian_filter(od_no_bg,5,mode='constant') # # plt.figure() # # plt.imshow(blur) # # plt.show() # upper_bounds = [defaults.max_od, defaults.max_od, xmax, ymax, width, height, 0.000375, 0.000375] # lower_bounds = [-defaults.max_od, 0, xmin, ymin, 0, 0, -0.000375, -0.000375] # guess = [0, 0.5, rp["xc"], rp["yc"], 0.2*width, 0.2*height, 0.0, 0.0] # pks=peak_local_max(blur, min_distance=20,exclude_border=2, num_peaks=3) # guesses = [guess] # for pk in pks: # yc = pk[0] # xc = pk[1] # peak = data[yc, xc] # offset = np.mean(data) # if peak > 0: # (sigx, sigy) = 15, 15 # guess = [offset, peak, xmin+xc, ymin+yc, sigx, sigy, 0.0, 0.0] # guesses.append(guess) # best_fit = None # best_guess = np.inf # for guess in guesses: # print(upper_bounds) # print(lower_bounds) # print(guess) # try: # res = least_squares(gauss_grad_fit_45, guess, args=([xaxis, yaxis], data), bounds=(lower_bounds, upper_bounds)) # print(res.cost) # print(res.x) # if not res.success: # print("Warning: fit did not converge.") # elif res.cost < best_guess: # best_guess = res.cost # best_fit = res # except ValueError as e: # print(e) # res = best_fit # fits = { # "f": fname, # "offset": res.x[0], # "peak": res.x[1], # "xc": res.x[2], # "yc": res.x[3], # "sigx": res.x[4], # "sigy": res.x[5], # "gradx": res.x[6], # "grady": res.x[7] # } # fitted = gauss_grad_fit_45(res.x, [xaxis, yaxis], 0) # fitted = np.reshape(fitted, (height, width)) # fitted_x = np.sum(fitted, axis=0) * defaults.od_to_number * binning**2.0 / height # fitted_y = np.sum(fitted, axis=1) * defaults.od_to_number * binning**2.0 / width # return (fits, fitted_x, fitted_y) elif fname == "Fermi 2D": (fit_gauss, f_x, f_y) = fitter("Gaussian", data, bounds, xaxis, yaxis, rp, binning) guess = [fit_gauss["offset"], fit_gauss["peak"], fit_gauss["xc"], fit_gauss["sigx"], 0] # q=0 is T/TF=0.78 upper_bounds = [fit_gauss["offset"]+0.1, defaults.max_od, xmax, width, 50] # q=50 is T/TF=0.02 lower_bounds = [fit_gauss["offset"]-0.1, -0.1, xmin, 0, -5] # q=-5 is T/TF=8 # Integrate out vertical dimension data_int = np.sum(data, axis=0) / height res = least_squares(fermi2d, guess, args=(xaxis, angle, data_int), bounds=(lower_bounds, upper_bounds)) if not res.success: print "Warning: fit did not converge." fits = { "f": fname, "offset": res.x[0], "peak": res.x[1], "xc": res.x[2], "sigx": res.x[3]/np.sqrt(f(np.exp(res.x[4]))), "TTF": TTF2d(res.x[4]) } fitted = fermi2d(res.x, xaxis, np.array([0])) fitted_x = fitted * defaults.od_to_number * binning**2.0 fits.update( { "peakGauss": fit_gauss["peak"], "sigxGauss": fit_gauss["sigx"], "sigyGauss": fit_gauss["sigy"], "ycGauss": fit_gauss["yc"], "angle" : 0.0 }) return (fits, fitted_x, []) elif fname == "Fermi 3D": (fit_gauss, f_x, f_y) = fitter("Gaussian", data, bounds, xaxis, yaxis, rp, binning, angle) guess = [fit_gauss["offset"], fit_gauss["peak"], fit_gauss["xc"], fit_gauss["yc"], fit_gauss["sigx"], fit_gauss["sigy"], 0] # q=0 is T/TF=0.57 upper_bounds = [fit_gauss["offset"]+0.1, fit_gauss["peak"]+0.5, xmax, ymax, width, height, 50] # q=50 is T/TF=0.02 lower_bounds = [fit_gauss["offset"]-0.1, fit_gauss["peak"]-0.5, xmin, ymin, 0, 0, -6] # q=-6 is T/TF=4 res = least_squares(fermi3d, guess, args=([xaxis, yaxis], angle, data), bounds=(lower_bounds, upper_bounds)) if not res.success: print "Warning: fit did not converge." fits = { "f": fname, "offset": res.x[0], "peak": res.x[1], "xc": res.x[2], "yc": res.x[3], "sigx": res.x[4]/np.sqrt(f(np.exp(res.x[6]))), "sigy": res.x[5]/np.sqrt(f(np.exp(res.x[6]))), "TTF": TTF3d(res.x[6]) } fitted = fermi3d(res.x, [xaxis, yaxis], angle, np.array([0])) fitted = np.reshape(fitted, (height, width)) fitted_x = np.sum(fitted, axis=0) * defaults.od_to_number * binning**2.0 / height fitted_y = np.sum(fitted, axis=1) * defaults.od_to_number * binning**2.0 / width fits.update( { "peakGauss": fit_gauss["peak"], "sigxGauss": fit_gauss["sigx"], "sigyGauss": fit_gauss["sigy"], "angle" : angle }) return (fits, fitted_x, fitted_y)
def extract(image_sg, image_og, og_filenames, classlist, nu_filenames): # image_og = cv2.cvtColor(image_og, cv2.COLOR_BGR2RGB) #thresholding ret, thresh = cv2.threshold(image_sg, 180, 255, cv2.THRESH_BINARY) #morphological transformation kernel = np.ones((5, 5), np.uint8) #class_img = cv2.dilate(class_img,kernel,iterations = 1) thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) #kernel = np.ones((9,9),np.uint8) #class_img = cv2.erode(class_img,kernel,iterations = 1) # compute the exact Euclidean distance from every binary # pixel to the nearest zero pixel, then find peaks in this # distance map D = ndimage.distance_transform_edt(thresh) kernel = np.ones((5, 5), np.float32) / 25 D = cv2.filter2D(D, -1, kernel) localMax = peak_local_max(D, indices=False, min_distance=10, labels=thresh) #im = Image.fromarray(D).convert('1') #im.show(D) # perform a connected component analysis on the local peaks, # using 8-connectivity, then appy the Watershed algorithm markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0] labels = watershed(-D, markers, mask=thresh) print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1)) l = [] for label in np.unique(labels): # if the label is zero, we are examining the 'background' # so simply ignore it if label == 0: continue # otherwise, allocate memory for the label region and draw # it on the mask mask = np.zeros(image_sg.shape, dtype="uint8") mask[labels == label] = 255 # detect contours in the mask and grab the largest one #cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #cnts = imutils.grab_contours(cnts) # find contours - cv2.findCountours() function changed from OpenCV3 to OpenCV4: now it have only two parameters instead of 3 cv2MajorVersion = cv2.__version__.split(".")[0] # check for contours on thresh if int(cv2MajorVersion) == 4: ctrs, hier = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) else: im2, ctrs, hier = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #sort contours sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0]) for i, ctr in enumerate(sorted_ctrs): #get centroid M = cv2.moments(ctr) if M["m00"] > 0: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) #print(cX, cY) else: continue a = int(64 / 2) # Getting ROI roi = image_og[(cY - a):(cY + a), (cX - a):(cX + a), :] if roi.shape != (a * 2, a * 2, 3): continue l.append([cX, cY, np.asarray(ctr)]) print('l=', len(l)) s = [] for j, name in enumerate(nu_filenames): cX_nu = int(name[-11:-8]) cY_nu = int(name[-7:-4]) s.append([cX_nu, cY_nu, classlist[j]]) for m in range(len(l)): for n in range(len(s)): if l[m][0] == s[n][0] and l[m][1] == s[n][1]: if int(s[n][2]) == 1: # draw the contour and center of the shape on the image cv2.drawContours(image_og, [l[m][2]], -1, (0, 255, 255), 2) elif int(s[n][2]) == 0: cv2.drawContours(image_og, [l[m][2]], -1, (255, 0, 0), 2) # labels = labels + 50 # labels[labels==50] = 0 im = Image.fromarray(image_og).convert('RGB') # im.show(image_og) savepath = os.path.join( os.path.join( 'C:/CRC project/CRC_pytorch_chenyu/experiments/base_model/output_imgs_mxif_tumorcell_bottom2last/', 'marked1'), ('%s.png' % (og_filenames))) cv2.imwrite(savepath, image_og)
def find_disks(image, size_range, maximum=100, canny_sigma=1): """ Find circular edges in a 2D image using hough transforms. An edge is a sharp light-dark or dark-light transition. These are found using a canny edge filter. Subsequently, the edges undergo a circular Hough transformation for a range of circle radii. Peaks in the hough transformed image correspond to circle centers. Parameters ---------- image : ndarray, 2d size_range : tuple of numbers the range of circle radii to look for, in pixels maximum : number, optional The maximum number of disks canny_sigma : number, optional The sigma value used in the Canny edge filter. Default 1. See also -------- http://scikit-image.org/docs/dev/auto_examples/plot_canny.html http://scikit-image.org/docs/dev/auto_examples/edges/plot_circular_elliptical_hough_transform.html """ # Define the radius at for which hough transforms are done. Take integer # values and a maximum of 30 intermediate steps. step = max(int(round(abs(size_range[1] - size_range[0]) / 30)), 1) radii = np.arange(size_range[0], size_range[1], step=step, dtype=np.intp) # Find edges in the image edges = canny(image, sigma=canny_sigma) # Perform a circular hough transform of the edges circles = hough_circle(edges, radii) # Collect the peaks in hough space, these are circle centers data = [] for radius, circle in zip(radii, circles): peaks = peak_local_max(circle, threshold_rel=0.5, num_peaks=int(maximum)) try: accumulator = circle[peaks[:, 0], peaks[:, 1]] except TypeError: continue data.append( pd.DataFrame( dict(r=[radius] * peaks.shape[0], y=peaks[:, 0], x=peaks[:, 1], accum=accumulator))) if len(data) == 0: return pd.DataFrame(columns=['r', 'y', 'x', 'accum']) data = pd.concat(data, ignore_index=True) # drop features that are closer than the average radius together # keep the ones that are brightest in hough space (= the most circular ones) to_drop = where_close(data[['y', 'x']].values, data['r'].mean(), intensity=data['accum'].values) data.drop(to_drop, inplace=True) # Keep only brightest n circles try: # work around API change in pandas 0.17 data = data.sort_values(by=['accum'], ascending=False) except AttributeError: data = data.sort(columns=['accum'], ascending=False) return data.head(maximum).copy()
kernel = np.ones((5,5),np.uint8) erosion_a = cv.erode(inner_a,kernel,iterations = 2) erosion_b = cv.erode(inner_b,kernel,iterations = 2) innerA = cv.dilate(erosion_a,kernel,iterations = 1) innerB = cv.dilate(erosion_b,kernel,iterations = 1) cv.imwrite('innerA.png',innerA) cv.imwrite('innerB.png',innerB) eucl_a = ndimage.distance_transform_edt(innerA) eucl_b = ndimage.distance_transform_edt(innerB) localMaxA = peak_local_max(eucl_a, indices=False, labels=innerA) localMaxB = peak_local_max(eucl_b, indices=False, labels=innerB) markers_a = ndimage.label(localMaxA, structure=np.ones((3, 3)))[0] markers_b = ndimage.label(localMaxB, structure=np.ones((3, 3)))[0] labels_a = watershed(-eucl_a, markers_a, mask=innerA) labels_b = watershed(-eucl_b, markers_b, mask=innerB) def get_area(labels, inner_mask, img): area = 0 for label in np.unique(labels): if label== 0: continue mask = np.zeros(inner_mask.shape, dtype="uint8")
def Workflow_slc25a17(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [2, 36] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_3d_sigma = 1 dot_3d_cutoff = 0.045 #0.03 #0.04 minArea = 3 #5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: LOG 3d response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) bw = response > dot_3d_cutoff bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) out_img_list.append(bw.copy()) out_name_list.append('interm_mask') # step 2: 'local_maxi + watershed' for cell cutting local_maxi = peak_local_max(struct_img,labels=label(bw), min_distance=2, indices=False) out_img_list.append(local_maxi.copy()) out_name_list.append('interm_local_max') distance = distance_transform_edt(bw) im_watershed = watershed(-1*distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True) ################### # POST-PROCESSING ################### seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) ###### HACK: Only for 2019 April Release ##### if np.count_nonzero(seg>0)<50000: print('FLAG: please check the meta data of the original CZI for QC') # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function #output_fun(out_img_list, out_name_list, output_path, fn) print('please provide custom output function') elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = SLC25A17_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
thresh = threshold_otsu( img_gray) # return threshold value based on on otsu's method if bright_background: foreground_mask = img_gray <= thresh # for bright background else: foreground_mask = img_gray > thresh # for dark background # compute the Euclidean distance from every binary pixel to the nearest zero pixel # and then find peaks in this distance map # distance = ndimage.distance_transform_edt(foreground_mask) # return a boolean array shaped like image, with peaks represented by True values localMax = peak_local_max(distance, indices=False, min_distance=30, labels=foreground_mask) # perform a connected component analysis on the local peaks using 8-connectivity markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0] # apply the Watershed algorithm labels = watershed(-distance, markers, mask=foreground_mask) print ' [x] Analyzing image %s' % (image_name) print ' [x] there are %d segments found' % (len(np.unique(labels)) - 1) # loop over the unique labels returned by the Watershed algorithm # each label is a unique object img.setflags(write=1) for label in np.unique(labels):
def _step_4_find_peaks( aligned_composite_bg_removed_im, aligned_roi_rect, raw_mask_rects, border_size, field_df, sigproc_params, ): """ Find peaks on the composite image TASK: Remove the mask rect checks and replace with the same masking logic that is now implemented in the alignment phase. That is, just remove the peaks from the source instead of in post-processing. """ from skimage.feature import peak_local_max # Defer slow import from scipy.stats import iqr n_outchannels, n_inchannels, n_cycles, dim = sigproc_params.channels_cycles_dim assert ( aligned_composite_bg_removed_im.shape[0] == aligned_composite_bg_removed_im.shape[1] ) aligned_dim, _ = aligned_composite_bg_removed_im.shape check.array_t(aligned_composite_bg_removed_im, is_square=True) hat_rad = sigproc_params.hat_rad brim_rad = sigproc_params.hat_rad + 1 hat_mask, brim_mask = _hat_masks(hat_rad, brim_rad) kernel = imops.generate_gauss_kernel(1.0) kernel = kernel - kernel.mean() _fiducial_im = imops.convolve(aligned_composite_bg_removed_im, kernel) # Black out the convolution artifact around the perimeter of the _fiducial_im search_roi_rect = Rect( aligned_roi_rect.b + brim_rad, aligned_roi_rect.t - brim_rad, aligned_roi_rect.l + brim_rad, aligned_roi_rect.r - brim_rad, ) search_roi = search_roi_rect.roi() composite_fiducial_im = np.zeros_like(aligned_composite_bg_removed_im) # Use Inter-Quartile Range for some easy filtering _iqr = 0 if sigproc_params.iqr_rng is not None: _iqr = iqr( _fiducial_im[search_roi], rng=(100 - sigproc_params.iqr_rng, sigproc_params.iqr_rng), ) composite_fiducial_im[search_roi] = (_fiducial_im[search_roi] - _iqr).clip(min=0) locs = peak_local_max( composite_fiducial_im, min_distance=hat_rad, threshold_abs=sigproc_params.threshold_abs, ) # Emergency exit to prevent memory overflows # check.affirm(len(locs) < 7000, f"Too many peaks {len(locs)}") shift = field_df.set_index("cycle_i").sort_index()[["shift_y", "shift_x"]].values shift_y = shift[:, 0] shift_x = shift[:, 1] # Discard any peak in any mask_rect # ALIGN the mask rects to the composite coordinate system aligned_mask_rects = [] for channel in range(sigproc_params.n_output_channels): channel_rects = safe_list_get(raw_mask_rects, channel, []) for cycle in range(n_cycles): for rect in safe_list_get(channel_rects, cycle, []): yx = XY(rect[0], rect[1]) hw = WH(rect[2], rect[3]) yx += XY(border_size, border_size) - XY(shift_x[cycle], shift_y[cycle]) aligned_mask_rects += [(yx[0], yx[1], yx[0] + hw[0], yx[1] + hw[1])] aligned_mask_rects = np.array(aligned_mask_rects) if aligned_mask_rects.shape[0] > 0: # To compare every loc with every mask rect we use the tricky np.fn.outer() y_hits = np.greater_equal.outer(locs[:, 0], aligned_mask_rects[:, 0]) y_hits &= np.less.outer(locs[:, 0], aligned_mask_rects[:, 2]) x_hits = np.greater_equal.outer(locs[:, 1], aligned_mask_rects[:, 1]) x_hits &= np.less.outer(locs[:, 1], aligned_mask_rects[:, 3]) inside_rect = x_hits & y_hits # inside a rect if x and y are inside the rect locs_to_keep = ~np.any( inside_rect, axis=1 ) # Reject if inside of any masked rect locs = locs[locs_to_keep] circle_im = np.zeros((aligned_dim, aligned_dim)) center = aligned_dim / 2 peak_rows = [] for field_peak_i, loc in enumerate(locs): if sigproc_params.radial_filter is not None: radius = math.sqrt((loc[0] - center) ** 2 + (loc[1] - center) ** 2) radius /= center if radius >= sigproc_params.radial_filter: continue imops.set_with_mask_in_place(circle_im, brim_mask, 1, loc=loc, center=True) peak_rows += [ Munch( peak_i=0, field_peak_i=field_peak_i, aln_y=int(loc[0]), aln_x=int(loc[1]), ) ] peak_df = pd.DataFrame(peak_rows) return peak_df, circle_im, aligned_mask_rects
def depth_callback(depth_message): global model global graph global prev_mp global ROBOT_Z global fx, cx, fy, cy global crop_size global Input_Res global rgb_crop global grey_crop with TimeIt('prediction'): # with TimeIt('Crop'): # depth = bridge.imgmsg_to_cv2(depth_message) rgbdImg = bridge.imgmsg_to_cv2(depth_message) depthImg = rgbdImg[:, :, 3] rgbImg = rgbdImg[:, :, :3] rgb_raw_crop = cv2.resize( rgbdImg[(304 - crop_size) // 2:(304 - crop_size) // 2 + crop_size, (304 - crop_size) // 2:(304 - crop_size) // 2 + crop_size], (Input_Res, Input_Res)) grey_crop = cv2.cvtColor(rgb_raw_crop, cv2.COLOR_RGB2GRAY) near = 0.01 far = 0.24 depth = far * near / (far - (far - near) * depthImg) depth_crop = cv2.resize( depth[(304 - crop_size) // 2:(304 - crop_size) // 2 + crop_size, (304 - crop_size) // 2:(304 - crop_size) // 2 + crop_size], (Input_Res, Input_Res)) depth_crop = cv2.resize(depth, (Input_Res, Input_Res)) # Replace nan with 0 for inpainting. depth_crop = depth_crop.copy() depth_nan = np.isnan(depth_crop).copy() # print(depth_nan) depth_crop[depth_nan] = 0 # np.save("/home/aarons/catkin_kinect/src/yumi_grasp/src/depth_raw_pub2.npy", depth_crop) # with TimeIt('Inpaint'): # open cv inpainting does weird things at the border. depth_crop = cv2.copyMakeBorder(depth_crop, 1, 1, 1, 1, cv2.BORDER_DEFAULT) mask = (depth_crop == 0).astype(np.uint8) # Scale to keep as float, but has to be in bounds -1:1 to keep opencv happy. depth_scale = np.abs(depth_crop).max() depth_crop = depth_crop.astype(np.float32) / ( depth_scale) # Has to be float32, 64 not supported. depth_crop = cv2.inpaint(depth_crop, mask, 1, cv2.INPAINT_NS) # Back to original size and value range. depth_crop = depth_crop[1:-1, 1:-1] depth_crop = depth_crop * depth_scale # kinect output unit is millemeter, but realsense output unit is meter # with TimeIt('Calculate Depth'): # Figure out roughly the depth in mm of the part between the grippers for collision avoidance. depth_crop_neighbor = depth_crop.copy() # cv2.imshow('fram22e',depth_crop_neighbor) # depth_center = depth_crop[100:141, 130:171].flatten() depth_center = depth_crop.flatten() depth_center.sort() # depth_center = depth_center[:10].mean() * 1000.0 depth_center = depth_center.mean() * 1000.0 depth_crop = (depth_crop - depth_crop.min() ) / np.float32(depth_crop.max() - depth_crop.min()) depth_raw_pub.publish(bridge.cv2_to_imgmsg(grey_crop)) rgb_crop = np.expand_dims( ((grey_crop - grey_crop.min()) / np.float32(grey_crop.max() - grey_crop.min())), -1) depth_crop = np.expand_dims(depth_crop, axis=2) rgbd_input = np.concatenate((rgb_crop, depth_crop), axis=2) rgbd_input = np.expand_dims(rgbd_input, axis=0) with TimeIt('Inference'): with graph.as_default(): # print("begin prediction") # pred_out = model.predict(depth_crop.reshape((1, Input_Res, Input_Res, 1))) pred_out = model.predict(rgbd_input) points_out = pred_out[0].squeeze() points_out[depth_nan] = 0 # with TimeIt('Trig'): # Calculate the angle map. cos_out = pred_out[1].squeeze() sin_out = pred_out[2].squeeze() ang_out = np.arctan2(sin_out, cos_out) / 2.0 width_out = pred_out[3].squeeze() * 150.0 # Scaled 0-150:0-1 # with TimeIt('Filter'): # Filter the outputs. points_out = ndimage.filters.gaussian_filter(points_out, 5.0) # 3.0 5.0 aaron ang_out = ndimage.filters.gaussian_filter(ang_out, 2.0) # with TimeIt('Control'): # Calculate the best pose from the camera intrinsics. maxes = None ALWAYS_MAX = False # Use ALWAYS_MAX = True for the open-loop solution. if ROBOT_Z > 0.34 or ALWAYS_MAX: # > 0.34 initialises the max tracking when the robot is reset. # Track the global max. max_pixel = np.array( np.unravel_index(np.argmax(points_out), points_out.shape)) prev_mp = max_pixel.astype(np.int) else: # Calculate a set of local maxes. Choose the one that is closes to the previous one. # maxes = peak_local_max(points_out, min_distance=20, threshold_abs=0.1, num_peaks=20) #min_distance=10, threshold_abs=0.1, num_peaks=3 15 0.1 20 maxes = peak_local_max( points_out, min_distance=5, threshold_abs=0.1, num_peaks=1 ) #min_distance=10, threshold_abs=0.1, num_peaks=3 15 0.1 20 if maxes.shape[0]: max_pixel = maxes[np.argmin( np.linalg.norm(maxes - prev_mp, axis=1))] # max_pixel = np.array(np.unravel_index(np.argmax(points_out), points_out.shape)) visual_max_pixel = max_pixel.copy() # Keep a global copy for next iteration. # prev_mp = (max_pixel * 0.25 + prev_mp * 0.75).astype(np.int) grasp_quality = points_out[max_pixel[0], max_pixel[1]] else: rospy.loginfo("no lacal maxes! ") grasp_quality = 0 cmd_msg = Float32MultiArray() cmd_msg.data = [ -63, -52, 699, 0.38, 56, 697, grasp_quality, 730, 109, 85 ] # rospy.loginfo(cmd_msg) cmd_pub.publish(cmd_msg) state_msg = Float32MultiArray() state_msg.data = [True] rospy.loginfo(state_msg) state_pub.publish(state_msg) return # max_pixel = maxes[np.argmin(np.linalg.norm(maxes - prev_mp, axis=1))] # visual_max_pixel = max_pixel.copy() # # Keep a global copy for next iteration. # prev_mp = (max_pixel * 0.25 + prev_mp * 0.75).astype(np.int) # # print(max_pixel) # grasp_quality = points_out[max_pixel[0],max_pixel[1]] if max_pixel[0] >= 10 and max_pixel[0] <= 394 and max_pixel[ 1] >= 10 and max_pixel[1] <= 394: # print('bound exists! ') depth_grasp_neighbor = depth_crop_neighbor[max_pixel[0] - 10:max_pixel[0] + 10, max_pixel[1] - 10:max_pixel[1] + 10].flatten() depth_grasp_neighbor.sort() depth_grasp_neighbor = depth_grasp_neighbor[:50].mean() * 1000.0 # print(depth_grasp_neighbor) else: depth_grasp_neighbor = depth_center ang = ang_out[max_pixel[0], max_pixel[1]] width = width_out[max_pixel[0], max_pixel[1]] if abs(depth_grasp_neighbor - depth_center) < 2 or abs(grey_crop.min() - grey_crop.mean()) < 35: rospy.loginfo('task space is empty!') print(depth_center - depth_grasp_neighbor) grasp_quality = 0 # Convert max_pixel back to uncropped/resized image coordinates in order to do the camera transform. max_pixel = ((np.array(max_pixel) / 304.0 * crop_size) + np.array([(304 - crop_size) // 2, (304 - crop_size) // 2])) #[2,1] max_pixel = np.round(max_pixel).astype(np.int) point_depth = depthImg[max_pixel[0], max_pixel[1]] # convert image space to world space OpenGL view_matrix = np.array( [[0.0, 1.0, -0.0, 0.0], [-1.0, 0.0, -0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [-0.0, -0.6499999761581421, -1.2400000095367432, 1.0]]) proj_matrix = np.array([[4.510708808898926, 0.0, 0.0, 0.0], [0.0, 4.510708808898926, 0.0, 0.0], [0.0, 0.0, -1.0020020008087158, -1.0], [0.0, 0.0, -0.0200200192630291, 0.0]]) inter_gl = np.dot(view_matrix, proj_matrix) px = 2.0 * (max_pixel[1] - 0) / 304.0 - 1.0 py = 1.0 - (2.0 * max_pixel[0]) / 304.0 pz = 2.0 * point_depth - 1.0 PP3D = np.array([px, py, pz, 1.0]) PP_world = np.dot(PP3D, np.linalg.inv(inter_gl)) # PP_world = np.dot( np.linalg.inv(inter_gl), PP3D) rospy.loginfo("PP_world") print(PP3D) # print(PP_world) print(PP_world / PP_world[3]) x = PP_world[0] / PP_world[3] y = PP_world[1] / PP_world[3] z = PP_world[2] / PP_world[3] # with TimeIt('Draw'): # Draw grasp markers on the points_out and publish it. (for visualisation) grasp_img = np.zeros((Input_Res, Input_Res, 3), dtype=np.uint8) # with open('/home/aarons/catkin_kinect/src/yumi_grasp/src/heatmap.pkl', 'w') as f: # pickle.dump(points_out, f) # print(points_out.shape) # np.save("/home/aarons/catkin_kinect/src/yumi_grasp/src/realsense_Umodel.npy", points_out) # np.savetxt("/home/aarons/catkin_kinect/src/yumi_grasp/src/light_txt.npy", points_out) # exit() # pd_pointout = pd.DataFrame(points_out) # pd_pointout.to_csv('/home/aarons/catkin_kinect/src/yumi_grasp/src/points_out.csv') # heatmap test code # fig, ax = plt.subplots() # ax = sns.heatmap(ang_out, cmap='jet', xticklabels=False, yticklabels=False, cbar=False) # fig.add_axes(ax) # fig.canvas.draw() # data_heatmap = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='') # data_heatmap = data_heatmap.reshape(fig.canvas.get_width_height()[::-1] + (3,)) # data_crop = cv2.resize(data_heatmap[(480-crop_size)//2:(480-crop_size)//2+crop_size, (640-crop_size)//2:(640-crop_size)//2+crop_size,:], (Input_Res, Input_Res)) # print(data_crop.shape) if VISUALISE: pointout_pub.publish( bridge.cv2_to_imgmsg(points_out)) # for visualization module grasp_img_plain = grasp_img.copy() grasp_img[:, :, 2] = (points_out * 255.0) # rr, cc = circle(prev_mp[0], prev_mp[1], 5) rr, cc = circle(visual_max_pixel[0], visual_max_pixel[1], 5) # depth_crop[rr, cc] = 200 grasp_img[rr, cc, 0] = 0 # R grasp_img[rr, cc, 1] = 255 # G grasp_img[rr, cc, 2] = 0 # B # with TimeIt('Publish'): grasp_img = bridge.cv2_to_imgmsg(grasp_img, 'bgr8') grasp_img.header = depth_message.header grasp_pub.publish(grasp_img) grasp_img_plain = bridge.cv2_to_imgmsg(grasp_img_plain, 'rgb8') grasp_img_plain.header = depth_message.header grasp_plain_pub.publish(grasp_img_plain) depth_pub.publish(bridge.cv2_to_imgmsg(depth_crop)) ang_pub.publish(bridge.cv2_to_imgmsg(ang_out)) # Output the best grasp pose relative to camera. cmd_msg = Float32MultiArray() cmd_msg.data = [ x, y, z, ang, width, depth_grasp_neighbor, grasp_quality, depth_center, visual_max_pixel[0], visual_max_pixel[1] ] rospy.loginfo(cmd_msg) cmd_pub.publish(cmd_msg) state_msg = Float32MultiArray() state_msg.data = [False] rospy.loginfo(state_msg) state_pub.publish(state_msg)
#im = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) im = img import numpy as np import matplotlib.pyplot as plt from scipy import ndimage as ndi from skimage.segmentation import watershed from skimage.feature import peak_local_max import time # Generate an initial image with two overlapping circles # image_max is the dilation of im with a 20*20 structuring element # It is used within peak_local_max function image_max = ndi.maximum_filter(im, size=100, mode='constant') # Comparison between image_max and im to find the coordinates of local maxima coordinates = peak_local_max(im, min_distance=300) # display results fig, axes = plt.subplots(1, 3, figsize=(8, 3), sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(im, cmap=plt.cm.gray) ax[0].axis('off') ax[0].set_title('Original') ax[1].imshow(image_max, cmap=plt.cm.gray) ax[1].axis('off') ax[1].set_title('Maximum filter') ax[2].imshow(im, cmap=plt.cm.gray) ax[2].autoscale(False) ax[2].plot(coordinates[:, 1], coordinates[:, 0], 'r.')