Click here to Skip to main content
15,880,469 members
Articles / Multimedia / GDI+

Computer Vision Application with C# - Part III

Rate me:
Please Sign up or sign in to vote.
4.97/5 (26 votes)
9 May 2009CPOL9 min read 115.9K   9K   98  
Meanshift tracking implementation
  • cvmeanshift.zip
    • CVMeanshift
      • AviSequence
        • 0.jpg
        • 1.jpg
        • 10.jpg
        • 100.jpg
        • 101.jpg
        • 102.jpg
        • 103.jpg
        • 104.jpg
        • 105.jpg
        • 106.jpg
        • 107.jpg
        • 108.jpg
        • 109.jpg
        • 11.jpg
        • 110.jpg
        • 111.jpg
        • 112.jpg
        • 113.jpg
        • 114.jpg
        • 115.jpg
        • 116.jpg
        • 117.jpg
        • 118.jpg
        • 119.jpg
        • 12.jpg
        • 120.jpg
        • 121.jpg
        • 122.jpg
        • 123.jpg
        • 124.jpg
        • 125.jpg
        • 126.jpg
        • 127.jpg
        • 128.jpg
        • 129.jpg
        • 13.jpg
        • 130.jpg
        • 131.jpg
        • 132.jpg
        • 133.jpg
        • 134.jpg
        • 135.jpg
        • 136.jpg
        • 137.jpg
        • 138.jpg
        • 139.jpg
        • 14.jpg
        • 140.jpg
        • 141.jpg
        • 142.jpg
        • 143.jpg
        • 144.jpg
        • 145.jpg
        • 146.jpg
        • 147.jpg
        • 148.jpg
        • 149.jpg
        • 15.jpg
        • 150.jpg
        • 151.jpg
        • 152.jpg
        • 153.jpg
        • 154.jpg
        • 155.jpg
        • 156.jpg
        • 157.jpg
        • 158.jpg
        • 159.jpg
        • 16.jpg
        • 160.jpg
        • 161.jpg
        • 162.jpg
        • 163.jpg
        • 164.jpg
        • 165.jpg
        • 166.jpg
        • 167.jpg
        • 168.jpg
        • 169.jpg
        • 17.jpg
        • 170.jpg
        • 171.jpg
        • 172.jpg
        • 173.jpg
        • 174.jpg
        • 175.jpg
        • 176.jpg
        • 177.jpg
        • 178.jpg
        • 179.jpg
        • 18.jpg
        • 180.jpg
        • 181.jpg
        • 182.jpg
        • 183.jpg
        • 184.jpg
        • 185.jpg
        • 186.jpg
        • 187.jpg
        • 188.jpg
        • 189.jpg
        • 19.jpg
        • 190.jpg
        • 191.jpg
        • 192.jpg
        • 193.jpg
        • 194.jpg
        • 195.jpg
        • 196.jpg
        • 197.jpg
        • 198.jpg
        • 199.jpg
        • 2.jpg
        • 20.jpg
        • 200.jpg
        • 201.jpg
        • 202.jpg
        • 203.jpg
        • 204.jpg
        • 205.jpg
        • 206.jpg
        • 207.jpg
        • 208.jpg
        • 209.jpg
        • 21.jpg
        • 210.jpg
        • 211.jpg
        • 212.jpg
        • 213.jpg
        • 214.jpg
        • 215.jpg
        • 216.jpg
        • 217.jpg
        • 218.jpg
        • 219.jpg
        • 22.jpg
        • 220.jpg
        • 221.jpg
        • 222.jpg
        • 223.jpg
        • 224.jpg
        • 225.jpg
        • 226.jpg
        • 227.jpg
        • 228.jpg
        • 229.jpg
        • 23.jpg
        • 230.jpg
        • 231.jpg
        • 232.jpg
        • 233.jpg
        • 234.jpg
        • 235.jpg
        • 236.jpg
        • 237.jpg
        • 238.jpg
        • 239.jpg
        • 24.jpg
        • 240.jpg
        • 241.jpg
        • 242.jpg
        • 243.jpg
        • 244.jpg
        • 245.jpg
        • 246.jpg
        • 247.jpg
        • 248.jpg
        • 249.jpg
        • 25.jpg
        • 250.jpg
        • 251.jpg
        • 252.jpg
        • 253.jpg
        • 254.jpg
        • 255.jpg
        • 256.jpg
        • 257.jpg
        • 258.jpg
        • 259.jpg
        • 26.jpg
        • 260.jpg
        • 261.jpg
        • 262.jpg
        • 263.jpg
        • 264.jpg
        • 265.jpg
        • 266.jpg
        • 267.jpg
        • 268.jpg
        • 269.jpg
        • 27.jpg
        • 270.jpg
        • 271.jpg
        • 272.jpg
        • 273.jpg
        • 274.jpg
        • 275.jpg
        • 276.jpg
        • 277.jpg
        • 278.jpg
        • 279.jpg
        • 28.jpg
        • 280.jpg
        • 281.jpg
        • 282.jpg
        • 283.jpg
        • 284.jpg
        • 285.jpg
        • 286.jpg
        • 287.jpg
        • 288.jpg
        • 289.jpg
        • 29.jpg
        • 290.jpg
        • 291.jpg
        • 292.jpg
        • 293.jpg
        • 294.jpg
        • 295.jpg
        • 296.jpg
        • 297.jpg
        • 298.jpg
        • 299.jpg
        • 3.jpg
        • 30.jpg
        • 300.jpg
        • 301.jpg
        • 302.jpg
        • 303.jpg
        • 304.jpg
        • 305.jpg
        • 306.jpg
        • 307.jpg
        • 308.jpg
        • 309.jpg
        • 31.jpg
        • 310.jpg
        • 311.jpg
        • 312.jpg
        • 313.jpg
        • 314.jpg
        • 315.jpg
        • 316.jpg
        • 317.jpg
        • 318.jpg
        • 319.jpg
        • 32.jpg
        • 320.jpg
        • 321.jpg
        • 322.jpg
        • 323.jpg
        • 324.jpg
        • 325.jpg
        • 326.jpg
        • 327.jpg
        • 328.jpg
        • 329.jpg
        • 33.jpg
        • 330.jpg
        • 331.jpg
        • 332.jpg
        • 333.jpg
        • 334.jpg
        • 335.jpg
        • 336.jpg
        • 337.jpg
        • 338.jpg
        • 339.jpg
        • 34.jpg
        • 340.jpg
        • 341.jpg
        • 342.jpg
        • 343.jpg
        • 344.jpg
        • 345.jpg
        • 346.jpg
        • 347.jpg
        • 348.jpg
        • 349.jpg
        • 35.jpg
        • 350.jpg
        • 351.jpg
        • 352.jpg
        • 353.jpg
        • 354.jpg
        • 355.jpg
        • 356.jpg
        • 357.jpg
        • 358.jpg
        • 359.jpg
        • 36.jpg
        • 360.jpg
        • 361.jpg
        • 362.jpg
        • 363.jpg
        • 364.jpg
        • 365.jpg
        • 366.jpg
        • 367.jpg
        • 368.jpg
        • 369.jpg
        • 37.jpg
        • 370.jpg
        • 371.jpg
        • 372.jpg
        • 373.jpg
        • 374.jpg
        • 375.jpg
        • 376.jpg
        • 377.jpg
        • 378.jpg
        • 379.jpg
        • 38.jpg
        • 380.jpg
        • 381.jpg
        • 382.jpg
        • 383.jpg
        • 384.jpg
        • 385.jpg
        • 386.jpg
        • 387.jpg
        • 388.jpg
        • 389.jpg
        • 39.jpg
        • 390.jpg
        • 391.jpg
        • 392.jpg
        • 393.jpg
        • 394.jpg
        • 395.jpg
        • 396.jpg
        • 397.jpg
        • 398.jpg
        • 399.jpg
        • 4.jpg
        • 40.jpg
        • 400.jpg
        • 401.jpg
        • 402.jpg
        • 403.jpg
        • 404.jpg
        • 405.jpg
        • 406.jpg
        • 407.jpg
        • 408.jpg
        • 409.jpg
        • 41.jpg
        • 410.jpg
        • 411.jpg
        • 412.jpg
        • 413.jpg
        • 414.jpg
        • 415.jpg
        • 416.jpg
        • 417.jpg
        • 418.jpg
        • 419.jpg
        • 42.jpg
        • 420.jpg
        • 421.jpg
        • 422.jpg
        • 423.jpg
        • 424.jpg
        • 425.jpg
        • 426.jpg
        • 427.jpg
        • 428.jpg
        • 429.jpg
        • 43.jpg
        • 430.jpg
        • 431.jpg
        • 432.jpg
        • 433.jpg
        • 434.jpg
        • 435.jpg
        • 436.jpg
        • 437.jpg
        • 438.jpg
        • 439.jpg
        • 44.jpg
        • 440.jpg
        • 441.jpg
        • 442.jpg
        • 443.jpg
        • 444.jpg
        • 445.jpg
        • 446.jpg
        • 447.jpg
        • 448.jpg
        • 449.jpg
        • 45.jpg
        • 450.jpg
        • 451.jpg
        • 452.jpg
        • 453.jpg
        • 454.jpg
        • 455.jpg
        • 456.jpg
        • 457.jpg
        • 458.jpg
        • 459.jpg
        • 46.jpg
        • 460.jpg
        • 461.jpg
        • 462.jpg
        • 463.jpg
        • 464.jpg
        • 465.jpg
        • 466.jpg
        • 467.jpg
        • 468.jpg
        • 469.jpg
        • 47.jpg
        • 470.jpg
        • 471.jpg
        • 472.jpg
        • 473.jpg
        • 474.jpg
        • 475.jpg
        • 476.jpg
        • 477.jpg
        • 478.jpg
        • 479.jpg
        • 48.jpg
        • 480.jpg
        • 481.jpg
        • 482.jpg
        • 483.jpg
        • 484.jpg
        • 485.jpg
        • 486.jpg
        • 487.jpg
        • 488.jpg
        • 489.jpg
        • 49.jpg
        • 490.jpg
        • 491.jpg
        • 492.jpg
        • 493.jpg
        • 494.jpg
        • 495.jpg
        • 496.jpg
        • 497.jpg
        • 498.jpg
        • 499.jpg
        • 5.jpg
        • 50.jpg
        • 500.jpg
        • 501.jpg
        • 502.jpg
        • 503.jpg
        • 504.jpg
        • 505.jpg
        • 506.jpg
        • 507.jpg
        • 508.jpg
        • 509.jpg
        • 51.jpg
        • 510.jpg
        • 511.jpg
        • 512.jpg
        • 513.jpg
        • 514.jpg
        • 515.jpg
        • 516.jpg
        • 517.jpg
        • 518.jpg
        • 519.jpg
        • 52.jpg
        • 520.jpg
        • 521.jpg
        • 522.jpg
        • 523.jpg
        • 524.jpg
        • 525.jpg
        • 526.jpg
        • 527.jpg
        • 528.jpg
        • 529.jpg
        • 53.jpg
        • 530.jpg
        • 531.jpg
        • 532.jpg
        • 533.jpg
        • 534.jpg
        • 535.jpg
        • 536.jpg
        • 537.jpg
        • 538.jpg
        • 539.jpg
        • 54.jpg
        • 540.jpg
        • 541.jpg
        • 542.jpg
        • 543.jpg
        • 544.jpg
        • 545.jpg
        • 546.jpg
        • 547.jpg
        • 548.jpg
        • 549.jpg
        • 55.jpg
        • 550.jpg
        • 551.jpg
        • 552.jpg
        • 553.jpg
        • 554.jpg
        • 555.jpg
        • 556.jpg
        • 557.jpg
        • 558.jpg
        • 559.jpg
        • 56.jpg
        • 560.jpg
        • 561.jpg
        • 562.jpg
        • 563.jpg
        • 564.jpg
        • 565.jpg
        • 566.jpg
        • 567.jpg
        • 568.jpg
        • 569.jpg
        • 57.jpg
        • 570.jpg
        • 571.jpg
        • 572.jpg
        • 573.jpg
        • 574.jpg
        • 575.jpg
        • 576.jpg
        • 577.jpg
        • 578.jpg
        • 579.jpg
        • 58.jpg
        • 580.jpg
        • 581.jpg
        • 582.jpg
        • 583.jpg
        • 584.jpg
        • 585.jpg
        • 586.jpg
        • 587.jpg
        • 588.jpg
        • 589.jpg
        • 59.jpg
        • 590.jpg
        • 591.jpg
        • 592.jpg
        • 593.jpg
        • 594.jpg
        • 595.jpg
        • 596.jpg
        • 597.jpg
        • 598.jpg
        • 599.jpg
        • 6.jpg
        • 60.jpg
        • 600.jpg
        • 61.jpg
        • 62.jpg
        • 63.jpg
        • 64.jpg
        • 65.jpg
        • 66.jpg
        • 67.jpg
        • 68.jpg
        • 69.jpg
        • 7.jpg
        • 70.jpg
        • 71.jpg
        • 72.jpg
        • 73.jpg
        • 74.jpg
        • 75.jpg
        • 76.jpg
        • 77.jpg
        • 78.jpg
        • 79.jpg
        • 8.jpg
        • 80.jpg
        • 81.jpg
        • 82.jpg
        • 83.jpg
        • 84.jpg
        • 85.jpg
        • 86.jpg
        • 87.jpg
        • 88.jpg
        • 89.jpg
        • 9.jpg
        • 90.jpg
        • 91.jpg
        • 92.jpg
        • 93.jpg
        • 94.jpg
        • 95.jpg
        • 96.jpg
        • 97.jpg
        • 98.jpg
        • 99.jpg
      • CVMeanshift.sln
      • CVMeanshift
      • ImageProcessor
      • Statistic
      • Tracker
      • UIGraphic
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

