def dna_size_shape(labeled, scale=1., minarea=float('-inf'), maxarea=float('+inf'), minroundness=-1.): ''' positives = dna_size_shape(dnamasks, scale=1., minarea=-Inf, maxarea=+Inf, minroundness=0) Only accepts DNA objects that fulfill the following criterion: * are greater than minarea * are smaller than maxarea * are rounder than minroundness ''' nr_objects = labeled .max() positives = np.zeros(nr_objects+1, np.bool) minarea /= scale maxarea /= scale for obj in xrange(1,nr_objects+1): objimg = croptobbox(labeled == obj) area = objimg.sum() if area > maxarea or area < minarea: continue hull = convexhull(objimg) hullArea = hull.sum() hullPerim = bwperim(hull).sum() roundness = hullPerim**2/(4*np.pi*hullArea) if roundness < minroundness: continue positives[obj] = 1 return positives
def _hull_computations(imageproc,imagehull = None): # Just share code between the two functions below if imagehull is None: imagehull = convexhull(imageproc > 0) Ahull = _bwarea(imagehull) Phull = _bwarea(bwperim(imagehull)) cofy,cofx = center_of_mass(imagehull) hull_mu00 = imgcentmoments(imagehull,0,0,cofy,cofx) hull_mu11 = imgcentmoments(imagehull,1,1,cofy,cofx) hull_mu02 = imgcentmoments(imagehull,0,2,cofy,cofx) hull_mu20 = imgcentmoments(imagehull,2,0,cofy,cofx) # Parameters of the 'image ellipse' # (the constant intensity ellipse with the same mass and # second order moments as the original image.) # From Prokop, RJ, and Reeves, AP. 1992. CVGIP: Graphical # Models and Image Processing 54(5):438-460 hull_semimajor = sqrt((2 * (hull_mu20 + hull_mu02 + \ sqrt((hull_mu20 - hull_mu02)**2 + \ 4 * hull_mu11**2)))/hull_mu00) hull_semiminor = sqrt((2 * (hull_mu20 + hull_mu02 - \ sqrt((hull_mu20 - hull_mu02)**2 + \ 4 * hull_mu11**2)))/hull_mu00) return imagehull,Ahull, Phull, hull_semimajor, hull_semiminor
def objectfeatures(img): """ values=objectfeatures(img) This implements the object features described in "Object Type Recognition for Automated Analysis of Protein Subcellular Location" by Ting Zhao, Meel Velliste, Michael V. Boland, and Robert F. Murphy in IEEE Transaction on Image Processing """ protimg = img.get("procprotein") dnaimg = img.channeldata.get("procdna", None) assert ( dnaimg is None or protimg.shape == dnaimg.shape ), "pymorph.objectfeatures: DNA image is not of same size as Protein image." labeled, N = ndimage.label(protimg, ones((3, 3))) if not N: return np.zeros((0, 11)) sofs = np.zeros((N, 11)) indices = np.arange(1, N + 1) if dnaimg is not None: dnacofy, dnacofx = ndimage.center_of_mass(dnaimg) bindna = dnaimg > 0 # According to the documentation, it shouldn't matter if indices is None, # but in my version of scipy.ndimage, you *have* to use indices. centers = ndimage.center_of_mass(protimg, labeled, indices) if N == 1: centers = list(centers) centers = np.asarray(centers) centers -= np.array((dnacofy, dnacofx)) centers **= 2 sofs[:, 1] = np.sqrt(centers.sum(1)) locations = ndimage.find_objects(labeled, N) sofs[:, 9] = ndimage.measurements.sum(protimg, labeled, indices) for obji in xrange(N): slice = locations[obji] binobj = (labeled[slice] == (obji + 1)).copy() protobj = protimg[slice] binskel = thin(binobj) objhull = convexhull(binobj) no_of_branch_points = fast_sum(find_branch_points(binskel)) hfeats = hullfeatures(binobj, objhull) sofs[obji, 0] = fast_sum(binobj) if dnaimg is not None: sofs[obji, 2] = fast_sum(binobj & bindna[slice]) sofs[obji, 3] = hfeats[2] sofs[obji, 4] = euler(binobj) sofs[obji, 5] = hfeats[1] sofs[obji, 6] = fast_sum(binskel) sofs[obji, 7] = hfeats[0] sofs[obji, 9] /= fast_sum(binskel * protobj) sofs[obji, 10] = no_of_branch_points sofs[:, 2] /= sofs[:, 0] sofs[:, 8] = sofs[:, 6] / sofs[:, 0] sofs[:, 10] /= sofs[:, 6] return sofs
def _compute_features(img): bimg = (img > 0) s00,s01,s10,s11 = bbox(bimg) if s00 > 0: s00 -= 1 if s10 > 0: s10 -= 1 bimg = bimg[s00:s01+1,s10:s11+1] hull = convexhull(bimg - pymorph.erode(bimg)) Allfeats = np.r_[features.hullfeatures.hullfeatures(img,hull),features.hullfeatures.hullsizefeatures(img,hull)] return Allfeats[np.array([0,1,2,3,5,6,7],int)]
def realconvexhull(bwimg): """ Calcuate the real convex hull of an image. The default convex hull algorithms, part of mahotas, returns the coordinates of the pixels on the hull. Therefore, that convex hull intersects with the outer pixels. Here we calculate the hull over a set containing the 4 border points of each pixel. :param bwimg: black-and-white image with 1 for occupied pixels and 0 at empty pixels :type bwimg: numpy array :return: numpy array of points in the hull """ # based on convexhull from mahotas.polygon # extra points are added to prevent intersection between the hull and pixel centers Y, X = np.where(bwimg) newim = np.zeros((2 * bwimg.shape[0], 2 * bwimg.shape[1])) for i in range(len(Y)): y = Y[i] x = X[i] newim[2 * x - 1:2 * x + 2, 2 * y - 1:2 * y + 2] = 1 return np.array(polygon.convexhull(newim)) / 2.0
def hullfeatures(imageproc,imagehull=None): """ Compute hull features: hullfract: bwarea/hullarea hullshape: roundness of hull hull_eccentricity: eccentricity of hull ellipse """ if imagehull is None: imagehull = convexhull(imageproc > 0) imagehull,Ahull, Phull, hull_semimajor, hull_semiminor = _hull_computations(imageproc,imagehull) if Ahull == 0: return numpy.array([0,0,0]) hullfract = double((imageproc > 0).sum())/Ahull hullshape = (Phull**2)/(4*pi*Ahull) if hull_semimajor != 0.: hull_eccentricity = sqrt(hull_semimajor**2 - hull_semiminor**2) / hull_semimajor else: hull_eccentricity = 0. return numpy.array([hullfract,hullshape,hull_eccentricity])
def _objskelfeats(objimg): """ feats = _objskelfeats(objimg) Calculate skeleton features for the object OBJIMG. """ objimg = objimg objbin = objimg > 0 objsize = objbin.sum() if objsize == 0: return numpy.zeros(5) objskel = thin(objbin) skellen = objskel.sum() skelhull = convexhull(objskel); hullsize = skelhull.sum() hullsize = max(hullsize, skellen) # Corner cases such as [[1]] skel_hull_area_ratio = skellen / hullsize skel_obj_area_ratio = skellen/objsize skel_fluor = (objimg * objskel).sum() obj_fluor = objimg.sum() skel_obj_fluor_ratio = skel_fluor/obj_fluor branch_points = find_branch_points(objskel) no_of_branch_points = branch_points.sum() return numpy.array([ skellen, skel_hull_area_ratio, skel_obj_area_ratio, skel_obj_fluor_ratio, no_of_branch_points/skellen])