I am trying to create object detection in C# windows form Project using AForge.NET.
I wrote this code:
public void DetectCorners()
{
// Load image and create everything you need for drawing
Bitmap image = new Bitmap(#"C:\Users\ssammour\Desktop\Unbenannt.PNG");
originalPicture.ImageLocation = #"C:\Users\ssammour\Desktop\Unbenannt.PNG";
BlobCounter blobCounter = new BlobCounter();
blobCounter.ProcessImage(image);
Graphics g = this.CreateGraphics();
Blob[] blobs = blobCounter.GetObjectsInformation();
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
Pen redPen = new Pen(Color.Red);
for (int i = 0, n = blobs.Length; i < n; i++)
{
List<IntPoint> corners;
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
{
g.DrawPolygon(redPen, ToPointsArray(corners));
image = new Bitmap(image.Width, image.Height, g);
}
}
// Display
newPicture.Image = image;
}
private System.Drawing.Point[] ToPointsArray(List<IntPoint> points)
{
System.Drawing.Point[] array = new System.Drawing.Point[points.Count];
return array;
}
the result is always Black photo, I don't know why.
I used this photo to try the code:
but still receive a black photo.
any help? and why is that?
and if you please can tell me how can I detect all objects inside the image.
You are not doing anything in ToPointsArray. You are just returning an array of the same length.
You should do something like this instead (I don't know IntPoint):
private System.Drawing.Point[] ToPointsArray(List<IntPoint> points)
{
System.Drawing.Point[] array = new System.Drawing.Point[points.Count];
int i = 0;
foreach (IntPoint p in points)
{
array[i++] = new System.Drawing.Point(p.X, p.Y);
}
return array;
}
Furthermore you are ruining your image in your for loop. This code works:
public void DetectCorners()
{
// Load image and create everything you need for drawing
Bitmap image = new Bitmap(#"C:\Users\ssammour\Desktop\Unbenannt.PNG");
BlobCounter blobCounter = new BlobCounter();
blobCounter.ProcessImage(image);
Bitmap result = new Bitmap(image.Width, image.Height, Graphics.FromImage(image));
Graphics g = Graphics.FromImage(result);
g.DrawImage(image,0,0);
Blob[] blobs = blobCounter.GetObjectsInformation();
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
Pen redPen = new Pen(Color.Red);
for (int i = 0, n = blobs.Length; i < n; i++)
{
List<IntPoint> corners;
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
{
corners.Dump();
g.DrawPolygon(redPen, ToPointsArray(corners, image.Height));
}
}
result.Save(#"c:\result.png", ImageFormat.Png);
}
I get these points:
(0 0),(574 0),(574 398),(0 398)
(161 391),(162 390),(165 393),(165 394)
(301 394),(304 392),(310 398),(303 398)
(552 398),(558 392),(561 392),(562 398)
(155 397),(156 396),(157 398),(155 398)
So, it looks like the BlobCounter doesn't find the blobs you are looking for.
Related
I wrote it like this, but the rectangular bars do not appear. How can I detect these bars?
I specified the problem in the picture.
Thank you..
Bitmap bitmap = (Bitmap)panel1.BackgroundImage;
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinHeight = 1;
blobCounter.MinWidth = 1;
blobCounter.ObjectsOrder = ObjectsOrder.Size;
blobCounter.ProcessImage(bitmap);
Pen yellowPen = new Pen(Color.Red, 6);
Graphics g = Graphics.FromImage(bitmap);
Blob[] blobs = blobCounter.GetObjectsInformation();
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
foreach (var blob in blobs)
{
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);
List<IntPoint> cornerPoints;
if (shapeChecker.IsQuadrilateral(edgePoints, out cornerPoints))
{
if (shapeChecker.CheckPolygonSubType(cornerPoints) == PolygonSubType.RectangledTriangle)
{
List<System.Drawing.Point> Points = new List<System.Drawing.Point>();
foreach (var point in cornerPoints)
{
Points.Add(new System.Drawing.Point(point.X, point.Y));
}
g.DrawPolygon(new Pen(Color.Red, 5.0f), Points.ToArray());
bitmap.Save(#"C:\Users\OkanBerk\Desktop\result.png");
}
}
}
panel1.BackgroundImage = bitmap;
panel1.Invalidate();
https://i.stack.imgur.com/PM4mj.jpg
I currently work on image processing application. I have 'Main' PictureBox as canvas. I want to insert some PictureBox into 'Main' PictureBox and merge all as one Image then save it to png. This is my code. Can anybody help me to acccomplish this task please?
Bitmap bmp = new Bitmap(pictureEdit.Width, pictureEdit.Height);
bmp = (Bitmap)pictureEdit.Image;
foreach (Control c in pictureEdit.Controls)
{
if (c is Functions.pictureEdit)
{
using (var bitmap = new Bitmap(pictureEdit.Image.Width, pictureEdit.Image.Height)) {
using (var canvas = Graphics.FromImage(bitmap)) {
canvas.DrawImage(bmp, new Rectangle(0, 0, pictureEdit.Image.Width, pictureEdit.Image.Height));
canvas.DrawImage(((Functions.pictureEdit)c).img, new Rectangle(0, 0, pictureEdit.Image.Width, pictureEdit.Image.Height));
canvas.Save();
}
bitmap.Save(#"D:\Test\new.png", System.Drawing.Imaging.ImageFormat.Png);
}
}
}
Hope you are okay with Combining images together
Following code does that
private Bitmap CombineBitmap(List lstImages, int width, int height)
{
int iTilesPerWidth = 5;
//create a bitmap to hold the combined image
Bitmap finalImage = new System.Drawing.Bitmap(width, height);
//get a graphics object from the image so we can draw on it
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(finalImage))
{
PointF point1 = new PointF(0, 0);
int nCount = 1;
foreach (Bitmap BM in lstImages)
{
//512, 256
g.DrawImage(BM, point1);
point1.X += BM.Width;
if (nCount % iTilesPerWidth == 0)
{
point1.X = 0;
point1.Y += BM.Height;
}
nCount++;
}
}
return finalImage;
}
I try to write simple shape detection app. I'm using sample from Aforge.net library. But I always get same error:
cannot convert from 'AForge.Point[]' to 'System.Drawing.PointF[]'
I try to change some things in ImageProcess method as well as in ToPointsArray, but effect is always the same. What else can I try? What I do wrong?
Here is code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
ProcessImage((Bitmap)Bitmap.FromFile(openFileDialog1.FileName));
}
catch
{
MessageBox.Show("Załadowanie obrazu niepowiodło się.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void ProcessImage(Bitmap bitmap)
{
//-------------------------------------
BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, bitmap.PixelFormat);
//-------------------------------------
ColorFiltering colorFilter = new ColorFiltering();
colorFilter.Red = new IntRange(0, 64);
colorFilter.Green = new IntRange(0, 64);
colorFilter.Blue = new IntRange(0, 64);
colorFilter.FillOutsideRange = false;
colorFilter.ApplyInPlace(bitmapData);
//-------------------------------------
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinHeight = 5;
blobCounter.MinWidth = 5;
blobCounter.ProcessImage(bitmapData);
Blob[] blobs = blobCounter.GetObjectsInformation();
bitmap.UnlockBits(bitmapData);
//-------------------------------------
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
Graphics g = Graphics.FromImage(bitmap);
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 = blobs.Length; i < n; i++)
{
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
{
List<IntPoint> corners;
// is triangle or quadrilateral
if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
{
// get sub-type
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));
}
}
}
redPen.Dispose();
greenPen.Dispose();
bluePen.Dispose();
brownPen.Dispose();
g.Dispose();
// put new image to clipboard
Clipboard.SetDataObject(bitmap);
// and to picture box
pictureBox1.Image = bitmap;
UpdatePictureBoxPosition();
}
private Point[] ToPointsArray(List<IntPoint> points)
{
Point[] array = new Point[points.Count];
for (int i = 0, n = points.Count; i < n; i++)
{
array[i] = new Point(points[i].X, points[i].Y);
}
return array;
}
Your problem is that AForge have there own Point struct so your ToPointArray method actually returns an Aforge Points array rather than an array of the needed .net Point. The simplest solution is to fully qualify the type you want to use, so your method would become
private System.Drawing.Point[] ToPointsArray(List<IntPoint> points)
{
System.Drawing.Point[] array = new System.Drawing.Point[points.Count];
...
}
Alternatively, if you wanted to save a few characters you could alias the namespace with a using statement at the top of the class.
using NetPoint = System.Drawing.Point;
private NetPoint ToPointsArray(List<IntPoint> points)
{
NetPoint array = new NetPoint[points.Count];
...
}
As a side note this method could be shortened if linq is available to use. For example,
private System.Drawing.Point[] ToPointsArray(List<IntPoint> points)
{
return points.Select(p => new System.Drawing.Point(p.X, p.Y)).ToArray();
}
For me the Aforge rectangle detection gives completely false coordinates.
Here's my code:
public List<System.Drawing.Rectangle> Detect(string path)
{
var image = GetImage(path);
var blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinWidth = 50;
blobCounter.MinHeight = 50;
blobCounter.ProcessImage(image);
var rects = blobCounter.GetObjectsRectangles();
return rects.ToList();
}
public System.Drawing.Bitmap GetImage(string path)
{
BitmapSource bSource = new BitmapImage(new Uri(path));
var image = Helpers.BitmapConverter.GetBitmap(bSource);
return image;
}
and my test image is this:
I've also tried reverting the colors, but nothing seems to help.
I always get just: {X = 16 Y = 42 Width = 51 Height = 141} That is obviously wrong for that rectangle in the image. How do I use Aforge to detect rectangles?
By using the AForge BlobCounter class GetObjectsInformation method.
Using the image provided, a snippet of the code provided in a simple Windows Forms Application with a picture box and a button I was able to detect the rectangle by drawing a lime green line over the original image using the following code.
//after pictureBox1's image has been set to the provided image.
Bitmap image = new Bitmap(pictureBox1.Image);
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinWidth = 50;
blobCounter.MinHeight = 50;
blobCounter.ProcessImage(image);
Blob[] blobs = blobCounter.GetObjectsInformation();
Blob blob = blobs[0];
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
Graphics g = Graphics.FromImage(image);
Pen redPen = new Pen(Color.Red, 2);
Pen greenPen = new Pen(Color.Lime, 2);
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);
List<IntPoint> corners;
if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
{
PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners);
Pen pen;
if (subType == PolygonSubType.Unknown)
{
pen = (corners.Count == 4) ? redPen : redPen;
}
else
{
pen = greenPen;
}
System.Drawing.Point[] array = new System.Drawing.Point[corners.Count];
for (int i = 0, n = corners.Count; i < n; i++)
{
array[i] = new System.Drawing.Point(corners[i].X + 1, corners[i].Y + 1);
}
g.DrawPolygon(pen, array);
}
redPen.Dispose();
greenPen.Dispose();
g.Dispose();
pictureBox1.Image = image;
pictureBox1.Width = image.Width;
pictureBox1.Height = image.Height;
Provided Image
Processed Image
I'm trying to draw on an image
Graphics g = Graphics.FromImage(BWImage);
Pen red = new Pen(Color.Red, 2);
foreach (Blob blob in blobs)
{
List<IntPoint> leftPoints, rightPoints, edgePoints = new List<IntPoint>();
// get blob's edge points
blobCounter.GetBlobsLeftAndRightEdges(blob,
out leftPoints, out rightPoints);
edgePoints.AddRange(leftPoints);
edgePoints.AddRange(rightPoints);
// blob's convex hull
List<IntPoint> hull = hullFinder.FindHull(edgePoints);
g.DrawPolygon(red, ToPointsArray(hull));
}
I get frames from a webcam, and for each frame I do some processing then do that code, but it didn't work, I tried to debug it, I found that the line
Graphics g = Graphics.FromImage(BWImage);
It keeps executing forever without executing any line after it!
Any help please? Thanks.
Here is my code
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();
ProcessImage(bitmap);
}
and the ProcessImage method:
#region Skin Detection
YCbCrFiltering YCbCrFilter = new YCbCrFiltering();
YCbCrFilter.Y = new Range(0, 1);
YCbCrFilter.Cb = new Range(-0.1862745098039216f, 0.0294117647058824f);
YCbCrFilter.Cr = new Range(0.0137254901960784f, 0.2254901960784314f);
// apply the filter
var YCbCrFilteredImage = YCbCrFilter.Apply(bitmap);
#endregion
#region GrayScale
// create grayscale filter (BT709)
Grayscale Gray_filter = new Grayscale(0.2125, 0.7154, 0.0721);
// apply the filter
Bitmap grayImage = Gray_filter.Apply(YCbCrFilteredImage);
Threshold threshold = new Threshold(50);
Bitmap BWImage = threshold.Apply(grayImage);
#endregion
#region Remove noise
// create filter
BlobsFiltering BlobsFilteringfilter = new BlobsFiltering();
// configure filter
BlobsFilteringfilter.CoupledSizeFiltering = true;
BlobsFilteringfilter.MinWidth = 150;
BlobsFilteringfilter.MinHeight = 150;
BlobsFilteringfilter.MaxHeight = 600;
BlobsFilteringfilter.MaxWidth = 600;
// apply the filter
var BWImageFiltered = BlobsFilteringfilter.Apply(BWImage);
#endregion
#region Fill Holes
FillHoles FillHolesfilter = new FillHoles();
FillHolesfilter.MaxHoleHeight = 50;
FillHolesfilter.MaxHoleWidth = 50;
FillHolesfilter.CoupledSizeFiltering = false;
var BWImageFilteredHoles = FillHolesfilter.Apply(BWImageFiltered);
#endregion
#region Contouring
// process image with blob counter
BlobCounter blobCounter = new BlobCounter();
blobCounter.ProcessImage(BWImageFilteredHoles);
Blob[] blobs = blobCounter.GetObjectsInformation();
Graphics g = Graphics.FromImage(BWImageFilteredHoles);
Pen red = new Pen(Color.Red, 2);
// create convex hull searching algorithm
GrahamConvexHull hullFinder = new GrahamConvexHull();
foreach (Blob blob in blobs)
{
List<IntPoint> AllEdgesPoints = new List<IntPoint>();
List<IntPoint> leftPoints, rightPoints, edgePoints = new List<IntPoint>();
// get blob's edge points
blobCounter.GetBlobsLeftAndRightEdges(blob,
out leftPoints, out rightPoints);
edgePoints.AddRange(leftPoints);
edgePoints.AddRange(rightPoints);
// blob's convex hull
List<IntPoint> hull = hullFinder.FindHull(edgePoints);
g.DrawPolygon(red, ToPointsArray(hull));
g.Dispose();
#endregion
pictureBox1.Image = grayImage;
pictureBox2.Image = BWImage;
}
Is there an exception handler around this code that isn't shown? Graphics.FromImage() should be throwing an exception because you're passing an image with an indexed pixel format; Grayscale.Apply() returns an image with Format8bppIndexed, and BlobsFiltering.Apply() would preserve that.
Bottom line, you need to create a new Bitmap with the same size as BWImage, get your Graphics from that, paint BWImage onto the new image, then rectangle your blobs.