Click here to Skip to main content
15,885,244 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 116K   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.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

using ImageProcessor;
using Tracker;
using UIGraphic;
using Statistic;

namespace CVMeanshift
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
            
        private void Form1_Load(object sender, EventArgs e)
        {            
            _path = "..\\..\\";
            //Load images   
            _isTracking = false;                 
        }

        //create the target selector
        private void CreateSelector()
        {
            if (_selector == null)
            {
                _selector = new Selector(picPreview.Width, picPreview.Height);
                _selector.TargetROISelected = new Selector.TargetSelected(this.CreateTargetModel);
                //wire preview window events to selector's events
                picPreview.MouseDown += new MouseEventHandler(_selector.OnMouseDown);
                picPreview.MouseMove += new MouseEventHandler(_selector.OnMouseMove);
                picPreview.MouseUp += new MouseEventHandler(_selector.OnMouseUp);
            }
        }

        //create the model when the target is slected
        private void CreateTargetModel()
        {
            //create the model
            Tracker.CreateTargetModel((Bitmap)picPreview.Image, Bin1, Bin2, Bin3, _selector.TargetWindow, _selector.SearchWindow);
            //show target histogram
            DisplayHistogram(ref _histTarget, picPreview, picTargetHist);
         }

        private void DisplayHistogram(ref Histogram hist, PictureBox picBox, PictureBox histBox)
        {
            Image bmp = picBox.Image;
            if (bmp != null)
            {
                hist = CreateHistogram((Bitmap)bmp);
                histBox.Refresh(); //force paint event
            }            
        }

        private int Bin1
        {
            get { return Convert.ToInt32(textBox1.Text); }
        }

        private int Bin2
        {
            get { return Convert.ToInt32(textBox2.Text); }
        }

        private int Bin3
        {
            get { return Convert.ToInt32(textBox3.Text); }
        }

        //creates the histograms
        private Histogram CreateHistogram(Bitmap img)
        {
            return _imgProc.Create1DHistogram(img, Bin1, Bin2, Bin3);
        }

        //Displays the histogram
        private void DisplayModel(Histogram model, int height, int width, PaintEventArgs e, Color color, int binRange)
        {
            if (model != null)
            {
                Pen p = new Pen(color, 1);
                SolidBrush b = new SolidBrush(color);
                float[] copy = new float[model.Data.Length];
                Array.Copy(model.Data, copy, model.Data.Length);
                Array.Sort(copy);
                float max = copy[copy.Length - 1];
                float scale = height / max;
                if (float.IsNaN(scale))
                    scale = 1;
                //Approximation: divide by total bins and remove 4 from width to account for picbox border
                float w = (float)(width - 4) / (float)(model.Data.Length); 
                for (int count = 0; count < model.Data.Length; count++)
                {
                    if (model.Data[count] > 0)
                    {
                        e.Graphics.DrawRectangle(p, (float)count * w, (float)height - (model.Data[count] * scale), w, model.Data[count] * scale);
                        e.Graphics.FillRectangle(b, (float)count * w, (float)height - (model.Data[count] * scale), w, model.Data[count] * scale);

                    }
                }
            }
        }

       private void DisplayInformation(Dictionary<string, string> information)
        {
            lblInfo.Text = "";
            foreach (KeyValuePair<string, string> kv in information)
            {
                lblInfo.Text += kv.Key + ": " + kv.Value + Environment.NewLine;
            }
            lblInfo.Refresh();
        }
                
        //Track the object
        private void TrackObject(Bitmap bmp)
        {
            //run track on the tracker to find centroid
            Window roi;
            Window searchRoi;
            Dictionary<string, string> information;

            Tracker.Track(bmp, out roi, out searchRoi, out information);
            
            Bitmap b = Tracker.ProcessedImage;

            //Draw the centroid if valid
            if (roi.CentreX > 0 && roi.CentreY > 0)
            {
                //Display Info
                DisplayInformation(information);
            }

            picPreview.Image = b;
            picPreview.Refresh();

            //Display the candidate histogram
            if (_tracker.GetType().Name != "Centroid")
                DisplayHistogram(ref _histCandidate, picPreview, picCandidateHist);

            //Drawer.DrawWindow(picPreview, roi, Color.Red);
            //Drawer.DrawWindow(picPreview, searchRoi, Color.Yellow);
        }

        private ITracker Tracker
        {
            get
            {
                if (_tracker == null)
                    CreateTracker();

                return _tracker;
            }
        }

        private void CreateTracker()
        {            
            if (radTrackerCentroid.Checked)
                _tracker = new TrackerFactory(TrackerType.CENTROID).Tracker;
            else if (radTrackerMS.Checked)
                _tracker = new TrackerFactory(TrackerType.MEANSHIFT).Tracker;
            else if (radTrackerMSK.Checked)
                _tracker = new TrackerFactory(TrackerType.MEANSHIFTKERNEL).Tracker;
            else if (radTrackerMSKBG.Checked)
                _tracker = new TrackerFactory(TrackerType.MEANSHIFTKERNELBG).Tracker;
        }
           
        #region "CONTROL EVENTS"
        private void picTargetHist_Paint(object sender, PaintEventArgs e)
        {
            DisplayModel(_histTarget, picTargetHist.Height, picTargetHist.Width, e, Color.Red, Bin1 * Bin2 * Bin3);
        }

        private void picCandidateHist_Paint(object sender, PaintEventArgs e)
        {
            DisplayModel(_histCandidate, picCandidateHist.Height, picCandidateHist.Width, e, Color.Blue, Bin1 * Bin2 * Bin3);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (_count < _trackSequenceCount)
            {
                //set the next image
                Bitmap bmp = (Bitmap)Image.FromFile(_path + "\\" + _count + _imageFileExtension);
                TrackObject(bmp); //do tracking
                _count++; //move to next image
            }
            else
            {
                btnTrack.Text = "Start Tracking";
                _count = 0;
                timer1.Enabled = false;
                timer1.Stop();
            }
        }
   
        private void btnLoadSequence_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.SelectedPath = "C:\\CodeProject\\AviSequence";
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {

                Cursor.Current = Cursors.WaitCursor;

                //_isTracking = true;
                _path = folderBrowserDialog1.SelectedPath;

                picPreview.Image = null;
                picPreview.Refresh();
                _histTarget = null;
                _histCandidate = null;
                picTargetHist.Refresh();
                picCandidateHist.Refresh();
                lblInfo.Text = "";
                _count = 0;
                string imagePath = "";
                Bitmap b = null;

                string[] files = Directory.GetFiles(_path, "*.jpg");

                if (files.Length > 0)
                {
                    imagePath = files[0];
                    b = (Bitmap)Image.FromFile(imagePath);
                }
                else
                {
                    files = Directory.GetFiles(_path, "*.bmp");
                    imagePath = files[0];
                    b = (Bitmap)Image.FromFile(imagePath);
                    _imageFileExtension = ".bmp";
                }
                picPreview.Image = b;
                FileInfo fi = new FileInfo(imagePath);
                _imageFileExtension = fi.Extension;
                picPreview.Refresh();

                _trackSequenceCount = files.Length;
                                
                CreateSelector();

                Cursor.Current = Cursors.Default;
            }
        }

       
        private void btnTrack_Click(object sender, EventArgs e)
        {
            //start the frame grabber
            if (btnTrack.Text == "Start Tracking")
            {
                _isTracking = true;
                btnTrack.Text = "Stop Tracking";

                timer1.Enabled = true;
                timer1.Start();
            }
            else if (btnTrack.Text == "Stop Tracking")
            {
                timer1.Stop();
                timer1.Enabled = false;                
                btnTrack.Text = "Start Tracking";
            }
        }
        #endregion

        string _imageFileExtension = ".jpg";
        int _trackSequenceCount = 0;
        int _count = 0;
        string _path = "";
        Processor _imgProc = new Processor();
        Histogram _histTarget = null;
        Histogram _histCandidate = null;
        Selector _selector = null;
        ITracker _tracker = null;
        bool _isTracking = false;
                
    }
}

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