示例#1
0
        public override IObservable <KeyPointOpticalFlow> Process(IObservable <Tuple <KeyPointCollection, IplImage> > source)
        {
            return(Observable.Defer(() =>
            {
                IplImage previousImage = null;
                IplImage previousPyramid = null;
                IplImage currentPyramid = null;
                return source.Select(input =>
                {
                    var previous = input.Item1;
                    var currentImage = input.Item2;
                    var currentKeyPoints = new KeyPointCollection(currentImage);
                    if (previous.Count == 0)
                    {
                        return new KeyPointOpticalFlow(previous, currentKeyPoints);
                    }

                    if (currentPyramid == null || currentPyramid.Size != currentImage.Size)
                    {
                        previousImage = null;
                        previousPyramid = new IplImage(currentImage.Size, currentImage.Depth, currentImage.Channels);
                        currentPyramid = new IplImage(currentImage.Size, currentImage.Depth, currentImage.Channels);
                    }

                    var maxIterations = MaxIterations;
                    var epsilon = Epsilon;
                    var terminationType = TermCriteriaType.None;
                    if (maxIterations > 0)
                    {
                        terminationType |= TermCriteriaType.MaxIter;
                    }
                    if (epsilon > 0)
                    {
                        terminationType |= TermCriteriaType.Epsilon;
                    }
                    var termCriteria = new TermCriteria(terminationType, maxIterations, epsilon);
                    var flags = previousImage == previous.Image ? LKFlowFlags.PyrAReady : LKFlowFlags.None;

                    var previousFeatures = new Point2f[previous.Count];
                    for (int i = 0; i < previousFeatures.Length; i++)
                    {
                        previousFeatures[i] = previous[i];
                    }

                    var currentFeatures = new Point2f[previousFeatures.Length];
                    var status = new byte[previousFeatures.Length];
                    var trackError = new float[previousFeatures.Length];
                    CV.CalcOpticalFlowPyrLK(
                        previous.Image,
                        currentImage,
                        previousPyramid,
                        currentPyramid,
                        previousFeatures,
                        currentFeatures,
                        WindowSize,
                        Level,
                        status,
                        trackError,
                        termCriteria,
                        flags);

                    var previousKeyPoints = new KeyPointCollection(previous.Image);
                    for (int i = 0; i < status.Length; i++)
                    {
                        if (status[i] == 0 ||
                            trackError[i] > MaxError ||
                            currentFeatures[i].X <0 ||
                                                  currentFeatures[i].Y <0 ||
                                                                        currentFeatures[i].X> currentImage.Width - 1 ||
                                                  currentFeatures[i].Y> currentImage.Height - 1)
                        {
                            continue;
                        }

                        previousKeyPoints.Add(previousFeatures[i]);
                        currentKeyPoints.Add(currentFeatures[i]);
                    }

                    var temp = currentPyramid;
                    currentPyramid = previousPyramid;
                    previousPyramid = temp;
                    previousImage = currentImage;
                    return new KeyPointOpticalFlow(previousKeyPoints, currentKeyPoints);
                });
            }));
        }