예제 #1
0
 /// <summary>
 /// Creates a deep copy of the source buffer
 /// </summary>
 /// <param name="source"></param>
 public InstantSpeedBuffer(InstantSpeedBuffer source)
 {
     _bufferSize = source._bufferSize;
     Stride      = source.Stride;
     _buffer     = (float *)Marshal.AllocHGlobal(Stride);
     ip.ippiCopy_32f_C1R(source._buffer, source.Stride, _buffer, Stride, Size);
 }
예제 #2
0
        /// <summary>
        /// Computes instant speeds from a coordinate trace and returns a
        /// new instant speed buffer with the results
        /// </summary>
        /// <param name="path">The movement path</param>
        /// <param name="frameRate">The acquisition framerate</param>
        /// <returns>A new instant speed buffer with the speed results</returns>
        public InstantSpeedBuffer ComputeInstantSpeeds(CentroidBuffer path, int frameRate)
        {
            InstantSpeedBuffer retval = new InstantSpeedBuffer(path.Size.width);

            ComputeInstantSpeeds(path, frameRate, retval);
            return(retval);
        }
예제 #3
0
 public void Dispose()
 {
     if (IsDisposed)
     {
         return;
     }
     if (_analysisThread != null)
     {
         _analysisThread.Dispose();
         _analysisThread = null;
     }
     if (_smoother != null)
     {
         _smoother.Dispose();
         _smoother = null;
     }
     if (_mova != null)
     {
         _mova.Dispose();
         _mova = null;
     }
     if (_isb != null)
     {
         _isb.Dispose();
         _isb = null;
     }
     IsDisposed = true;
 }
예제 #4
0
 /// <summary>
 /// Creates a new online bout detector with custom
 /// bout detection parameters
 /// </summary>
 /// <param name="chunkSize">The number of centroids to accumulate before processing</param>
 /// <param name="frameRate">The framerate of imaging</param>
 /// <param name="smoothingWindowSize">The size of the filtering window for centroid smoothing</param>
 /// <param name="speedThreshold">The absolute speed threshold in bout detection</param>
 /// <param name="minFramesPerBout">The minimum number of frames per bout</param>
 /// <param name="maxFramesAtPeak">The maximum number of peak frames in each bout</param>
 public OnlineBoutDetector(int chunkSize, int frameRate, int smoothingWindowSize, float speedThreshold, int minFramesPerBout, int maxFramesAtPeak)
 {
     if (frameRate < 1)
     {
         throw new ArgumentOutOfRangeException("The class only works with framerates of 1Hz or larger");
     }
     if (chunkSize < frameRate)
     {
         throw new ArgumentOutOfRangeException("The chunksize has to be the framerate or larger.");
     }
     _frameRate           = frameRate;
     _chunkSize           = chunkSize;
     _smoothingWindowSize = smoothingWindowSize;
     _speedThreshold      = speedThreshold;
     _minFramesPerBout    = minFramesPerBout;
     _maxFramesAtPeak     = maxFramesAtPeak;
     _centBuffers         = new CentroidBuffer[2];
     _centBuffers[0]      = new CentroidBuffer(_chunkSize);
     _centBuffers[1]      = new CentroidBuffer(_chunkSize);
     _isb                 = new InstantSpeedBuffer(_chunkSize);
     _smoother            = new CoordinateSmoother(_chunkSize, _smoothingWindowSize);
     _mova                = new MovementAnalyzer(_chunkSize);
     _currentActiveBuffer = 0;
     _centroidsReceived   = 0;
     _bufferReady         = new AutoResetEvent(false);
     _newCalcDoneSignal   = new AutoResetEvent(false);
     //start our analysis thread
     _analysisThread = new Worker(AnalyzeBouts, true, 3000);
 }
예제 #5
0
 public MovementAnalyzer(int nFrames)
 {
     //Pre-allocate and blank buffers
     _calc1  = new CentroidBuffer(nFrames);
     _calc2  = new CentroidBuffer(nFrames);
     _isCalc = new InstantSpeedBuffer(nFrames);
     ip.ippiSet_32f_C1R(0, _calc1.Buffer, _calc1.Stride, _calc1.Size);
     ip.ippiSet_32f_C1R(0, _calc2.Buffer, _calc2.Stride, _calc2.Size);
     ip.ippiSet_32f_C1R(0, _isCalc.Buffer, _isCalc.Stride, _isCalc.Size);
 }
예제 #6
0
 public void Dispose()
 {
     if (IsDisposed)
     {
         return;
     }
     if (_calc1 != null)
     {
         _calc1.Dispose();
         _calc1 = null;
     }
     if (_calc2 != null)
     {
         _calc2.Dispose();
         _calc2 = null;
     }
     if (_isCalc != null)
     {
         _isCalc.Dispose();
         _isCalc = null;
     }
     IsDisposed = true;
 }
