Commit 5a066174 SK

merge

2 个父辈 c3ea698d aa186f79
...@@ -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;
...@@ -251,6 +252,9 @@ namespace Acc.Img ...@@ -251,6 +252,9 @@ namespace Acc.Img
} }
} }
private static void LabelBlobsInCircle(ref string[] labels, List<CvBlob> blobList, double centerX, double centerY, double radius) private static void LabelBlobsInCircle(ref string[] labels, List<CvBlob> blobList, double centerX, double centerY, double radius)
{ {
int labelCount = 0; int labelCount = 0;
...@@ -378,14 +382,68 @@ namespace Acc.Img ...@@ -378,14 +382,68 @@ namespace Acc.Img
} }
return Math.Sqrt(avgArea); return Math.Sqrt(avgArea);
} }
//百分比阀值
private static CvBlobs AutoThreshBlobs(ref Mat imageMat, int blobArea = -1) 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++)
{ {
if (blobArea == -1) sum = sum + hist.Get<float>(Y);
if (sum >= amount * tile / 100) return Y;
}
return -1;
}
//判断直方图是否是双峰的函数
public static bool IsDimodal(double[] histGram)
{ {
//获取元器件特征时,假定的blob面积 int count = 0;
blobArea = 3; 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,out int standArea)
{
Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda
Mat hist = new Mat();//用来接收直方图 Mat hist = new Mat();//用来接收直方图
int[] channels = new int[] { 0 };//一个通道,初始化为通道0 int[] channels = new int[] { 0 };//一个通道,初始化为通道0
...@@ -400,7 +458,6 @@ namespace Acc.Img ...@@ -400,7 +458,6 @@ 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;
...@@ -423,37 +480,121 @@ namespace Acc.Img ...@@ -423,37 +480,121 @@ namespace Acc.Img
} }
} }
//int avgIndex = (startIndex + endIndex) / 2; int avgIndex = (startIndex + endIndex) / 2;
//Mat threshMat = new Mat();
//Cv2.Threshold(imageMat, threshMat, avgIndex, 255, ThresholdTypes.BinaryInv); //avgIndex = GetIntermodesThreshold(hist);
//CvBlobs resultBlobs = new CvBlobs();
//resultBlobs.Label(threshMat);
//List<CvBlob> autoBlobList = resultBlobs.Values.Where(b => b.Area > blobArea).ToList();
//int blobCount = resultBlobs.Count();
Mat threshMat = new Mat(); Mat threshMat = new Mat();
int blobCount = 0; 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();
int threshIndex = (startIndex + endIndex) / 2; resultBlobs.Label(threshMat);
Console.WriteLine("Avg Thresh: " + threshIndex + " blobArea =" + blobArea); List<CvBlob> autoBlobList = resultBlobs.Values.Where(b => b.Area > blobArea).ToList();
int blobCount = resultBlobs.Count();
int threshIndex = avgIndex;
double theArea = blobArea * 0.8; double theArea = blobArea * 0.8;
if (theArea < 1) theArea = 1; if (theArea < 1) theArea = 1;
for (int index = startIndex; index < endIndex; index++)
while (true)
{ {
Mat tempThreshMat = new Mat(); //阈值向下走,找满足条件Blob数量最多的
Cv2.Threshold(imageMat, tempThreshMat, threshIndex, 255, ThresholdTypes.BinaryInv); threshIndex = threshIndex - 1;
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(tempThreshMat); 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();
if (blobList.Count > blobCount) if (blobList.Count > blobCount)
{ {
threshMat = tempThreshMat;
threshIndex = index;
resultBlobs = blobs; resultBlobs = blobs;
blobCount = blobList.Count; 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> 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("result thresh: " + threshIndex + "==== Blob: " + blobCount + " Area:" + theArea); Console.WriteLine(threshIndex + "==== Blob: " + blobCount + " Area:" + theArea);
return resultBlobs; return resultBlobs;
} }
...@@ -468,7 +609,6 @@ namespace Acc.Img ...@@ -468,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)
{ {
//全局自动二值 化 //全局自动二值 化
...@@ -512,11 +652,12 @@ namespace Acc.Img ...@@ -512,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;
} }
...@@ -532,8 +673,18 @@ namespace Acc.Img ...@@ -532,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;
} }
...@@ -541,7 +692,7 @@ namespace Acc.Img ...@@ -541,7 +692,7 @@ namespace Acc.Img
{ {
return count; return count;
} }
return 1; return 0;
} }
/// <summary> /// <summary>
...@@ -694,10 +845,12 @@ namespace Acc.Img ...@@ -694,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++)
...@@ -715,6 +868,7 @@ namespace Acc.Img ...@@ -715,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)
{ {
...@@ -738,9 +892,19 @@ namespace Acc.Img ...@@ -738,9 +892,19 @@ namespace Acc.Img
break; break;
} }
} }
else
{
if (ct > 100)
{
////hasFind = true;
hasPixToHandle = false;
break;
} }
} }
} }
}
}
if (hasFind) if (hasFind)
{ {
break; break;
...@@ -750,10 +914,11 @@ namespace Acc.Img ...@@ -750,10 +914,11 @@ namespace Acc.Img
{ {
item.calOneItem(oneBlobRadius); item.calOneItem(oneBlobRadius);
} }
if (item.isEnd || !hasPixToHandle) if (item.isEnd || !hasPixToHandle )
{ {
break; break;
} }
} }
return item; return item;
} }
...@@ -769,6 +934,9 @@ namespace Acc.Img ...@@ -769,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];
...@@ -802,28 +970,36 @@ namespace Acc.Img ...@@ -802,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)
{ {
...@@ -834,13 +1010,13 @@ namespace Acc.Img ...@@ -834,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)
{ {
...@@ -852,40 +1028,62 @@ namespace Acc.Img ...@@ -852,40 +1028,62 @@ 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; if (blob.Centroid.DistanceTo(new Point2d(rediusPt.pt.X,rediusPt.pt.Y)) < rediusPt.radius-10)
srcMat.Circle((int)blob.Centroid.X, (int)blob.Centroid.Y, (int)maxRadius/2, Scalar.LightGreen); {
continue;
}
totalCount = totalCount + 1;
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(reelCenter) < rediusPt.radius)
// {
// continue;
// }
// //if (blob.Centroid.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
// //{
// // continue;
// //}
//}
if (blob.Centroid.DistanceTo(new Point2d(rediusPt.pt.X, rediusPt.pt.Y)) < rediusPt.radius-10)
{ {
continue; continue;
} }
}
//多个元器件,查找 所有圆 //多个元器件,查找 所有圆
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)
//{ //{
...@@ -901,161 +1099,260 @@ namespace Acc.Img ...@@ -901,161 +1099,260 @@ 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 gray = new Mat();
// Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY);
// ////开运算
// 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);
// Mat distanceMat = new Mat();
// Mat labels = new Mat() ;
// Cv2.DistanceTransform(gray, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3) ;
// Cv2.Normalize(distanceMat, gray, 0, 255, NormTypes.MinMax);
// gray.ConvertTo(gray, MatType.CV_8UC1);
// Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu);
// Mat colorImg = Mat.Zeros(gray.Size(), MatType.CV_8UC3);
// Cv2.ConnectedComponents(gray, labels, PixelConnectivity.Connectivity8);
// Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
// for(int y=0;y<labels.Rows; y++)
// {
// for (int x = 0; x < labels.Cols; x++)
// {
// int label = labels.At<int>(y, x);
// float distance = distanceMat.At<float>(y, x);
// SplitItem item = new SplitItem();
// if (blobCircles.ContainsKey(label))
// {
// item = blobCircles[label];
// }
// if (distance > item.currentMaxRadius)
// {
// item.currentMaxRadius = distance;
// item.centerX = x;
// item.centerY = y;
// }
// blobCircles[label] = item;
// byte b = (byte)(label % 255);
// byte g = 0;
// if (b < 128 && b>0)
// {
// g = (byte)(255 - b);
// }
// Vec3b color = new Vec3b(b,g,0);
// colorImg.Set<Vec3b>(y, x, color);
// }
// }
// foreach (SplitItem circle in blobCircles.Values)
// {
// circle.calOneItem(-1);
// }
// while (true)
// {
// for (int y = 0; y < labels.Rows; y++)
// {
// for (int x = 0; x < labels.Cols; x++)
// {
// int label = labels.At<int>(y, x);
// if (label == 0) continue;
// SplitItem item = new SplitItem();
// if (blobCircles.ContainsKey(label))
// {
// item = blobCircles[label];
// }
// if (!item.isEnd)
// {
// double distance = distanceMat.At<float>(y, x);
// //此Blob未结束
// // bool validPoint = item.isValidPoint(x, y);
// bool validPoint = false;
// if (validPoint)
// {
// if (distance > item.currentMaxRadius)
// {
// item.currentMaxRadius = distance;
// item.centerX = x;
// item.centerY = y;
// blobCircles[label] = item;
// }
// }
// }
// }
// }
// bool needContinue = false;
// foreach (SplitItem circle in blobCircles.Values)
// {
// circle.calOneItem();
// if (!circle.isEnd)
// {
// needContinue = true;
// }
// }
// if (!needContinue)
// {
// break;
// }
// }
// int totalCount = 0;
// foreach (SplitItem item in blobCircles.Values)
// {
// foreach(Circle circle in item.circles)
// {
// Cv2.Circle(colorImg, circle.x, circle.y, (int)circle.radius,Scalar.White);
// totalCount++;
// }
// }
// Console.WriteLine("Total: " + totalCount);
// return BitmapConverter.ToBitmap(colorImg);
// //dist.SaveImage("d:\\image\\dsitdist1.jpg");
// //Cv2.Threshold(dist, dist, 79, 255, ThresholdTypes.Binary);
// //Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR);
// //dist.ConvertTo(dist, MatType.CV_8UC1);
// //image = BitmapConverter.ToBitmap(dist);
// //return image;
//}
/// <summary>
/// 获取单个元器件的特征
/// </summary>
/// <param name="image"></param>
/// <param name="markX"></param>
/// <param name="markY"></param>
/// <returns></returns>
public static int GetFeature(ref Image image, int markX, int markY)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Mat gray = new Mat(); Mat dst = new Mat();
Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY); Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY);
////开运算 //全局二值化
Mat k1 = Mat.Ones(new OpenCvSharp.Size(1, 1), MatType.CV_8UC1); Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.BinaryInv);
Cv2.MorphologyEx(gray, gray, MorphTypes.Open, k1, new OpenCvSharp.Point(0, 0), 3); image = BitmapConverter.ToBitmap(dst);
Mat distanceMat = new Mat(); CvBlobs blobs = new CvBlobs();
Mat labels = new Mat() ; blobs.Label(dst);
Cv2.DistanceTransform(gray, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3) ; int blobArea = -1;
foreach(CvBlob blob in blobs.Values) {
Cv2.Normalize(distanceMat, gray, 0, 255, NormTypes.MinMax); if (blob.Rect.Contains(new OpenCvSharp.Point(markX, markY)))
gray.ConvertTo(gray, MatType.CV_8UC1);
Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu);
Mat colorImg = Mat.Zeros(gray.Size(), MatType.CV_8UC3);
Cv2.ConnectedComponents(gray, labels, PixelConnectivity.Connectivity8);
Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
for(int y=0;y<labels.Rows; y++)
{
for (int x = 0; x < labels.Cols; x++)
{
int label = labels.At<int>(y, x);
float distance = distanceMat.At<float>(y, x);
SplitItem item = new SplitItem();
if (blobCircles.ContainsKey(label))
{ {
item = blobCircles[label]; if (blob.Area < blobArea || blobArea == -1)
}
if (distance > item.currentMaxRadius)
{ {
item.currentMaxRadius = distance; blobArea = blob.Area;
item.centerX = x;
item.centerY = y;
} }
blobCircles[label] = item;
byte b = (byte)(label % 255);
byte g = 0;
if (b < 128 && b>0)
{
g = (byte)(255 - b);
} }
Vec3b color = new Vec3b(b,g,0);
colorImg.Set<Vec3b>(y, x, color);
} }
return blobArea;
} }
//获取圆心半径
foreach (SplitItem circle in blobCircles.Values) public struct RediusPt
{ {
circle.calOneItem(-1); public OpenCvSharp.Point pt;
public int radius;
} }
public static bool GetCenter(Mat srcMat, out RediusPt rediusPt)
while (true)
{ {
for (int y = 0; y < labels.Rows; y++) 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)
{ {
for (int x = 0; x < labels.Cols; x++) 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)
{ {
int label = labels.At<int>(y, x); if (centerMat == null)
if (label == 0) continue;
SplitItem item = new SplitItem();
if (blobCircles.ContainsKey(label))
{ {
item = blobCircles[label]; centerMat = item;
} }
if (!item.isEnd) else if (centerMat.Rect.Width < item.Rect.Width)
{ {
double distance = distanceMat.At<float>(y, x); centerMat = item;
//此Blob未结束
// bool validPoint = item.isValidPoint(x, y);
bool validPoint = false;
if (validPoint)
{
if (distance > item.currentMaxRadius)
{
item.currentMaxRadius = distance;
item.centerX = x;
item.centerY = y;
blobCircles[label] = item;
}
}
} }
} }
} }
bool needContinue = false; if (centerMat != null)
foreach (SplitItem circle in blobCircles.Values)
{
circle.calOneItem();
if (!circle.isEnd)
{ {
needContinue = true; pt = centerMat.CalcCentroid();
} rediusPt.pt.X = centerMat.Rect.Width/2+centerMat.Rect.X;
rediusPt.pt.Y = centerMat.Rect.Height/ 2 + centerMat.Rect.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;
} }
if (!needContinue) else
{ {
break; rediusPt.radius = -1;
rediusPt.pt = new OpenCvSharp.Point(0, 0);
return false;
} }
} }
int totalCount = 0; //获取最外轮廓
foreach (SplitItem item in blobCircles.Values) 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)
{ {
foreach(Circle circle in item.circles) if (centerMat == null)
{ {
Cv2.Circle(colorImg, circle.x, circle.y, (int)circle.radius,Scalar.White); centerMat = item;
totalCount++;
} }
else if (centerMat.Rect.Width < item.Rect.Width)
{
centerMat = item;
} }
Console.WriteLine("Total: " + totalCount);
return BitmapConverter.ToBitmap(colorImg);
//dist.SaveImage("d:\\image\\dsitdist1.jpg");
//Cv2.Threshold(dist, dist, 79, 255, ThresholdTypes.Binary);
//Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR);
//dist.ConvertTo(dist, MatType.CV_8UC1);
//image = BitmapConverter.ToBitmap(dist);
//return image;
} }
/// <summary>
/// 获取单个元器件的特征
/// </summary>
/// <param name="image"></param>
/// <param name="markX"></param>
/// <param name="markY"></param>
/// <returns></returns>
public static int GetFeature(ref Image image, int markX, int markY)
{
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Mat dst = new Mat();
Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY);
//全局二值化
//Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.BinaryInv);
//image = BitmapConverter.ToBitmap(dst);
//CvBlobs blobs = new CvBlobs();
//blobs.Label(dst);
CvBlobs blobs = AutoThreshBlobs(ref dst);
image = BitmapConverter.ToBitmap(dst);
int blobArea = -1;
foreach (CvBlob blob in blobs.Values) {
if (blob.Rect.Contains(new OpenCvSharp.Point(markX, markY)))
{
if (blob.Area < blobArea || blobArea == -1)
{
blobArea = blob.Area;
} }
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;
} }
return blobArea;
} }
} }
} }
...@@ -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!