Click here to Skip to main content
15,886,004 members
Articles / Multimedia / GDI+

Computer Vision Applications with C# - Part II

Rate me:
Please Sign up or sign in to vote.
4.94/5 (30 votes)
25 Apr 2009CPOL6 min read 100.4K   9.2K   88  
Applied Computer Vision - Moments.
  • cvmoments.zip
    • 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
    • CVMoments.sln
    • CVMoments
    • ImageProcessor
    • Tracker
    • UIGraphic
using System;
using System.Drawing;
using System.Drawing.Imaging;

using ImageProcessor;

namespace Tracker
{
	/// <summary>
	/// Summary description for MeanShiftKernel.
	/// </summary>
	public class MeanShiftKernel : ITracker
	{
		private const int MEANSHIFT_ITERATIONS = 15;

		private Model _targetModel = null;
		private Model _candidateModel = null;
		private Model _targetLModel = null;
		private Model _candidateLModel = null;
		int _previousTargetCentreX = 0;
		int _previousTargetCentreY = 0;
		float _centreOffsetX = 0;
		float _centreOffsetY = 0;
		int count = 0;	
		int _numberOfBins = 0;
		
		public MeanShiftKernel(int numberOfBins)
		{
			_numberOfBins = numberOfBins;
			Processor.NumberOfBins = numberOfBins;
		}

		public Model TargetModel
		{
			get {return _targetModel;}
		}

		public Model CandidateModel
		{
			get {return _candidateModel;}
		}

		public Model TargetLModel
		{
			get {return _targetLModel;}
		}

		public Model CandidateLModel
		{
			get {return _candidateLModel;}
		}

		public int Iterations
		{
			get {return 0;}
		}

		public Bitmap BackProjectionImage
		{
			get {return null; }
		}

		public void CreateTargetModel(Bitmap bmp, Rectangle window)
		{			
			_targetLModel = Processor.CreateHueModelWithEpanichnekovKernel(bmp, window);
			//bmp.Clone(window, PixelFormat.Format24bppRgb).Save("Model\\t.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
			//PrintTargetModel(window);

			//Find the centre Yo of the target
			_previousTargetCentreX = (window.Left + window.Right) / 2;
			_previousTargetCentreY = (window.Top + window.Bottom) / 2;
			//string t = "Count: " + count + " window: " + window.ToString() + " msX: " + _previousTargetCentreX.ToString() + " msY: " + _previousTargetCentreY.ToString()  + "\r\n";
			//PrintWindow(t);
		}
				
		public virtual Rectangle Track(Bitmap bmp, Rectangle window)
		{	
			//Get window width & height
			int width = window.Width;
			int height = window.Height;	
			//Centre of the window
			int Xc = (window.Left + window.Right) / 2;
			int Yc = (window.Top + window.Bottom) / 2;
			//Normalised Space coordinates & kernel distance
			float Xn = 0;
			float Yn = 0;
			//Meanshift vector
			float msX = 0;
			float msY = 0;
			float weight = 0;
			float totalWeight = 0;
			//Colour value index
			int colourValue = 0;
			//Centre of meanshift
			int targetCentreX = 0;
			int targetCentreY = 0;			
			//Find the correct bin range
			int binRange = 256 / _numberOfBins;		
						
			//Find the new candidate model
			_candidateLModel = Processor.CreateHueModelWithEpanichnekovKernel(bmp, window);
			//Crop the image for less processing time 
			Bitmap croppedBmp = bmp.Clone(new Rectangle(window.Left, window.Top, window.Right-window.Left, window.Bottom-window.Top),PixelFormat.Format24bppRgb);
			
			string t = "Start X: " + _previousTargetCentreX.ToString() + " Y: " + _previousTargetCentreY.ToString() + "\r\n";;

			int loopCount = 0;
			//Do maximum of 15 reps
			for (loopCount=0; loopCount<MEANSHIFT_ITERATIONS; loopCount++)
			{
				//Find meanshift vector
				for (int y=window.Top; y<window.Bottom; y++)
				{
					for (int x=window.Left; x<window.Right; x++)
					{
						//Find the normalised x & y
						Xn = 2 * (x - Xc) / (float) width;
						Yn = 2 * (y - Yc) / (float) height;
						if (float.IsNaN(Xn))
							Xn = 0;
						if (float.IsNaN(Yn))
							Yn = 0;
						//Get the colour value at this location which serves as an index to 
						//the bins							
						colourValue = Processor.GetHueComponent(bmp, x, y);
						//Find meanshift vector components
						weight = _targetLModel.Bins[colourValue / binRange] / _candidateLModel.Bins[colourValue / binRange];
						if (float.IsNaN(weight))
							weight = 0;
						msX += Xn * weight;
						msY += Yn * weight;
						totalWeight += weight;
					}
				}
				//Find the meanshift vector
				msX = msX / totalWeight;
				msY = msY / totalWeight;
				//Find the centre in the image space
				targetCentreX = Xc + (int)(msX * width) / 2;
				targetCentreY = Yc + (int)(msY * height) / 2;
				//Check if the centre has not moved, then the target is localised and break
				if ((_previousTargetCentreX == targetCentreX) && (_previousTargetCentreY == targetCentreY))
					break;
				else
				{
					//Move the window's centre to the meanshift vector
					window = GetNewTargetWindow(window, targetCentreX, targetCentreY);
					//window.Offset((int) (_previousTargetCentreX - targetCentreX), (int) (_previousTargetCentreY - targetCentreY));
					//update the centre value
					_previousTargetCentreX = targetCentreX;
					_previousTargetCentreY = targetCentreY;					
				}
			}

			t += "Iteration Count: " + loopCount.ToString() + "\r\n";
			t += "MS X: " + _previousTargetCentreX.ToString() + " Y: " + _previousTargetCentreY.ToString();
			PrintWindow(t);
			count++;
			//return the new window based on the current centre
			//window.Offset((int) (_previousTargetCentreX - targetCentreX), (int) (_previousTargetCentreY - targetCentreY));
			return GetNewTargetWindow(window, targetCentreX, targetCentreY);;
			//return the new window on the candidate target
			//return MoveMeanShiftVector(bmp, window);			
		}

