// ==========================================================================================================
// Components:
// ==========================================================================================================
private List<Shapes.Component> FindComponentsFunct(Bitmap bitmap)
{
// Locating objects
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinHeight = 8;
blobCounter.MinWidth = 8;
blobCounter.ProcessImage(bitmap);
Blob[] blobs = blobCounter.GetObjectsInformation();
// create convex hull searching algorithm
GrahamConvexHull hullFinder = new GrahamConvexHull();
ClosePointsMergingOptimizer optimizer1 = new ClosePointsMergingOptimizer();
FlatAnglesOptimizer optimizer2 = new FlatAnglesOptimizer();
List<Shapes.Component> Components = new List<Shapes.Component>();
// process each blob
foreach (Blob blob in blobs)
{
List<IntPoint> leftPoints, rightPoints, edgePoints = new List<IntPoint>();
if ((blob.Rectangle.Height > 400) && (blob.Rectangle.Width > 600))
{
break; // The whole image could be a blob, discard that
}
// get blob's edge points
blobCounter.GetBlobsLeftAndRightEdges(blob,
out leftPoints, out rightPoints);
edgePoints.AddRange(leftPoints);
edgePoints.AddRange(rightPoints);
// blob's convex hull
List<IntPoint> Outline = hullFinder.FindHull(edgePoints);
optimizer1.MaxDistanceToMerge = 4;
optimizer2.MaxAngleToKeep = 170F;
Outline = optimizer2.OptimizeShape(Outline);
Outline = optimizer1.OptimizeShape(Outline);
// find Longest line segment
float dist = 0;
LineSegment Longest = new LineSegment(Outline[0], Outline[1]);
LineSegment line;
dist = Longest.Length;
int LongestInd = 0;
for (int i = 1; i < Outline.Count; i++)
{
if (i != Outline.Count - 1)
{
line = new LineSegment(Outline[i], Outline[i + 1]);
}
else
{
// last iteration
if (Outline[i] == Outline[0])
{
break;
}
line = new LineSegment(Outline[i], Outline[0]);
}
if (line.Length > dist)
{
Longest = line;
dist = line.Length;
LongestInd = i;
}
}
// Get the center point of it
AForge.Point LongestCenter = new AForge.Point();
LongestCenter.X = (float)Math.Round((Longest.End.X - Longest.Start.X) / 2.0 + Longest.Start.X);
LongestCenter.Y = (float)Math.Round((Longest.End.Y - Longest.Start.Y) / 2.0 + Longest.Start.Y);
AForge.Point NormalStart = new AForge.Point();
AForge.Point NormalEnd = new AForge.Point();
// Find normal:
// start= longest.start rotated +90deg relative to center
// end= longest.end rotated -90deg and relative to center
// If you rotate point (px, py) around point (ox, oy) by angle theta you'll get:
// p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
// p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy
// cos90 = 0, sin90= 1 =>
// p'x= -(py-oy) + ox= oy-py+ox, p'y= (px-ox)+ oy
NormalStart.X = LongestCenter.Y - Longest.Start.Y + LongestCenter.X;
NormalStart.Y = (Longest.Start.X - LongestCenter.X) + LongestCenter.Y;
// cos-90=0, sin-90= -1 =>
// p'x= (py-oy) + ox
// p'y= -(px-ox)+oy= ox-px+oy
NormalEnd.X = (Longest.Start.Y - LongestCenter.Y) + LongestCenter.X;
NormalEnd.Y = LongestCenter.X - Longest.Start.X + LongestCenter.Y;
// Make line out of the points
Line Normal = Line.FromPoints(NormalStart, NormalEnd);
// Find the furthest intersection to the normal (skip the Longest)
AForge.Point InterSection = new AForge.Point();
AForge.Point Furthest = new AForge.Point();
bool FurhtestAssinged = false;
LineSegment seg;
dist = 0;
for (int i = 0; i < Outline.Count; i++)
{
if (i == LongestInd)
{
continue;
}
if (i != Outline.Count - 1)
{
seg = new LineSegment(Outline[i], Outline[i + 1]);
}
else
{
// last iteration
if (Outline[i] == Outline[0])
{
break;
}
seg = new LineSegment(Outline[i], Outline[0]);
}
if (seg.GetIntersectionWith(Normal) == null)
{
continue;
}
InterSection = (AForge.Point)seg.GetIntersectionWith(Normal);
if (InterSection.DistanceTo(LongestCenter) > dist)
{
Furthest = InterSection;
FurhtestAssinged = true;
dist = InterSection.DistanceTo(LongestCenter);
}
}
// Check, if there is a edge point that is close to the normal even further
AForge.Point fPoint = new AForge.Point();
for (int i = 0; i < Outline.Count; i++)
{
fPoint.X = Outline[i].X;
fPoint.Y = Outline[i].Y;
if (Normal.DistanceToPoint(fPoint) < 1.5)
{
if (fPoint.DistanceTo(LongestCenter) > dist)
{
Furthest = fPoint;
FurhtestAssinged = true;
dist = fPoint.DistanceTo(LongestCenter);
}
}
}
AForge.Point ComponentCenter = new AForge.Point();
if (FurhtestAssinged)
{
// Find the midpoint of LongestCenter and Furthest: This is the centerpoint of component
ComponentCenter.X = (float)Math.Round((LongestCenter.X - Furthest.X) / 2.0 + Furthest.X);
ComponentCenter.Y = (float)Math.Round((LongestCenter.Y - Furthest.Y) / 2.0 + Furthest.Y);
// Alignment is the angle of longest
double Alignment;
if (Math.Abs(Longest.End.X - Longest.Start.X) < 0.001)
{
Alignment = 0;
}
else
{
Alignment = Math.Atan((Longest.End.Y - Longest.Start.Y) / (Longest.End.X - Longest.Start.X));
Alignment = Alignment * 180.0 / Math.PI; // in deg.
}
Components.Add(new Shapes.Component(ComponentCenter, Alignment, Outline, Longest, NormalStart, NormalEnd));
}
}
return Components;
}