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.
Related
I am using aforge dll to detect rectangles on an image.
Example:
static void Main(string[] args)
{
string path = "rectangles.png";
Bitmap image = (Bitmap)Bitmap.FromFile(path);
// locating objects
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinHeight = 400;
blobCounter.MinWidth = 600;
blobCounter.ProcessImage(image);
Blob[] blobs = blobCounter.GetObjectsInformation();
// check for rectangles
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
foreach (var blob in blobs)
{
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);
List<IntPoint> cornerPoints;
// use the shape checker to extract the corner points
if (shapeChecker.IsQuadrilateral(edgePoints, out cornerPoints))
{
// only do things if the corners form a rectangle
if (shapeChecker.CheckPolygonSubType(cornerPoints) == PolygonSubType.Rectangle)
{
How do i count how many rectangles there is in here
//List<Point> Points = new List<Point>();
//foreach (var point in cornerPoints)
//{
//}
}
}
}
}
So in the above I want to count and return how many rectangle there are in an image.
So my output should be count = 3 because there are 3 rectangles. How do I count them?
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'm trying to rotate the picture in order to make it look like a 3D effect, I am using the Graphics.DrawImage(Image, Point[]) and I am having a real problem in fixing the new points.
private void button1_Click_1(object sender, EventArgs e)
{
Point[] destinationPoints = {
new Point(200, 20), // destination for upper-left point of
// original
new Point(110, 100), // destination for upper-right point of
// original
new Point(250, 30)}; // destination for lower-left point of
// original
if (pictureBox.Image != null)
{
Image image = new Bitmap(this.imageFiles[(this.selected) % this.imageFiles.Length]);
g = Graphics.FromImage(pictureBox.Image);
// pictureBox.Image = null;
// Draw the image unaltered with its upper-left corner at (0, 0).
// g.DrawImage(image,150, 150);
// Draw the image mapped to the parallelogram.
g.Clear(pictureBox.BackColor);
g.DrawImage(image, destinationPoints);
pictureBox.Refresh();
// Bitmap image2 = new Bitmap(image);
// image = RotateImage(image2,0 );
// g.Dispose();
//pictureBox.Invalidate();
// pictureBox.Image = image2;
};
Any help ?
Example :
I want to find small black squares/rectangles in scanned sheet to:
deskewing image if needed.
remove white page margin.
Input image:
sample image 1 http://us.cdn.persiangig.com/preview/ii2jf6/2.jpg
Output image:
sample image 2 http://us.cdn.persiangig.com/preview/9ntpnc/1.jpg
My code to find square is:
Bitmap pic =(Bitmap) pictureBox1.Image;
// create filter
AForge.Imaging.Filters.Median Medianfilter = new AForge.Imaging.Filters.Median();
// apply the filter
Medianfilter.ApplyInPlace(pic);
Bitmap grayImage;
if (pic.PixelFormat != PixelFormat.Format16bppGrayScale && pic.PixelFormat != PixelFormat.Format8bppIndexed)
{
AForge.Imaging.Filters.Grayscale grayscalefilter = new AForge.Imaging.Filters.Grayscale(0.2125, 0.7154, 0.0721);
grayImage = grayscalefilter.Apply((Bitmap)pictureBox1.Image);
}
else
{
grayImage = pic;
}
// black & white:
Threshold(ref grayImage, Convert.ToInt32(textBox1.Text), Convert.ToInt32(textBox1.Text));
// invert filter
Invert invertfilter = new Invert();
// apply the filter
invertfilter.ApplyInPlace(grayImage);
// Edge Detector filter
DifferenceEdgeDetector EdgeDetectorfilter = new DifferenceEdgeDetector();
// apply the filter
EdgeDetectorfilter.ApplyInPlace(grayImage);
// create filter
Dilatation Dilatationfilter = new Dilatation();
// apply the filter
Dilatationfilter.ApplyInPlace(grayImage);
Finding object(square/rectangle) in image:
// lock image
BitmapData bitmapData = grayImage.LockBits(new Rectangle(0, 0, grayImage.Width, grayImage.Height),
ImageLockMode.ReadWrite, grayImage.PixelFormat);
// step 2 - locating objects
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinHeight = 10; //*-*-*-*-
blobCounter.MinWidth = 10;
blobCounter.MaxHeight = 50;
blobCounter.MaxWidth = 50;
blobCounter.ProcessImage(bitmapData);
Blob[] blobs = blobCounter.GetObjectsInformation();
grayImage.UnlockBits(bitmapData);
// step 3 - check objects' type and highlight
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
Graphics g = Graphics.FromImage(pic);
Pen redPen = new Pen(Color.Red, 2); // quadrilateral
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.IsQuadrilateral(edgePoints, out corners))
{
// get sub-type
PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners);
Pen pen;
if (subType == PolygonSubType.Square)
{
pen = (corners.Count == 4) ? bluePen : redPen;
g.DrawPolygon(pen, ToPointsArray(corners));
}
}
}
redPen.Dispose();
bluePen.Dispose();
g.Dispose();
pictureBox1.Image = pic;
Problem is low accuracy on detecting squares and rectangles!!!
How can I solve this problem?
If you can use OpenCV this is quite easy. Use the Hough transform and find peaks in the output. Those correspond to straight lines in your input.
If you can't use OpenCV, you'll need to implement it yourself. Here's something to get you started.
https://en.wikipedia.org/?title=Hough_transform
EDIT
As Anders Gustafsson points out in the comment below, the Hough Transform is available in AForge for .NET so implementing it yourself isn't a necessity.
http://www.aforgenet.com/framework/features/hough_transformation.html
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