Commit b290e77b SK

分组算法优化

1 个父辈 bf447aef
...@@ -3,11 +3,13 @@ using OpenCvSharp; ...@@ -3,11 +3,13 @@ using OpenCvSharp;
using OpenCvSharp.Blob; using OpenCvSharp.Blob;
using OpenCvSharp.Extensions; using OpenCvSharp.Extensions;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Acc.Img namespace Acc.Img
...@@ -60,14 +62,21 @@ namespace Acc.Img ...@@ -60,14 +62,21 @@ namespace Acc.Img
Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR); Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR);
Mat grayMat = BitmapConverter.ToMat(bitmap); Mat grayMat = BitmapConverter.ToMat(bitmap);
Cv2.CvtColor(grayMat, grayMat, ColorConversionCodes.RGB2GRAY); Cv2.CvtColor(grayMat, grayMat, ColorConversionCodes.RGB2GRAY);
Console.WriteLine("Start Thresh");
Stopwatch sw = new Stopwatch();
sw.Start();
CvBlobs blobs = AutoThreshBlobs(ref grayMat, itemArea); CvBlobs blobs = AutoThreshBlobs(ref grayMat, itemArea);
//CvBlobs blobs = AutoThreshBlobsTask(ref grayMat, itemArea);
sw.Stop();
Console.WriteLine("Thresh End: " + sw.ElapsedMilliseconds + " ms");
int totalCount = findCircles(ref imageMat, grayMat, blobs, itemArea); int totalCount = findCircles(ref imageMat, grayMat, blobs, itemArea);
//imageMat = grayMat; //imageMat = grayMat;
//int totalCount = CountBlobs(blobs, itemArea, ref imageMat); //int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
image = BitmapConverter.ToBitmap(imageMat); image = BitmapConverter.ToBitmap(imageMat);
return totalCount; return totalCount;
} }
/// <summary> /// <summary>
/// 查找Blobs包含的元器件数量 /// 查找Blobs包含的元器件数量
...@@ -79,59 +88,47 @@ namespace Acc.Img ...@@ -79,59 +88,47 @@ namespace Acc.Img
/// <returns></returns> /// <returns></returns>
public static int findCircles(ref Mat srcMat, Mat threshMat, CvBlobs blobs, int avgArea) public static int findCircles(ref Mat srcMat, Mat threshMat, CvBlobs blobs, int avgArea)
{ {
Mat distanceMat = new Mat(); Stopwatch sw = new Stopwatch();
Cv2.DistanceTransform(threshMat, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3); sw.Start();
double[,] distanceArr = new double[threshMat.Cols, threshMat.Rows]; double[,] distanceArr = new double[threshMat.Cols, threshMat.Rows];
Task distanceTask = Task.Factory.StartNew(delegate {
Mat distanceMat = new Mat();
Console.WriteLine("Start to distance array"); Cv2.DistanceTransform(threshMat, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3);
unsafe
{ Console.WriteLine("Start to distance array");
Stopwatch sw = new Stopwatch(); unsafe
sw.Start();
for (int y = 0; y < threshMat.Rows; y++)
{ {
for (int x = 0; x < threshMat.Cols; x++) for (int y = 0; y < threshMat.Rows; y++)
{ {
float* dd = (float*)distanceMat.Ptr(y, x); for (int x = 0; x < threshMat.Cols; x++)
distanceArr[x, y] = dd[0]; {
float* dd = (float*)distanceMat.Ptr(y, x);
distanceArr[x, y] = dd[0];
}
} }
} }
sw.Stop(); });
Console.WriteLine("=" + sw.ElapsedMilliseconds + " ms");
}
Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
Console.WriteLine("Start find reel center");
RediusPt rediusPt, rediusPtOut;
GetCenter(srcMat, out rediusPt);
GetOutContour(srcMat, out rediusPtOut);
Point2d reelCenter = new Point2d(0, 0);
reelCenter.X = rediusPtOut.pt.X;
reelCenter.Y = rediusPtOut.pt.Y;
srcMat.Line(new OpenCvSharp.Point(rediusPtOut.pt.X - 10, rediusPtOut.pt.Y), new OpenCvSharp.Point(rediusPtOut.pt.X + 10, rediusPtOut.pt.Y), Scalar.Blue);
srcMat.Line(new OpenCvSharp.Point(rediusPtOut.pt.X, rediusPtOut.pt.Y - 10), new OpenCvSharp.Point(rediusPtOut.pt.X, rediusPtOut.pt.Y + 10), Scalar.Blue);
srcMat.Circle(rediusPt.pt, (int)rediusPt.radius -10, Scalar.Red);
srcMat.Circle(rediusPtOut.pt, (int)rediusPtOut.radius - 10, Scalar.Red);
Console.WriteLine("Start find reel Max Radius, max Width");
List<double> widths = new List<double>(); List<Circle> resultCircles = new List<Circle>();
List<double> heights = new List<double>(); int totalCount = 0;
List<double> radiusList = new List<double>();
List<Task> oneBlobTasks = new List<Task>(); List<CvBlob> bigBlobs = new List<CvBlob>();
foreach (CvBlob blob in blobs.Values)
{ double maxWidth = 0;
Task task = Task.Factory.StartNew(delegate { double maxHeight = 0;
double maxRadius = 0;
Task findOneBlobTask = Task.Factory.StartNew(delegate {
Console.WriteLine("Start find reel Max Radius, max Width");
List<double> widths = new List<double>();
List<double> heights = new List<double>();
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob); int count = BlobHasItem(avgArea, blob);
if (count == 1) if (count == 1)
{ {
//结果数量+1
Interlocked.Increment(ref totalCount);
var list = blob.Contour.ConvertToPolygon().ToList(); var list = blob.Contour.ConvertToPolygon().ToList();
var minRect = Cv2.MinAreaRect(list); var minRect = Cv2.MinAreaRect(list);
var width = minRect.Size.Width; var width = minRect.Size.Width;
...@@ -143,90 +140,111 @@ namespace Acc.Img ...@@ -143,90 +140,111 @@ namespace Acc.Img
} }
widths.Add(width); widths.Add(width);
heights.Add(height); heights.Add(height);
}
else if(count > 1)
{
bigBlobs.Add(blob);
}
}
maxWidth = GetStandardMax(widths);
maxHeight = GetStandardMax(heights);
});
RediusPt rediusPt, rediusPtOut;
Console.WriteLine("Start find reel center");
GetCenter(srcMat, out rediusPt);
GetOutContour(srcMat, out rediusPtOut);
Point2d reelCenter = new Point2d(0, 0);
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter); reelCenter.X = rediusPtOut.pt.X;
reelCenter.Y = rediusPtOut.pt.Y;
srcMat.Line(new OpenCvSharp.Point(rediusPtOut.pt.X - 10, rediusPtOut.pt.Y), new OpenCvSharp.Point(rediusPtOut.pt.X + 10, rediusPtOut.pt.Y), Scalar.Blue);
srcMat.Line(new OpenCvSharp.Point(rediusPtOut.pt.X, rediusPtOut.pt.Y - 10), new OpenCvSharp.Point(rediusPtOut.pt.X, rediusPtOut.pt.Y + 10), Scalar.Blue);
Task.WaitAll(distanceTask);
Task findMaxRadius = Task.Factory.StartNew(delegate {
List<double> radiusList = new List<double>();
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob);
if (count == 1)
{
//这里只会找一个最大的圆
SplitItem item = findCircleInBlob(distanceArr, blobs, blob);
Scalar color = Scalar.LightGreen; Scalar color = Scalar.LightGreen;
foreach (Circle c in item.circles) foreach (Circle c in item.circles)
{ {
radiusList.Add(c.radius); radiusList.Add(c.radius);
c.color = color;
resultCircles.Add(c);
} }
} }
}); }
oneBlobTasks.Add(task); maxRadius = GetStandardMax(radiusList);
} });
Task.WaitAll(oneBlobTasks.ToArray());
Task.WaitAll(findMaxRadius, findOneBlobTask);
var maxWidth = GetStandardMax(widths);
var maxHeight = GetStandardMax(heights);
var maxRadius = GetStandardMax(radiusList);
Console.WriteLine(maxWidth + " = " + maxHeight + " R=" + maxRadius); Console.WriteLine(maxWidth + " = " + maxHeight + " R=" + maxRadius);
//放大宽度,防止误判断
maxWidth = maxWidth * 1.6;
Console.WriteLine("Start count");
List<Circle> resultCircles = new List<Circle>(); //
List<Task> countTasks = new List<Task>(); SplitItem.DIFF_PERCENT = 0.4;
foreach (CvBlob blob in blobs.Values) if(maxHeight < maxRadius * 2)
{ {
maxHeight = maxRadius * 2;
}
maxWidth = maxWidth * 1.5;
Console.WriteLine("Start count");
Scalar color = Scalar.RandomColor(); //从大到小排序 ,大的先执行
if (blob.Area > 1000) bigBlobs.OrderByDescending(b => b.Area);
{
blob.Contour.Render(srcMat, color);
Cv2.PutText(srcMat, blob.Label + "", new OpenCvSharp.Point(blob.Centroid.X - 40, blob.Centroid.Y + 30), HersheyFonts.HersheyComplex, 1.0, color);
}
Task countTask = Task.Factory.StartNew(delegate List<Task> countTasks = new List<Task>();
foreach (CvBlob blob in bigBlobs)
{
bool isReelCenter = blob.Centroid.DistanceTo(new Point2d(rediusPt.pt.X, rediusPt.pt.Y)) < rediusPt.radius - 10;
if (!isReelCenter)
{ {
int count = BlobHasItem(avgArea, blob); Task countTask = Task.Factory.StartNew(delegate {
if (count >= 1) //多个元器件,查找 所有圆
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, maxWidth, maxRadius);
//对所有圆进行分组
List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxHeight, reelCenter);
foreach (List<Circle> groupCircle in groupCircles)
{ {
if (groupCircle.Count == 0)
bool isReelCenter = blob.Centroid.DistanceTo(new Point2d(rediusPt.pt.X, rediusPt.pt.Y)) < rediusPt.radius - 10;
if (!isReelCenter)
{ {
if (count == 1) continue;
{
Circle c = new Circle();
c.radius = maxRadius;
c.x = (int)blob.Centroid.X;
c.y = (int)blob.Centroid.Y;
resultCircles.Add(c);
}
else
{
//多个元器件,查找 所有圆
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius);
//对所有圆进行分组
List<List<Circle>> groupCircles = item.groupCircles(maxWidth, 2 * maxRadius, reelCenter);
foreach (List<Circle> groupCircle in groupCircles)
{
if (groupCircle.Count == 0)
{
continue;
}
Circle c = groupCircle[0];
c.color = color;
resultCircles.Add(c);
}
}
} }
//resultCircles.AddRange(groupCircle);
Interlocked.Increment(ref totalCount);
resultCircles.Add(groupCircle[0]);
} }
}); });
countTasks.Add(countTask); countTasks.Add(countTask);
} }
}
Task.WaitAll(countTasks.ToArray()); Task.WaitAll(countTasks.ToArray());
foreach (var c in resultCircles) int index = 0;
foreach (var c in resultCircles)
{ {
if(c == null)
{
continue;
}
index++;
srcMat.Circle(c.x, c.y, (int)c.radius, c.color); srcMat.Circle(c.x, c.y, (int)c.radius, c.color);
} }
int totalCount = resultCircles.Count;
Cv2.PutText(srcMat, totalCount + "", new OpenCvSharp.Point(reelCenter.X - 40, reelCenter.Y + 30), HersheyFonts.HersheyComplex, 1.0, Scalar.LightGreen); Cv2.PutText(srcMat, totalCount + "", new OpenCvSharp.Point(reelCenter.X - 40, reelCenter.Y + 30), HersheyFonts.HersheyComplex, 1.0, Scalar.LightGreen);
Console.WriteLine("===========" + totalCount); sw.Stop();
Console.WriteLine("Count: " + totalCount + " Time:" + sw.ElapsedMilliseconds + " ms");
return totalCount; return totalCount;
} }
...@@ -271,7 +289,7 @@ namespace Acc.Img ...@@ -271,7 +289,7 @@ namespace Acc.Img
int avgIndex = (startIndex + endIndex) / 2; int avgIndex = (startIndex + endIndex) / 2;
int blobCount = 0; int blobCount = 0;
int threshIndex = avgIndex; int threshIndex = avgIndex;
double theArea = blobArea * 0.8; double theArea = blobArea * 0.8;
...@@ -280,6 +298,7 @@ namespace Acc.Img ...@@ -280,6 +298,7 @@ namespace Acc.Img
Mat resultMat = new Mat(); Mat resultMat = new Mat();
for (int index = startIndex; index < endIndex; index++) for (int index = startIndex; index < endIndex; index++)
{ {
Console.WriteLine(" Thresh Task " + index);
Mat threshMat = new Mat(); Mat threshMat = new Mat();
Cv2.Threshold(imageMat, threshMat, index, 255, ThresholdTypes.BinaryInv); Cv2.Threshold(imageMat, threshMat, index, 255, ThresholdTypes.BinaryInv);
CvBlobs blobs = new CvBlobs(); CvBlobs blobs = new CvBlobs();
...@@ -298,6 +317,90 @@ namespace Acc.Img ...@@ -298,6 +317,90 @@ namespace Acc.Img
return resultBlobs; return resultBlobs;
} }
private static CvBlobs AutoThreshBlobsTask(ref Mat grayMat, int blobArea)
{
Mat[] mats = new Mat[] { grayMat };//一张图片,初始化
Mat hist = new Mat();//用来接收直方图
int[] channels = new int[] { 0 };//一个通道,初始化为通道0
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,值范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats, channels, mask, hist, 1, histsize, range);//计算灰度图,dim为1 1维
double total = 0;
for (int i = 0; i < 256; i++)//灰度值总数量
{
total = total + hist.Get<double>(i);
}
double percent = 0;
int startIndex = -1;
int endIndex = -1;
for (int i = 0; i < 256; i++)//直方图
{
double len = hist.Get<double>(i);
if (len > 100)
{//灰度值的像素数小于100的忽略
if (startIndex == -1)
{
startIndex = i;
}
endIndex = i - 1;
percent = percent + len / total;
//近似的认为元器件的灰度值 数量占总数的百分比小于10%
if (percent > 0.1)
{
break;
}
}
}
int avgIndex = (startIndex + endIndex) / 2;
int threshIndex = avgIndex;
double theArea = blobArea * 0.8;
if (theArea < 1) theArea = 1;
Console.WriteLine(" Thresh Task Start.. ");
Mat srcMat = grayMat;
List<Task> tasks = new List<Task>();
int index = startIndex;
object lockObj = new object();
int maxBlobCount = 0;
int bestThreshIndex = 0;
CvBlobs resultBlobs = new CvBlobs();
Mat resultMat = new Mat();
for (int i = 0; i < 2; i++)
{
Task task = Task.Factory.StartNew(delegate
{
while (index < endIndex)
{
index = Interlocked.Increment(ref index); ;
Console.WriteLine(" Thresh Task " + index);
Mat threshMat = new Mat();
Cv2.Threshold(srcMat, threshMat, index, 255, ThresholdTypes.BinaryInv);
CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
lock (lockObj)
{
if (blobList.Count > maxBlobCount)
{
maxBlobCount = blobList.Count;
bestThreshIndex = index;
resultBlobs = blobs;
resultMat = threshMat;
}
}
}
});
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("best thresh= " + bestThreshIndex + " Blob: " + resultBlobs.Count + "middle thresh= " + threshIndex + " Area:" + theArea);
return resultBlobs;
}
//获取圆心半径 //获取圆心半径
public struct RediusPt public struct RediusPt
{ {
...@@ -448,7 +551,7 @@ namespace Acc.Img ...@@ -448,7 +551,7 @@ namespace Acc.Img
/// <param name="oneBlobWidth"></param> /// <param name="oneBlobWidth"></param>
/// <param name="oneBlobRadius"></param> /// <param name="oneBlobRadius"></param>
/// <returns></returns> /// <returns></returns>
public static SplitItem findCircleInBlob(double[,] matDistanceArr, CvBlobs blobs, CvBlob blob, Point2d reelCenter, double oneBlobWidth = -1, double oneBlobRadius = -1) public static SplitItem findCircleInBlob(double[,] matDistanceArr, CvBlobs blobs, CvBlob blob, double oneBlobWidth = -1, double oneBlobRadius = -1)
{ {
SplitItem item = new SplitItem(); SplitItem item = new SplitItem();
while (true) while (true)
...@@ -459,7 +562,7 @@ namespace Acc.Img ...@@ -459,7 +562,7 @@ namespace Acc.Img
{ {
for (int y = blob.MinY; y < blob.MaxY; y++) for (int y = blob.MinY; y < blob.MaxY; y++)
{ {
double distance = matDistanceArr[x,y]; double distance = matDistanceArr[x, y];
if (distance > 0) if (distance > 0)
{ {
int label = blobs.GetLabel(x, y); int label = blobs.GetLabel(x, y);
...@@ -471,22 +574,22 @@ namespace Acc.Img ...@@ -471,22 +574,22 @@ namespace Acc.Img
hasPixToHandle = true; hasPixToHandle = true;
if (!item.isEnd) if (!item.isEnd)
{ {
if(distance < SplitItem.DIFF_PERCENT * oneBlobRadius) if (distance < SplitItem.DIFF_PERCENT * oneBlobRadius)
{ {
matDistanceArr[x,y] = 0; matDistanceArr[x, y] = 0;
continue; continue;
} }
//点到圆心的距离 //点到圆心的距离
double distanceToCircle = item.minDistanceToCircles(x, y, reelCenter, oneBlobWidth, oneBlobRadius); double distanceToCircle = item.minDistanceToCircles(x, y, oneBlobWidth, oneBlobRadius);
if (distanceToCircle == 0) if (distanceToCircle == 0)
{ {
matDistanceArr[x,y] = 0; matDistanceArr[x, y] = 0;
continue; continue;
} }
if (distanceToCircle > 0 && distanceToCircle < distance) if (distanceToCircle > 0 && distanceToCircle < distance)
{ {
distance = distanceToCircle; distance = distanceToCircle;
matDistanceArr[x,y] = distance; matDistanceArr[x, y] = distance;
} }
if (distance > item.currentMaxRadius) if (distance > item.currentMaxRadius)
{ {
...@@ -495,41 +598,12 @@ namespace Acc.Img ...@@ -495,41 +598,12 @@ namespace Acc.Img
item.centerY = y; item.centerY = y;
if (oneBlobRadius != -1 && distance >= oneBlobRadius) if (oneBlobRadius != -1 && distance >= oneBlobRadius)
{ {
item.calOneItem(oneBlobRadius); hasFind = true;
//填充1.5倍的方框 Circle circle = item.calOneItem(oneBlobRadius);
int left = (int) (x - oneBlobRadius - SplitItem.DIFF_PERCENT * oneBlobRadius); if (circle != null)
if(left < 0)
{
left = 0;
}
int right = (int)(x + oneBlobRadius + SplitItem.DIFF_PERCENT * oneBlobRadius);
int top = (int)(y - oneBlobRadius - SplitItem.DIFF_PERCENT * oneBlobRadius);
if(top < 0)
{
top = 0;
}
int bottom = (int)(y + oneBlobRadius + SplitItem.DIFF_PERCENT * oneBlobRadius);
for (int rectX=left; rectX<right; rectX++)
{ {
if(right >= matDistanceArr.GetLength(1)) removeCircleFromDistanceArr(ref matDistanceArr, circle.x, circle.y, circle.radius, blob.Label, blobs);
{
break;
}
int len = matDistanceArr.GetLength(0);
for (int rectY = top; rectY < bottom; rectY++)
{
if (rectY >=len)
{
break;
}
int pixLabel = blobs.GetLabel(rectX, rectY);
if (pixLabel == blob.Label)
{
matDistanceArr[rectX,rectY] = 0;
}
}
} }
hasFind = true;
break; break;
} }
} }
...@@ -542,28 +616,50 @@ namespace Acc.Img ...@@ -542,28 +616,50 @@ namespace Acc.Img
break; break;
} }
} }
if (!hasFind) if (!hasFind)
{ {
item.calOneItem(oneBlobRadius); Circle circle = item.calOneItem(oneBlobRadius);
}
if (item.isEnd || !hasPixToHandle) if (circle != null)
{ {
break; removeCircleFromDistanceArr(ref matDistanceArr, circle.x, circle.y, circle.radius, blob.Label, blobs);
}
} }
//if(item.circles.Count > 3000)
//{
// return item;
//}
//单个Blob只查找 最大的一个 //单个Blob只查找 最大的一个
if(oneBlobRadius == -1 && item.circles.Count == 1) if (oneBlobRadius == -1 && item.circles.Count == 1)
{ {
return item; return item;
} }
if (item.isEnd || !hasPixToHandle)
{
break;
}
} }
return item; return item;
} }
private static void removeCircleFromDistanceArr(ref double[,] distanceArr, int x, int y, double radius, int label, CvBlobs blobs)
{
//填充外接正方形
for (int rectX = (int)(x - radius); rectX < (int)(x + radius); rectX++)
{
// int len = distanceArr.GetLength(0);
for (int rectY = (int)(y - radius); rectY < (int)(y + radius); rectY++)
{
// int pixLabel = blobs.GetLabel(rectX, rectY);
//if (pixLabel == label)
{
distanceArr[rectX, rectY] = 0;
}
}
}
}
public static double GetStandardMax(List<double> datas) public static double GetStandardMax(List<double> datas)
{ {
int count = datas.Count; int count = datas.Count;
...@@ -576,8 +672,15 @@ namespace Acc.Img ...@@ -576,8 +672,15 @@ namespace Acc.Img
// 除以数量,然后开方 // 除以数量,然后开方
double std = Math.Sqrt(sum / count); double std = Math.Sqrt(sum / count);
List<double> list = datas.Where(d => Math.Abs(d - avg) < std).ToList(); List<double> list = datas.Where(d => Math.Abs(d - avg) < std).ToList();
if (list.Count > 0)
{
return list.Max();
}
else
{
return avg;
}
return list.Max();
} }
return 0; return 0;
} }
......
...@@ -9,7 +9,7 @@ namespace AccImage ...@@ -9,7 +9,7 @@ namespace AccImage
{ {
public class SplitItem public class SplitItem
{ {
public static double DIFF_PERCENT = 0.5; public static double DIFF_PERCENT = 0.4;
public bool isEnd = false; public bool isEnd = false;
public double avgRadius = 0; public double avgRadius = 0;
public int centerX = 0; public int centerX = 0;
...@@ -17,12 +17,10 @@ namespace AccImage ...@@ -17,12 +17,10 @@ namespace AccImage
public double currentMaxRadius = 0; public double currentMaxRadius = 0;
public List<Circle> circles = new List<Circle>(); public List<Circle> circles = new List<Circle>();
private List<Circle> nearbyCircles = new List<Circle>();
/// <summary> /// <summary>
/// 一遍结束后调用 /// 一遍结束后调用, 返回当前圆是否有效
/// </summary> /// </summary>
public void calOneItem(double theFixRadius=-1) public Circle calOneItem(double theFixRadius=-1)
{ {
//该半径是否有效 //该半径是否有效
bool isValid = false; bool isValid = false;
...@@ -44,7 +42,7 @@ namespace AccImage ...@@ -44,7 +42,7 @@ namespace AccImage
if(currentMaxRadius == 0) if(currentMaxRadius == 0)
{ {
isEnd = true; isEnd = true;
return; return null;
} }
Circle circle = new Circle(); Circle circle = new Circle();
if(theFixRadius != -1 && currentMaxRadius > theFixRadius) if(theFixRadius != -1 && currentMaxRadius > theFixRadius)
...@@ -55,11 +53,6 @@ namespace AccImage ...@@ -55,11 +53,6 @@ namespace AccImage
circle.x = centerX; circle.x = centerX;
circle.y = centerY; circle.y = centerY;
circles.Add(circle); circles.Add(circle);
if(nearbyCircles.Count % 50 == 0)
{
nearbyCircles = nearbyCircles.Where(c => centerX - c.x < 2 * currentMaxRadius).ToList();
}
nearbyCircles.Add(circle);
currentMaxRadius = 0; currentMaxRadius = 0;
centerX = 0; centerX = 0;
centerY = 0; centerY = 0;
...@@ -67,13 +60,14 @@ namespace AccImage ...@@ -67,13 +60,14 @@ namespace AccImage
{ {
avgRadius = circle.radius; avgRadius = circle.radius;
} }
return circle;
} }
else else
{ {
isEnd = true; isEnd = true;
} }
return null;
} }
...@@ -84,46 +78,87 @@ namespace AccImage ...@@ -84,46 +78,87 @@ namespace AccImage
{ {
c.calDistanceToCenter(center); c.calDistanceToCenter(center);
} }
List<List<Circle>> allGroupCircle = new List<List<Circle>>(); //排序
List<int> allreadyGroup = new List<int>(); circles.OrderBy(c => c.distanceToCenter);
//List<Circle> groupCircle = new List<Circle>(); List<List<Circle>> lineCircles = new List<List<Circle>>();
//groupCircle.Clear(); List<int> allreadyLabel = new List<int>();
//与圆心距离在h范围内的分为一组
while (true) while (true)
{ {
List<Circle> groupCircle = new List<Circle>(); List<Circle> lineCircle = new List<Circle>();
Circle labelCircle = null; Circle firstLineCircle = null;
for (int i=0;i<circles.Count; i++) for (int i = 0; i < circles.Count; i++)
{ {
if (!allreadyGroup.Contains(i)) if (!allreadyLabel.Contains(i))
{ {
Circle c = circles[i]; Circle c = circles[i];
if (labelCircle == null) if (firstLineCircle == null)
{ {
labelCircle = c; firstLineCircle = c;
allreadyGroup.Add(i); allreadyLabel.Add(i);
groupCircle.Add(c); lineCircle.Add(c);
} }
else else
{ {
//到圆心的距离差小于H //到圆心的距离差小于H
if (Math.Abs(c.distanceToCenter - labelCircle.distanceToCenter) < h) if (Math.Abs(c.distanceToCenter - firstLineCircle.distanceToCenter) < h)
{ {
//两圆心之间的距离+直径小于W认为是同一个元器件 lineCircle.Add(c);
if (c.distanceToCircle(labelCircle) < w+h*2/3) allreadyLabel.Add(i);
{
groupCircle.Add(c);
allreadyGroup.Add(i);
}
} }
} }
} }
} }
allGroupCircle.Add(groupCircle); lineCircles.Add(lineCircle);
if (allreadyGroup.Count == circles.Count) if (allreadyLabel.Count == circles.Count)
{ {
break; break;
} }
} }
//再按长度划分
List<List<Circle>> allGroupCircle = new List<List<Circle>>();
foreach (var lineCircle in lineCircles)
{
//排序
lineCircle.OrderBy(c => c.x);
List<int> lineAllreadyLabel = new List<int>();
while (true)
{
List<Circle> groupCircle = new List<Circle>();
Scalar color = Scalar.Yellow;
for (int i = 0; i < lineCircle.Count; i++)
{
if (!lineAllreadyLabel.Contains(i))
{
Circle c = lineCircle[i];
//圆心之间的距离+直径小于W认为是同一个元器件
bool inGroup = true;
foreach (var gCircle in groupCircle)
{
if (c.distanceToCircle(gCircle) > w)
{
inGroup = false;
}
}
if (inGroup)
{
c.color = color;
groupCircle.Add(c);
lineAllreadyLabel.Add(i);
}
}
}
allGroupCircle.Add(groupCircle);
if (lineAllreadyLabel.Count == lineCircle.Count)
{
break;
}
}
}
return allGroupCircle; return allGroupCircle;
} }
...@@ -133,14 +168,14 @@ namespace AccImage ...@@ -133,14 +168,14 @@ namespace AccImage
/// <param name="px"></param> /// <param name="px"></param>
/// <param name="py"></param> /// <param name="py"></param>
/// <returns></returns> /// <returns></returns>
public double minDistanceToCircles(int px, int py, Point2d reelCenter, double oneBlobWidth =-1, double oneBlobRadius = -1) public double minDistanceToCircles(int px, int py, double oneBlobWidth =-1, double oneBlobRadius = -1)
{ {
Point2d point = new Point2d(px, py); Point2d point = new Point2d(px, py);
double minDistanceToCircle = -1; double minDistanceToCircle = -1;
List<Circle> neighbourCircles = nearbyCircles; List<Circle> neighbourCircles = circles;
if (oneBlobRadius > 0) if (oneBlobRadius > 0)
{ {
neighbourCircles = nearbyCircles.Where(c => Math.Abs(c.x - px) <= 2 * oneBlobRadius && Math.Abs(c.y - py) <= 2 * oneBlobRadius).ToList(); neighbourCircles = neighbourCircles.Where(c => Math.Abs(c.x - px) <= 2 * oneBlobRadius && Math.Abs(c.y - py) <= 2 * oneBlobRadius).ToList();
} }
foreach (Circle c in neighbourCircles) foreach (Circle c in neighbourCircles)
{ {
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!