Commit 0524be05 cuiyadong

提高检测精度

1 个父辈 9e086d51
...@@ -77,7 +77,7 @@ namespace Acc.Img ...@@ -77,7 +77,7 @@ namespace Acc.Img
Mat threshMat = Threshhold(imageMat, thresh); Mat threshMat = Threshhold(imageMat, thresh);
return BitmapConverter.ToBitmap(threshMat); return BitmapConverter.ToBitmap(threshMat);
} }
/// <summary> /// <summary>
/// 获取鼠标位置的元器件特征值 /// 获取鼠标位置的元器件特征值
/// </summary> /// </summary>
...@@ -205,13 +205,14 @@ namespace Acc.Img ...@@ -205,13 +205,14 @@ namespace Acc.Img
/// <returns></returns> /// <returns></returns>
public static int CountItems(ref Image image, int itemArea) public static int CountItems(ref Image image, int itemArea)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); Bitmap bitmap = new Bitmap(image);
Mat imageMat = BitmapConverter.ToMat(bitmap);
Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR); Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR);
Mat grayMat = BitmapConverter.ToMat(new Bitmap(image)); Mat grayMat = BitmapConverter.ToMat(bitmap);
Cv2.CvtColor(grayMat, grayMat, ColorConversionCodes.RGB2GRAY); Cv2.CvtColor(grayMat, grayMat, ColorConversionCodes.RGB2GRAY);
CvBlobs blobs = AutoThreshBlobs(ref grayMat, itemArea); CvBlobs blobs = AutoThreshBlobs(ref grayMat, itemArea,out itemArea);
int totalCount = findCircles(ref imageMat, grayMat, blobs, itemArea); int totalCount = findCircles(ref imageMat, grayMat, blobs, itemArea);
//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;
...@@ -381,9 +382,67 @@ namespace Acc.Img ...@@ -381,9 +382,67 @@ namespace Acc.Img
} }
return Math.Sqrt(avgArea); return Math.Sqrt(avgArea);
} }
//百分比阀值
public static int GetPTileThreshold(Mat hist, double tile = 40)
{
int Y;
double amount = 0, sum = 0;
for (Y = 0; Y < 256; Y++) amount += hist.Get<float>(Y);
for (Y = 0; Y < 256; Y++)
{
sum = sum + hist.Get<float>(Y);
if (sum >= amount * tile / 100) return Y;
}
return -1;
}
//判断直方图是否是双峰的函数
public static bool IsDimodal(double[] histGram)
{
int count = 0;
for (int i = 1; i < 255; i++)
{
if (histGram[i - 1] < histGram[i] && histGram[i + 1] < histGram[i])
{
count++;
if (count > 2) return false;
}
}
if (count == 2)
return true;
else
return false;
}
//基于双峰平均值的阈值
public static int GetIntermodesThreshold(Mat hist)
{
int Y, Iter = 0, Index;
double[] HistGramC = new double[256]; // 基于精度问题,一定要用浮点数来处理,否则得不到正确的结果
double[] HistGramCC = new double[256]; // 求均值的过程会破坏前面的数据,因此需要两份数据
for (Y = 0; Y < 256; Y++)
{
HistGramC[Y] = hist.Get<float>(Y);
HistGramCC[Y] = hist.Get<float>(Y);
}
// 通过三点求均值来平滑直方图
while (IsDimodal(HistGramCC) == false) // 判断是否已经是双峰的图像了
{
HistGramCC[0] = (HistGramC[0] + HistGramC[0] + HistGramC[1]) / 3; // 第一点
for (Y = 1; Y < 255; Y++)
HistGramCC[Y] = (HistGramC[Y - 1] + HistGramC[Y] + HistGramC[Y + 1]) / 3; // 中间的点
HistGramCC[255] = (HistGramC[254] + HistGramC[255] + HistGramC[255]) / 3; // 最后一点
System.Buffer.BlockCopy(HistGramCC, 0, HistGramC, 0, 256 * sizeof(double)); // 备份数据,为下一次迭代做准备
Iter++;
if (Iter >= 10000) return -1; // 似乎直方图无法平滑为双峰的,返回错误代码
}
// 阈值为两峰值的平均值
int[] Peak = new int[2];
for (Y = 1, Index = 0; Y < 255; Y++)
if (HistGramCC[Y - 1] < HistGramCC[Y] && HistGramCC[Y + 1] < HistGramCC[Y]) Peak[Index++] = Y - 1;
return ((Peak[0] + Peak[1]) / 2);
private static CvBlobs AutoThreshBlobs(ref Mat imageMat, int blobArea) }
private static CvBlobs AutoThreshBlobs(ref Mat imageMat,int blobArea,out int standArea)
{ {
Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda
Mat hist = new Mat();//用来接收直方图 Mat hist = new Mat();//用来接收直方图
...@@ -399,14 +458,13 @@ namespace Acc.Img ...@@ -399,14 +458,13 @@ namespace Acc.Img
{ {
total = total + hist.Get<double>(i); total = total + hist.Get<double>(i);
} }
double percent = 0; double percent = 0;
int startIndex = -1; int startIndex = -1;
int endIndex = -1; int endIndex = -1;
for (int i = 0; i < 256; i++)//直方图 for (int i = 0; i < 256; i++)//直方图
{ {
double len = hist.Get<double>(i); double len = hist.Get<double>(i);
if(len > 100) if (len > 100)
{//灰度值的像素数小于100的忽略 {//灰度值的像素数小于100的忽略
percent = percent + len / total; percent = percent + len / total;
if (startIndex == -1) if (startIndex == -1)
...@@ -423,8 +481,13 @@ namespace Acc.Img ...@@ -423,8 +481,13 @@ namespace Acc.Img
} }
int avgIndex = (startIndex + endIndex) / 2; int avgIndex = (startIndex + endIndex) / 2;
//avgIndex = GetIntermodesThreshold(hist);
Mat threshMat = new Mat(); Mat threshMat = new Mat();
Cv2.Threshold(imageMat, threshMat, avgIndex, 255, ThresholdTypes.BinaryInv); Cv2.Threshold(imageMat, threshMat, avgIndex, 255, ThresholdTypes.BinaryInv);
//Mat erodeMat = Mat.Ones(new OpenCvSharp.Size(3, 3), MatType.CV_8UC1);
//Cv2.MorphologyEx(threshMat,threshMat,MorphTypes.Open,erodeMat);
CvBlobs resultBlobs = new CvBlobs(); CvBlobs resultBlobs = new CvBlobs();
resultBlobs.Label(threshMat); resultBlobs.Label(threshMat);
List<CvBlob> autoBlobList = resultBlobs.Values.Where(b => b.Area > blobArea).ToList(); List<CvBlob> autoBlobList = resultBlobs.Values.Where(b => b.Area > blobArea).ToList();
...@@ -432,12 +495,13 @@ namespace Acc.Img ...@@ -432,12 +495,13 @@ namespace Acc.Img
int threshIndex = avgIndex; int threshIndex = avgIndex;
double theArea = blobArea * 0.8; double theArea = blobArea * 0.8;
if (theArea < 1) theArea = 1; if (theArea < 1) theArea = 1;
while (true) while (true)
{ {
//阈值向下走,找满足条件Blob数量最多的 //阈值向下走,找满足条件Blob数量最多的
threshIndex = threshIndex - 1; threshIndex = threshIndex - 1;
Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv); Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv);
//Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, erodeMat);
CvBlobs blobs = new CvBlobs(); CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat); blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList(); List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
...@@ -457,6 +521,7 @@ namespace Acc.Img ...@@ -457,6 +521,7 @@ namespace Acc.Img
//阈值向上走,找满足条件Blob数量最多的 //阈值向上走,找满足条件Blob数量最多的
threshIndex = threshIndex + 1; threshIndex = threshIndex + 1;
Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv); Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv);
//Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, erodeMat);
CvBlobs blobs = new CvBlobs(); CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat); blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList(); List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
...@@ -470,6 +535,64 @@ namespace Acc.Img ...@@ -470,6 +535,64 @@ namespace Acc.Img
break; break;
} }
} }
List<CvBlob> averBlobs = resultBlobs.Values.Where(a => a.Area > blobArea * 0.5 && a.Area < blobArea * 3).ToList();
if (averBlobs.Count != 0 && blobArea < 120)
{
double averArea = averBlobs.Sum(a => a.Area) / averBlobs.Count;
double veri = averBlobs.Sum(a => Math.Pow(a.Area - averArea, 2)) / averBlobs.Count;
double standerdeviation = Math.Sqrt(veri);
standArea = (int)Math.Round(averArea + standerdeviation);
threshIndex = avgIndex;
theArea = (int)Math.Round(averArea - standerdeviation);
while (true)
{
//阈值向下走,找满足条件Blob数量最多的
threshIndex = threshIndex - 1;
Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv);
//Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, erodeMat);
CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
if (blobList.Count > blobCount)
{
resultBlobs = blobs;
blobCount = blobList.Count;
}
else
{
break;
}
}
threshIndex = avgIndex;
while (true)
{
//阈值向上走,找满足条件Blob数量最多的
threshIndex = threshIndex + 1;
Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv);
//Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, erodeMat);
CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
if (blobList.Count > blobCount)
{
resultBlobs = blobs;
blobCount = blobList.Count;
}
else
{
break;
}
}
List<CvBlob> blobL = resultBlobs.Values.Where(a => a.Area > 0 && a.Area < averArea * 3).ToList();
standArea = (int)Math.Round((double)blobL.Sum(a => a.Area) / blobL.Count);
}
else
{
standArea = blobArea;
}
imageMat = threshMat; imageMat = threshMat;
Console.WriteLine(threshIndex + "==== Blob: " + blobCount + " Area:" + theArea); Console.WriteLine(threshIndex + "==== Blob: " + blobCount + " Area:" + theArea);
return resultBlobs; return resultBlobs;
...@@ -486,7 +609,6 @@ namespace Acc.Img ...@@ -486,7 +609,6 @@ namespace Acc.Img
{ {
Mat dst = new Mat(); Mat dst = new Mat();
Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY); Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY);
if (thresh == -1) if (thresh == -1)
{ {
//全局自动二值 化 //全局自动二值 化
...@@ -530,11 +652,12 @@ namespace Acc.Img ...@@ -530,11 +652,12 @@ namespace Acc.Img
{ {
int blobArea = blob.Area; int blobArea = blob.Area;
double minArea = 0.5 * averageArea; double minArea = 0.5 * averageArea;
double k = 1.5;
if (averageArea < 50) if (averageArea < 50)
{ {
minArea = 0.2 * averageArea; minArea = 0.2 * averageArea;
} }
if (blobArea < minArea) if (blobArea < minArea*2/3)
{ {
return 0; return 0;
} }
...@@ -550,8 +673,18 @@ namespace Acc.Img ...@@ -550,8 +673,18 @@ namespace Acc.Img
//{ //{
// return 3; // return 3;
//} //}
int count = (int)((blobArea + 1.5 * averageArea) / (1.5 * averageArea)); int count = 0;
if (count == 0) //if (blobArea < 130)
//{
// count = (int)((blobArea + k * averageArea) / (k * averageArea));
//}
//else
//{
// count = (int)Math.Round((blobArea + k * averageArea) / (k * averageArea));
//}
count = (int)((blobArea + k * averageArea) / (k * averageArea));
if (count == 0 || count == 1)
{ {
count = 1; count = 1;
} }
...@@ -559,7 +692,7 @@ namespace Acc.Img ...@@ -559,7 +692,7 @@ namespace Acc.Img
{ {
return count; return count;
} }
return 1; return 0;
} }
/// <summary> /// <summary>
...@@ -712,10 +845,12 @@ namespace Acc.Img ...@@ -712,10 +845,12 @@ namespace Acc.Img
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, Point2d reelCenter, double oneBlobWidth= -1, double oneBlobRadius = -1)
{ {
SplitItem item = new SplitItem(); SplitItem item = new SplitItem();
int ct = 0;
while (true) while (true)
{ {
bool hasFind = false; bool hasFind = false;
bool hasPixToHandle = false; bool hasPixToHandle = false;
ct += 1;
for (int x = blob.MinX; x< blob.MaxX; x++) for (int x = blob.MinX; x< blob.MaxX; x++)
{ {
for (int y = blob.MinY; y < blob.MaxY; y++) for (int y = blob.MinY; y < blob.MaxY; y++)
...@@ -733,6 +868,7 @@ namespace Acc.Img ...@@ -733,6 +868,7 @@ namespace Acc.Img
hasPixToHandle = true; hasPixToHandle = true;
if (!item.isEnd) if (!item.isEnd)
{ {
//点到圆心的距离
double distanceToCircle = item.minDistanceToCircles(x, y, reelCenter); double distanceToCircle = item.minDistanceToCircles(x, y, reelCenter);
if (distanceToCircle == 0) if (distanceToCircle == 0)
{ {
...@@ -756,9 +892,19 @@ namespace Acc.Img ...@@ -756,9 +892,19 @@ namespace Acc.Img
break; break;
} }
} }
else
{
if (ct > 100)
{
////hasFind = true;
hasPixToHandle = false;
break;
}
}
} }
} }
}
}
if (hasFind) if (hasFind)
{ {
break; break;
...@@ -767,11 +913,12 @@ namespace Acc.Img ...@@ -767,11 +913,12 @@ namespace Acc.Img
if (!hasFind) if (!hasFind)
{ {
item.calOneItem(oneBlobRadius); item.calOneItem(oneBlobRadius);
} }
if (item.isEnd || hasPixToHandle) if (item.isEnd || !hasPixToHandle )
{ {
break; break;
} }
} }
return item; return item;
} }
...@@ -787,6 +934,9 @@ namespace Acc.Img ...@@ -787,6 +934,9 @@ namespace Acc.Img
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(); Mat distanceMat = new Mat();
RediusPt rediusPt, rediusPtOut;
GetCenter(srcMat,out rediusPt);
GetOutContour(srcMat, out rediusPtOut);
Cv2.DistanceTransform(threshMat, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3); Cv2.DistanceTransform(threshMat, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3);
double[,] distanceArr = new double[threshMat.Cols, threshMat.Rows]; double[,] distanceArr = new double[threshMat.Cols, threshMat.Rows];
...@@ -820,28 +970,36 @@ namespace Acc.Img ...@@ -820,28 +970,36 @@ namespace Acc.Img
Console.WriteLine("Start find reel center"); Console.WriteLine("Start find reel center");
Point2d reelCenter = new Point2d(0,0) ; Point2d reelCenter = new Point2d(0,0) ;
//查找中心 ////查找中心
foreach (CvBlob blob in blobs.Values) //foreach (CvBlob blob in blobs.Values)
{ //{
int count = BlobHasItem(avgArea, blob); // int count = BlobHasItem(avgArea, blob);
if (count > 10 && reelCenter.X == 0) // if (count > 10 && reelCenter.X == 0)
{ // {
Point2d center = blob.Centroid; // Point2d center = blob.Centroid;
//中间的圆,查找圆心 // //中间的圆,查找圆心
if (center.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200) // if (center.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
{ // {
reelCenter = center; // reelCenter = center;
srcMat.Line(new OpenCvSharp.Point(center.X-10, center.Y), new OpenCvSharp.Point(center.X+10, center.Y), Scalar.Blue); // srcMat.Line(new OpenCvSharp.Point(center.X - 10, center.Y), new OpenCvSharp.Point(center.X + 10, center.Y), Scalar.Blue);
srcMat.Line(new OpenCvSharp.Point(center.X, center.Y-10), new OpenCvSharp.Point(center.X, center.Y+10), Scalar.Blue); // srcMat.Line(new OpenCvSharp.Point(center.X, center.Y - 10), new OpenCvSharp.Point(center.X, center.Y + 10), Scalar.Blue);
break; // break;
} // }
} // }
} //}
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);
Console.WriteLine("Start find reel Max Radius, max Width"); Console.WriteLine("Start find reel Max Radius, max Width");
//最大 //最大
double maxRadius = 0; double maxRadius = 0;
double maxWidth = 0; double maxWidth = 0;
List<SplitItem> averItem = new List<SplitItem>();
averItem.Clear();
foreach (CvBlob blob in blobs.Values) foreach (CvBlob blob in blobs.Values)
{ {
...@@ -852,13 +1010,13 @@ namespace Acc.Img ...@@ -852,13 +1010,13 @@ namespace Acc.Img
{ {
maxWidth = blob.Rect.Width; maxWidth = blob.Rect.Width;
} }
if (blob.Rect.Height > maxWidth) if (blob.Rect.Height > maxWidth)
{ {
maxWidth = blob.Rect.Height; maxWidth = blob.Rect.Height;
} }
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter); SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter);
averItem.Add(item);
foreach (Circle c in item.circles) foreach (Circle c in item.circles)
{ {
...@@ -870,25 +1028,28 @@ namespace Acc.Img ...@@ -870,25 +1028,28 @@ namespace Acc.Img
} }
} }
} }
//平均半径
double averRadius = averItem.Sum(a => a.circles.Sum(b => b.radius)) / averItem.Sum(a => a.circles.Count);
maxRadius = averRadius*3/2;
//放大宽度,防止误判断 //放大宽度,防止误判断
maxWidth = maxWidth * 1.1; //maxWidth = maxWidth * 1.6;
Console.WriteLine("Start count"); Console.WriteLine("Start count");
int totalCount = 0; int totalCount = 0;
foreach (CvBlob blob in blobs.Values) foreach (CvBlob blob in blobs.Values)
{ {
int count = BlobHasItem(avgArea, blob); int count = BlobHasItem(avgArea, blob);
if(count == 1) if (count == 1)
{ {
//单个元器件 //单个元器件
totalCount = totalCount +1; totalCount = totalCount + 1;
srcMat.Circle((int)blob.Centroid.X, (int)blob.Centroid.Y, (int)maxRadius/2, Scalar.LightGreen); srcMat.Circle((int)blob.Centroid.X, (int)blob.Centroid.Y, (int)maxRadius / 2, Scalar.LightGreen);
} }
else if (count > 1) else if (count > 1)
{ {
if (count > 20) if (count > 20)
{ {
//中间的圆,去除 //中间的圆,去除
if(blob.Centroid.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200) if (blob.Centroid.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
{ {
continue; continue;
} }
...@@ -897,13 +1058,20 @@ namespace Acc.Img ...@@ -897,13 +1058,20 @@ namespace Acc.Img
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius); SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius);
//对所有圆进行分组 //对所有圆进行分组
List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxRadius, reelCenter); List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxRadius, reelCenter);
Scalar color = Scalar.RandomColor(); //Scalar color = Scalar.RandomColor();
blob.Contour.Render(srcMat, color); //blob.Contour.Render(srcMat, color);
foreach (List<Circle> groupCircle in groupCircles) foreach (List<Circle> groupCircle in groupCircles)
{ {
if (groupCircle.Count == 0)
{
continue;
}
Circle c = groupCircle[0]; Circle c = groupCircle[0];
srcMat.Circle(c.x, c.y, (int)c.radius/2, Scalar.Yellow); srcMat.Circle(c.x, c.y, (int)c.radius / 2, Scalar.Yellow);
totalCount = totalCount + 1; totalCount = totalCount + 1;
//foreach (Circle cg in groupCircle) //foreach (Circle cg in groupCircle)
//{ //{
...@@ -919,128 +1087,128 @@ namespace Acc.Img ...@@ -919,128 +1087,128 @@ namespace Acc.Img
} }
//TODO: 测试距离变换,用后删除 ////TODO: 测试距离变换,用后删除
public static Image DistanceTransform(Image image) //public static Image DistanceTransform(Image image)
{ //{
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); // Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Mat gray = new Mat(); // Mat gray = new Mat();
Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY); // Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY);
////开运算 // ////开运算
Mat k1 = Mat.Ones(new OpenCvSharp.Size(1, 1), MatType.CV_8UC1); // Mat k1 = Mat.Ones(new OpenCvSharp.Size(1, 1), MatType.CV_8UC1);
Cv2.MorphologyEx(gray, gray, MorphTypes.Open, k1, new OpenCvSharp.Point(0, 0), 3); // Cv2.MorphologyEx(gray, gray, MorphTypes.Open, k1, new OpenCvSharp.Point(0, 0), 3);
Mat distanceMat = new Mat(); // Mat distanceMat = new Mat();
Mat labels = new Mat() ; // Mat labels = new Mat() ;
Cv2.DistanceTransform(gray, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3) ; // Cv2.DistanceTransform(gray, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3) ;
Cv2.Normalize(distanceMat, gray, 0, 255, NormTypes.MinMax); // Cv2.Normalize(distanceMat, gray, 0, 255, NormTypes.MinMax);
gray.ConvertTo(gray, MatType.CV_8UC1); // gray.ConvertTo(gray, MatType.CV_8UC1);
Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu); // Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu);
Mat colorImg = Mat.Zeros(gray.Size(), MatType.CV_8UC3); // Mat colorImg = Mat.Zeros(gray.Size(), MatType.CV_8UC3);
Cv2.ConnectedComponents(gray, labels, PixelConnectivity.Connectivity8); // Cv2.ConnectedComponents(gray, labels, PixelConnectivity.Connectivity8);
Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>(); // Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
for(int y=0;y<labels.Rows; y++) // for(int y=0;y<labels.Rows; y++)
{ // {
for (int x = 0; x < labels.Cols; x++) // for (int x = 0; x < labels.Cols; x++)
{ // {
int label = labels.At<int>(y, x); // int label = labels.At<int>(y, x);
float distance = distanceMat.At<float>(y, x); // float distance = distanceMat.At<float>(y, x);
SplitItem item = new SplitItem(); // SplitItem item = new SplitItem();
if (blobCircles.ContainsKey(label)) // if (blobCircles.ContainsKey(label))
{ // {
item = blobCircles[label]; // item = blobCircles[label];
} // }
if (distance > item.currentMaxRadius) // if (distance > item.currentMaxRadius)
{ // {
item.currentMaxRadius = distance; // item.currentMaxRadius = distance;
item.centerX = x; // item.centerX = x;
item.centerY = y; // item.centerY = y;
} // }
blobCircles[label] = item; // blobCircles[label] = item;
byte b = (byte)(label % 255); // byte b = (byte)(label % 255);
byte g = 0; // byte g = 0;
if (b < 128 && b>0) // if (b < 128 && b>0)
{ // {
g = (byte)(255 - b); // g = (byte)(255 - b);
} // }
Vec3b color = new Vec3b(b,g,0); // Vec3b color = new Vec3b(b,g,0);
colorImg.Set<Vec3b>(y, x, color); // colorImg.Set<Vec3b>(y, x, color);
} // }
} // }
foreach (SplitItem circle in blobCircles.Values) // foreach (SplitItem circle in blobCircles.Values)
{ // {
circle.calOneItem(-1); // circle.calOneItem(-1);
} // }
while (true) // while (true)
{ // {
for (int y = 0; y < labels.Rows; y++) // for (int y = 0; y < labels.Rows; y++)
{ // {
for (int x = 0; x < labels.Cols; x++) // for (int x = 0; x < labels.Cols; x++)
{ // {
int label = labels.At<int>(y, x); // int label = labels.At<int>(y, x);
if (label == 0) continue; // if (label == 0) continue;
SplitItem item = new SplitItem(); // SplitItem item = new SplitItem();
if (blobCircles.ContainsKey(label)) // if (blobCircles.ContainsKey(label))
{ // {
item = blobCircles[label]; // item = blobCircles[label];
} // }
if (!item.isEnd) // if (!item.isEnd)
{ // {
double distance = distanceMat.At<float>(y, x); // double distance = distanceMat.At<float>(y, x);
//此Blob未结束 // //此Blob未结束
// bool validPoint = item.isValidPoint(x, y); // // bool validPoint = item.isValidPoint(x, y);
bool validPoint = false; // bool validPoint = false;
if (validPoint) // if (validPoint)
{ // {
if (distance > item.currentMaxRadius) // if (distance > item.currentMaxRadius)
{ // {
item.currentMaxRadius = distance; // item.currentMaxRadius = distance;
item.centerX = x; // item.centerX = x;
item.centerY = y; // item.centerY = y;
blobCircles[label] = item; // blobCircles[label] = item;
} // }
} // }
} // }
} // }
} // }
bool needContinue = false; // bool needContinue = false;
foreach (SplitItem circle in blobCircles.Values) // foreach (SplitItem circle in blobCircles.Values)
{ // {
circle.calOneItem(); // circle.calOneItem();
if (!circle.isEnd) // if (!circle.isEnd)
{ // {
needContinue = true; // needContinue = true;
} // }
} // }
if (!needContinue) // if (!needContinue)
{ // {
break; // break;
} // }
} // }
int totalCount = 0; // int totalCount = 0;
foreach (SplitItem item in blobCircles.Values) // foreach (SplitItem item in blobCircles.Values)
{ // {
foreach(Circle circle in item.circles) // foreach(Circle circle in item.circles)
{ // {
Cv2.Circle(colorImg, circle.x, circle.y, (int)circle.radius,Scalar.White); // Cv2.Circle(colorImg, circle.x, circle.y, (int)circle.radius,Scalar.White);
totalCount++; // totalCount++;
} // }
} // }
Console.WriteLine("Total: " + totalCount); // Console.WriteLine("Total: " + totalCount);
return BitmapConverter.ToBitmap(colorImg); // return BitmapConverter.ToBitmap(colorImg);
//dist.SaveImage("d:\\image\\dsitdist1.jpg"); // //dist.SaveImage("d:\\image\\dsitdist1.jpg");
//Cv2.Threshold(dist, dist, 79, 255, ThresholdTypes.Binary); // //Cv2.Threshold(dist, dist, 79, 255, ThresholdTypes.Binary);
//Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR); // //Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR);
//dist.ConvertTo(dist, MatType.CV_8UC1); // //dist.ConvertTo(dist, MatType.CV_8UC1);
//image = BitmapConverter.ToBitmap(dist); // //image = BitmapConverter.ToBitmap(dist);
//return image; // //return image;
} //}
/// <summary> /// <summary>
/// 获取单个元器件的特征 /// 获取单个元器件的特征
...@@ -1071,5 +1239,108 @@ namespace Acc.Img ...@@ -1071,5 +1239,108 @@ namespace Acc.Img
} }
return blobArea; return blobArea;
} }
//获取圆心半径
public struct RediusPt
{
public OpenCvSharp.Point pt;
public int radius;
}
public static bool GetCenter(Mat srcMat, out RediusPt rediusPt)
{
Mat grayMAT = srcMat.Clone();
Cv2.CvtColor(grayMAT, grayMAT, ColorConversionCodes.BGR2GRAY);
Binarizer.Sauvola(grayMAT, grayMAT, 91, 0.1, 61);
Cv2.MedianBlur(grayMAT, grayMAT, 5);
Mat element = Cv2.GetStructuringElement(MorphShapes.Cross, new OpenCvSharp.Size(41, 41));
Cv2.Erode(grayMAT, grayMAT, element);
CvBlobs blobs = new CvBlobs();
blobs.Label(grayMAT);
CvBlob centerMat = null;
Point2d pt;
foreach (CvBlob item in blobs.Values)
{
item.SetMoments();
pt = item.CalcCentroid();
if (pt.X - 3072 * 0.5 < 150 && pt.Y - 3072 * 0.5 < 150 && 3072 * 0.5 - pt.X < 150 && 3072 * 0.5 - pt.Y < 150 && item.Rect.Width < 900)
{
if (centerMat == null)
{
centerMat = item;
}
else if (centerMat.Rect.Width < item.Rect.Width)
{
centerMat = item;
}
}
}
if (centerMat != null)
{
pt = centerMat.CalcCentroid();
rediusPt.pt.X = (int)pt.X;
rediusPt.pt.Y = (int)pt.Y;
if (centerMat.Rect.Width > centerMat.Rect.Height)
rediusPt.radius = (int)Math.Round(centerMat.Rect.Width * 0.5);
else
rediusPt.radius = (int)Math.Round(centerMat.Rect.Height * 0.5);
return true;
}
else
{
rediusPt.radius = -1;
rediusPt.pt = new OpenCvSharp.Point(0, 0);
return false;
}
}
//获取最外轮廓
public static bool GetOutContour(Mat srcMat, out RediusPt rediusPt)
{
Mat grayMAT = srcMat.Clone();
Cv2.CvtColor(grayMAT, grayMAT, ColorConversionCodes.BGR2GRAY);
Binarizer.Sauvola(grayMAT, grayMAT, 91, 0.1, 61);
Cv2.MedianBlur(grayMAT, grayMAT, 5);
Mat element = Cv2.GetStructuringElement(MorphShapes.Cross, new OpenCvSharp.Size(41, 41));
Cv2.Erode(grayMAT, grayMAT, element);
grayMAT = ~grayMAT;
CvBlobs blobs = new CvBlobs();
blobs.Label(grayMAT);
CvBlob centerMat = null;
Point2d pt;
foreach (CvBlob item in blobs.Values)
{
item.SetMoments();
pt = item.CalcCentroid();
if (pt.X - 3072 * 0.5 < 150 && pt.Y - 3072 * 0.5 < 150 && 3072 * 0.5 - pt.X < 150 && 3072 * 0.5 - pt.Y < 150)
{
if (centerMat == null)
{
centerMat = item;
}
else if (centerMat.Rect.Width < item.Rect.Width)
{
centerMat = item;
}
}
}
if (centerMat != null)
{
pt = centerMat.CalcCentroid();
rediusPt.pt.X = (int)pt.X;
rediusPt.pt.Y = (int)pt.Y;
if (centerMat.Rect.Width > centerMat.Rect.Height)
rediusPt.radius = (int)Math.Round(centerMat.Rect.Width * 0.5);
else
rediusPt.radius = (int)Math.Round(centerMat.Rect.Height * 0.5);
return true;
}
else
{
rediusPt.radius = -1;
rediusPt.pt = new OpenCvSharp.Point(0, 0);
return false;
}
}
} }
} }
...@@ -31,13 +31,18 @@ namespace AccImage ...@@ -31,13 +31,18 @@ namespace AccImage
{ {
//与平均半径差值在10%以内,认为OK //与平均半径差值在10%以内,认为OK
double diff = avgRadius - currentMaxRadius; double diff = avgRadius - currentMaxRadius;
if (diff/avgRadius <= 0.4) if (diff/avgRadius <= 0.5)
{ {
isValid = true; isValid = true;
} }
} }
if (isValid) if (isValid)
{ {
if(currentMaxRadius == 0)
{
isEnd = true;
return;
}
Circle circle = new Circle(); Circle circle = new Circle();
if(theFixRadius != -1 && currentMaxRadius > theFixRadius) if(theFixRadius != -1 && currentMaxRadius > theFixRadius)
{ {
...@@ -78,6 +83,8 @@ namespace AccImage ...@@ -78,6 +83,8 @@ namespace AccImage
} }
List<List<Circle>> allGroupCircle = new List<List<Circle>>(); List<List<Circle>> allGroupCircle = new List<List<Circle>>();
List<int> allreadyGroup = new List<int>(); List<int> allreadyGroup = new List<int>();
//List<Circle> groupCircle = new List<Circle>();
//groupCircle.Clear();
while (true) while (true)
{ {
List<Circle> groupCircle = new List<Circle>(); List<Circle> groupCircle = new List<Circle>();
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!