def __img_size_tiff(self, fn): # We can use the VIPS module here for TIFF, since it can handle all the # ins and outs of the TIFF image format quite nicely. from vipsCC import VImage im = VImage.VImage(fn) size = (im.Xsize(), im.Ysize()) del im return size
def get_image_info(filepath, tilewidth): # First, find the largest dimension of the image image = VImage.VImage(filepath) width = image.Xsize() height = image.Ysize() largest_dim = width if width > height else height # Now figure out the number of zooms zoom_levels = math.ceil(math.log((largest_dim + 1) / (tilewidth), 2)) + 1 return (int(zoom_levels), (width, height))
def __img_size_tiff(self, fn): # We can use the VIPS module here for TIFF, since it can handle all the # ins and outs of the TIFF image format quite nicely. # if we're not dealing with TIFF, we don't need to import a non-core library. # Since jpeg2000 works by reading the header directly, we've made the choice to # import this with every call. It's not ideal, but it shouldn't be too bad. # If you are dealing with TIFF files and want to make a slight optimization you # can move this import statement to the top of this script. from vipsCC import VImage im = VImage.VImage(fn) size = (im.Xsize(), im.Ysize()) del im return size
def run(): global img_file, res_prefix, s_factors, n_splits, ovlap # print(img_file) # print(res_prefix) # print(s_factors) # print(n_splits) # print(ovlap) r = ET.Element('meta') t = ET.SubElement(r, 'file') t.text = img_file t = ET.SubElement(r, 'parameters') t1 = ET.SubElement(t, 'prefix') t1.text = res_prefix t1 = ET.SubElement(t, 'shrink') for s in s_factors: t2 = ET.SubElement(t1, 'factor') t2.text = str(s) t1 = ET.SubElement(t, 'split') for s in n_splits: t2 = ET.SubElement(t1, 'tile') t2.text = str(s) t1 = ET.SubElement(t, 'overlap') t1.text = str(ovlap) img = VImage.VImage(img_file) t1 = ET.SubElement(r, 'original') t2 = ET.SubElement(t1, 'width') t2.text = str(img.Xsize()) t2 = ET.SubElement(t1, 'height') t2.text = str(img.Ysize()) t2 = ET.SubElement(t1, 'channels') t2.text = str(img.Bands()) t2 = ET.SubElement(t1, 'xres') t2.text = str(img.Xres()) t2 = ET.SubElement(t1, 'yres') t2.text = str(img.Yres()) t2 = ET.SubElement(t1, 'scale') t2.text = '1.0' t2 = ET.SubElement(t1, 'tile') t2.text = '(1, 1)' path = res_prefix + '/' + os.path.basename(img_file) if os.path.exists(path): print('Warning: Overwriting old files!') else: os.mkdir(path) print("ROI detection: ") # Find the ROI: # img_scaled = img.shrink(100, 100) os.spawnv(os.P_WAIT, 'div100', ['./div100', img_file, path + '/small.ppm']) # save downscaled image - not the best way for going to Scikit Image, # but for large images we go through disk I/O anyway: # print(" -saving small version of the image") # img_scaled.write(path+'/small.ppm') print(" -read into scikit-learn") img_scaled = imread(path + '/small.ppm') # compute a minimal area based on the resolution of the image # -the image is 100x smaller than the original -> resolution is print(" -computing mask") xres, yres = img.Xres() / 100, img.Yres() / 100 min_area = 4 * min(xres, yres) # ~4 mm**2 mask, _ = tissue_region_from_rgb(img_scaled, min_area) # save the mask: print(" -saving mask") imsave(path + '/' + 'mask_div100.pbm', mask) t2 = ET.SubElement(t1, 'mask') t2.text = 'mask_div100.pbm' # coordinates of the ROI encompassing the objects, at 0.01 of original image print(" -detect ROI") rmin, cmin, rmax, cmax = bounding_box(mask) mask = mask[rmin:rmax + 1, cmin:cmax + 1] # get back to original coordinates, with an approximation of 100 pixels... rmin *= 100 cmin *= 100 rmax = min((rmax + 1) * 100, img.Ysize()) cmax = min((cmax + 1) * 100, img.Xsize()) t2 = ET.SubElement(t1, 'roi', { 'xmin': str(cmin), 'ymin': str(rmin), 'xmax': str(cmax), 'ymax': str(rmax) }) print("...end ROI detection.") # Save initial level 0: print("Crop ROI and save...") img_cropped = img.extract_area(cmin, rmin, cmax - cmin + 1, rmax - rmin + 1) img_cropped.write(path + '/pyramid-level_0.ppm') new_width, new_height = img_cropped.Xsize(), img_cropped.Ysize() img_cropped = None print("...OK") mask = None img = None # done with it gc.collect() # Generate the pyramid t1 = ET.SubElement(r, 'pyramid') t2 = ET.SubElement(t1, 'level', { 'value': '0', 'file': 'pyramid-level_0.ppm' }) t2 = ET.SubElement(t1, 'level', { 'value': '1', 'file': 'pyramid-level_1.ppm' }) t2 = ET.SubElement(t1, 'level', { 'value': '2', 'file': 'pyramid-level_2.ppm' }) t2 = ET.SubElement(t1, 'level', { 'value': '3', 'file': 'pyramid-level_3.ppm' }) t2 = ET.SubElement(t1, 'level', { 'value': '4', 'file': 'pyramid-level_4.ppm' }) t2 = ET.SubElement(t1, 'level', { 'value': '5', 'file': 'pyramid-level_5.ppm' }) # call external tool: print("Computing pyramid...") os.spawnv(os.P_WAIT, 'pyr', [ './pyr', path + '/pyramid-level_0.ppm', path + '/pyramid', str(n_levels) ]) print("...done") k = 0 for l in np.arange(n_levels + 1): f = s_factors[l] pt = path + '/' + str(s_factors[l]) if not os.path.exists(pt): os.mkdir(pt) t1 = ET.SubElement(r, 'version') t2 = ET.SubElement(t1, 'scale') t2.text = str(f) n_horiz, n_vert = n_splits[k] t2 = ET.SubElement(t1, 'split') t2.text = str((n_horiz, n_vert)) # img_scaled = img_cropped.shrink(f, f) # load the corresponding level in the pyramid: img_scaled = VImage.VImage(path + '/pyramid-level_' + str(l) + '.ppm') width = img_scaled.Xsize() height = img_scaled.Ysize() w = width / n_horiz h = height / n_vert ov = ovlap / 100.0 / 2.0 # ovlap is in % and we need half of it sv = int(n_vert != 1) sh = int(n_horiz != 1) print('Processing scale %d and tile %d,%d' % (f, n_horiz, n_vert)) y0 = 0 for i in np.arange(n_vert): x0 = 0 if i < n_vert - 1: y1 = int(y0 + h * (1.0 + sv * ov)) - 1 else: y1 = height - 1 for j in np.arange(n_horiz): if j < n_horiz - 1: x1 = int(x0 + w * (1.0 + sh * ov)) - 1 else: x1 = width - 1 tile_name = 'tile_' + str(i) + '_' + str(j) + '.' + res_format res_file = pt + '/' + tile_name print('Save to' + res_file) t2 = ET.SubElement( t1, 'tile', { 'name': tile_name, 'x0': str(x0), 'y0': str(y0), 'x1': str(x1), 'y1': str(y1) }) #print('x0 = %d, y0 = %d, x1 = %d, y1 = %d, sh = %d, ov = %f; image: %d x %d' % (x0, y0, x1, y1, sh, ov, width, height)) # do the actual work... img_sub = img_scaled.extract_area(x0, y0, x1 - x0 + 1, y1 - y0 + 1) img_sub.write(res_file) x0 = int(x1 + 1 - 2.0 * w * ov) y0 = int(y1 + 1 - 2.0 * w * ov) k += 1 raw_txt = ET.tostring(r, 'utf-8') reparsed = minidom.parseString(raw_txt) pp_txt = reparsed.toprettyxml(indent=' ') #print(pp_txt) meta_file = open(path + '/meta.xml', 'w') meta_file.write(pp_txt) return
def main(opts): directory = opts['outd'] resize_images = opts['resz'] quality = opts['qual'] tilesize = opts['tsze'] compression = opts['comp'] twid = float(tilesize) # set the compression options. We only need to munge it # for jpeg -- all the other options we don't need a quality # declaration. If one is specified, we ignore it. if compression == "jpeg": compression = "{0}:{1}".format(compression, quality) # Create a directory called "processed" within that directory # If that directory already exists, fail if os.path.isdir(os.path.join(directory, 'processed')): print 'There already is a processed directory! Delete it and try again.' sys.exit(1) else: os.mkdir(os.path.join(directory, 'processed')) # Store the zooms of the files in a list # Use another list to store filenames (same indices etc) max_zoom_list = [] filename_list = [] dimensions_list = [] for dirpath, dirnames, filenames in os.walk(directory): for filename in filenames: if filename.startswith("."): continue max_zoom, dimensions = get_image_info(os.path.join(directory, filename), twid) print "file: {0} has a maximum zoom of {1} ({2} zoom levels).".format(filename, (max_zoom - 1), max_zoom) max_zoom_list.append(max_zoom) filename_list.append(filename) dimensions_list.append(dimensions) # Now get the absolute lowest and highest max zoom lowest_max_zoom = min(max_zoom_list) # Store the number of images to figure out how many 0s we need num_images = len(filename_list) num_zeroes = len(str(num_images)) # Now figure out which files have a zoom larger than that for i,filename in enumerate(filename_list): fn,ext = os.path.splitext(filename) input_file = os.path.join(directory, filename) new_fn = fn.replace(' ', '_') # Replaces all spaces with _ because spaces can cause problems in the long run output_file = os.path.join(directory, 'processed', "{0}.tif".format(new_fn)) print "Processing {0}".format(input_file) vimage = VImage.VImage(input_file) # If the image needs to be resized if max_zoom_list[i] > lowest_max_zoom and resize_images: print '{0} needs to be resized, resizing and converting now'.format(filename) # Resize this image to the proper size ... prepend resized_ width, height = dimensions_list[i] new_width, new_height = resize_image(lowest_max_zoom, width, height, twid) vimage.resize_linear(new_width, new_height).vips2tiff('{0}:{1},tile:{2}x{2},pyramid'.format(output_file, compression, tilesize)) else: vimage.vips2tiff('{0}:{1},tile:{2}x{2},pyramid'.format(output_file, compression, tilesize)) # Now print out the max_zoom this document has print "This document has a max zoom of: {0}".format(lowest_max_zoom)
def __process_tiff(self, input_file, output_file): from vipsCC import VImage vimage = VImage.VImage(input_file) vimage.vips2tiff('{0}:{1},tile:256x256,pyramid'.format( output_file, self.compression)) del vimage
def image_size(fn): img = VImage.VImage(fn) size = (img.Xsize(), img.Ysize()) del img return size
def run(): global img_file, res_prefix, s_factors, n_splits, ovlap print(img_file) print(res_prefix) print(s_factors) print(n_splits) print(ovlap) r = ET.Element('meta') t = ET.SubElement(r, 'file') t.text = img_file t = ET.SubElement(r, 'parameters') t1 = ET.SubElement(t, 'prefix') t1.text = res_prefix t1 = ET.SubElement(t, 'shrink') for s in s_factors: t2 = ET.SubElement(t1, 'factor') t2.text = str(s) t1 = ET.SubElement(t, 'split') for s in n_splits: t2 = ET.SubElement(t1, 'tile') t2.text = str(s) t1 = ET.SubElement(t, 'overlap') t1.text = str(ovlap) img = VImage.VImage(img_file) t1 = ET.SubElement(r, 'original') t2 = ET.SubElement(t1, 'width') t2.text = str(img.Xsize()) t2 = ET.SubElement(t1, 'height') t2.text = str(img.Ysize()) t2 = ET.SubElement(t1, 'channels') t2.text = str(img.Bands()) t2 = ET.SubElement(t1, 'xres') t2.text = str(img.Xres()) t2 = ET.SubElement(t1, 'yres') t2.text = str(img.Yres()) t2 = ET.SubElement(t1, 'scale') t2.text = '1.0' t2 = ET.SubElement(t1, 'tile') t2.text = '(1, 1)' path = res_prefix + '/' + os.path.basename(img_file) if os.path.exists(path): print('Warning: Overwriting old files!') else: os.mkdir(path) k = 0 for f in s_factors: pt = path + '/' + str(f) if not os.path.exists(pt): os.mkdir(pt) t1 = ET.SubElement(r, 'version') t2 = ET.SubElement(t1, 'scale') t2.text = str(f) n_horiz, n_vert = n_splits[k] t2 = ET.SubElement(t1, 'split') t2.text = str((n_horiz, n_vert)) img_scaled = img.shrink(f, f) width = img_scaled.Xsize() height = img_scaled.Ysize() w = width / n_horiz h = height / n_vert ov = ovlap / 100.0 / 2.0 # ovlap is in % and we need half of it sv = int(n_vert != 1) sh = int(n_horiz != 1) print('Processing scale %d and tile %d,%d' % (f, n_horiz, n_vert)) y0 = 0 for i in np.arange(n_vert): x0 = 0 if i < n_vert - 1: y1 = int(y0 + h * (1.0 + sv * ov)) - 1 else: y1 = height - 1 for j in np.arange(n_horiz): if j < n_horiz - 1: x1 = int(x0 + w * (1.0 + sh * ov)) - 1 else: x1 = width - 1 tile_name = 'tile_' + str(i) + '_' + str(j) + '.' + res_format res_file = pt + '/' + tile_name print('Save to' + res_file) t2 = ET.SubElement( t1, 'tile', { 'name': tile_name, 'x0': str(x0), 'y0': str(y0), 'x1': str(x1), 'y1': str(y1) }) #print('x0 = %d, y0 = %d, x1 = %d, y1 = %d, sh = %d, ov = %f; image: %d x %d' % (x0, y0, x1, y1, sh, ov, width, height)) # do the actual work... img_sub = img_scaled.extract_area(x0, y0, x1 - x0 + 1, y1 - y0 + 1) img_sub.write(res_file) x0 = int(x1 + 1 - 2.0 * w * ov) y0 = int(y1 + 1 - 2.0 * w * ov) k += 1 raw_txt = ET.tostring(r, 'utf-8') reparsed = minidom.parseString(raw_txt) pp_txt = reparsed.toprettyxml(indent=' ') #print(pp_txt) meta_file = open(path + '/meta.xml', 'w') meta_file.write(pp_txt)