		private Rectangle GetNewTargetWindow(Rectangle window, int meanshiftX, int meanshiftY)
		{
			int windowX = (window.Left + window.Right) / 2;
			int windowY = (window.Top + window.Bottom) /2;
		
			//Centre the new window at windowX & windowY
			if (meanshiftX > windowX)
				meanshiftX = window.Left + (meanshiftX - windowX);
			else
				meanshiftX = window.Left - (windowX - meanshiftX);
			
			if (meanshiftY > windowY)
				meanshiftY = window.Top + (meanshiftY - windowY);
			else
				meanshiftY = window.Top - (windowY - meanshiftY);

			//look out for negative values
			meanshiftX = (meanshiftX < 0) ? 0 : meanshiftX;
			meanshiftY = (meanshiftY < 0) ? 0 : meanshiftY;

			//adjust the size if going out of the window size: 320*240
			if (meanshiftX + window.Width >= 320)
				meanshiftX = 320 - window.Width;
			if (meanshiftY + window.Height >= 240)
				meanshiftY = 240 - window.Height;
			
			return new Rectangle(meanshiftX, meanshiftY, window.Width, window.Height);
		}

		private Rectangle MoveMeanShiftVector(Bitmap bmp, Rectangle window)
		{
			//Find meanshift vector in X & Y direction
			float meanshiftX = 0;
			float meanshiftY = 0;	
			string t = "";
				
			//Iterate to move the meanshift vector closer to the centre. Loop until the 
			//current pixel moves less than one pixel from the previous pixel in the image space
			for (int i=0; i<15; i++)
			{
				count++;
				//Find the new candidate model
				_candidateModel = Processor.CreateHueHistogramWithEpanechnikovKernel(bmp, window);				
				//bmp.Clone(window, PixelFormat.Format24bppRgb).Save("Model\\c" + count.ToString() + ".jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
				
				//PrintTargetModel();
				//PrintCandidateModel(window);

				//Find meanshift vector
				FindMeanShiftVector2(ref meanshiftX, ref meanshiftY);
				
				if ((_previousTargetCentreX == meanshiftX) && (_previousTargetCentreY == meanshiftY))
					break;
				else
				{
					_centreOffsetX = meanshiftX - _previousTargetCentreX;
					_centreOffsetY = meanshiftY - _previousTargetCentreY;
					_previousTargetCentreX = (int)meanshiftX;
					_previousTargetCentreY = (int)meanshiftY;
//					window = GetNewSearchWindow2(window, _centreOffsetX, _centreOffsetY);

					window = GetNewSearchWindow2(window, meanshiftX, meanshiftY);
				}
				
				t += "Count: " + count + " window: " + window.ToString() + " msX: " + meanshiftX.ToString() + " msY: " + meanshiftY.ToString()  + "\r\n";
				PrintWindow(t);
			}
			

			return window;
		}

		private void PrintWindow(string text)
		{
			if (text != "")
			{
				System.IO.StreamWriter file = new System.IO.StreamWriter("Model\\window" + count.ToString() + ".txt");
				file.WriteLine(text);
				file.Close();
			}
		}

