public override IObservable <Contours> Process(IObservable <IplImage> source) { return(Observable.Defer(() => { IplImage temp = null; return source.Select(input => { Seq currentContour; temp = IplImageHelper.EnsureImageFormat(temp, input.Size, IplDepth.U8, 1); CV.Copy(input, temp); var storage = new MemStorage(); var scanner = CV.StartFindContours(temp, storage, Contour.HeaderSize, Mode, Method, Offset); while ((currentContour = scanner.FindNextContour()) != null) { if (MinArea.HasValue || MaxArea.HasValue) { var contourArea = CV.ContourArea(currentContour, SeqSlice.WholeSeq); if (contourArea < MinArea || contourArea > MaxArea) { scanner.SubstituteContour(null); } } } return new Contours(scanner.EndFindContours(), input.Size); }); })); }
//tracking routine public float[] GetParams(IplImage input) { //subtract mask from frame CV.Sub(Mask, input, output); //threshold to remove any small background noise CV.Threshold(output, output, thr, 255, ThresholdTypes.Binary); //find countours of the rest of the pixels Seq currentContour; using (var storage = new MemStorage()) using (var scanner = CV.StartFindContours(output, storage, Contour.HeaderSize, ContourRetrieval.External, ContourApproximation.ChainApproxNone, new Point(0, 0))) { bfArea = 0; while ((currentContour = scanner.FindNextContour()) != null) { //calculate the number of pixels inside the contour contourArea = CV.ContourArea(currentContour, SeqSlice.WholeSeq); //if number of pixels fit the expected for the fly, calculate the distribution moments if (contourArea > bfArea && (contourArea > MinArea && contourArea < MaxArea)) { scanner.SubstituteContour(null); //calculate the pixel distribution moments moments = new Moments(currentContour); if (moments.M00 > 0) { //transform moments into X,Y and orentation param[0] = Convert.ToSingle(moments.M10 / moments.M00); param[1] = Convert.ToSingle(moments.M01 / moments.M00); param[2] = 180f * Convert.ToSingle(0.5 * Math.Atan2(2 * (moments.M11 / moments.M00 - param[0] * param[1]), (moments.M20 / moments.M00 - param[0] * param[0]) - (moments.M02 / moments.M00 - param[1] * param[1]))) / Convert.ToSingle(Math.PI); } } bfArea = contourArea; } } //return position and orientation return(param); }