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 ImageProcessor;
using Tracker;
using UIGraphic;
namespace CVMoments
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_path = "..\\..\\";
//Load images
LoadImages();
}
//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()
{
if (_isTracking)
{
//create the model
Tracker.CreateTargetModel((Bitmap)picPreview.Image, Bin1, Bin2, Bin3, _selector.TargetWindow, _selector.SearchWindow);
//show target histogram
DisplayHistogram(ref _histTarget, picPreview, picTargetHist);
}
else
{
//Find info
ProcessImage();
}
}
//process the whole image to show backprojection and moments info
private void ProcessImage()
{
Bitmap bitmap = (Bitmap)picPreview.Image;
//create target histogram
Bitmap targetBmp = bitmap.Clone(_selector.TargetWindow.RegionOfInterest, bitmap.PixelFormat);
Histogram hist = _imgProc.Create1DHistogram(targetBmp, Bin1, Bin2, Bin3);
//create backprojection image
Bitmap bpImage = _imgProc.CreateBackprojectionImage(bitmap, hist);
//Find moments of the backprojection image
Moment mom = new Moment(bpImage);
//Find centroid of the backprojection image
int centreX = (int)(mom.FirstMomentX / mom.ZerothMoment);
int centreY = (int)(mom.FirstMomentY / mom.ZerothMoment);
//Display length & width of moments
bpImage = Drawer.DrawMoment(bpImage, mom, new Point(centreX, centreY));
picProcessed.Image = bpImage;
picProcessed.Refresh();
//Display Info
mom.Information.Add("Centroid", "(" + centreX.ToString() + ", " + centreY.ToString() + ")");
DisplayInformation(mom.Information);
}
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);
}
}
}
}
//Show tracker info
private void DisplayInformation(Dictionary<string, string> information)
{
lblInfo.Text = "";
foreach (KeyValuePair<string, string> kv in information)
{
lblInfo.Text += kv.Key + ": " + kv.Value + Environment.NewLine;
}
}
//Track the object
private void TrackObject()
{
//run track on the tracker to find centroid
Window roi;
Window searchRoi;
Tracker.Track((Bitmap)picPreview.Image, out roi, out searchRoi);
Bitmap b = Tracker.ProcessedImage;
//Draw the centroid if valid
if (roi.CentreX > 0 && roi.CentreY > 0)
{
//Display Info
DisplayInformation(Tracker.Information);
}
picProcessed.Image = b;
picProcessed.Refresh();
//Display the candidate histogram
DisplayHistogram(ref _histCandidate, picPreview, picCandidateHist);
Drawer.DrawWindow(picPreview, roi, Color.Red);
Drawer.DrawWindow(picPreview, searchRoi, Color.Yellow);
}
private ITracker Tracker
{
get
{
if (_tracker == null)
_tracker = new TrackerFactory(TrackerType.CENTROID).Tracker;
return _tracker;
}
}
#region "IMAGE LOADING"
//Load BMP images from a pre-defined location
private void LoadImages()
{
//start clean
listView1.Clear();
listView1.Refresh();
imageList1.Images.Clear();
//setup the list
imageList1.ImageSize = new Size(50, 50);
imageList1.ColorDepth = ColorDepth.Depth32Bit;
imageList1.TransparentColor = Color.White;
//get the location
string[] images = Directory.GetFiles(_path, "*" + _imageFileExtension);
//load the list image list
foreach (string img in images)
{
System.Drawing.Image img1 = System.Drawing.Image.FromFile(img);
imageList1.Images.Add(GetThumbnaiImage(imageList1.ImageSize.Width, img1));
}
//populate the list view
int j = 0;
foreach (string img in images)
{
FileInfo fi = new FileInfo(img);
this.listView1.Items.Add(fi.Name);
this.listView1.Items[j].ImageIndex = j;
j++;
}
//display the list
this.listView1.View = View.LargeIcon;
this.listView1.LargeImageList = imageList1;
}
private Image GetThumbnaiImage(int width, Image img)
{
Image thumb = new Bitmap(width, width);
Image tmp = null;
//If the original image is small than the Thumbnail size, just draw in the center
if (img.Width < width && img.Height < width)
{
using (Graphics g = Graphics.FromImage(thumb))
{
int xoffset = (int)((width - img.Width) / 2);
int yoffset = (int)((width - img.Height) / 2);
g.DrawImage(img, xoffset, yoffset, img.Width, img.Height);
}
}
else //Otherwise we have to get the thumbnail for drawing
{
Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
if (img.Width == img.Height)
{
thumb = img.GetThumbnailImage(width, width, myCallback, IntPtr.Zero);
}
else
{
int k = 0;
int xoffset = 0;
int yoffset = 0;
if (img.Width < img.Height)
{
k = (int)(width * img.Width / img.Height);
tmp = img.GetThumbnailImage(k, width, myCallback, IntPtr.Zero);
xoffset = (int)((width - k) / 2);
}
if (img.Width > img.Height)
{
k = (int)(width * img.Height / img.Width);
tmp = img.GetThumbnailImage(width, k, myCallback, IntPtr.Zero);
yoffset = (int)((width - k) / 2);
}
using (Graphics g = Graphics.FromImage(thumb))
{
g.DrawImage(tmp, xoffset, yoffset, tmp.Width, tmp.Height);
}
}
}
using (Graphics g = Graphics.FromImage(thumb))
{
g.DrawRectangle(Pens.Green, 0, 0, thumb.Width - 1, thumb.Height - 1);
}
return thumb;
}
private bool ThumbnailCallback()
{
return true;
}
#endregion
#region "CONTROL EVENTS"
private void btnSelect_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
picPreview.Image = Image.FromFile(_path + "\\" + listView1.SelectedItems[0].Text);
_isTracking = false;
CreateSelector();
//reset the selector window
_selector.Reset();
//information
lblInfo.Text = "";
picProcessed.Image = null;
picCandidateHist.Image = null;
DisplayHistogram(ref _histTarget, picPreview, picTargetHist);
}
}
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
picPreview.Image = Image.FromFile(_path + "\\" + _count + _imageFileExtension);
picPreview.Refresh();
TrackObject(); //do tracking
_count++; //move to next image
}
else
{
_count = 0;
timer1.Enabled = false;
timer1.Stop();
//MessageBox.Show("Done");
}
}
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();
picProcessed.Image = null;
picProcessed.Refresh();
_histTarget = null;
_histCandidate = null;
picTargetHist.Refresh();
picCandidateHist.Refresh();
lblInfo.Text = "";
_count = 0;
string imagePath = Directory.GetFiles(_path)[0];
Bitmap b = (Bitmap)Image.FromFile(imagePath);
picPreview.Image = b;
FileInfo fi = new FileInfo(imagePath);
_imageFileExtension = fi.Extension;
picPreview.Refresh();
LoadImages();
_trackSequenceCount = this.listView1.Items.Count;
CreateSelector();
Cursor.Current = Cursors.Default;
}
}
private void btnTrack_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer1.Start();
}
#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 = true;
}
}