		private void PrintCandidateModel(Rectangle window)
		{
			string text2 = "";
			
			for (int j=window.Top; j<window.Bottom; j++)
			{
				for (int i=window.Left; i<window.Right; i++)
				{
					text2 += _candidateModel.GetCoordinateValue(i, j).ToString() + ",";
				}		
				text2 += "\r\n";
			}
			
			System.IO.StreamWriter file = new System.IO.StreamWriter("Model\\candidatemodel" + count.ToString() + ".txt");
			file.WriteLine(text2);
			file.Close();

		}

		private void PrintTargetModel(Rectangle window)
		{
			string text2 = "";
			float val = 0;
			Bitmap bmp = (Bitmap) Image.FromFile("Model\\0.bmp");
			
			for (int j=window.Top; j<window.Bottom; j++)
			{
				for (int i=window.Left; i<window.Right; i++)
				{
					val = _targetModel.GetCoordinateValue(i, j);
					text2 += val.ToString() + ",";
					bmp.SetPixel(i, j, GetColor(val));
				}		
				text2 += "\r\n";
			}
			
			bmp.Save("Model\\target.bmp", ImageFormat.Bmp);			
			
			System.IO.StreamWriter file = new System.IO.StreamWriter("Model\\targetmodel" + count.ToString() + ".txt");
			file.WriteLine(text2);
			file.Close();

		}

		private Color GetColor(float val)
		{
			return Color.FromArgb((int) val, Color.Gray);			
		}
		
		private Rectangle GetNewSearchWindow2(Rectangle window, float meanshiftX, float meanshiftY)
		{
			float windowX = (float) (window.Left + window.Right) / 2;
			float windowY = (float) (window.Top + window.Bottom) /2;

			meanshiftX = windowX - (meanshiftX * (float)window.Width) / 2;
			meanshiftY = windowY - (meanshiftY * (float)window.Height) / 2;

			//Centre the new window at windowX & windowY
			if (meanshiftX > windowX)
				meanshiftX = (float)window.Left + (meanshiftX - windowX);
			else
				meanshiftX = (float)window.Left - (windowX - meanshiftX);
			
			if (meanshiftY > windowY)
				meanshiftY = (float)window.Top + (meanshiftY - windowY);
			else
				meanshiftY = (float)window.Top - (windowY - meanshiftY);

			//look out for negative values
			meanshiftX = (meanshiftX < 0) ? 0 : meanshiftX;
			meanshiftY = (meanshiftY < 0) ? 0 : meanshiftY;

			//adjust the size if going out of the window size: 320*240
			if (meanshiftX + window.Width >= 320)
				meanshiftX = 320 - window.Width;
			if (meanshiftY + window.Height >= 240)
				meanshiftY = 240 - window.Height;
			
			return new Rectangle((int) meanshiftX, (int) meanshiftY, window.Width, window.Height);
		}

		private Rectangle GetNewSearchWindow(Rectangle window, int windowX, int windowY)
		{
			int winCentreX = (window.Left + window.Right) / 2;
			int winCentreY = (window.Top + window.Bottom) / 2;

			//Centre the new window at windowX & windowY
			if (windowX >= winCentreX)
				windowX = window.Left + (windowX - winCentreX);
			else
				windowX = window.Left - (winCentreX - windowX);
			
			if (windowY >= winCentreY)
				windowY = window.Top + (windowY - winCentreY);
			else
				windowY = window.Top - (winCentreY - windowY);

			//look out for negative values
			windowX = (windowX < 0) ? 0 : windowX;
			windowY = (windowY < 0) ? 0 : windowY;

			//adjust the size if going out of the window size: 320*240
			if (windowX + window.Width >= 320)
				windowX = 320 - window.Width;
			if (windowY + window.Height >= 240)
				windowY = 240 - window.Height;
			
			return new Rectangle((int) windowX, (int) windowY, window.Width, window.Height);
		}

		private void MapNormalisedSpaceToImageSpace(Rectangle window, float normalX, float normalY, ref int imageX, ref int imageY)
		{
			imageX = (int)((normalX * (float)window.Width /2) + (float)(window.Left + window.Right) / 2);
			imageY = (int)((normalY * (float)window.Height /2) + (float)(window.Bottom + window.Top) / 2);
				
//			float winCentreX = (window.Left + window.Right) / 2;
//			float winCentreY = (window.Top + window.Bottom) / 2;
//
//			if (normalX == 0) //On the centre
//				imageX = (int) winCentreX;
//			else if (normalX < 0) //In left hand side - negative
//				imageX = (int) (winCentreX + (winCentreX - window.Left) * normalX);
//			else  //In right hand side - positive
//				imageX = (int) (winCentreX + (window.Right - winCentreX) * normalX);
//
//			if (normalY == 0) //On the centre
//				imageY = (int) winCentreY;
//			else if (normalY < 0) //In bottom section - negative
//				imageY = (int) (winCentreY - (window.Bottom - winCentreY) * normalY);
//			else  //In top section - positive
//				imageY = (int) (winCentreY - (winCentreY - window.Top) * normalY);
//
//			if (imageX == 0)
//				imageX = window.Left;
//
//			if (imageY == 0)
//				imageY = window.Top;
//			
		}