예제 #7
0
 /// <summary>
 /// Computes instants speeds from a coordinate trace and stores the result
 /// in the provided buffer
 /// </summary>
 /// <param name="path">The movement path</param>
 /// <param name="frameRate">The framerate at acquisition</param>
 /// <param name="isb">The buffer to store the speed in</param>
 public void ComputeInstantSpeeds(CentroidBuffer path, int frameRate, InstantSpeedBuffer isb)
 {
     if (IsDisposed)
     {
         throw new ObjectDisposedException(this.ToString());
     }
     if (isb.Size.width != path.Size.width)
     {
         throw new ArgumentException("Path length and size of speed buffer must be the same!");
     }
     //Check that our buffers are present and match, otherwise fix
     if (_calc1 == null)
     {
         _calc1 = new CentroidBuffer(path.Size.width);
         _calc2 = new CentroidBuffer(path.Size.width);
     }
     else if (_calc1.Size.width != path.Size.width)
     {
         _calc1.Dispose();
         _calc2.Dispose();
         _calc1 = new CentroidBuffer(path.Size.width);
         _calc2 = new CentroidBuffer(path.Size.width);
     }
     //compute difference trace subtracting the position at t from the position at t+1 by subtracting the unshifted input buffer from its shifted version
     //the result gets stored in calc1 with the first value being 0
     ip.ippiSet_32f_C1R(0, _calc1.Buffer, _calc1.Stride, _calc1.Size);
     IppHelper.IppCheckCall(ip.ippiSub_32f_C1R(path.Buffer, path.Stride, (float *)((byte *)path.Buffer + 4), path.Stride, (float *)((byte *)_calc1.Buffer + 4), _calc1.Stride, new IppiSize(path.Size.width - 1, 2)));
     //square the difference trace, storing the result in _calc2
     IppHelper.IppCheckCall(ip.ippiSqr_32f_C1R(_calc1.Buffer, _calc1.Stride, _calc2.Buffer, _calc2.Stride, _calc1.Size));
     //Add the values of the x and y coordinates, storing the sum of squares in the first row of _calc1
     IppHelper.IppCheckCall(ip.ippiAdd_32f_C1R(_calc2.Buffer, _calc2.Stride, (float *)((byte *)_calc2.Buffer + _calc2.Stride), _calc2.Stride, _calc1.Buffer, _calc1.Stride, new IppiSize(_calc1.Size.width, 1)));
     //Compute the square root of the sum-of-squares and copy the result to the first row of _calc2
     IppHelper.IppCheckCall(ip.ippiSqrt_32f_C1R(_calc1.Buffer, _calc1.Stride, _calc2.Buffer, _calc2.Stride, new IppiSize(_calc1.Size.width, 1)));
     //Multiply the distances by the framerate and store the result in our instant speed buffer
     IppHelper.IppCheckCall(ip.ippiMulC_32f_C1R(_calc2.Buffer, _calc2.Stride, frameRate, isb.Buffer, isb.Stride, isb.Size));
 }
예제 #8
0
        /// <summary>
        /// Detects bouts and returns summary information
        /// </summary>
        /// <param name="isb">The instant speed trace</param>
        /// <param name="speedThreshold">Speeds below this threshold will be set to 0</param>
        /// <param name="minFramesPerBout">For a movement to be called a bout we require at least this number of frames</param>
        /// <param name="maxFramesAtPeak">Bouts should have clearly defined peaks. Bouts with a peak longer than this number get rejected</param>
        /// <param name="frameRate">The framerate used for acquisition</param>
        /// <returns>A bout summary info structure</returns>
        public BoutSummary AnalyzeBouts(InstantSpeedBuffer isb, float speedThreshold, int minFramesPerBout, int maxFramesAtPeak, int frameRate)
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(this.ToString());
            }

            if (_isCalc == null)
            {
                _isCalc = new InstantSpeedBuffer(isb.Size.width);
            }
            else if (_isCalc.Size.width != isb.Size.width)
            {
                _isCalc.Dispose();
                _isCalc = new InstantSpeedBuffer(isb.Size.width);
            }

            BoutSummary retval = new BoutSummary();
            Bout        b      = new Bout();

            int i = 0;

            //threshold the speed trace - copy result into our calculation buffer
            ip.ippiThreshold_LTVal_32f_C1R(isb.Buffer, isb.Stride, _isCalc.Buffer, _isCalc.Stride, isb.Size, speedThreshold, 0);

            while (i < _isCalc.Size.width)
            {
                if (_isCalc[i] == 0)
                {
                    i++;
                    continue;
                }
                else//found potential bout start since speed above threshold
                {
                    int peaklength = 0;
                    b.BoutStart         = i;
                    b.PeakSpeed         = _isCalc[i];
                    b.BoutPeak          = i;
                    b.TotalDisplacement = _isCalc[i] / frameRate;
                    //loop over following frames collecting all frames that belong to the bout
                    while (i < _isCalc.Size.width && _isCalc[i] > 0)
                    {
                        if (_isCalc[i] > b.PeakSpeed)
                        {
                            b.PeakSpeed = _isCalc[i];
                            b.BoutPeak  = i;
                            peaklength  = 0;                //new peakspeed found, reset peaklength
                        }
                        else if (_isCalc[i] == b.PeakSpeed) //another frame with the same speed as our peak
                        {
                            peaklength++;
                        }
                        b.TotalDisplacement += _isCalc[i] / frameRate;
                        i++;
                    }
                    b.BoutEnd = i - 1;
                    //check our bout criteria
                    if ((b.BoutEnd - b.BoutStart + 1) >= minFramesPerBout && peaklength <= maxFramesAtPeak)
                    {
                        //we have a valid bout
                        if (b.BoutStart == b.BoutPeak)
                        {
                            b.BoutStart--;
                        }
                        retval.NumberOfBouts++;
                        retval.AverageDisplacement += b.TotalDisplacement;
                        retval.AveragePeakSpeed    += b.PeakSpeed;
                        retval.AverageLength       += (b.BoutEnd - b.BoutStart + 1);
                    }
                }//found potential bout
            }
            retval.AverageDisplacement /= retval.NumberOfBouts;
            retval.AveragePeakSpeed    /= retval.NumberOfBouts;
            retval.AverageLength       /= retval.NumberOfBouts;
            return(retval);
        }