def get_heartbeat_movie(frames, fps=60., bpm_limits=(40, 200), pyramid_type='laplacian', pyramid_nlevels=4): nt, nr, nc = frames.shape frames = np.array(frames, dtype=np.float, copy=True) frames -= frames.min() frames /= frames.max() if pyramid_type == 'laplacian': downsamp = laplacian_downsample(frames, pyramid_nlevels) elif pyramid_type == 'gaussian': downsamp = gaussian_downsample(frames, pyramid_nlevels) lowcut, highcut = (ll / 60. for ll in bpm_limits) bandpassed = butter_bandpass(downsamp, lowcut, highcut, fps) # for ii, us in enumerate(bandpassed): # for jj in xrange(pyramid_nlevels): # us = cv2.pyrUp(us) # frames[ii] = us[:nr, :nc] for ii, us in enumerate(bandpassed): for jj in xrange(pyramid_nlevels): us = transform.pyramid_expand(us) frames[ii] = us[:nr, :nc] return frames
def main(): args = vars(parser.parse_args()) filename = os.path.join(os.getcwd(), args["image"][0]) image = skimage.img_as_uint(color.rgb2gray(io.imread(filename))) subsample = 1 if (not args["subsample"] == 1): subsample = args["subsample"][0] image = transform.downscale_local_mean(image, (subsample, subsample)) image = transform.pyramid_expand(image, subsample, 0, 0) image = exposure.rescale_intensity(image, out_range=(0,args["depth"][0])) if (args["visualize"]): io.imshow(image) io.show() source = generate_face(image, subsample, args["depth"][0], FLICKER_SPEED) if source: with open(args["output"][0], 'w') as file_: file_.write(source) else: print "Attempted to generate source code, failed."
def scale_images(input_folder = '../train-256', output_folder = '../train-128', pixel_size = 128.): input_list = set([file for file in os.listdir(input_folder) if file.endswith('.jpeg')]) output_list = set([file for file in os.listdir(output_folder) if file.endswith('.jpeg')]) files_to_process = list(input_list - output_list) for fn in files_to_process: original_image = io.imread(input_folder + '/' + fn) scale = original_image.shape[0] / pixel_size if scale > 1: output_image = transform.pyramid_reduce(original_image, downscale=scale) elif scale < 1: output_image = transform.pyramid_expand(original_image, upscale=1/scale) else: output_image = original_image if output_image.shape != (pixel_size, pixel_size): x = pixel_size - output_image.shape[0] y = pixel_size - output_image.shape[1] if x < 0: image = output_image[:x, :] if y < 0: image = output_image[:, :y] output_image = (output_image - output_image.min()) / output_image.max() try: io.imsave(output_folder + '/' + fn, output_image) except ValueError: print fn + ' not saved!'
def _process_img_morph(img, threshold=.5, scale=1): if scale > 1: up_img = transform.pyramid_expand(img, upscale=scale, order=3) # type: np.ndarray img = (255. * up_img).astype(img.dtype) img_min, img_max = img.min(), img.max() bin_img = (img >= img_min + (img_max - img_min) * threshold) skel, dist_map = morphology.medial_axis(bin_img, return_distance=True) return img, bin_img, skel, dist_map
def _properties2d(image, dim): """ Compute shape property of the input 2D image. Accounts for partial volume information. :param image: 2D input image in uint8 or float (weighted for partial volume) that has a single object. :param dim: [px, py]: Physical dimension of the image (in mm). X,Y respectively correspond to AP,RL. :return: """ upscale = 5 # upscale factor for resampling the input image (for better precision) pad = 3 # padding used for cropping # Check if slice is empty if not image.any(): logging.debug('The slice is empty.') return None # Normalize between 0 and 1 (also check if slice is empty) image_norm = (image - image.min()) / (image.max() - image.min()) # Convert to float64 image_norm = image_norm.astype(np.float64) # Binarize image using threshold at 0. Necessary input for measure.regionprops image_bin = np.array(image_norm > 0.5, dtype='uint8') # Get all closed binary regions from the image (normally there is only one) regions = measure.regionprops(image_bin, intensity_image=image_norm) # Check number of regions if len(regions) > 1: logging.debug('There is more than one object on this slice.') return None region = regions[0] # Get bounding box of the object minx, miny, maxx, maxy = region.bbox # Use those bounding box coordinates to crop the image (for faster processing) image_crop = image_norm[np.clip(minx-pad, 0, image_bin.shape[0]): np.clip(maxx+pad, 0, image_bin.shape[0]), np.clip(miny-pad, 0, image_bin.shape[1]): np.clip(maxy+pad, 0, image_bin.shape[1])] # Oversample image to reach sufficient precision when computing shape metrics on the binary mask image_crop_r = transform.pyramid_expand(image_crop, upscale=upscale, sigma=None, order=1) # Binarize image using threshold at 0. Necessary input for measure.regionprops image_crop_r_bin = np.array(image_crop_r > 0.5, dtype='uint8') # Get all closed binary regions from the image (normally there is only one) regions = measure.regionprops(image_crop_r_bin, intensity_image=image_crop_r) region = regions[0] # Compute area with weighted segmentation and adjust area with physical pixel size area = np.sum(image_crop_r) * dim[0] * dim[1] / upscale ** 2 # Compute ellipse orientation, rotated by 90deg because image axis are inverted, modulo pi, in deg, and between [0, 90] orientation = _fix_orientation(region.orientation) # Find RL and AP diameter based on major/minor axes and cord orientation= [diameter_AP, diameter_RL] = \ _find_AP_and_RL_diameter(region.major_axis_length, region.minor_axis_length, orientation, [i / upscale for i in dim]) # TODO: compute major_axis_length/minor_axis_length by summing weighted voxels along axis # Fill up dictionary properties = {'area': area, 'diameter_AP': diameter_AP, 'diameter_RL': diameter_RL, 'centroid': region.centroid, 'eccentricity': region.eccentricity, 'orientation': orientation, 'solidity': region.solidity # convexity measure } return properties
def upsample(data: np.ndarray) -> np.array: """ :type data: array :param data: data to transform apply pyramid expand with params upscale 2 and order 1, mode reflect. """ return transform.pyramid_expand(data, upscale=2, sigma=None, order=1, mode='reflect', cval=0)
def weight_pyramid(generator, weights=[1, 1, 1]): nb_layers = len(weights) - 1 for batch in generator: batch_merged = [] for img in batch: img = img[0] lap_pyr = [] prev = img for i in range(nb_layers): gauss = pyramid_reduce(prev) lap_pyr.append(prev - pyramid_expand(gauss)) prev = gauss merged = gauss*weights[0] for i, lap in enumerate(reversed(lap_pyr)): merged = pyramid_expand(merged) + weights[i+1]*lap batch_merged.append(merged) yield np.stack(batch_merged).reshape(batch.shape)
def preprocess_images(input_folder = '../train', output_folder = '../train-256', pixel_size = 256.): input_list = set([file for file in os.listdir(input_folder) if file.endswith('.jpeg')]) output_list = set([file for file in os.listdir(output_folder) if file.endswith('.jpeg')]) files_to_process = list(input_list - output_list) for fn in files_to_process: original_image = io.imread(input_folder + '/' + fn) shape = original_image.shape[1] - original_image.shape[0] if shape < 0: shape = -shape if shape % 2 == 0: shape += 1 kernel = np.ones((shape, 1)) else: if shape % 2 == 0: shape += 1 kernel = np.ones((1, shape)) output_image = remove_padding(original_image, kernel) grayed_image = color.rgb2gray(padded_image) blurred_image = gaussian_filter(grayed_image,sigma=6, multichannel=False) difference_image = equalize_hist(grayed_image - blurred_image) scale = difference_image.shape[0] / pixel_size if scale > 1: output_image = transform.pyramid_reduce(difference_image, downscale=scale) elif scale < 1: output_image = transform.pyramid_expand(difference_image, upscale=1/scale) else: output_image = difference_image if output_image.shape != (pixel_size, pixel_size): x = pixel_size - output_image.shape[0] y = pixel_size - output_image.shape[1] if x < 0: image = output_image[:x, :] if y < 0: image = output_image[:, :y] output_image = (output_image - output_image.min()) / output_image.max() try: io.imsave(output_folder + '/' + fn, output_image) except ValueError: print fn + ' not saved!'
comps = detector.mixture.mixture_components() #theta = kernels.reshape((kernels.shape[0], -1)) llhs = [[] for i in xrange(detector.num_mixtures)] print 'Iterating CAD images' for cad_i, cad_filename in enumerate(cad_files): cad = gv.img.load_image(cad_filename) f = cad.shape[0]/size[0] if f > 1: cad = pyramid_reduce(cad, downscale=f) elif f < 1: cad = pyramid_expand(cad, upscale=1/f) mixcomp = comps[cad_i] alpha = cad[...,3] gray_cad = gv.img.asgray(cad) bkg_img = bkg_generator.next() # Notice, gray_cad is not multiplied by alpha, since most files use premultiplied alpha composite = gray_cad + bkg_img * (1 - alpha) # Get features X_full = descriptor.extract_features(composite, settings=dict(spread_radii=radii)) X = gv.sub.subsample(X_full, subsize)
def test_pyramid_expand(): rows, cols, dim = image.shape out = pyramid_expand(image, upscale=2) assert_array_equal(out.shape, (rows * 2, cols * 2, dim))
def to_RLE(mask): """Convert mask to run length encoded format""" dm = np.diff(mask.T.flatten().astype('int16')) start = np.nonzero(dm>0)[0] stop = np.nonzero(dm<0)[0] RLE = np.vstack((start+2, stop-start)) return ' '.join(str(n) for n in RLE.flatten(order='F')) RLE = [] for i, file in enumerate(orderedfnames, 1): # Load the prediction file raw = np.load(file)[0,:,:] upsized = transform.pyramid_expand(raw,2) # Apply masking function prediction = upsized > DECISION_BOUNDARY if i==1: print prediction.shape area = prediction.sum() # Apply size-based cutoff and output RLE if area < AREA_CUTOFF: RLE.append((i,'')) else: RLE.append((i,to_RLE(prediction))) out = '\n'.join('{i},{rle}'.format(i=r[0],rle=r[1]) for r in RLE) with open('output.csv','w') as f: f.write('img,pixels\n')
def _process_file(settings, bkg_stack, bkg_stack_num, fn, mixcomp): ag.info("Processing file", fn) seed = np.abs(hash(fn) % 123124) descriptor_name = settings["detector"]["descriptor"] img_size = settings["detector"]["image_size"] part_size = settings[descriptor_name]["part_size"] psize = settings["detector"]["subsample_size"] # The 4 is for the edge border that falls off # orig_sh = (img_size[0] - part_size[0] - 4 + 1, img_size[1] - part_size[1] - 4 + 1) orig_sh = img_size sh = gv.sub.subsample_size(np.ones(orig_sh), psize) # We need the descriptor to generate and manipulate images descriptor = gv.load_descriptor(settings) counts = np.zeros( (settings["detector"]["num_mixtures"], sh[0], sh[1], descriptor.num_parts + 1, descriptor.num_parts), dtype=np.uint16, ) prnds = [np.random.RandomState(seed + i) for i in xrange(5)] # Binarize support and Extract alpha # color_img, alpha = gv.img.load_image_binarized_alpha(fn) color_img = gv.img.load_image(fn) from skimage.transform import pyramid_reduce, pyramid_expand f = color_img.shape[0] / settings["detector"]["image_size"][0] if f > 1: color_img = pyramid_reduce(color_img, downscale=f) elif f < 1: color_img = pyramid_expand(color_img, upscale=1 / f) alpha = color_img[..., 3] img = gv.img.asgray(color_img) # Resize it # TODO: This only looks at the first axis assert img.shape == settings["detector"]["image_size"], "Target size not achieved: {0} != {1}".format( img.shape, settings["detector"]["image_size"] ) # Settings bsettings = settings["edges"].copy() radius = bsettings["radius"] bsettings["radius"] = 0 # offsets = gv.sub.subsample_offset_shape(sh, psize) # locations0 = xrange(offsets[0], sh[0], psize[0]) # locations1 = xrange(offsets[1], sh[1], psize[1]) locations0 = xrange(sh[0]) locations1 = xrange(sh[1]) # locations0 = xrange(10-4, 10+5) # locations1 = xrange(10-4, 10+5) # locations0 = xrange(10, 11) # locations1 = xrange(10, 11) # padded_theta = descriptor.unspread_parts_padded # pad = 10 pad = 5 size = settings[descriptor_name]["part_size"] X_pad_size = (size[0] + pad * 2, size[1] + pad * 2) img_pad = ag.util.zeropad(img, pad) alpha_pad = ag.util.zeropad(alpha, pad) # Iterate every duplicate dups = settings["detector"].get("duplicates", 1) bkgs = np.empty(((descriptor.num_parts + 1) * dups,) + X_pad_size) # cads = np.empty((descriptor.num_parts,) + X_pad_size) # alphas = np.empty((descriptor.num_parts,) + X_pad_size, dtype=np.bool) radii = settings["detector"]["spread_radii"] psize = settings["detector"]["subsample_size"] cb = settings["detector"].get("crop_border") sett = dict(spread_radii=radii, subsample_size=psize, crop_border=cb) plt.clf() plt.imshow(img) plt.savefig("output/img.png") if 0: # NEW{ totfeats = np.zeros(sh + (descriptor.num_parts,) * 2) for f in xrange(descriptor.num_parts): num = bkg_stack_num[f] for d in xrange(dups): feats = np.zeros(sh + (descriptor.num_parts,), dtype=np.uint8) for i, j in itr.product(locations0, locations1): x = i * psize[0] y = i * psize[1] bkg_i = prnds[4].randint(num) bkg = bkg_stack[f, bkg_i] selection = [slice(x, x + X_pad_size[0]), slice(y, y + X_pad_size[1])] # X_pad = edges_pad[selection].copy() patch = img_pad[selection] alpha_patch = alpha_pad[selection] # patch = np.expand_dims(patch, 0) # alpha_patch = np.expand_dims(alpha_patch, 0) # TODO: Which one? # img_with_bkg = patch + bkg * (1 - alpha_patch) img_with_bkg = patch * alpha_patch + bkg * (1 - alpha_patch) edges_pads = ag.features.bedges(img_with_bkg, **bsettings) X_pad_spreads = ag.features.bspread(edges_pads, spread=bsettings["spread"], radius=radius) padding = pad - 2 X_spreads = X_pad_spreads[padding:-padding:, padding:-padding] partprobs = ag.features.code_parts( X_spreads, descriptor._log_parts, descriptor._log_invparts, descriptor.settings["threshold"], descriptor.settings["patch_frame"], ) part = partprobs.argmax() if part > 0: feats[i, j, part - 1] = 1 # Now spread the parts feats = ag.features.bspread(feats, spread="box", radius=2) totfeats[:, :, f] += feats # } kernels = totfeats[:, :, 0].astype(np.float32) / (descriptor.num_parts * dups) # Subsample kernels sub_kernels = gv.sub.subsample(kernels, psize, skip_first_axis=False) np.save("tmp2.npy", sub_kernels) print "saved tmp2.npy" import sys sys.exit(0) # ag.info("Iteration {0}/{1}".format(loop+1, num_duplicates)) # ag.info("Iteration") for i, j in itr.product(locations0, locations1): x = i * psize[0] y = i * psize[1] print "processing", i, j selection = [slice(x, x + X_pad_size[0]), slice(y, y + X_pad_size[1])] # X_pad = edges_pad[selection].copy() patch = img_pad[selection] alpha_patch = alpha_pad[selection] patch = np.expand_dims(patch, 0) alpha_patch = np.expand_dims(alpha_patch, 0) for f in xrange(descriptor.num_parts + 1): num = bkg_stack_num[f] for d in xrange(dups): bkg_i = prnds[4].randint(num) bkgs[f * dups + d] = bkg_stack[f, bkg_i] img_with_bkgs = patch * alpha_patch + bkgs * (1 - alpha_patch) if 0: edges_pads = ag.features.bedges(img_with_bkgs, **bsettings) X_pad_spreads = ag.features.bspread(edges_pads, spread=bsettings["spread"], radius=radius) padding = pad - 2 X_spreads = X_pad_spreads[:, padding:-padding:, padding:-padding] # partprobs = ag.features.code_parts_many(X_spreads, descriptor._log_parts, descriptor._log_invparts, # descriptor.settings['threshold'], descriptor.settings['patch_frame']) # parts = partprobs.argmax(axis=-1) parts = np.asarray([descriptor.extract_features(im, settings=sett)[0, 0] for im in img_with_bkgs]) for f in xrange(descriptor.num_parts + 1): hist = np.bincount(parts[f * dups : (f + 1) * dups].ravel(), minlength=descriptor.num_parts + 1) counts[mixcomp, i, j, f] += hist[1:] # import pdb; pdb.set_trace() # for f in xrange(descriptor.num_parts): # for d in xrange(dups): # # Code parts # #parts = descriptor.extract_parts(X_spreads[f*dups+d].astype(np.uint8)) # # f_plus = parts[f*dups+d] # if f_plus > 0: # tau = self.settings.get('tau') # if self.settings.get('tau'): # parts = partprobs.argmax(axis=-1) # Accumulate and return # counts[mixcomp,i,j,f,f_plus-1] += 1#parts[0,0] if 0: kernels = counts[:, :, :, 0].astype(np.float32) / (descriptor.num_parts * dups) import pdb pdb.set_trace() radii = (2, 2) aa_log = np.log(1 - kernels) aa_log = ag.util.zeropad(aa_log, (0, radii[0], radii[1], 0)) integral_aa_log = aa_log.cumsum(1).cumsum(2) offsets = gv.sub.subsample_offset(kernels[0], psize) if 1: # Fix kernels istep = 2 * radii[0] jstep = 2 * radii[1] sh = kernels.shape[1:3] for mixcomp in xrange(1): # Note, we are going in strides of psize, given a certain offset, since # we will be subsampling anyway, so we don't need to do the rest. for i in xrange(offsets[0], sh[0], psize[0]): for j in xrange(offsets[1], sh[1], psize[1]): p = gv.img.integrate(integral_aa_log[mixcomp], i, j, i + istep, j + jstep) kernels[mixcomp, i, j] = 1 - np.exp(p) # Subsample kernels sub_kernels = gv.sub.subsample(kernels, psize, skip_first_axis=True) np.save("tmp.npy", sub_kernels) print "saved tmp.npy" import sys sys.exit(0) if 0: for f in xrange(descriptor.num_parts): # Pick only one background for this part and file num = bkg_stack_num[f] # Assumes num > 0 bkg_i = prnds[4].randint(num) bkgmap = bkg_stack[f, bkg_i] # Composite img_with_bkg = gv.img.composite(patch, bkgmap, alpha_patch) # Retrieve unspread edges (with a given background gray level) edges_pad = ag.features.bedges(img_with_bkg, **bsettings) # Pad the edges # edges_pad = ag.util.zeropad(edges, (pad, pad, 0)) # Do spreading X_pad_spread = ag.features.bspread(edges_pad, spread=bsettings["spread"], radius=radius) # De-pad padding = pad - 2 X_spread = X_pad_spread[padding:-padding, padding:-padding] # Code parts parts = descriptor.extract_parts(X_spread.astype(np.uint8)) # Accumulate and return counts[mixcomp, i, j, f] += parts[0, 0] # Translate counts to spread counts (since we're assuming independence of samples within one CAD image) return counts
def laplacian_reconstruct(pyr): # Takes tuple of Laplacian pyramid levels and reconstructs original images if len(pyr) == 1: return pyr[0] else: return pyr[0] + skt.pyramid_expand(laplacian_reconstruct(pyr[1:]), upscale=2, sigma=10, mode='constant', cval=0.0)
def _properties2d(image, dim): """ Compute shape property of the input 2D image. Accounts for partial volume information. :param image: 2D input image in uint8 or float (weighted for partial volume) that has a single object. :param dim: [px, py]: Physical dimension of the image (in mm). X,Y respectively correspond to AP,RL. :return: """ upscale = 5 # upscale factor for resampling the input image (for better precision) pad = 3 # padding used for cropping # Check if slice is empty if not image.any(): logging.debug('The slice is empty.') return None # Normalize between 0 and 1 (also check if slice is empty) image_norm = (image - image.min()) / (image.max() - image.min()) # Convert to float64 image_norm = image_norm.astype(np.float64) # Binarize image using threshold at 0. Necessary input for measure.regionprops image_bin = np.array(image_norm > 0.5, dtype='uint8') # Get all closed binary regions from the image (normally there is only one) regions = measure.regionprops(image_bin, intensity_image=image_norm) # Check number of regions if len(regions) > 1: logging.debug('There is more than one object on this slice.') return None region = regions[0] # Get bounding box of the object minx, miny, maxx, maxy = region.bbox # Use those bounding box coordinates to crop the image (for faster processing) image_crop = image_norm[np.clip(minx - pad, 0, image_bin.shape[0]):np. clip(maxx + pad, 0, image_bin.shape[0]), np.clip(miny - pad, 0, image_bin.shape[1]):np. clip(maxy + pad, 0, image_bin.shape[1])] # Oversample image to reach sufficient precision when computing shape metrics on the binary mask image_crop_r = transform.pyramid_expand(image_crop, upscale=upscale, sigma=None, order=1) # Binarize image using threshold at 0. Necessary input for measure.regionprops image_crop_r_bin = np.array(image_crop_r > 0.5, dtype='uint8') # Get all closed binary regions from the image (normally there is only one) regions = measure.regionprops(image_crop_r_bin, intensity_image=image_crop_r) region = regions[0] # Compute area with weighted segmentation and adjust area with physical pixel size area = np.sum(image_crop_r) * dim[0] * dim[1] / upscale**2 # Compute ellipse orientation, modulo pi, in deg, and between [0, 90] orientation = fix_orientation(region.orientation) # Find RL and AP diameter based on major/minor axes and cord orientation= [diameter_AP, diameter_RL] = \ _find_AP_and_RL_diameter(region.major_axis_length, region.minor_axis_length, orientation, [i / upscale for i in dim]) # TODO: compute major_axis_length/minor_axis_length by summing weighted voxels along axis # Deal with https://github.com/neuropoly/spinalcordtoolbox/issues/2307 if any(x in platform.platform() for x in ['Darwin-15', 'Darwin-16']): solidity = np.nan else: solidity = region.solidity # Fill up dictionary properties = { 'area': area, 'diameter_AP': diameter_AP, 'diameter_RL': diameter_RL, 'centroid': region.centroid, 'eccentricity': region.eccentricity, 'orientation': orientation, 'solidity': solidity # convexity measure } return properties