using ImageProcessor;
using UIGraphic;
using Statistic;

namespace Tracker
{
    public class Meanshift : ITracker
    {
        public Meanshift()
        {
            _imgProc = new Processor(); //create image processor
        }

        #region ITracker Members

        public virtual void CreateTargetModel(Bitmap bitmap, int binCountCh1, int binCountCh2, int binCountCh3, Window targetRoi, UIGraphic.Window searchRoi)
        {
            _targetRoi = targetRoi;
            _searchRoi = searchRoi;

            //set previous centre values
            _previousCentreX = _targetRoi.CentreX;
            _previousCentreY = _targetRoi.CentreY;

            searchRoi.EnsureLimits(); //make sure it is not out of the picture
            
            //create target histogram
            _histTarget = _imgProc.Create1DHistogram(bitmap, binCountCh1, binCountCh2, binCountCh3, targetRoi.RegionOfInterest, _searchRoi.RegionOfInterest);
        }

        public virtual void Track(Bitmap bitmap, out Window targetRoi, out Window searchRoi, out Dictionary<string, string> information)
        {
            const int MEANSHIFT_ITERATIONS = 30;
            const int DISTANCE_ITERATIONS = 30;

            float bhatCoeff1 = 0;
            float bhatCoeff2 = 0;
            int dIterations = 0;
            int msIterations = 0;
            float distance = 0;
            Bitmap cropped = null;
            int centreX = _targetRoi.CentreX;
            int centreY = _targetRoi.CentreY;
                        
            //Limit the iterations to a fixed number to avoid performance degradation
            do
            {
                _searchRoi.EnsureLimits();
                //Find candidate model at the region of interest
                _histCand = _imgProc.Create1DHistogram(bitmap, _histTarget.BinCount1, _histTarget.BinCount2, _histTarget.BinCount3, _targetRoi.RegionOfInterest, _searchRoi.RegionOfInterest);

                //Get BC
                bhatCoeff1 = Metric.Evaluate(new BhattacharryyaCoefficient(_histTarget, _histCand));

                //Calculate moments                
                cropped = GetImageSection(bitmap, _targetRoi);//crop the region of interest                
                _moment = new MSMoment(cropped, _histTarget, _histCand);
                                
                //Find the new centre
                centreX = _targetRoi.RegionOfInterest.X + (int)(_moment.FirstMomentX / _moment.ZerothMoment);
                centreY = _targetRoi.RegionOfInterest.Y + (int)(_moment.FirstMomentY / _moment.ZerothMoment);
                
                //Move the roi & search window to the new centroid
                _targetRoi.Offset(centreX - _targetRoi.CentreX, centreY - _targetRoi.CentreY);
                _searchRoi.Offset(centreX - _searchRoi.CentreX, centreY - _searchRoi.CentreY);
                
                //Find candidate model at the new location
                _searchRoi.EnsureLimits();
                _histCand = _imgProc.Create1DHistogram(bitmap, _histTarget.BinCount1, _histTarget.BinCount2, _histTarget.BinCount3, _targetRoi.RegionOfInterest, _searchRoi.RegionOfInterest);

                //Get BC at the new location
                bhatCoeff2 = Metric.Evaluate(new BhattacharryyaCoefficient(_histTarget, _histCand));

                while ((bhatCoeff2 < bhatCoeff1) && (dIterations < DISTANCE_ITERATIONS))
                {
                    centreX = (int)Math.Ceiling(((float)(centreX + _previousCentreX)) / 2);
                    centreY = (int)Math.Ceiling(((float)(centreY + _previousCentreY)) / 2);

                    //Move ROI to the new location
                    _targetRoi.Offset(centreX - _targetRoi.CentreX, centreY - _targetRoi.CentreY);
                    _searchRoi.Offset(centreX - _searchRoi.CentreX, centreY - _searchRoi.CentreY);
                                        
                    //Find candidate model at the new location
                    _searchRoi.EnsureLimits();
                    _histCand = _imgProc.Create1DHistogram(bitmap, _histTarget.BinCount1, _histTarget.BinCount2, _histTarget.BinCount3, _targetRoi.RegionOfInterest, _searchRoi.RegionOfInterest);

                    //Get BC at the new location
                    bhatCoeff2 = Metric.Evaluate(new BhattacharryyaCoefficient(_histTarget, _histCand));

                    dIterations++;
                }

                //Calculate the distance between two vectors
                distance = (float)Math.Sqrt(Math.Pow((centreX - _previousCentreX), 2)
                    + Math.Pow((centreY - _previousCentreY), 2));

                _previousCentreX = centreX;
                _previousCentreY = centreY;

                msIterations++;

            } while ((distance >= 0.1) && (msIterations < MEANSHIFT_ITERATIONS));
                       
            //save info
            //_moment.Information.Clear();
            _moment.Information.Add("Meanshift Iterations: ", msIterations.ToString());
            _moment.Information.Add("Bhattacharyya Coeff: ", bhatCoeff2.ToString());

            //check validity
            if (centreX > 0 && centreY > 0)
            {
                //Move the roi & search window to the new centroid
                _targetRoi.Offset(centreX - _targetRoi.CentreX, centreY - _targetRoi.CentreY);
                _searchRoi.Offset(centreX - _searchRoi.CentreX, centreY - _searchRoi.CentreY);

                _moment.Information.Add("Centroid: ", _targetRoi.CentreX.ToString() + ", " + _targetRoi.CentreY.ToString());

                //_processedImage = Drawer.DrawMoment(bitmap, _moment, new Point(centreX, centreY));
                _processedImage = Drawer.DrawWindow(bitmap, _targetRoi, Color.Red);
                _processedImage = Drawer.DrawWindow(bitmap, _searchRoi, Color.Yellow);
            }

            //save ROIs for next frame
            targetRoi = _targetRoi;
            searchRoi = _searchRoi;
            information = _moment.Information;
        }

        public virtual Bitmap ProcessedImage
        {
            get { return _processedImage; }
        }

        #endregion

        private Bitmap GetImageSection(Bitmap bmp, Window roi)
        {
            roi.EnsureLimits(); //make sure it is not out of the picture
            //return _imgProc.Crop(bmp, roi.RegionOfInterest);
            return bmp.Clone(roi.RegionOfInterest, bmp.PixelFormat); //select the section            
        }

        protected IProcessor _imgProc = null;
        protected Bitmap _processedImage = null;
        private Histogram _histTarget = null;
        private Histogram _histCand = null;        
        private Window _targetRoi;
        private Window _searchRoi;
        private MSMoment _moment = new MSMoment();
        private int _previousCentreX = 0;
        private int _previousCentreY = 0;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
I have been in the IT industry since April 1996. My main expertise is in Microsoft space.

Coming from engineering background, any application of programming to engineering and related fields easily excites me. I like to use OO and design patterns and find them very useful.

I have been an avid reader of CodeProject. I decided it was time to make a commitment to make my contribution to the community - so here I am.

My Website: http://www.puresolutions-online.com

Comments and Discussions