Commit 0524be05 cuiyadong

提高检测精度

1 个父辈 9e086d51
......@@ -77,7 +77,7 @@ namespace Acc.Img
Mat threshMat = Threshhold(imageMat, thresh);
return BitmapConverter.ToBitmap(threshMat);
}
/// <summary>
/// 获取鼠标位置的元器件特征值
/// </summary>
......@@ -205,13 +205,14 @@ namespace Acc.Img
/// <returns></returns>
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);
Mat grayMat = BitmapConverter.ToMat(new Bitmap(image));
Mat grayMat = BitmapConverter.ToMat(bitmap);
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);
//imageMat = grayMat;
//int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
image = BitmapConverter.ToBitmap(imageMat);
return totalCount;
......@@ -381,9 +382,67 @@ namespace Acc.Img
}
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 hist = new Mat();//用来接收直方图
......@@ -399,14 +458,13 @@ namespace Acc.Img
{
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)
if (len > 100)
{//灰度值的像素数小于100的忽略
percent = percent + len / total;
if (startIndex == -1)
......@@ -423,8 +481,13 @@ namespace Acc.Img
}
int avgIndex = (startIndex + endIndex) / 2;
//avgIndex = GetIntermodesThreshold(hist);
Mat threshMat = new Mat();
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();
resultBlobs.Label(threshMat);
List<CvBlob> autoBlobList = resultBlobs.Values.Where(b => b.Area > blobArea).ToList();
......@@ -432,12 +495,13 @@ namespace Acc.Img
int threshIndex = avgIndex;
double theArea = blobArea * 0.8;
if (theArea < 1) theArea = 1;
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();
......@@ -457,6 +521,7 @@ namespace Acc.Img
//阈值向上走,找满足条件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();
......@@ -470,6 +535,64 @@ namespace Acc.Img
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;
Console.WriteLine(threshIndex + "==== Blob: " + blobCount + " Area:" + theArea);
return resultBlobs;
......@@ -486,7 +609,6 @@ namespace Acc.Img
{
Mat dst = new Mat();
Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY);
if (thresh == -1)
{
//全局自动二值 化
......@@ -530,11 +652,12 @@ namespace Acc.Img
{
int blobArea = blob.Area;
double minArea = 0.5 * averageArea;
double k = 1.5;
if (averageArea < 50)
{
minArea = 0.2 * averageArea;
}
if (blobArea < minArea)
if (blobArea < minArea*2/3)
{
return 0;
}
......@@ -550,8 +673,18 @@ namespace Acc.Img
//{
// return 3;
//}
int count = (int)((blobArea + 1.5 * averageArea) / (1.5 * averageArea));
if (count == 0)
int 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;
}
......@@ -559,7 +692,7 @@ namespace Acc.Img
{
return count;
}
return 1;
return 0;
}
/// <summary>
......@@ -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)
{
SplitItem item = new SplitItem();
int ct = 0;
while (true)
{
bool hasFind = false;
bool hasPixToHandle = false;
ct += 1;
for (int x = blob.MinX; x< blob.MaxX; x++)
{
for (int y = blob.MinY; y < blob.MaxY; y++)
......@@ -733,6 +868,7 @@ namespace Acc.Img
hasPixToHandle = true;
if (!item.isEnd)
{
//点到圆心的距离
double distanceToCircle = item.minDistanceToCircles(x, y, reelCenter);
if (distanceToCircle == 0)
{
......@@ -756,9 +892,19 @@ namespace Acc.Img
break;
}
}
else
{
if (ct > 100)
{
////hasFind = true;
hasPixToHandle = false;
break;
}
}
}
}
}
}
if (hasFind)
{
break;
......@@ -767,11 +913,12 @@ namespace Acc.Img
if (!hasFind)
{
item.calOneItem(oneBlobRadius);
}
if (item.isEnd || hasPixToHandle)
}
if (item.isEnd || !hasPixToHandle )
{
break;
}
}
return item;
}
......@@ -787,6 +934,9 @@ namespace Acc.Img
public static int findCircles(ref Mat srcMat, Mat threshMat, CvBlobs blobs, int avgArea)
{
Mat distanceMat = new Mat();
RediusPt rediusPt, rediusPtOut;
GetCenter(srcMat,out rediusPt);
GetOutContour(srcMat, out rediusPtOut);
Cv2.DistanceTransform(threshMat, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3);
double[,] distanceArr = new double[threshMat.Cols, threshMat.Rows];
......@@ -820,28 +970,36 @@ namespace Acc.Img
Console.WriteLine("Start find reel center");
Point2d reelCenter = new Point2d(0,0) ;
//查找中心
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob);
if (count > 10 && reelCenter.X == 0)
{
Point2d center = blob.Centroid;
//中间的圆,查找圆心
if (center.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
{
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, center.Y-10), new OpenCvSharp.Point(center.X, center.Y+10), Scalar.Blue);
break;
}
}
}
////查找中心
//foreach (CvBlob blob in blobs.Values)
//{
// int count = BlobHasItem(avgArea, blob);
// if (count > 10 && reelCenter.X == 0)
// {
// Point2d center = blob.Centroid;
// //中间的圆,查找圆心
// if (center.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
// {
// 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, center.Y - 10), new OpenCvSharp.Point(center.X, center.Y + 10), Scalar.Blue);
// 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");
//最大
double maxRadius = 0;
double maxWidth = 0;
List<SplitItem> averItem = new List<SplitItem>();
averItem.Clear();
foreach (CvBlob blob in blobs.Values)
{
......@@ -852,13 +1010,13 @@ namespace Acc.Img
{
maxWidth = blob.Rect.Width;
}
if (blob.Rect.Height > maxWidth)
{
maxWidth = blob.Rect.Height;
}
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter);
averItem.Add(item);
foreach (Circle c in item.circles)
{
......@@ -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");
int totalCount = 0;
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob);
if(count == 1)
if (count == 1)
{
//单个元器件
totalCount = totalCount +1;
srcMat.Circle((int)blob.Centroid.X, (int)blob.Centroid.Y, (int)maxRadius/2, Scalar.LightGreen);
totalCount = totalCount + 1;
srcMat.Circle((int)blob.Centroid.X, (int)blob.Centroid.Y, (int)maxRadius / 2, Scalar.LightGreen);
}
else if (count > 1)
{
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;
}
......@@ -897,13 +1058,20 @@ namespace Acc.Img
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius);
//对所有圆进行分组
List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxRadius, reelCenter);
Scalar color = Scalar.RandomColor();
blob.Contour.Render(srcMat, color);
//Scalar color = Scalar.RandomColor();
//blob.Contour.Render(srcMat, color);
foreach (List<Circle> groupCircle in groupCircles)
{
if (groupCircle.Count == 0)
{
continue;
}
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;
//foreach (Circle cg in groupCircle)
//{
......@@ -919,128 +1087,128 @@ namespace Acc.Img
}
//TODO: 测试距离变换,用后删除
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) ;
////TODO: 测试距离变换,用后删除
//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);
// 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];
}
// 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;
// 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);
}
}
// 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);
}
// 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);
// 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");
// //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;
}
// //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>
/// 获取单个元器件的特征
......@@ -1071,5 +1239,108 @@ namespace Acc.Img
}
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
{
//与平均半径差值在10%以内,认为OK
double diff = avgRadius - currentMaxRadius;
if (diff/avgRadius <= 0.4)
if (diff/avgRadius <= 0.5)
{
isValid = true;
}
}
if (isValid)
{
if(currentMaxRadius == 0)
{
isEnd = true;
return;
}
Circle circle = new Circle();
if(theFixRadius != -1 && currentMaxRadius > theFixRadius)
{
......@@ -78,6 +83,8 @@ namespace AccImage
}
List<List<Circle>> allGroupCircle = new List<List<Circle>>();
List<int> allreadyGroup = new List<int>();
//List<Circle> groupCircle = new List<Circle>();
//groupCircle.Clear();
while (true)
{
List<Circle> groupCircle = new List<Circle>();
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!