Esempio n. 1
0
def find_flies(old0, old1, obs):
    """All arguments are EllipseLists. Returns an EllipseList."""
    # possibly matchidentities should be smart enough to deal with this case
    # instead of handling it specially here

    if len(obs) == 0:
        flies = ell.TargetList()
        #for e in old1:
        #    flies.append( Ellipse() ) # no obs for any target
        return flies

    # make predicted targets
    targ = m_id.cvpred(old0, old1)

    # make a cost matrix containing the distance from each target to each obs
    ids = []
    for i in targ.iterkeys():
        ids.append(i)
    vals = []
    for i in targ.itervalues():
        vals.append(i)
    cost = num.zeros((len(obs), len(targ)))
    for i, observation in enumerate(obs):
        for j, target in enumerate(vals):
            if target.isDummy():
                cost[i, j] = params.max_jump + eps  # will be ignored
            else:
                cost[i, j] = observation.dist(target)

    # find optimal matching between targ and observations
    obs_for_target, unass_obs = m_id.matchidentities(cost)

    # make a new list containing the best matches to each prediction
    flies = ell.TargetList()
    for tt in range(len(targ)):
        if obs_for_target[tt] >= 0:
            obs[obs_for_target[tt]].identity = ids[tt]
            flies.append(obs[obs_for_target[tt]])
        #else:
        #    flies.append( Ellipse() ) # empty ellipse as a placeholder

    # append the targets that didn't match any observation
    for oo in range(len(obs)):
        if unass_obs[oo]:
            obs[oo].identity = params.nids
            params.nids += 1
            flies.append(obs[oo])

    return (flies, obs_for_target, unass_obs)
Esempio n. 2
0
def cvpred(X1, X2):
    """Make prediction (target) based on two observations.
    Expects two EllipseLists, returns a single EllipseList."""

    X3 = ell.TargetList()
    # set position and size as an extrapolation
    for ee in X2.iterkeys():
        if X1.hasItem(ee):

            # only use the cv prediction if not jumping
            dx = X2[ee].center.x - X1[ee].center.x
            dy = X2[ee].center.y - X1[ee].center.y
            centerd = num.sqrt((dx**2. + dy**2.))
            if centerd >= params.min_jump:
                new_x = X2[ee].center.x
                new_y = X2[ee].center.y
                dangle = X2[ee].angle
            else:
                new_x = X2[ee].center.x + (1. - params.dampen) * dx
                new_y = X2[ee].center.y + (1. - params.dampen) * dy
                dangle = ((X2[ee].angle - X1[ee].angle + num.pi/2.) \
                    % (num.pi)) - (num.pi/2.)

            new_w = X2[ee].size.width
            new_h = X2[ee].size.height
            new_angle = X2[ee].angle + (1. - params.angle_dampen) * dangle
            X3.append(
                ell.Ellipse(new_x, new_y, new_w, new_h, new_angle,
                            X2[ee].identity))
        else:
            X3.append(X2[ee].copy())

    return X3
Esempio n. 3
0
    def GetTargetMotion(self):

        # get current positions
        obs_curr = self.GetObsFiltered()
        # get previous positions
        obs_prev = self.GetObsPrev()
        # give identities to previous positions
        target_prev = ell.TargetList()
        for i, obs in enumerate(obs_prev):
            obs.identity = i
            target_prev.append(obs)
        # match previous and current targets, no velocity
        oldnids = params.params.nids
        target_curr = ell.find_flies(target_prev, target_prev, obs_curr)
        # don't actually assign new identities
        params.params.nids = oldnids
        # delete targets that aren't in both frames
        keyscurr = set(target_curr.keys())
        keysprev = set(target_prev.keys())
        keysremove = keyscurr - keysprev
        for i in keysremove:
            tmp = target_curr.pop(i)
        keysremove = keysprev - keyscurr
        for i in keysremove:
            tmp = target_prev.pop(i)

        # compute predicted positions
        target_pred = cvpred(target_prev, target_curr)
        # store
        targetmotion = (target_prev, target_curr, target_pred)
        # return
        return targetmotion
Esempio n. 4
0
    Y += ellipse.center.y
    h = mpl.plot(X, Y, format, **params)
    return h


try:
    os.remove('tmp.ann')
