This post is about how to use the AForge API to recognize simple shapes. These shapes are poorly drawn on a paper and were captured on my camera.
CameraHandler
This class is used to list our connected cameras and update frames. I gues it’s selfexplaining.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using AForge.Video; using AForge.Video.DirectShow; namespace CameraTesting { class CameraHandler { private FilterInfoCollection videoDevices = null; private VideoCaptureDevice videoSource = null; private PictureBox pbCamPreview = null; private Bitmap currentImage= null; // initialize with picturebox - used to load new frames later on public CameraHandler(PictureBox pbCamPreview) { this.pbCamPreview = pbCamPreview; } public Bitmap getSnapshot() { return currentImage; } // this function stops the image capturing public void stopCapture() { if (!(videoSource == null)) if (videoSource.IsRunning) { videoSource.SignalToStop(); videoSource = null; } } // starts the video capturering function public bool startCapture() { try { videoSource.Start(); return true; } catch (Exception e) { return false; } } // sets a VideoSource to capture images public bool setVideoSourceByIndex(int index) { videoSource = null; try { videoSource = new VideoCaptureDevice(videoDevices[index].MonikerString); videoSource.NewFrame += new NewFrameEventHandler(setNewFrame); return true; } catch { return false; } } /* refreshes the list of video sources for further processing and * returns a list of all devices, found on the system */ public FilterInfoCollection refreshCameraList() { videoDevices = null; try { videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); if (videoDevices.Count == 0) throw new ApplicationException(); } catch (ApplicationException) { } return videoDevices; } //eventhandler for every new frame private void setNewFrame(object sender, NewFrameEventArgs eventArgs) { try { currentImage = (Bitmap)eventArgs.Frame.Clone(); //do show image in assigned picturebox pbCamPreview.Image = currentImage; } catch (Exception e) { } } } }
PictureModificator
This class converts a given bitmap to greyscale, removes all surfaces and applies a black background with less color depth. There is also a function which scans the picture for shapes and marks them on the picture itself.
using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; using System.Reflection; using AForge; using AForge.Imaging; using AForge.Imaging.Filters; using AForge.Math.Geometry; namespace CameraTesting { class PictureModificator { private Bitmap currentImage; public PictureModificator(Bitmap currentImage) { this.currentImage = currentImage; } public PictureModificator() { this.currentImage = null; } public bool applySobelEdgeFilter() { if (currentImage != null) { try { // create filter SobelEdgeDetector filter = new SobelEdgeDetector(); // apply the filter filter.ApplyInPlace(currentImage); return true; } catch (Exception e) { } } return false; } public bool applyGrayscale() { if (currentImage != null) { try { // create grayscale filter (BT709) Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); // apply the filter currentImage = filter.Apply(currentImage); return true; } catch (Exception e) { } } return false; } public bool markKnownForms() { if (currentImage != null) { try { Bitmap image = new Bitmap(this.currentImage); // lock image BitmapData bmData = image.LockBits( new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat); // turn background to black ColorFiltering cFilter = new ColorFiltering(); cFilter.Red = new IntRange(0, 64); cFilter.Green = new IntRange(0, 64); cFilter.Blue = new IntRange(0, 64); cFilter.FillOutsideRange = false; cFilter.ApplyInPlace(bmData); // locate objects BlobCounter bCounter = new BlobCounter(); bCounter.FilterBlobs = true; bCounter.MinHeight = 30; bCounter.MinWidth = 30; bCounter.ProcessImage(bmData); Blob[] baBlobs = bCounter.GetObjectsInformation(); image.UnlockBits(bmData); // coloring objects SimpleShapeChecker shapeChecker = new SimpleShapeChecker(); Graphics g = Graphics.FromImage(image); Pen yellowPen = new Pen(Color.Yellow, 2); // circles Pen redPen = new Pen(Color.Red, 2); // quadrilateral Pen brownPen = new Pen(Color.Brown, 2); // quadrilateral with known sub-type Pen greenPen = new Pen(Color.Green, 2); // known triangle Pen bluePen = new Pen(Color.Blue, 2); // triangle for (int i = 0, n = baBlobs.Length; i < n; i++) { List<IntPoint> edgePoints = bCounter.GetBlobsEdgePoints(baBlobs[i]); AForge.Point center; float radius; // is circle ? if (shapeChecker.IsCircle(edgePoints, out center, out radius)) { g.DrawEllipse(yellowPen, (float)(center.X - radius), (float)(center.Y - radius), (float)(radius * 2), (float)(radius * 2)); } else { List<IntPoint> corners; // is triangle or quadrilateral if (shapeChecker.IsConvexPolygon(edgePoints, out corners)) { PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners); Pen pen; if (subType == PolygonSubType.Unknown) { pen = (corners.Count == 4) ? redPen : bluePen; } else { pen = (corners.Count == 4) ? brownPen : greenPen; } g.DrawPolygon(pen, ToPointsArray(corners)); } } } yellowPen.Dispose(); redPen.Dispose(); greenPen.Dispose(); bluePen.Dispose(); brownPen.Dispose(); g.Dispose(); this.currentImage = image; return true; } catch (Exception e) { } } return false; } private System.Drawing.Point[] ToPointsArray(List<IntPoint> points) { System.Drawing.Point[] array = new System.Drawing.Point[points.Count]; for (int i = 0, n = points.Count; i < n; i++) { array[i] = new System.Drawing.Point(points[i].X, points[i].Y); } return array; } public void setCurrentImage(Bitmap currentImage) { this.currentImage = currentImage; } public Bitmap getCurrentImage() { return currentImage; } } }
Example
Here is a example, which shows you how to use those classes.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using AForge.Video; using AForge.Video.DirectShow; namespace CameraTesting { public partial class MainWindow : Form { private CameraHandler myCamHandler = null; private PictureModificator myPicAnalyzer = new PictureModificator(); public MainWindow() { InitializeComponent(); timer1.Start(); } private void Form1_Load(object sender, EventArgs e) { myCamHandler = new CameraHandler(pbCamPreview); setNewListBoxContent(); if (myCamHandler.setVideoSourceByIndex(lstDeviceList.SelectedIndex)) { myCamHandler.startCapture(); } } private void start_Click(object sender, EventArgs e) { if (myCamHandler.setVideoSourceByIndex(lstDeviceList.SelectedIndex)) { myCamHandler.startCapture(); } } public void setNewListBoxContent() { try { lstDeviceList.Items.Clear(); FilterInfoCollection videoDevices = myCamHandler.refreshCameraList(); foreach (FilterInfo device in videoDevices) { lstDeviceList.Items.Add(device.Name); } lstDeviceList.SelectedIndex = 0; //make dafault to first cam } catch (Exception e) { } } private void refresh_Click(object sender, EventArgs e) { setNewListBoxContent(); } private void btnSnapshot_Click(object sender, EventArgs e) { pbSnapshotView.Image = myCamHandler.getSnapshot(); } private void analyzePicture() { try { myPicAnalyzer.setCurrentImage((Bitmap)pbSnapshotView.Image); myPicAnalyzer.applyGrayscale(); myPicAnalyzer.applySobelEdgeFilter(); myPicAnalyzer.markKnownForms(); pbSnapshotView.Image = myPicAnalyzer.getCurrentImage(); } catch (Exception exc) { } } private void btnAnalyze_Click(object sender, EventArgs e) { analyzePicture(); } private void timer1_Tick(object sender, EventArgs e) { pbSnapshotView.Image = myCamHandler.getSnapshot(); analyzePicture(); } } }
Result
My application looks like this:
Real wonderful visual appeal on this web site, I’d value it 10.
Can you send a code of this project.Thanks very much,your work is amazing
Thank you very much, but a couple of these codes was my job, have a problem with a full round objects that are yellow in color There is no shortage here, but I still amber yellow color, which is the number of objects and how do I do wanna get those hollow objects
Can u plz provide a whole project…
Can you send the whole code of this project. This is awesome , Brilliant project.
excellent!!!
Can you please mail me the whole project…
Would you kindly send me the whole code of this project. I really appreciate it
Im sorry, i do not have the source code anymore.
I have found this very useful Thanks
This code is not working properly.Please Give me whole code if possible.Thanks 🙂
Sorry, since these posts are quite old, i do not have the source code anymore, but the description should be enough to get it running again.