Click here to Skip to main content
15,867,308 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.5K   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 Statistic;

namespace ImageProcessor
{
    public unsafe class Moment
    {
        public Moment() { }

        public Moment(Bitmap bitmap)
        {
            FindMoments(bitmap);
            FindParameters(bitmap);
            WriteParameters();
        }

        public float ZerothMoment { get { return _zerothMoment; } }
        public float FirstMomentX { get { return _firstMomentX; } }
        public float FirstMomentY { get { return _firstMomentY; } }
        public float SecondMomentX { get { return _secondMomentX; } }
        public float SecondMomentY { get { return _secondMomentY; } }
        public float FirstMomentXY { get { return _firstMomentXY; } }
        public int Length { get { return (int)_length; } }
        public int Width { get { return (int)_width; } }
        public float RollRadians { get { return _rollRad; } }
        public float ToRadians(float angle)
        {
            return (3.14160f /  180.0f) * angle; 
        }
        public float ToDegrees(float angle)
        {
            return (180.0f / 3.14160f) * angle; 
        }
        public Dictionary<string, string> Information
        {
            get { return _information; }
        }
        private void FindMoments(Bitmap bitmap)
        {
            UnsafeBitmap fastBitmap = new UnsafeBitmap(bitmap);
            fastBitmap.LockBitmap();
            Point size = fastBitmap.Size;

            for (int y = 0; y < size.Y; y++)
            {
                BGRA* pPixel = fastBitmap[0, y];
                for (int x = 0; x < size.X; x++)
                {
                    //Find moments - for backprojection image r, g, b intensities are the same
                    _firstMomentX += pPixel->red * x;
                    _firstMomentY += pPixel->red * y;
                    _secondMomentX += pPixel->red * x * x;
                    _secondMomentY += pPixel->red * y * y;
                    _firstMomentXY += pPixel->red * x * y;
                    _zerothMoment += pPixel->red;
            
                    //increment the pointer
                    pPixel++;
                }
            }

            fastBitmap.UnlockBitmap();

        }

        protected void FindParameters(Bitmap bitmap)
        {
            int Xc = bitmap.Width / 2;
            int Yc = bitmap.Height / 2;

            
            float a = (_secondMomentX / _zerothMoment) - (float)(Xc * Xc);
            float b = 2 * ((_firstMomentXY / _zerothMoment) - (float)(Xc * Yc));
            float c = (_secondMomentY / _zerothMoment) - (float)(Yc * Yc);
            float aplusc = a + c;
            float aminusc = a - c;
            float bacsqrt = (float)Math.Sqrt(b * b + aminusc * aminusc);

            _length = (float)Math.Sqrt((aplusc + bacsqrt) * 0.5);
            _width = (float)Math.Sqrt((aminusc + bacsqrt) * 0.5);

            _rollRad = (float)Math.Atan(2 * b / Math.Abs((a - c))) / 2;            
        }

        protected virtual void WriteParameters()
        {
            _information.Add("Zeroth Moment", ZerothMoment.ToString());
            _information.Add("First Moment X", FirstMomentX.ToString());
            _information.Add("First Moment Y", FirstMomentY.ToString());
            _information.Add("First Moment XY", FirstMomentXY.ToString());
            _information.Add("Second Moment X", SecondMomentX.ToString());
            _information.Add("Second Moment Y", SecondMomentY.ToString());
            _information.Add("Length", Length.ToString());
            _information.Add("Width", Width.ToString());
            _information.Add("Roll", ToDegrees(RollRadians).ToString());
        }

        protected float _length = 0;
        protected float _width = 0;
        protected float _rollRad = 0;
        protected float _zerothMoment = 0;
        protected float _firstMomentX = 0;
        protected float _firstMomentY = 0;
        protected float _secondMomentX = 0;
        protected float _secondMomentY = 0;
        protected float _firstMomentXY = 0;
        protected Dictionary<string, string> _information = new Dictionary<string, string>();
    }

    public unsafe class MSMoment : Moment
    {
        public MSMoment(Bitmap bitmap, Histogram target, Histogram candidate)
        {
            FindMoments(bitmap, target, candidate);
            //FindParameters(bitmap);
            //WriteParameters();
        }

        public MSMoment() { }
        public Bitmap CroppedImage
        {
            get { return _croppedBmp; }
            set { _croppedBmp = value; }
        }
        public Histogram CandidateHistogram
        {
            get { return _candidateHistogram; }
            set { _candidateHistogram = value; }
        }
        public Histogram TargetHistogram
        {
            get { return _targetHistogram; }
            set { _targetHistogram = value; }
        }
        public void FindMoments()
        {
            FindMoments(_croppedBmp, _targetHistogram, _candidateHistogram);
        }
        private void FindMoments(Bitmap croppedBitmap, Histogram target, Histogram candidate)
        {
            float weight = 0;
            
            UnsafeBitmap fastBitmap = new UnsafeBitmap(croppedBitmap);
            fastBitmap.LockBitmap();
            Point size = fastBitmap.Size;
            int idx = 0;
            
            for (int y = 0; y < size.Y; y++)
            {
                BGRA* pPixel = fastBitmap[0, y];
                for (int x = 0; x < size.X; x++)
                {
                    //find the bin index where the value of this colour falls
                    idx = _imgProc.GetSingleBinIndex(target.BinCount1, target.BinCount2, target.BinCount3, pPixel);
                    //find weight at this pixel location
                    weight = CreateValidWeight(target.Data[idx], candidate.Data[idx]);
                    
                    //find weighted moments
                    _firstMomentX += x * weight;
                    _firstMomentY += y * weight;
                    _secondMomentX += x * x * weight;
                    _secondMomentY += y * y * weight;
                    _firstMomentXY += x * y * weight;
                    _zerothMoment += weight;

                    //increment the pointer
                    pPixel++;
                }
            }

            fastBitmap.UnlockBitmap();

            
        }

        private float CreateValidWeight(float targetValue, float candidateValue)
        {
            float w = targetValue / candidateValue;

            if (float.IsNaN(w))//check 0/0
                w = 0;
            else if (float.IsInfinity(w))//check x/0
                w = (float)Math.Sqrt(targetValue);
            else
                w = (float)Math.Sqrt(w);

            return w;
        }

        Processor _imgProc = new Processor();
        private Bitmap _croppedBmp = null;
        private Histogram _targetHistogram = null;
        private Histogram _candidateHistogram = null;
    }
}

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