Source code for src.measure.contour

import numpy as np

[docs]def findContours(exc,minarea): ''' detect contour of connected pixels whose area is larger than minarea :return: dictionary of a list of blobs in each frame. {frame0:[blob0, ..., blobn], frame1:[blob0, ..., blobn], ...} ''' import cv2 exc[:,0,:] = False exc[:,-1,:] = False exc[:,:,0] = False exc[:,:,-1] = False nzzs = np.where(exc.max(1).max(1))[0] bs = {i:[] for i in nzzs}# {pz:[b0,b1,...],pz+1:[...], ...} for pz in nzzs: im = exc[pz].astype(np.uint8) numLabels, labels, stats, centroids = cv2.connectedComponentsWithStats(im, 8) for label in range(1,numLabels): area = stats[label, cv2.CC_STAT_AREA] if area < minarea: continue m = labels==label pixels = np.stack(np.where(m),-1) cnt = np.fliplr(np.squeeze(cv2.findContours(m.astype(np.uint8),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0])) b = Blob(pixels,cnt,pz,len(bs[pz])) bs[pz].append(b) return bs
[docs]class Blob(object): def __init__(self,pixels,cnt,pz,j): self.pixels = pixels self.pixelsp = [(x,y) for x,y in pixels]# location of pixels inside of blob[(x0,y0),(x1,y1), ...] self.cnt = cnt self.cntp = [(x,y) for x,y in cnt]# location of pixels along the edge of blob [(x0,y0),(x1,y1), ...] self.pz = pz self.j = j
[docs] def sparseContour(self,N=5):# [(x0,y0),(x1,y1),...] ''' find evently spaced points along the contour and the outward facing bisector at each point N defines the distance between neighboring points :return: a list of dictionaries which contains the xy position and unit bisector vector ''' cntp = self.cntp i0,i1 = 0,1# i0 points to the left of a segment with lenght N, i1 points to the right cntp2 = [cntp[i0]] while i1<len(cntp): while i1<len(cntp) and np.linalg.norm([[cntp[i0][0]-cntp[i1][0]],[cntp[i0][1]-cntp[i1][1]]])<N: i1 += 1# i1 move right until reaching the right end or the distance between i0 and i1 point is less than N if i1==len(cntp): break if np.linalg.norm([[cntp2[0][0]-cntp[i1][0]],[cntp2[0][1]-cntp[i1][1]]])<N/2:# stop when distance between i1 point and the left most point is less than N/2 break cntp2.append(cntp[i1]) i0 = i1 i1 += 1 sparsexy = np.stack(cntp2,axis=0).astype(int) # vectors connecting neighoring two sparse points along contour uv = np.vstack([np.diff(sparsexy,axis=0),sparsexy[0]-sparsexy[-1]])#uv[i-1] points towards i, uv[i] points away from i uv = uv/np.expand_dims(np.linalg.norm(uv,axis=1),1) # outward facing bisector vectors at sparse points sparseuv = np.zeros(uv.shape) for i in range(uv.shape[0]): sparseuv[i] = uv[i-1]-uv[i]# sparseuv[i] bisecs edges centered at i for i in np.where(np.linalg.norm(sparseuv,axis=1)==0)[0]:# special case: two vectors parallel sparseuv[i] = np.flip(uv[i])*np.array([1,-1])# rotate parallel vector by 90 degrees sparseuv = sparseuv/np.expand_dims(np.linalg.norm(sparseuv,axis=1),1)# bisector of two given vector from skimage.measure import points_in_poly concave = points_in_poly(sparsexy+sparseuv*0.1, sparsexy)# invert inward pointing vectors sparseuv[concave] *= -1 self.points = [{'xy':sparsexy[i],'uv':sparseuv[i]} for i in range(len(sparsexy))]