def _initData(self): """ Initialize the cluster centers and initial values of the pixel-wise cluster assignment and distance values. """ self.clusters = -1 * np.ones(self.img.shape[:2]) self.distances = self.FLT_MAX * np.ones(self.img.shape[:2]) centers = [] for i in xrange(self.step, self.width - self.step/2, self.step): for j in xrange(self.step, self.height - self.step/2, self.step): nc = self._findLocalMinimum(center=(i, j)) color = self.labimg[nc[1], nc[0]] center = [color[0], color[1], color[2], nc[0], nc[1]] centers.append(center) self.center_counts = np.zeros(len(centers)) self.centers = np.array(centers)
def generateSuperPixels(self): """ Compute the over-segmentation based on the step-size and relative weighting of the pixel and colour values. """ self._initData() indnp = np.mgrid[0:self.height,0:self.width].swapaxes(0,2).swapaxes(0,1) for i in range(self.ITERATIONS): self.distances = self.FLT_MAX * np.ones(self.img.shape[:2]) for j in xrange(self.centers.shape[0]): xlow, xhigh = int(self.centers[j][3] - self.step), int(self.centers[j][3] + self.step) ylow, yhigh = int(self.centers[j][4] - self.step), int(self.centers[j][4] + self.step) if xlow <= 0: xlow = 0 if xhigh > self.width: xhigh = self.width if ylow <=0: ylow = 0 if yhigh > self.height: yhigh = self.height cropimg = self.labimg[ylow : yhigh , xlow : xhigh].astype(np.int64) colordiff = cropimg - self.labimg[self.centers[j][4], self.centers[j][3]] colorDist = np.sqrt(np.sum(np.square(colordiff.astype(np.int64)), axis=2)) yy, xx = np.ogrid[ylow : yhigh, xlow : xhigh] pixdist = ((yy-self.centers[j][4])**2 + (xx-self.centers[j][3])**2)**0.5 dist = ((colorDist/self.nc)**2 + (pixdist/self.ns)**2)**0.5 distanceCrop = self.distances[ylow : yhigh, xlow : xhigh] idx = dist < distanceCrop distanceCrop[idx] = dist[idx] self.distances[ylow : yhigh, xlow : xhigh] = distanceCrop self.clusters[ylow : yhigh, xlow : xhigh][idx] = j for k in xrange(len(self.centers)): idx = (self.clusters == k) colornp = self.labimg[idx] distnp = indnp[idx] self.centers[k][0:3] = np.sum(colornp, axis=0) sumy, sumx = np.sum(distnp, axis=0) self.centers[k][3:] = sumx, sumy self.centers[k] /= np.sum(idx) self._createConnectivity() superpixels = self._segmentSuperpixels() return superpixels
def _createConnectivity(self): """ Enforce connectivity of the superpixels. Needs to be optimized. """ label = 0 adjlabel = 0 lims = self.width * self.height / self.centers.shape[0] dx4 = [-1, 0, 1, 0] dy4 = [0, -1, 0, 1] new_clusters = -1 * np.ones(self.img.shape[:2]).astype(np.int64) elements = [] for i in xrange(self.width): for j in xrange(self.height): if new_clusters[j, i] == -1: elements = [] elements.append((j, i)) for dx, dy in zip(dx4, dy4): x = elements[0][1] + dx y = elements[0][0] + dy if (x>=0 and x < self.width and y>=0 and y < self.height and new_clusters[y, x] >=0): adjlabel = new_clusters[y, x] count = 1 c = 0 while c < count: for dx, dy in zip(dx4, dy4): x = elements[c][1] + dx y = elements[c][0] + dy if (x>=0 and x<self.width and y>=0 and y<self.height): if new_clusters[y, x] == -1 and self.clusters[j, i] == self.clusters[y, x]: elements.append((y, x)) new_clusters[y, x] = label count+=1 c+=1 #print count if (count <= lims >> 2): for c in range(count): new_clusters[elements[c]] = adjlabel label-=1 label+=1 self.new_clusters = new_clusters
def lktrack(img1, img2, ptsI, nPtsI, winsize_ncc=10, win_size_lk=4, method=cv.CV_TM_CCOEFF_NORMED): """ **SUMMARY** (Dev Zone) Lucas-Kanede Tracker with pyramids **PARAMETERS** img1 - Previous image or image containing the known bounding box (Numpy array) img2 - Current image ptsI - Points to track from the first image Format ptsI[0] - x1, ptsI[1] - y1, ptsI[2] - x2, .. nPtsI - Number of points to track from the first image winsize_ncc - size of the search window at each pyramid level in LK tracker (in int) method - Paramete specifying the comparison method for normalized cross correlation (see http://opencv.itseez.com/modules/imgproc/doc/object_detection.html?highlight=matchtemplate#cv2.matchTemplate) **RETURNS** fb - forward-backward confidence value. (corresponds to euclidean distance between). ncc - normCrossCorrelation values status - Indicates positive tracks. 1 = PosTrack 0 = NegTrack ptsJ - Calculated Points of second image """ template_pt = [] target_pt = [] fb_pt = [] ptsJ = [-1] * len(ptsI) for i in range(nPtsI): template_pt.append((ptsI[2 * i], ptsI[2 * i + 1])) target_pt.append((ptsI[2 * i], ptsI[2 * i + 1])) fb_pt.append((ptsI[2 * i], ptsI[2 * i + 1])) template_pt = np.asarray(template_pt, dtype="float32") target_pt = np.asarray(target_pt, dtype="float32") fb_pt = np.asarray(fb_pt, dtype="float32") target_pt, status, track_error = cv2.calcOpticalFlowPyrLK( img1, img2, template_pt, target_pt, winSize=(win_size_lk, win_size_lk), flags=cv.OPTFLOW_USE_INITIAL_FLOW, criteria=(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03)) fb_pt, status_bt, track_error_bt = cv2.calcOpticalFlowPyrLK( img2, img1, target_pt, fb_pt, winSize=(win_size_lk, win_size_lk), flags=cv.OPTFLOW_USE_INITIAL_FLOW, criteria=(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03)) status = status & status_bt ncc = normCrossCorrelation(img1, img2, template_pt, target_pt, status, winsize_ncc, method) fb = euclideanDistance(template_pt, target_pt) newfb = -1 * np.ones(len(fb)) newncc = -1 * np.ones(len(ncc)) for i in np.argwhere(status): i = i[0] ptsJ[2 * i] = target_pt[i][0] ptsJ[2 * i + 1] = target_pt[i][1] newfb[i] = fb[i] newncc[i] = ncc[i] return newfb, newncc, status, ptsJ
def createNotchFilter(self, dia1, dia2=None, cen=None, size=(64, 64), type="lowpass"): """ **SUMMARY** Creates a disk shaped notch filter of given diameter at given center. **PARAMETERS** * *dia1* - int - diameter of the disk shaped notch - list - provide a list of three diameters to create a 3 channel filter * *dia2* - int - outer diameter of the disk shaped notch used for bandpass filter - list - provide a list of three diameters to create a 3 channel filter * *cen* - tuple (x, y) center of the disk shaped notch if not provided, it will be at the center of the filter * *size* - size of the filter (width, height) * *type*: - lowpass or highpass filter **RETURNS** DFT notch filter **EXAMPLE** >>> notch = DFT.createNotchFilter(dia1=200, cen=(200, 200), size=(512, 512), type="highpass") >>> notch = DFT.createNotchFilter(dia1=200, dia2=300, cen=(200, 200), size=(512, 512)) >>> img = Image('lenna') >>> notch.applyFilter(img).show() """ if isinstance(dia1, list): if len(dia1) != 3 and len(dia1) != 1: warnings.warn("diameter list must be of size 1 or 3") return None if isinstance(dia2, list): if len(dia2) != 3 and len(dia2) != 1: warnings.warn("diameter list must be of size 3 or 1") return None if len(dia2) == 1: dia2 = [dia2[0]] * len(dia1) else: dia2 = [dia2] * len(dia1) if isinstance(cen, list): if len(cen) != 3 and len(cen) != 1: warnings.warn("center list must be of size 3 or 1") return None if len(cen) == 1: cen = [cen[0]] * len(dia1) else: cen = [cen] * len(dia1) stackedfilter = DFT() for d1, d2, c in zip(dia1, dia2, cen): stackedfilter = stackedfilter._stackFilters( self.createNotchFilter(d1, d2, c, size, type)) image = Image(stackedfilter._numpy) retVal = DFT(numpyarray=stackedfilter._numpy, image=image, dia=dia1 + dia2, channels=len(dia1), size=size, type=stackedfilter._type, frequency=stackedfilter._freqpass) return retVal w, h = size if cen is None: cen = (w / 2, h / 2) a, b = cen y, x = np.ogrid[-a:w - a, -b:h - b] r = dia1 / 2 mask = x * x + y * y <= r * r flt = np.ones((w, h)) flt[mask] = 255 if type == "highpass": flt = 255 - flt if dia2 is not None: a, b = cen y, x = np.ogrid[-a:w - a, -b:h - b] r = dia2 / 2 mask = x * x + y * y <= r * r flt1 = np.ones((w, h)) flt1[mask] = 255 flt1 = 255 - flt1 flt = flt + flt1 np.clip(flt, 0, 255) type = "bandpass" img = Image(flt) notchfilter = DFT(size=size, numpyarray=flt, image=img, dia=dia1, type="Notch", frequency=type) return notchfilter
def lktrack(img1, img2, ptsI, nPtsI, winsize_ncc=10, win_size_lk=4, method=cv2.cv.CV_TM_CCOEFF_NORMED): """ **SUMMARY** (Dev Zone) Lucas-Kanede Tracker with pyramids **PARAMETERS** img1 - Previous image or image containing the known bounding box (Numpy array) img2 - Current image ptsI - Points to track from the first image Format ptsI[0] - x1, ptsI[1] - y1, ptsI[2] - x2, .. nPtsI - Number of points to track from the first image winsize_ncc - size of the search window at each pyramid level in LK tracker (in int) method - Paramete specifying the comparison method for normalized cross correlation (see http://opencv.itseez.com/modules/imgproc/doc/object_detection.html?highlight=matchtemplate#cv2.matchTemplate) **RETURNS** fb - forward-backward confidence value. (corresponds to euclidean distance between). ncc - normCrossCorrelation values status - Indicates positive tracks. 1 = PosTrack 0 = NegTrack ptsJ - Calculated Points of second image """ template_pt = [] target_pt = [] fb_pt = [] ptsJ = [-1]*len(ptsI) for i in range(nPtsI): template_pt.append((ptsI[2*i],ptsI[2*i+1])) target_pt.append((ptsI[2*i],ptsI[2*i+1])) fb_pt.append((ptsI[2*i],ptsI[2*i+1])) template_pt = np.asarray(template_pt,dtype="float32") target_pt = np.asarray(target_pt,dtype="float32") fb_pt = np.asarray(fb_pt,dtype="float32") target_pt, status, track_error = cv2.calcOpticalFlowPyrLK(img1, img2, template_pt, target_pt, winSize=(win_size_lk, win_size_lk), flags = cv2.OPTFLOW_USE_INITIAL_FLOW, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) fb_pt, status_bt, track_error_bt = cv2.calcOpticalFlowPyrLK(img2,img1, target_pt,fb_pt, winSize = (win_size_lk,win_size_lk),flags = cv2.OPTFLOW_USE_INITIAL_FLOW, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) status = status & status_bt ncc = normCrossCorrelation(img1, img2, template_pt, target_pt, status, winsize_ncc, method) fb = euclideanDistance(template_pt, target_pt) newfb = -1*np.ones(len(fb)) newncc = -1*np.ones(len(ncc)) for i in np.argwhere(status): i = i[0] ptsJ[2 * i] = target_pt[i][0] ptsJ[2 * i + 1] = target_pt[i][1] newfb[i] = fb[i] newncc[i] = ncc[i] return newfb, newncc, status, ptsJ
def createNotchFilter(self, dia1, dia2=None, cen=None, size=(64, 64), type="lowpass"): """ **SUMMARY** Creates a disk shaped notch filter of given diameter at given center. **PARAMETERS** * *dia1* - int - diameter of the disk shaped notch - list - provide a list of three diameters to create a 3 channel filter * *dia2* - int - outer diameter of the disk shaped notch used for bandpass filter - list - provide a list of three diameters to create a 3 channel filter * *cen* - tuple (x, y) center of the disk shaped notch if not provided, it will be at the center of the filter * *size* - size of the filter (width, height) * *type*: - lowpass or highpass filter **RETURNS** DFT notch filter **EXAMPLE** >>> notch = DFT.createNotchFilter(dia1=200, cen=(200, 200), size=(512, 512), type="highpass") >>> notch = DFT.createNotchFilter(dia1=200, dia2=300, cen=(200, 200), size=(512, 512)) >>> img = Image('lenna') >>> notch.applyFilter(img).show() """ if isinstance(dia1, list): if len(dia1) != 3 and len(dia1) != 1: warnings.warn("diameter list must be of size 1 or 3") return None if isinstance(dia2, list): if len(dia2) != 3 and len(dia2) != 1: warnings.warn("diameter list must be of size 3 or 1") return None if len(dia2) == 1: dia2 = [dia2[0]]*len(dia1) else: dia2 = [dia2]*len(dia1) if isinstance(cen, list): if len(cen) != 3 and len(cen) != 1: warnings.warn("center list must be of size 3 or 1") return None if len(cen) == 1: cen = [cen[0]]*len(dia1) else: cen = [cen]*len(dia1) stackedfilter = DFT() for d1, d2, c in zip(dia1, dia2, cen): stackedfilter = stackedfilter._stackFilters(self.createNotchFilter(d1, d2, c, size, type)) image = Image(stackedfilter._numpy) retVal = DFT(numpyarray=stackedfilter._numpy, image=image, dia=dia1+dia2, channels = len(dia1), size=size, type=stackedfilter._type, frequency=stackedfilter._freqpass) return retVal w, h = size if cen is None: cen = (w/2, h/2) a, b = cen y, x = np.ogrid[-a:w-a, -b:h-b] r = dia1/2 mask = x*x + y*y <= r*r flt = np.ones((w, h)) flt[mask] = 255 if type == "highpass": flt = 255-flt if dia2 is not None: a, b = cen y, x = np.ogrid[-a:w-a, -b:h-b] r = dia2/2 mask = x*x + y*y <= r*r flt1 = np.ones((w, h)) flt1[mask] = 255 flt1 = 255 - flt1 flt = flt + flt1 np.clip(flt, 0, 255) type = "bandpass" img = Image(flt) notchfilter = DFT(size=size, numpyarray=flt, image=img, dia=dia1, type="Notch", frequency=type) return notchfilter