Click here to Skip to main content
15,898,134 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 117.2K   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.Drawing;
using System.Drawing.Imaging;

using ImageProcessor;

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

		private Model _targetModel = null;
		private Model _candidateModel = null;
		private Model _targetLModel = null;
		private Model _candidateLModel = null;
		private Model _targetBrightnessModel = null;
		private Model _candidateBrightnessModel = null;
		private Model _targetSaturationModel = null;
		private Model _candidateSaturationModel = null;
		private int _oldCentreX = 0;
		private int _oldCentreY = 0;
		int _imageWidth = 0;
		int _imageHeight = 0;
		int _roiWidth = 0;
		int _roiHeight = 0;
		int _roiSize = 0;
		int _previousTargetCentreX = 0;
		int _previousTargetCentreY = 0;	
		int _numberOfBins = 0;
		int _msIterations = 0;
		Bitmap _backProjImage = null;

		enum TrackingComponent {HUE, SATURATION, VALUE, RED, GREEN, BLUE};
		
		public MeanShift()
		{
		}

		public MeanShift(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 _msIterations;}
		}

		public Bitmap BackProjectionImage
		{
			get {return _backProjImage; }
		}

		public void CreateTargetModel(Bitmap bmp, Rectangle window)
		{			
			_imageWidth = bmp.Width;
			_imageHeight = bmp.Height;
			_roiWidth = window.Width;
			_roiHeight = window.Height;	

			_targetLModel = Processor.CreateHsModel(bmp, window);

			//PrintModel(_targetLModel, "target");
			//_targetLModel = Processor.CreateHueModel(bmp, window);			
			//_targetBrightnessModel = Processor.CreateValueModel(bmp, window);
			//_targetSaturationModel = Processor.CreateSaturationModel(bmp, window);

			//window = Track(bmp, window);
			_previousTargetCentreX = (int) Math.Ceiling((window.Left + window.Right) / 2);
			_previousTargetCentreY = (int) Math.Ceiling((window.Top + window.Bottom) / 2);	
			
			
		}

		protected int ImageWidth
		{
			get {return _imageWidth;}
		}

		protected int ImageHeight
		{
			get {return _imageHeight;}
		}

		protected int OldCentreX
		{
			get {return _oldCentreX;}
			set {_oldCentreX = value;}
		}

		protected int OldCentreY
		{
			get {return _oldCentreY;}
			set {_oldCentreY = value;}
		}

		protected int CentreX
		{
			get {return _previousTargetCentreX;}
			set {_previousTargetCentreX = value;}
		}

		protected int CentreY
		{
			get {return _previousTargetCentreY;}
			set {_previousTargetCentreY = value;}
		}

		protected int ROIWidth
		{
			get {return _roiWidth;}
			set {_roiWidth = value;}
		}

		protected int ROIHeight
		{
			get {return _roiHeight;}
			set {_roiHeight = value;}
		}

		protected int ROISize
		{
			get {return _roiSize;}
			set {_roiSize = value;}
		}



		protected void FindMeanshiftVector(Bitmap bmp, Rectangle window, float[,] probabilityMap, ref float meanshiftX, ref float meanshiftY, ref float zerothMoment)
		{
			zerothMoment = 0; //zeroth moment
			meanshiftX = 0; //first moment for x(col)
			meanshiftY = 0; //first moment for y(col)

			//Find zeroth moment
			for (int col=window.Left; col<window.Right; col++)
			{
				for (int row=window.Top; row<window.Bottom; row++)
				{
					zerothMoment += probabilityMap[row, col];
				}
			}
			//Find first moment for x(col) and y(row)
			for (int col=window.Left; col<window.Right; col++)
			{
				for (int row=window.Top; row<window.Bottom; row++)
				{
					meanshiftX += (float) (col * probabilityMap[row, col]);
					meanshiftY += (float) (row * probabilityMap[row, col]);
				}
			}
			//Find the new centroid
			//x is cols
			meanshiftX = (float) (meanshiftX / zerothMoment);
			//y is rows
			meanshiftY = (float) (meanshiftY / zerothMoment);

			meanshiftX = float.IsNaN(meanshiftX)? 0 : meanshiftX;
			meanshiftX = float.IsInfinity(meanshiftX) ? 0 : meanshiftX;	
			meanshiftY = float.IsNaN(meanshiftY)? 0 : meanshiftY;
			meanshiftY = float.IsInfinity(meanshiftY) ? 0 : meanshiftY;	
		}

		public virtual Rectangle Track(Bitmap bmp, Rectangle window)
		{
			//Meanshift vector
			float msX = 0;
			float msY = 0;
			float hueWeight = 0;
			float satWeight = 0;
			float valWeight = 0;
			float totalWeight = 0;
			//Colour value index
			int hueValue = 0;
			int satValue = 0;
			int valValue = 0;
			//Find the correct bin range
			int binRange = 256 / _numberOfBins;	
			
//			_previousTargetCentreX = 0;
//			_previousTargetCentreY = 0;
			_msIterations = 0;

			_backProjImage = (Bitmap) bmp.Clone();							
			
			//Limit the iterations to a fixed number to avoid performance degradation
			for (_msIterations=0; _msIterations<MEANSHIFT_ITERATIONS; _msIterations++)
			{
				//Find the new candidate model
				_candidateLModel = null;
				_candidateLModel = Processor.CreateHsModel(bmp, window);
				//_candidateBrightnessModel = Processor.CreateValueModel(bmp, window);
				//_candidateSaturationModel = Processor.CreateSaturationModel(bmp, window);
				//PrintModel(_candidateLModel, "candidate");

				//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);
				//croppedBmp.Save("Model\\cropped0.bmp", ImageFormat.Bmp);
				//string t = "Start X: " + _centreX.ToString() + " Y: " + _centreY.ToString() + "\r\n";;

				totalWeight = 0; //clean up the accumulating variables
				msX = 0;
				msY = 0;
				
				//Find meanshift vector
				for (int y=window.Top; y<window.Bottom; y++)
				{
					for (int x=window.Left; x<window.Right; x++)
					{
						//Get the colour value at this location which serves as an index to 
						//the bins	
						Processor.GetHsvComponents(croppedBmp, x-window.Left, y-window.Top, ref hueValue, ref satValue, ref valValue);
						
						//Processor.GetHsvComponents((Bitmap)bmp.Clone(), x, y, ref hueValue, ref satValue, ref valValue);
						
						//TODO - Should we take square root?
						hueWeight = (float) (_targetLModel.Bins.Item(hueValue / binRange).Value / _candidateLModel.Bins.Item(hueValue / binRange).Value);
						hueWeight = float.IsNaN(hueWeight) ? 0 : hueWeight;
						hueWeight = float.IsInfinity(hueWeight) ? 0 : hueWeight;
						
						satWeight = (float) (_targetLModel.Bins.Item(satValue / binRange).Value / _candidateLModel.Bins.Item(satValue / binRange).Value);
						satWeight = float.IsNaN(satWeight) ? 0 : satWeight;
						satWeight = float.IsInfinity(satWeight) ? 0 : satWeight;

//						valWeight = (float) Math.Sqrt(_targetLModel.Bins.Item(valValue / binRange).Value / _candidateLModel.Bins.Item(valValue / binRange).Value);
//						valWeight = float.IsNaN(valWeight) ? 0 : valWeight;
//						valWeight = float.IsInfinity(valWeight) ? 0 : valWeight;

						msX += x * (hueWeight + satWeight + valWeight);
						msY += y * (hueWeight + satWeight + valWeight);
						totalWeight += (hueWeight + satWeight + valWeight);

						hueWeight = (float) _targetLModel.Bins.Item(hueValue / binRange).Value / _candidateLModel.Bins.Item(hueValue / binRange).Value;
						hueWeight = float.IsNaN(hueWeight) ? 0 : hueWeight;
						hueWeight = float.IsInfinity(hueWeight) ? 0 : hueWeight;
						hueWeight = Math.Min(hueWeight * 255, 255);
						_backProjImage.SetPixel(x, y, Color.FromArgb((int)hueWeight,
							(int)hueWeight, (int)hueWeight));
				
					}
				}
				//Find the meanshift vector
				if (totalWeight > 1)
				{
					msX = msX / totalWeight;
					msY = msY / totalWeight;
					//return the new window based on the current centre
					//window = GetNewTargetWindow(window, msX, msY);
				}
//				if (Math.Sqrt(1-BhattacharyyaCoefficient) < 0.2)
//					break;
//				else
//				{
//					//Move the window's centre to the meanshift vector
//					window = GetNewTargetWindow(window, (int)Math.Ceiling(msX), (int)Math.Ceiling(msY));
//					//window.Offset((int) (_previousTargetCentreX - targetCentreX), (int) (_previousTargetCentreY - targetCentreY));
//					//update the centre value
//					_previousTargetCentreX = (int)Math.Ceiling(msX);
//					_previousTargetCentreY = (int)Math.Ceiling(msY);					
//				}
				//Check if the centre has not moved, then the target is localised and break
				if (Math.Abs(_previousTargetCentreX - (int)Math.Ceiling(msX)) == 0 && Math.Abs(_previousTargetCentreY - (int)Math.Ceiling(msY)) == 0)
					break;
				else
				{
					//Move the window's centre to the meanshift vector
					window = GetNewTargetWindow(window, (int)Math.Ceiling(msX), (int)Math.Ceiling(msY));
					//window.Offset((int) (_previousTargetCentreX - targetCentreX), (int) (_previousTargetCentreY - targetCentreY));
					//update the centre value
					_previousTargetCentreX = (int)Math.Ceiling(msX);
					_previousTargetCentreY = (int)Math.Ceiling(msY);					
				}
			}
			
			//t += "MS X: " + msX.ToString() + " Y: " + msY.ToString();
			//PrintWindow(t);

			//_backProjImage = Processor.OverlayWindow(_backProjImage, window, Color.Yellow);
				
			return window;
		}

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

		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);
		}

		int count = 0;
		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 PrintModel(Model model, string name)
		{
			string t = "";
			for (int c=0;c<model.Bins.Count;c++)
			{
				t += "," + model.Bins.Item(c).Value.ToString();
			}
			t = t.Remove(0,1);
			System.IO.StreamWriter file = new System.IO.StreamWriter("Model\\" + name + (count++).ToString() + ".txt");
			file.WriteLine(t);
			file.Close();
		}

		
	}
}

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