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();
}
Related
I am trying to write a shape detection algorithm using Blobcounter with Aforge.Actually I want to get number of all pixels on the edges of the objects with this code but I could not be successfull about writing clearly and I am getting an error:
System.ArgumentOutOfRangeException: 'Index was out of range. It must not be a negative value and must be smaller than the size of the collection.
How can I fix that?
This is the code that I wrote:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using AForge.Imaging;
using System.Runtime.InteropServices;
using AForge.Math.Geometry;
using AForge;
using AForge.Imaging.Filters;
using System.Windows.Forms;
namespace blobdnm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog sfd = new OpenFileDialog();
sfd.Filter = "Image Files|*.bmp|All Files|*.*";
sfd.InitialDirectory = ".";
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
pictureBox1.ImageLocation = sfd.FileName;
}
private void button2_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Image);
BitmapData BmpData1 = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
bmp.UnlockBits(BmpData1);
Grayscale gfilter = new Grayscale(0.2125, 0.7154, 0.0721);
Invert ifilter = new Invert();
BradleyLocalThresholding thfilter = new BradleyLocalThresholding();
bmp = gfilter.Apply(bmp);
thfilter.ApplyInPlace(bmp);
ifilter.ApplyInPlace(bmp);
BitmapData BmpData2 = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BlobCounterBase blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinWidth = 1;
blobCounter.MinHeight = 1;
blobCounter.MaxWidth = 8;
blobCounter.MaxHeight = 8;
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(BmpData2);
blobCounter.ProcessImage(BmpData2);
bmp.UnlockBits(BmpData2);
Blob[] blobs = blobCounter.GetObjectsInformation();
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
Bitmap bmp3 = new Bitmap(bmp.Width, bmp.Height);
Graphics g = Graphics.FromImage(bmp3);
Pen redPen = new Pen(Color.Red, 2);
Pen brownPen = new Pen(Color.Brown, 2);
Pen greenPen = new Pen(Color.Green, 2);
Pen bluePen = new Pen(Color.Blue, 2);
for (int i = 0; i < blobs.Length; i++)
{
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
{
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 : bluePen;
}
else
{
pen = (corners.Count == 4) ? brownPen : greenPen;
}
g.DrawPolygon(pen, ToPointsArray(corners));
}
}
}
redPen.Dispose();
greenPen.Dispose();
bluePen.Dispose();
brownPen.Dispose();
g.Dispose();
Clipboard.SetDataObject(bmp3);
pictureBox1.Image = bmp3;
}
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;
}
}
}
This is the part that I am getting an error.
if (shapeChecker.IsConvexPolygon(edgePoints, out corners))//This is the part of the code that I am getting an error
{
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));
}
}
}
I tried to write a code for detecting elips objects with Aforge blobcounter function but when I want to draw it with graphics I am getting an error.
The error is:
Argument 2:cannot covert from 'AForge.IntPoint' to 'System.Drawing.PointF'.What is the thing that I am doing wrong and how can I fix it?
Here is the code:
namespace blobdnm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog sfd = new OpenFileDialog();
sfd.Filter = "Image Files|*.bmp|All Files|*.*";
sfd.InitialDirectory = ".";
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
pictureBox1.ImageLocation = sfd.FileName;
}
private void button2_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Image);
BitmapData BmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] data = new byte[bmp.Width*bmp.Height*3];
IntPtr ptr = BmpData.Scan0;
Marshal.Copy(ptr, data, 0, data.Length);
for (int i = 0; i < bmp.Width*bmp.Height*3; i=i+3)
{
double a = data[i] * 0.2125 + data[i + 1] * 0.7154 + data[i + 2] *0.0721;
if(a>100)
{
data[i] = 0;
data[i+1] = 0;
data[i+2] = 0;
}
}
Bitmap bmp2 = new Bitmap(bmp.Width,bmp.Height,PixelFormat.Format24bppRgb);
BitmapData BmpData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
Marshal.Copy(data, 0,BmpData2.Scan0, data.Length);
bmp2.UnlockBits(BmpData2);
ColorFiltering colorFilter = new ColorFiltering();
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinWidth = 5;
blobCounter.MinHeight = 5;
blobCounter.MaxWidth = 3000;
blobCounter.MaxHeight = 3000;
blobCounter.ProcessImage(BmpData2);
Blob[] blobs = blobCounter.GetObjectsInformation();
Graphics g = Graphics.FromImage(bmp2);
Pen redPen = new Pen(Color.Red, 2);
List<IntPoint> edgePoints=null;
for (int i = 0; i < blobs.Length; i++)
{
edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
for (int k = 0; k < edgePoints.Count; k++)
{
g.DrawPolygon(redPen, edgePoints[k]); //This is the part that I am getting an error
}
}
redPen.Dispose();
g.Dispose();
pictureBox1.Image = bmp2;
}
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;
}
}
}
You have to convert AForge.IntPoint into System.Drawing.Point and then pass it to Graphics.DrawPolygon() method.
This will do the job:
public System.Drawing.Point ToPoint(IntPoint point)
{
return new System.Drawing.Point(point.X, point.Y);
}
In fact you have method ToPointsArray() doing the same conversion but on the list of IntPoint in your code.
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.
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
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