Beispiel #1
0
    def affine(self, a, b, c, d, dx, dy, ox, oy, ow, oh, interpolate=None):
        """
        Returns a new VImage that is affine transformed from this image.
        Uses `interpolate` as the interpolation method.

        interpolate: interpolation method (near, bilinear). Default: bilinear

        For other parameters, see LibVips.im_affinei()
        """
        if interpolate is None or interpolate == "bilinear":
            interpolate = VIPS.vips_interpolate_bilinear_static
        elif interpolate == "near":
            interpolate = VIPS.vips_interpolate_nearest_static
        else:
            raise ValueError("interpolate must be near or bilinear, not {0!r}".format(interpolate))

        # Link output to self, because its buffer is related to self.image()
        # We don't want self to get destructed in C++ when Python garbage
        # collects self if it falls out of scope.
        output = VImage()
        output.__inputref = self

        VIPS.im_affinei(self.image(), output.image(), interpolate, a, b, c, d, dx, dy, ox, oy, ow, oh)

        return output
Beispiel #2
0
 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
Beispiel #3
0
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))
Beispiel #4
0
    def colorize(self, image, nodata=None):
        """Returns a new RGBA VImage that has been colorized"""
        if image.Bands() != 1:
            raise ValueError("image {0!r} has more than one band".format(image))

        logging.info("Coloring data")
        logging.debug("Algorithm: {0} {1}".format(type(self).__name__, self))

        # Convert to a numpy array
        data = numpy.frombuffer(buffer=image.tobuffer(), dtype=image.NumPyType())

        # Use numexpr to color the data as RGBA bands
        bands = self._colorize_bands(data=data, nodata=nodata)

        # Merge the bands into a single RGBA VImage
        width, height = image.Xsize(), image.Ysize()
        images = [
            VImage.from_numpy_array(array=band, width=width, height=height, bands=1, format=VImage.FMTUCHAR)
            for band in bands
        ]
        return VImage.gbandjoin(bands=images)
Beispiel #5
0
    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
Beispiel #6
0
    def from_gdal_dataset(cls, dataset, band):
        """
        Creates a new 1-band VImage from `dataset` at `band`

        dataset: GDAL Dataset
        band: Number of the band, starting from 1
        """
        with LibVips.disable_warnings():
            filename = dataset.GetFileList()[0]
            image1 = VImage(filename)

            # Extract the band
            image2 = image1.extract_bands(band=(band - 1), nbands=1)

            # Cast to the right datatype, if necessary
            datatype = dataset.GetRasterBand(band).NumPyDataType
            if image2.NumPyType == datatype:
                return image2
            types = dict((v, k) for k, v in cls.NUMPY_TYPES.iteritems())
            image3 = VImage.frombuffer(
                image2.tobuffer(), width=image2.Xsize(), height=image2.Ysize(), bands=1, format=types[datatype]
            )
            image3._buf = image2
            return image3
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
Beispiel #8
0
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)
Beispiel #9
0
 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
Beispiel #10
0
 def image_size(fn):
     img = VImage.VImage(fn)
     size = (img.Xsize(), img.Ysize())
     del img
     return size
Beispiel #11
0
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)