except:
    pass
tracks = ann.AnnotationFile('tmp.ann', None, True, False, False)
tracks.InitializeData(0, -1)
tracks.InitializeBufferForTracking(0)
# tracks = []

# frame 0
tracks.append(ell.TargetList())
# just one ellipse with id = 0
tracks[0][0] = ell.Ellipse(10., 10., 1., 2., num.pi / 3, 0., 0)
tracks[0][0].compute_area()
# frame 1
# just one ellipse with id = 0
tracks.append(ell.TargetList())
tracks[1][0] = tracks[0][0].copy()
tracks[1][0].x += 10.
tracks[1][0].y += 10.
# frame 2
# detection missed at pred
# new ellipse at another location
tracks.append(ell.TargetList())
#tracks[2][1] = ell.Ellipse(20.,20.,1.,2.,num.pi/3,0.,1)
prev = tracks[0].copy()
Esempio n. 5
0
    def Track(self):
        """Run the m-tracker."""

        ## initialization ##

        if DEBUG: print "Tracking from frame %d..." % self.start_frame
        if DEBUG:
            print "Last frame tracked = %d" % self.ann_file.lastframetracked

        print "YL:"
        print " bg_type", self.bg_imgs.bg_type
        print " norm_type", self.bg_imgs.norm_type
        print " thresh", params.n_bg_std_thresh, params.n_bg_std_thresh_low
        print " area", params.maxshape.area, params.minshape.area
        print " max_jump", params.max_jump, params.max_jump_split
        print " use_shadow_detector", params.use_shadow_detector
        print " recalc_bg_minutes", params.recalc_bg_minutes
        print " recalc_n_frames", self.movie.recalc_n_frames()
        print " fps %.1f" % self.movie.get_fps()
        strt = time.clock()

        if params.use_shadow_detector:
            fx, fy = self.matchTemplate()
            print " fx, fy", fx, fy
            bx = (fx[0] + fx[1]) / 2

        # maximum number of frames we will look back to fix errors
        self.maxlookback = max(params.lostdetection_length,
                               params.spuriousdetection_length,
                               params.mergeddetection_length,
                               params.splitdetection_length)

        if params.interactive:
            wx.Yield()

        # initialize hindsight data structures
        self.hindsight = hindsight.Hindsight(self.ann_file, self.bg_imgs)

        self.break_flag = False

        if DEBUG: print "Initializing buffer for tracking"
        self.ann_file.InitializeBufferForTracking(self.start_frame)

        # initialize dfore and connected component buffer
        self.bg_imgs.set_buffer_maxnframes()

        rc, rnf, bgs, nf = 0, self.movie.recalc_n_frames(
        ), [], self.movie.get_n_frames()

        def appendBg():
            bgRw = self.bg_imgs.centers if self.bg_imgs.varying_bg else [
                self.bg_imgs.center
            ]
            bgs.append(
                dict(bgs=[bg.astype(num.float32) for bg in bgRw],
                     varying_bg=self.bg_imgs.varying_bg,
                     mean_separator=self.bg_imgs.mean_separator))

        appendBg()
        for self.start_frame in range(self.start_frame, nf):

            # KB 20120109 added last_frame command-line option
            if self.start_frame >= self.last_frame:
                break

            if DEBUG_LEVEL > 0:
                print "Tracking frame %d / %d" % (self.start_frame, nf - 1)

            #if DEBUG:
            #    break

            if self.break_flag:
                break

            last_time = time.time()

            # recalculate background?
            rc += 1
            if rnf > 0 and rc > rnf:
                if nf - self.start_frame > rnf / 2:
                    assert self.start_frame % rnf == 0
                    # note: makes it easy to calculate which background was used;
                    #  not required for tracking
                    self.bg_imgs.bg_firstframe = self.start_frame
                    self.bg_imgs.bg_lastframe = self.start_frame + rnf - 1
                    self.OnComputeBg()
                    appendBg()
                rc = 1

            # perform background subtraction
            #try:
            (self.dfore,self.isfore,self.cc,self.ncc) = \
                self.bg_imgs.sub_bg( self.start_frame, dobuffer=True )
            #except:
            #    # catch all error types here, and just break out of loop
            #    break

            # write to sbfmf
            if self.dowritesbfmf:
                self.movie.writesbfmf_writeframe(self.isfore,
                                                 self.bg_imgs.curr_im,
                                                 self.bg_imgs.curr_stamp,
                                                 self.start_frame)

            # process gui events
            if params.interactive:
                wx.Yield()
            if self.break_flag:
                break

            # find observations
            self.ellipses = ell.find_ellipses(self.dfore, self.cc, self.ncc)

            # shadow detector
            if params.use_shadow_detector:
                ne = 2 * [0]  # idx: left, right (chamber)
                bei, bdist, bgood = 2 * [-1], 2 * [1000], 2 * [None]  # best
                for ei, e in enumerate(self.ellipses):
                    if e.area < params.minshape.area:
                        continue
                    good = e.area >= params.shadow_detector_minarea and (
                        not e.merged_areas or any(a >= params.minshape.area
                                                  for a in e.merged_areas))
                    i = e.center.x > bx
                    ne[i] += 1
                    dist = num.sqrt((e.center.x - fx[i])**2 +
                                    (e.center.y - fy[i])**2)
                    if bei[i] < 0 or good and not bgood[
                            i] or dist < bdist[i] and good == bgood[i]:
                        bei[i], bdist[i], bgood[i] = ei, dist, good
                #print "l:%d r:%d" %(ne)

                # keep only non-shadow ellipses
                numEll = len(self.ellipses)
                self.ellipses = [self.ellipses[i] for i in bei if i >= 0]
                if len(self.ellipses) < numEll:
                    print ">>> kept only", bei

            #if params.DOBREAK:
            #    print 'Exiting at frame %d'%self.start_frame
            #    sys.exit(1)

            # process gui events
            if params.interactive:
                wx.Yield()
            if self.break_flag:
                break

            # match target identities to observations
            if len(self.ann_file) > 1:
                flies = ell.find_flies(self.ann_file[-2], self.ann_file[-1],
                                       self.ellipses, self.ann_file)
            elif len(self.ann_file) == 1:
                flies = ell.find_flies(self.ann_file[-1], self.ann_file[-1],
                                       self.ellipses, self.ann_file)
            else:
                flies = ell.TargetList()
                for i, obs in enumerate(self.ellipses):
                    if obs.isEmpty():
                        if DEBUG: print 'empty observation'
                    else:
                        newid = self.ann_file.GetNewId()
                        obs.identity = newid
                        flies.append(obs)

            if DEBUG_LEVEL > 0:
                print "Done with frame %d, appending to ann_file" % self.start_frame

            # save to ann_data
            self.ann_file.append(flies)

            if DEBUG_LEVEL > 0:
                print "Added to ann_file, now running fixerrors"

            # fix any errors using hindsight
            self.hindsight.fixerrors()
            #print 'time to fix errors: '+str(time.time() - last_time)

            # draw?
            if self.request_refresh or (self.do_refresh and (
                (self.start_frame % self.framesbetweenrefresh) == 0)):
                if params.interactive:
                    if self.start_frame:
                        self.ShowCurrentFrame()
                else:
                    on = ("on " if self.bg_imgs.on else
                          "off ") if self.bg_imgs.varying_bg else ""
                    print "    Frame %d / %d %s[%ds]" \
                        %(self.start_frame, nf, on, time.clock()-strt)
                self.request_refresh = False

            # process gui events
            if params.interactive:
                wx.Yield()
            if self.break_flag:
                break

            if (self.start_frame %
                    100) == 0 and self.has('diagnostics_filename'):
                self.write_diagnostics()  # save ongoing

        self.saveBackgrounds(bgs)
        self.Finish()
