How to filter and track colors in C#
Based on the information provided on this page you will be able to implement color filtering and tracking with your C# camera application. As a first step, OZEKI Camera SDK has to be installed and a reference to OzekiSDK.dll has to be added to your Visual Studio project.
You can write a code to recognise the most dominant color in the picture, since the color with the biggest total rectangle area is the most dominant color (Figure 3). The total rectangle area can be calculated by adding the area of every rectangle of a tracked color.
If you count the number of rectangles, you are be able to count the objects with a choosen color (Figure 4). Keep in mind to only count the rectangles with the proper size.
Important: you should study this article in order to find out how to setup your Windows Forms Application correctly.
Getting started
To get started it is recommended to Download and Install the latest version of Ozeki Camera SDK.
After installation you can find the example code discussed in this
page with full source code in the following location on your harddisk with the windows version installed:
C:\Users\user\Documents\Ozeki\Ozeki SDK\Examples\Camera\04_ComputerVision\15_ColorTracking
Download Ozeki Camera SDK:
https://camera-sdk.com/p_6513-download-onvif-ozeki-camera-sdk-for-c-sharp.html
To compile this example you will need Microsoft Visual Studio installed on your computer.
Corporate use of color tracking
Color detection is a great application which can make your business life a lot more easier.
Color detection can be an effective help in public and private environments. For example: if you would like to detect the color of the car stopped at the barrier or if you wish to count the number of red cars in the parking lot or on the highway. By tracking a chosen color you can analyze the movement of unique colored objects.
How to use color filtering and tracking
You are capable to filter any color you choose from the RGB scale. The background of the filtered color can be in any color as well. The movement of the objects with a chosen color can be tracked. You will visually see the tracked colors in the form of moving rectangles. You can read the shape, position and number of rectangles in real time. You can also set the color of the rectangles.
Implement color detection in C#
Some computer vision possibilities which are supplied by the SDK require an extra ToolKit. This ToolKit is the OzekiComputerVision.dll to which a reference has to be added in the project, just like in the case of the OzekiSDK.dll. This dll is responsible for the algorithms and tools which are necessary for the CV (Computer Vision) actions.
Streaming video to the GUI
For detecting colors we advise you to use the ColorTracker
object of the Ozeki Camera SDK. This is an individual object working on it's own.
You need to connect the color detector to the media stream like this:
_connector = new MediaConnector(); _connector.Connect(_camera.VideoChannel, _colorTracker);
_connector.Connect(_colorTracker, _imageProvider); OriginalViewer.SetImageProvider(_imageProvider);
Used Variables in our Example (MainForm.cs)
- OzekiCamera _camera;
Webcamera instance, with the help of this we can get the camera stream. - MediaConnector _connector;
Using this we can connect the mediahandlers - CameraURLBuilderWF _myCameraUrlBuilder;
Make access to all avaiable cameras, which you can select from afterwards. - DrawingImageProvider _imageProvider, _processedImageProvider;
These object instances are connected to the camera stream with a MediaConnector, so you will be able to show the camera stream on your display. - ColorTracker _colorTracker, _colorFilter;
These are the object instances which can do the color detection. They have the following variables each:- Flags that turn on and off color detection functions (you can use both or neither too):
- Filter
- Tracking
- Color (Very important! This sets the detectable color.)
- BackColor (If Filter is true then this is the color of the unfiltered area.)
- DrawColor (If Tracking is true this is the frame color of the rectangles.)
- FillColor (If Tracking is true this is the fill color of the rectangles.)
- DrawThickness (If Tracking is true this is the thickness of the rectangle frames.)
- ObjectsFound (This is the list of the rectangles. Every Rectangle object contains the size and position of the rectangle. By counting the Rectangle objects you get the number of rectangles.)
- Flags that turn on and off color detection functions (you can use both or neither too):
C# code example for color detection
Windows Form |
Windows forms version
MainForm.cs
using Ozeki.Camera; using Ozeki.Media; using Ozeki.Vision; using System; using System.Drawing; using System.Windows.Forms; namespace ColorTracking { public partial class Mainform : Form { private OzekiCamera _camera; MediaConnector _connector; private CameraURLBuilderWF _myCameraUrlBuilder; DrawingImageProvider _imageProvider; DrawingImageProvider _processedImageProvider; ColorTracker _colorTracker; ColorTracker _colorFilter; public Mainform() { InitializeComponent(); _imageProvider = new DrawingImageProvider(); _processedImageProvider = new DrawingImageProvider(); _connector = new MediaConnector(); var data = new CameraURLBuilderData(); _myCameraUrlBuilder = new CameraURLBuilderWF(data); _colorTracker = new ColorTracker(); _colorTracker.DrawColor = Color.Blue; _colorTracker.FillColor = Color.FromArgb(50, Color.Blue); ; _colorTracker.DrawThickness = 5; _colorTracker.ObjectsFound += _colorTracker_ObjectsFound; _colorFilter = new ColorTracker(); _colorFilter.Filter = true; _colorFilter.BackColor = Color.White; OriginalViewer.SetImageProvider(_imageProvider); ProcessedViewer.SetImageProvider(_processedImageProvider); } private void _colorTracker_ObjectsFound(object sender, ColorObjectsFoundArgs e) { } void InvokeGuiThread(Action action) { BeginInvoke(action); } void InitDetectorFields() { InvokeGuiThread(() => { tb_Red.Text = _colorTracker.Color.R.ToString(); tb_Green.Text = _colorTracker.Color.G.ToString(); tb_Blue.Text = _colorTracker.Color.B.ToString(); colorDialog1.Color = _colorTracker.Color; }); } private void Form1_Load(object sender, EventArgs e) { SetVideoViewers(); InitDetectorFields(); } void SetVideoViewers() { OriginalViewer.SetImageProvider(_imageProvider); ProcessedViewer.SetImageProvider(_processedImageProvider); } void Start() { OriginalViewer.Start(); ProcessedViewer.Start(); _camera.Start(); _colorTracker.Start(); _colorFilter.Start(); } private void button_Compose_Click(object sender, EventArgs e) { var result = _myCameraUrlBuilder.ShowDialog(); if (result != DialogResult.OK) return; textBox1.Text = _myCameraUrlBuilder.CameraURL; button_Connect.Enabled = true; } private void button_Connect_Click(object sender, EventArgs e) { if (_camera != null) { _camera.CameraStateChanged -= _camera_CameraStateChanged; _camera.Disconnect(); _connector.Disconnect(_camera.VideoChannel, _imageProvider); _camera = null; } _camera = new OzekiCamera(_myCameraUrlBuilder.CameraURL); _camera.CameraStateChanged += _camera_CameraStateChanged; _connector.Connect(_camera.VideoChannel, _colorTracker); _connector.Connect(_colorTracker, _imageProvider); _connector.Connect(_camera.VideoChannel, _colorFilter); _connector.Connect(_colorFilter, _processedImageProvider); Start(); } private void _camera_CameraStateChanged(object sender, CameraStateEventArgs e) { InvokeGuiThread(() => { if (e.State == CameraState.Connecting) button_Connect.Enabled = false; if (e.State == CameraState.Streaming) button_Disconnect.Enabled = true; if (e.State == CameraState.Disconnected) { button_Disconnect.Enabled = false; button_Connect.Enabled = true; } }); InvokeGuiThread(() => { Lb_state.Text = e.State.ToString(); }); } private void button_Disconnect_Click(object sender, EventArgs e) { OriginalViewer.Stop(); ProcessedViewer.Stop(); _colorTracker.Stop(); _colorFilter.Stop(); _camera.CameraStateChanged -= _camera_CameraStateChanged; _camera.Disconnect(); _connector.Disconnect(_camera.VideoChannel, _colorTracker); _connector.Disconnect(_colorTracker, _imageProvider); _connector.Disconnect(_camera.VideoChannel, _colorFilter); _connector.Disconnect(_colorFilter, _processedImageProvider); _camera.Dispose(); _camera = null; } private void Set_Click(object sender, EventArgs e) { InvokeGuiThread(() => { byte red, green, blue; if (byte.TryParse(tb_Red.Text, out red) && byte.TryParse(tb_Green.Text, out green) && byte.TryParse(tb_Blue.Text, out blue)) { _colorTracker.Color = Color.FromArgb(red, green, blue); _colorFilter.Color = Color.FromArgb(red, green, blue); } }); } private void btn_Color_Click(object sender, EventArgs e) { colorDialog1.ShowDialog(); tb_Red.Text = colorDialog1.Color.R.ToString(); tb_Green.Text = colorDialog1.Color.G.ToString(); tb_Blue.Text = colorDialog1.Color.B.ToString(); _colorTracker.Color = colorDialog1.Color; _colorFilter.Color = colorDialog1.Color; } private void trackingBox_CheckedChanged(object sender, EventArgs e) { if (trackingBox.Checked) _colorTracker.Tracking = true; else _colorTracker.Tracking = false; } } }
GUI
Windows forms version
MainForm.Designer.cs is the code of the GUI
namespace ColorTracking { partial class Mainform { ////// Required designer variable. /// private System.ComponentModel.IContainer components = null; ////// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code ////// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.label1 = new System.Windows.Forms.Label(); this.textBox1 = new System.Windows.Forms.TextBox(); this.button_Compose = new System.Windows.Forms.Button(); this.button_Connect = new System.Windows.Forms.Button(); this.button_Disconnect = new System.Windows.Forms.Button(); this.stateLabel = new System.Windows.Forms.Label(); this.colorDialog1 = new System.Windows.Forms.ColorDialog(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.labelState = new System.Windows.Forms.Label(); this.Lb_state = new System.Windows.Forms.Label(); this.groupBox4 = new System.Windows.Forms.GroupBox(); this.tb_Red = new System.Windows.Forms.TextBox(); this.tb_Green = new System.Windows.Forms.TextBox(); this.tb_Blue = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label(); this.btn_Color = new System.Windows.Forms.Button(); this.label8 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); this.Set = new System.Windows.Forms.Button(); this.label5 = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label(); this.trackingBox = new System.Windows.Forms.CheckBox(); this.ProcessedViewer = new Ozeki.Media.VideoViewerWF(); this.OriginalViewer = new Ozeki.Media.VideoViewerWF(); this.groupBox1.SuspendLayout(); this.groupBox4.SuspendLayout(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(6, 20); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(71, 13); this.label1.TabIndex = 1; this.label1.Text = "Camera URL:"; // // textBox1 // this.textBox1.Location = new System.Drawing.Point(83, 17); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(156, 20); this.textBox1.TabIndex = 2; // // button_Compose // this.button_Compose.Location = new System.Drawing.Point(245, 15); this.button_Compose.Name = "button_Compose"; this.button_Compose.Size = new System.Drawing.Size(75, 23); this.button_Compose.TabIndex = 3; this.button_Compose.Text = "Compose"; this.button_Compose.UseVisualStyleBackColor = true; this.button_Compose.Click += new System.EventHandler(this.button_Compose_Click); // // button_Connect // this.button_Connect.Location = new System.Drawing.Point(83, 43); this.button_Connect.Name = "button_Connect"; this.button_Connect.Size = new System.Drawing.Size(75, 23); this.button_Connect.TabIndex = 4; this.button_Connect.Text = "Connect"; this.button_Connect.UseVisualStyleBackColor = true; this.button_Connect.Click += new System.EventHandler(this.button_Connect_Click); // // button_Disconnect // this.button_Disconnect.Location = new System.Drawing.Point(164, 42); this.button_Disconnect.Name = "button_Disconnect"; this.button_Disconnect.Size = new System.Drawing.Size(75, 23); this.button_Disconnect.TabIndex = 6; this.button_Disconnect.Text = "Disconnect"; this.button_Disconnect.UseVisualStyleBackColor = true; this.button_Disconnect.Click += new System.EventHandler(this.button_Disconnect_Click); // // stateLabel // this.stateLabel.AutoSize = true; this.stateLabel.Location = new System.Drawing.Point(12, 85); this.stateLabel.Name = "stateLabel"; this.stateLabel.Size = new System.Drawing.Size(0, 13); this.stateLabel.TabIndex = 7; // // colorDialog1 // this.colorDialog1.AnyColor = true; this.colorDialog1.FullOpen = true; this.colorDialog1.ShowHelp = true; // // groupBox1 // this.groupBox1.Controls.Add(this.labelState); this.groupBox1.Controls.Add(this.button_Compose); this.groupBox1.Controls.Add(this.button_Disconnect); this.groupBox1.Controls.Add(this.textBox1); this.groupBox1.Controls.Add(this.button_Connect); this.groupBox1.Controls.Add(this.label1); this.groupBox1.Location = new System.Drawing.Point(12, 7); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(325, 100); this.groupBox1.TabIndex = 26; this.groupBox1.TabStop = false; this.groupBox1.Text = "Connection"; // // labelState // this.labelState.AutoSize = true; this.labelState.Location = new System.Drawing.Point(6, 78); this.labelState.Name = "labelState"; this.labelState.Size = new System.Drawing.Size(35, 13); this.labelState.TabIndex = 7; this.labelState.Text = "State:"; // // Lb_state // this.Lb_state.AutoSize = true; this.Lb_state.Location = new System.Drawing.Point(51, 85); this.Lb_state.Name = "Lb_state"; this.Lb_state.Size = new System.Drawing.Size(0, 13); this.Lb_state.TabIndex = 27; // // groupBox4 // this.groupBox4.Controls.Add(this.trackingBox); this.groupBox4.Controls.Add(this.Set); this.groupBox4.Controls.Add(this.label9); this.groupBox4.Controls.Add(this.label8); this.groupBox4.Controls.Add(this.btn_Color); this.groupBox4.Controls.Add(this.label7); this.groupBox4.Controls.Add(this.label4); this.groupBox4.Controls.Add(this.label3); this.groupBox4.Controls.Add(this.label2); this.groupBox4.Controls.Add(this.tb_Blue); this.groupBox4.Controls.Add(this.tb_Green); this.groupBox4.Controls.Add(this.tb_Red); this.groupBox4.Location = new System.Drawing.Point(343, 7); this.groupBox4.Name = "groupBox4"; this.groupBox4.Size = new System.Drawing.Size(325, 100); this.groupBox4.TabIndex = 38; this.groupBox4.TabStop = false; this.groupBox4.Text = "Highlight"; // // tb_Red // this.tb_Red.Location = new System.Drawing.Point(89, 13); this.tb_Red.Name = "tb_Red"; this.tb_Red.Size = new System.Drawing.Size(100, 20); this.tb_Red.TabIndex = 22; // // tb_Green // this.tb_Green.Location = new System.Drawing.Point(89, 40); this.tb_Green.Name = "tb_Green"; this.tb_Green.Size = new System.Drawing.Size(100, 20); this.tb_Green.TabIndex = 23; // // tb_Blue // this.tb_Blue.Location = new System.Drawing.Point(89, 64); this.tb_Blue.Name = "tb_Blue"; this.tb_Blue.Size = new System.Drawing.Size(100, 20); this.tb_Blue.TabIndex = 24; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(6, 17); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(27, 13); this.label2.TabIndex = 26; this.label2.Text = "Red"; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(6, 43); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(36, 13); this.label3.TabIndex = 27; this.label3.Text = "Green"; // // label4 // this.label4.AutoSize = true; this.label4.Location = new System.Drawing.Point(6, 67); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(28, 13); this.label4.TabIndex = 28; this.label4.Text = "Blue"; // // label7 // this.label7.AutoSize = true; this.label7.Location = new System.Drawing.Point(195, 17); this.label7.Name = "label7"; this.label7.Size = new System.Drawing.Size(40, 13); this.label7.TabIndex = 31; this.label7.Text = "(0-255)"; // // btn_Color // this.btn_Color.Location = new System.Drawing.Point(252, 61); this.btn_Color.Name = "btn_Color"; this.btn_Color.Size = new System.Drawing.Size(67, 23); this.btn_Color.TabIndex = 32; this.btn_Color.Text = "Colors"; this.btn_Color.UseVisualStyleBackColor = true; this.btn_Color.Click += new System.EventHandler(this.btn_Color_Click); // // label8 // this.label8.AutoSize = true; this.label8.Location = new System.Drawing.Point(195, 43); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(40, 13); this.label8.TabIndex = 32; this.label8.Text = "(0-255)"; // // label9 // this.label9.AutoSize = true; this.label9.Location = new System.Drawing.Point(195, 67); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(40, 13); this.label9.TabIndex = 33; this.label9.Text = "(0-255)"; // // Set // this.Set.Location = new System.Drawing.Point(252, 10); this.Set.Name = "Set"; this.Set.Size = new System.Drawing.Size(67, 23); this.Set.TabIndex = 29; this.Set.Text = "Set"; this.Set.UseVisualStyleBackColor = true; this.Set.Click += new System.EventHandler(this.Set_Click); // // label5 // this.label5.AutoSize = true; this.label5.Location = new System.Drawing.Point(12, 111); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(45, 13); this.label5.TabIndex = 40; this.label5.Text = "Original:"; // // label6 // this.label6.AutoSize = true; this.label6.Location = new System.Drawing.Point(343, 111); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(60, 13); this.label6.TabIndex = 41; this.label6.Text = "Processed:"; // // trackingBox // this.trackingBox.AutoSize = true; this.trackingBox.Location = new System.Drawing.Point(252, 39); this.trackingBox.Name = "trackingBox"; this.trackingBox.Size = new System.Drawing.Size(68, 17); this.trackingBox.TabIndex = 34; this.trackingBox.Text = "Tracking"; this.trackingBox.UseVisualStyleBackColor = true; this.trackingBox.CheckedChanged += new System.EventHandler(this.trackingBox_CheckedChanged); // // ProcessedViewer // this.ProcessedViewer.BackColor = System.Drawing.Color.Black; this.ProcessedViewer.FlipMode = Ozeki.Media.FlipMode.None; this.ProcessedViewer.FrameStretch = Ozeki.Media.FrameStretch.Uniform; this.ProcessedViewer.FullScreenEnabled = true; this.ProcessedViewer.Location = new System.Drawing.Point(343, 128); this.ProcessedViewer.Name = "ProcessedViewer"; this.ProcessedViewer.RotateAngle = 0; this.ProcessedViewer.Size = new System.Drawing.Size(325, 244); this.ProcessedViewer.TabIndex = 39; this.ProcessedViewer.Text = "videoViewerWF1"; // // OriginalViewer // this.OriginalViewer.BackColor = System.Drawing.Color.Black; this.OriginalViewer.FlipMode = Ozeki.Media.FlipMode.None; this.OriginalViewer.FrameStretch = Ozeki.Media.FrameStretch.Uniform; this.OriginalViewer.FullScreenEnabled = true; this.OriginalViewer.Location = new System.Drawing.Point(12, 128); this.OriginalViewer.Name = "OriginalViewer"; this.OriginalViewer.RotateAngle = 0; this.OriginalViewer.Size = new System.Drawing.Size(325, 244); this.OriginalViewer.TabIndex = 0; this.OriginalViewer.Text = "videoViewerWF1"; // // Mainform // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(676, 378); this.Controls.Add(this.label6); this.Controls.Add(this.label5); this.Controls.Add(this.ProcessedViewer); this.Controls.Add(this.groupBox4); this.Controls.Add(this.Lb_state); this.Controls.Add(this.groupBox1); this.Controls.Add(this.stateLabel); this.Controls.Add(this.OriginalViewer); this.Name = "Mainform"; this.Text = "Color Tracking"; this.Load += new System.EventHandler(this.Form1_Load); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.groupBox4.ResumeLayout(false); this.groupBox4.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private Ozeki.Media.VideoViewerWF OriginalViewer; private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Button button_Compose; private System.Windows.Forms.Button button_Connect; private System.Windows.Forms.Button button_Disconnect; private System.Windows.Forms.Label stateLabel; private System.Windows.Forms.ColorDialog colorDialog1; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Label Lb_state; private System.Windows.Forms.Label labelState; private System.Windows.Forms.GroupBox groupBox4; private System.Windows.Forms.CheckBox trackingBox; private System.Windows.Forms.Button Set; private System.Windows.Forms.Label label9; private System.Windows.Forms.Label label8; private System.Windows.Forms.Button btn_Color; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox tb_Blue; private System.Windows.Forms.TextBox tb_Green; private System.Windows.Forms.TextBox tb_Red; private Ozeki.Media.VideoViewerWF ProcessedViewer; private System.Windows.Forms.Label label5; private System.Windows.Forms.Label label6; } }
Conclusion
With the help of this lecture you can successfully implement color detection with your C# camera application using the Ozeki Camera SDK. After examining this article you will have the needed information to be able to benefit from the color detection function on different fields of analytics.
Related pages
- How to download Ozeki Camera SDK
- How to implement circle detection in C#
- How to implement edge detection in C#
- How to implement corner detection in C#
FAQ
Below you can find the answers for the most frequently asked questions related to this topic:
-
I have not managed to build the solution. How to solve it?
- Please set the Target framework property of the project to .NET 4.0.
- You should add the OzekiSDK.dll to the references of the solution.
- You should add the OzekiComputerVision.dll to the references of the solution.
- Please import the missing classes.
-
What are the hardware requirements?
- 1 GHz or faster processor
- 1GB RAM (32-bit) || 2GB RAM (64-bit)
-
Which OS are supported? Does it work with Windows 10?
Yes, the SDK works with Windows 10. The following Operating Systems are supported:
- Microsoft Windows 10
- Microsoft Windows 8
- Microsoft Windows 7
- Microsoft Windows Server 2016
- Microsoft Windows Server 2019
More information
- How to implement circle detection in C#
- How to accomplish corner detection in C#
- How to detect, filter and track colors in C#
- How to implement edge detection in C#
- How to implement face detection in C#
- How to accomplish line detection in C#
- How to implement Motion detector in C#
- How to implement ObjectTracking in C#
- How to create Rectangle Detector in C#
- How to implement SURF function in C#
- How to measure the width of an object in C#