Source code for util.roi_handling_utils

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017 University of Dundee & Open Microscopy Environment.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

"""
Utility methods for manipulating roi.
"""

from numpy import asarray, int32, zeros, hstack, vstack
import omero.util.script_utils as script_utils
import math


[docs] def get_line_data(pixels, x1, y1, x2, y2, line_w=2, the_z=0, the_c=0, the_t=0): """ Grabs pixel data covering the specified line, and rotates it horizontally so that x1,y1 is to the left, Returning a numpy 2d array. Used by Kymograph.py script. Uses PIL to handle rotating and interpolating the data. Converts to numpy to PIL and back (may change dtype.) @param pixels: PixelsWrapper object @param x1, y1, x2, y2: Coordinates of line @param line_w: Width of the line we want @param the_z: Z index within pixels @param the_c: Channel index @param the_t: Time index """ size_x = pixels.getSizeX() size_y = pixels.getSizeY() line_x = x2-x1 line_y = y2-y1 rads = math.atan2(line_x, line_y) # How much extra Height do we need, top and bottom? extra_h = abs(math.sin(rads) * line_w) bottom = int(max(y1, y2) + extra_h // 2) top = int(min(y1, y2) - extra_h // 2) # How much extra width do we need, left and right? extra_w = abs(math.cos(rads) * line_w) left = int(min(x1, x2) - extra_w) right = int(max(x1, x2) + extra_w) # What's the larger area we need? - Are we outside the image? pad_left, pad_right, pad_top, pad_bottom = 0, 0, 0, 0 if left < 0: pad_left = abs(left) left = 0 x = left if top < 0: pad_top = abs(top) top = 0 y = top if right > size_x: pad_right = right-size_x right = size_x w = int(right - left) if bottom > size_y: pad_bottom = bottom-size_y bottom = size_y h = int(bottom - top) tile = (x, y, w, h) # get the Tile plane = pixels.getTile(the_z, the_c, the_t, tile) # pad if we wanted a bigger region if pad_left > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_left), dtype=plane.dtype) plane = hstack((pad_data, plane)) if pad_right > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_right), dtype=plane.dtype) plane = hstack((plane, pad_data)) if pad_top > 0: data_h, data_w = plane.shape pad_data = zeros((pad_top, data_w), dtype=plane.dtype) plane = vstack((pad_data, plane)) if pad_bottom > 0: data_h, data_w = plane.shape pad_data = zeros((pad_bottom, data_w), dtype=plane.dtype) plane = vstack((plane, pad_data)) pil = script_utils.numpy_to_image(plane, (plane.min(), plane.max()), int32) # Now need to rotate so that x1,y1 is horizontally to the left of x2,y2 to_rotate = 90 - math.degrees(rads) if x1 > x2: to_rotate += 180 # filter=Image.BICUBIC see # http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2172449/ rotated = pil.rotate(to_rotate, expand=True) # rotated.show() # finally we need to crop to the length of the line length = int(math.sqrt(math.pow(line_x, 2) + math.pow(line_y, 2))) rot_w, rot_h = rotated.size crop_x = (rot_w - length) // 2 crop_x2 = crop_x + length crop_y = (rot_h - line_w) // 2 crop_y2 = crop_y + line_w cropped = rotated.crop((crop_x, crop_y, crop_x2, crop_y2)) return asarray(cropped)
[docs] def points_string_to_xy_list(string): """ Method for converting the string returned from omero.model.ShapeI.getPoints() into list of (x,y) points (floats) e.g. "points[309,427, 366,503, 190,491]" """ point_lists = string.strip().split("points") if len(point_lists) < 2: if len(point_lists) == 1 and point_lists[0]: xys = point_lists[0].split() xy_list = [tuple(map(float, xy.split(','))) for xy in xys] return xy_list raise ValueError("Unrecognised ROI shape 'points' string: %s" % string) first_list = point_lists[1] xy_list = [] for xy in first_list.strip(" []").split(", "): x, y = xy.split(",") xy_list.append((float(x.strip()), float(y.strip()))) return xy_list