Esempio n. 6
0
def run_movie(moviefile, comms):
    """Run new-style tracking for a test movie."""
    quit_val = comms['quit_val']
    cmp_list = comms['cmp_list']
    shape_dict = comms['shape_dict']

    movie, bg_model, ann_file, hindsight = setup_tracking(moviefile, False)

    if quit_val.value > 0: return

    try:
        test_shape_bounds()
    except:
        print "**aborting with invalid shape bounds"
        print "minshape", params.minshape
        print "maxshape", params.maxshape
        print_vals()
        quit_val.value = 1
        raise

    shape_dict['minshape'] = params.minshape
    shape_dict['meanshape'] = params.meanshape
    shape_dict['maxshape'] = params.maxshape

    fst = time.time()

    params.start_frame = 0
    if MAX_FRAMES is None:
        max_frames = movie.get_n_frames()
    else:
        max_frames = min(movie.get_n_frames(), MAX_FRAMES)
    for frame in range(max_frames):
        if cmp_list is not None: counts = []

        # perform background subtraction
        (dfore, isfore, cc, ncc) = bg_model.sub_bg(frame)

        # find observations
        if PRINT_COUNTS and (frame == PRINT_FRAME or PRINT_FRAME is None):
            print frame, "ncc", ncc
        if cmp_list is not None: counts.append(ncc)
        ellipses = ell.find_ellipses(dfore, cc, ncc)
        if PRINT_COUNTS and (frame == PRINT_FRAME or PRINT_FRAME is None):
            print frame, "found ellipses", len(ellipses)
        if cmp_list is not None: counts.append(len(ellipses))

        try:
            test_ellipses(ellipses)
        except AssertionError:
            print "**find_ellipses output error in frame", frame
            print_vals()
            quit_val.value = 1
            raise

        # match target identities to observations
        if len(ann_file) > 1:
            flies = ell.find_flies(ann_file[-2], ann_file[-1], ellipses,
                                   ann_file)
        elif len(ann_file) == 1:
            flies = ell.find_flies(ann_file[-1], ann_file[-1], ellipses,
                                   ann_file)
        else:
            flies = ell.TargetList()
            for i, obs in enumerate(ellipses):
                newid = ann_file.GetNewId()
                obs.identity = newid
                flies.append(obs)

        try:
            test_ellipses(flies)
        except AssertionError:
            print "**find_flies output error in frame", frame
            print_vals()
            quit_val.value = 1
            raise

        if PRINT_COUNTS and (frame == PRINT_FRAME or PRINT_FRAME is None):
            print frame, "found flies", len(flies)
        if cmp_list is not None: counts.append(len(flies))
        ann_file.append(flies)

        # fix any errors using hindsight
        if PRINT_COUNTS and (frame == PRINT_FRAME or PRINT_FRAME is None):
            print frame, "pre-hindsight", len(ann_file[-1])
        if cmp_list is not None: counts.append(len(ann_file[-1]))
        hindsight.fixerrors()
        if PRINT_COUNTS and (frame == PRINT_FRAME or PRINT_FRAME is None):
            print frame, "post-hindsight", len(ann_file[-1])
        if cmp_list is not None: counts.append(len(ann_file[-1]))

        try:
            test_ellipses(ann_file[-1])
        except AssertionError:
            print "**hindsight output error in frame", frame
            print_vals()
            quit_val.value = 1
            raise

        if frame % 500 == 0:
            print "__tracking", frame, "/", movie.get_n_frames()

        if quit_val.value > 0: return

        if cmp_list is not None:
            cmp_list.append((counts, ann_file[-1]))

    ann_file.close()

    at = (time.time() - fst) / max_frames
    print "avg. per frame: %.3f s" % (at)