		private void FindMeanShiftVector2(ref float meanshiftX, ref float meanshiftY)
		{
			//Find meanshift vector in X & Y direction
			float totalWeight = 0;
			float msX = 0;
			float msY = 0;
			Bin candidateBin = null;
			Coordinate candidateCoord = null;
			float weight = 0;
			meanshiftX = 0;
			meanshiftY = 0;
			float t = 0;

			string text = "";
			
			for (int i=0; i<_candidateModel.Bins.Count; i++)
			{
				candidateBin = _candidateModel.Bins.Item(i);				
				for (int j=0; j<candidateBin.Coordinates.Count; j++)
				{
					candidateCoord = candidateBin.Coordinates.Item(j);
					//For this pixel of the candidate, get the Bin value for the same pixel
					//in the target model. Use normalised coordinates because the image space
					//coordinates would keep on changing as the ROI window moves
					t = _targetModel.GetBinValueByCoordinate(candidateCoord.NormalisedX, candidateCoord.NormalisedY);
					//Find the weight
					weight = (float) Math.Sqrt(t / candidateBin.NormalisedValue); 					
					//If there is 0/0, then use 0 otherwise the actual weight
					weight = float.IsNaN(weight)? 0 : weight;
					weight = float.IsInfinity(weight) ? 0 : weight;	
					//text += "X: " + candidateCoord.X.ToString() + " Y: " + candidateCoord.Y.ToString() + " W: " + weight.ToString() + "\r\n";
					//Get total of X by multiplying the actual pixel location value by the weight
					msX += candidateCoord.NormalisedX * weight;
					//Get total of Y by multiplying the actual pixel location value by the weight
					msY += candidateCoord.NormalisedY * weight;
					//Keep the total weight
					totalWeight += weight;
				}
			}

			meanshiftX = msX / totalWeight;
			meanshiftY = msY / totalWeight;

//			text += "MSX: " + meanshiftX.ToString() + " MSY: " + meanshiftY.ToString();
//			System.IO.StreamWriter file = new System.IO.StreamWriter("Model\\meanshift" + count.ToString() + ".txt");
//			file.WriteLine(text);
//			file.Close();
		}

		private void FindMeanShiftVector(ref float meanshiftX, ref float meanshiftY)
		{
			//Find meanshift vector in X & Y direction
			float totalWeight = 0f;
			float msX = 0f;
			float msY = 0f;
			Bin candidateBin = null;
			Bin targetBin = null;
			float weight = 0f;
			meanshiftX = 0;
			meanshiftY = 0;
			Coordinate coord = null;
			float val = 0;
			Bitmap bmp = (Bitmap) Image.FromFile("Model\\0.bmp");
			
			for (int i=0; i<_candidateModel.Bins.Count; i++)
			{
				candidateBin = _candidateModel.Bins.Item(i);
				targetBin = _targetModel.Bins.Item(i);
				
				for (int j=0; j<candidateBin.Coordinates.Count; j++)
				{	
					coord = candidateBin.Coordinates.Item(j);
					float t = _targetModel.Bins.GetCoordinateColorValue(coord.X, coord.Y);
					weight = t / coord.ColorValue; 					

					//If there is 0/0, then use 0 otherwise the actual weight
					weight = float.IsNaN(weight)? 0 : weight;
					weight = float.IsInfinity(weight) ? 0 : weight;

					bmp.SetPixel(coord.X, coord.Y, GetColor((int)weight));

					//Get total of X by multiplying the actual pixel location value by the weight
					val = coord.NormalisedX * weight;
					msX += val; //coord.NormalisedX * weight;
					//Get total of Y by multiplying the actual pixel location value by the weight
					msY += coord.NormalisedY * weight;
					//Keep the total weight
					totalWeight += weight;
				}
			}

			meanshiftX = msX / totalWeight;
			meanshiftY = msY / totalWeight;

			bmp.Save("Model\\candidate.bmp", ImageFormat.Bmp);
			
					
		}

		public float BhattacharyyaCoefficient
		{
			get
			{
				float coeff = 0;
				for (int i=0; i<_targetModel.Bins.Count; i++)
				{
					coeff += (float) Math.Sqrt(_targetModel.Bins.Item(i).NormalisedValue * _candidateModel.Bins.Item(i).NormalisedValue);
				}
				return coeff;
			}
		}

		
	}
}

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