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
Example #4
0
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
Example #5
0
    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
Example #6
0
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
Example #7
0
    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