Esempio n. 7
0
def run_movie_pre4(moviefile, comms):
    """Run old-style tracking for a test movie."""
    quit_val = comms['quit_val']
    cmp_list = comms['cmp_list']
    shape_dict = comms['shape_dict']

    movie, bg_model, ann_file, hindsight = setup_tracking(moviefile, True)
    params.movie = movie

    if quit_val.value > 0: return

    try:
        test_shape_bounds()
    except:
        print "**aborting pre4 with invalid shape bounds"
        print "minshape", params.minshape
        print "maxshape", params.maxshape
        print_vals()
        quit_val.value = 1
        raise

    if shape_dict is not None:
        while not shape_dict.has_key('maxshape'):
            time.sleep(0.5)
            if quit_val.value > 0: return
        try:
            assert (shape_dict['minshape'] == params.minshape)
            assert (shape_dict['meanshape'] == params.meanshape)
            assert (shape_dict['maxshape'] == params.maxshape)
        except AssertionError:
            print "**aborting after shape mismatch"
            print "minshape", shape_dict['minshape']
            print "pre4 minshape", params.minshape
            print "meanshape", shape_dict['meanshape']
            print "pre4 meanshape", params.meanshape
            print "maxshape", shape_dict['maxshape']
            print "pre4 maxshape", params.maxshape
            print_vals()
            quit_val.value = 1
            raise

    fst = time.time()

    params.start_frame = 0
    if MAX_FRAMES is None:
        max_frames = movie.get_n_frames()
    else:
        max_frames = min(movie.get_n_frames(), MAX_FRAMES)
    for frame in range(max_frames):
        # perform background subtraction
        (dfore, isfore, cc, ncc) = bg_model.sub_bg(frame, dobuffer=True)

        # find observations
        if PRINT_COUNTS: print "pre4", frame, "ncc", ncc
        ellipses = ell_pre4.find_ellipses(dfore, cc, ncc)
        if PRINT_COUNTS: print "pre4", frame, "found ellipses", len(ellipses)
        try:
            test_ellipses(ellipses)
        except AssertionError:
            print "**find_ellipse output error in pre4 frame", frame
            print_vals()
            quit_val.value = 1
            raise

        # match target identities to observations
        if len(ann_file) > 1:
            flies = ell.find_flies(ann_file[-2], ann_file[-1], ellipses,
                                   ann_file)
        elif len(ann_file) == 1:
            flies = ell.find_flies(ann_file[-1], ann_file[-1], ellipses,
                                   ann_file)
        else:
            flies = ell.TargetList()
            for i, obs in enumerate(ellipses):
                newid = ann_file.GetNewId()
                obs.identity = newid
                flies.append(obs)

        try:
            test_ellipses(flies)
        except AssertionError:
            print "**find_flies output error in pre4 frame", frame
            print_vals()
            quit_val.value = 1
            raise

        if PRINT_COUNTS: print "pre4", frame, "found flies", len(flies)
        ann_file.append(flies)

        # fix any errors using hindsight
        if PRINT_COUNTS:
            print "pre4", frame, "pre-hindsight", len(ann_file[-1])
        hindsight.fixerrors()
        if PRINT_COUNTS:
            print "pre4", frame, "post-hindsight", len(ann_file[-1])

        try:
            test_ellipses(ann_file[-1])
        except AssertionError:
            print "**hindsight output error in pre4 frame", frame
            print_vals()
            quit_val.value = 1
            raise

        if frame % 100 == 0:
            print "__pre4 tracking", frame, "/", movie.get_n_frames()

        # compare with newly tracked values
        if cmp_list is not None:
            while len(cmp_list) <= frame:
                time.sleep(0.5)
                if quit_val.value > 0: return

            old = ann_file[-1]
            counts, new = cmp_list[frame]
            if PRINT_COUNTS: print "new counts", counts

            try:
                assert (len(new) == len(old))
            except AssertionError:
                print "**aborting after data length error in frame", frame, "new", len(
                    new), "old", len(old)
                print moviefile
                print_vals()
                quit_val.value = 1
                raise

            try:
                compare_frames(new, old)
            except AssertionError:
                print "**data comparison error in frame", frame
                print "new", new
                print "old", old
                print moviefile
                print_vals()
                quit_val.value = 1
                raise

        if quit_val.value > 0: return

    ann_file.close()

    at = (time.time() - fst) / max_frames
    print "pre4 avg. per frame: %.3f s" % (at)
    #bt = num.mean( num.array( bgsub_times ) )
    #print "pre4 bg. sub: %.3f (%.1f%%); ellipses: %.3f (%.1f%%); flies: %.3f (%.1f%%); hindsight: %.3f (%.1f%%)" % (bt, 100.*bt/at, et, 100.*et/at, ft, 100.*ft/at, ht, 100.*ht/at)

    params.movie = None
Esempio n. 8
0
def add_fly(annfile, x, y, theta):
    flies = ell.TargetList()
    flies.append(ell.Ellipse(x, y, 5., 10., theta, 25., 0))
    annfile.append(flies)
Esempio n. 9
0
    def Track(self):
        """Run the tracker."""

        ## initialization ##
        if DEBUG: print "Tracking from frame %d..." % self.start_frame
        if DEBUG:
            print "Last frame tracked = %d" % self.ann_file.lastframetracked

        # maximum number of frames we will look back to fix errors
        self.maxlookback = max(params.lostdetection_length,
                               params.spuriousdetection_length,
                               params.mergeddetection_length,
                               params.splitdetection_length)

        if params.interactive:
            wx.Yield()

        # initialize hindsight data structures
        self.hindsight = hindsight.Hindsight(self.ann_file, self.bg_imgs)

        # initialize dfore and connected component buffer
        self.bg_imgs.set_buffer_maxnframes()

        self.track_timer_start_time = time.time()
        self.update_track_time()

        self.break_flag = False

        for self.start_frame in range(self.start_frame,
                                      self.movie.get_n_frames()):
            if DEBUG or DEBUG_TRACKINGSETTINGS: print "frame", self.start_frame

            # KB 20120109 added last_frame command-line option
            if self.start_frame >= self.last_frame:
                break

            if DEBUG_LEVEL > 0:
                print "Tracking frame %d / %d" % (
                    self.start_frame, self.movie.get_n_frames() - 1)

            if self.break_flag:
                break

            last_time = time.time()

            # perform background subtraction
            try:
                (dfore, isfore, cc,
                 ncc) = self.bg_imgs.sub_bg(self.start_frame)
            except IOError:
                if self.movie.type == 'cavi' and self.start_frame >= self.movie.get_n_frames(
                ) - 2:
                    # last frame or so wasn't present, no problem
                    print "ignoring compressed AVI IOError reading last frame"
                else:
                    traceback.print_exc()
                break
            except:
                # catch all error types here, and just break out of the loop
                traceback.print_exc()
                break
            if DEBUG_LEVEL > 1: print ncc, "connected components"

            # write to sbfmf
            if self.dowritesbfmf:
                self.movie.writesbfmf_writeframe(isfore, self.bg_imgs.curr_im,
                                                 self.bg_imgs.curr_stamp,
                                                 self.start_frame)

            # process gui events
            if params.interactive:
                wx.Yield()
            if self.break_flag:
                break

            # find observations
            ellipses = ell.find_ellipses(dfore, cc, ncc)
            if DEBUG_LEVEL > 1: print len(ellipses), "ellipses"

            # process gui events
            if params.interactive:
                wx.Yield()
            if self.break_flag:
                break

            # match target identities to observations
            if DEBUG_LEVEL > 0: print "matching identities"
            if len(self.ann_file) > 1:
                flies = ell.find_flies(self.ann_file[-2], self.ann_file[-1],
                                       ellipses, self.ann_file)
            elif len(self.ann_file) == 1:
                flies = ell.find_flies(self.ann_file[-1], self.ann_file[-1],
                                       ellipses, self.ann_file)
            else:
                flies = ell.TargetList()
                for i, obs in enumerate(ellipses):
                    if obs.isEmpty():
                        if DEBUG: print 'empty observation'
                    else:
                        newid = self.ann_file.GetNewId()
                        obs.identity = newid
                        flies.append(obs)
            if DEBUG_LEVEL > 1: print len(flies), "flies"

            if DEBUG_LEVEL > 0:
                print "Done with frame %d, appending to ann_file" % self.start_frame

            # save to ann_data
            self.ann_file.append(flies)

            # fix any errors using hindsight
            if DEBUG_LEVEL > 0:
                print "Added to ann_file, now running fixerrors"
            self.hindsight.fixerrors()

            # draw?
            if self.request_refresh or (self.do_refresh and (
                (self.start_frame % self.framesbetweenrefresh) == 0)):
                if params.interactive:
                    if self.start_frame:
                        self.ShowCurrentFrame()
                else:
                    print "    Frame %d / %d" % (self.start_frame,
                                                 self.movie.get_n_frames() - 1)
                self.request_refresh = False
            if DEBUG_LEVEL > 1:
                print len(self.ann_file[-1]), "flies in last frame"

            # process gui events
            if params.interactive:
                wx.Yield()
            if self.break_flag:
                break

            if (self.start_frame %
                    100) == 0 and self.has('diagnostics_filename'):
                self.write_diagnostics()  # save ongoing

        if hasattr(self, 'timer'):
            # timer.cancel() should work, but in case it doesn't, set a flag too
            self.timer.cancel()
            self.track_timer_cancel = True

        self.Finish()