Commit 6d28a16b 刘韬

1

1 个父辈 e6b8ac30
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace wafer_die_counter
{
internal class BlockTester
{
internal static List<KeyPoint> FindBlock(Mat src)
{
// 创建一个Mat对象
Mat mat = new Mat(src.Size(), MatType.CV_8UC1, new Scalar(255));
List<List<Point>> k = new List<List<Point>>();
// 遍历Mat对象的元素
for (int row = 0; row < mat.Rows; row++)
{
for (int col = 0; col < mat.Cols; col++)
{
// 使用Get方法获取元素值
byte value = mat.Get<byte>(row, col);
byte value2 = src.Get<byte>(row, col);
//Console.WriteLine($"{row},{col} = {value2}");
if (value == 255 && value2==0)
{
Cv2.FloodFill(src, new Point(col,row), new Scalar(125), out Rect rect, Scalar.All(0), Scalar.All(0), FloodFillFlags.Link8);
if (rect.Width == 746)
continue;
List<Point> selectedPixels = new List<Point>();
for (int y = 0; y < src[rect].Rows; y++)
{
for (int x = 0; x < src[rect].Cols; x++)
{
if (src[rect].Get<byte>(y, x) == 125)
{
mat.Set(y+rect.Y,x + rect.X, 125);
selectedPixels.Add(new Point(x + rect.X, y + rect.Y));
}
}
}
k.Add(selectedPixels);
}
}
}
int count = 0;
for (int i = 0; i < k.Count; i++)
{
if (k[i].Count > 10)
{
count = count + 3;
}
if (k[i].Count > 8)
{
count = count + 2;
}
//else if (k[i].Count > 7)
// count = count + 2;
//else if (k[i].Count > 6)
// count = count + 2;
else
count++;
}
// 显示结果图像
Cv2.ImShow("Magic Wand Result", mat);
Cv2.ImWrite("d:\\111.png",mat);
Cv2.ImWrite("d:\\222.png",src);
Cv2.WaitKey(1000000);
return new List<KeyPoint>();
}
}
}
using OpenCvSharp; using OpenCvSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -12,26 +13,39 @@ namespace wafer_die_counter ...@@ -12,26 +13,39 @@ namespace wafer_die_counter
public static Result docount(string srcfile, string resultfile, bool isdebug=false) public static Result docount(string srcfile, string resultfile, bool isdebug=false)
{ {
Result result = new Result(); Result result = new Result();
Stopwatch sw = Stopwatch.StartNew();
try try
{ {
Mat org = Cv2.ImRead(srcfile, ImreadModes.Grayscale); Mat org = Cv2.ImRead(srcfile, ImreadModes.Grayscale);
Mat bgimg = Cv2.ImRead(srcfile, ImreadModes.Color); Mat bgimg = Cv2.ImRead(srcfile, ImreadModes.Color);
var a = Cv2.HoughCircles(org, HoughModes.Gradient, 1, 100, 100, 50, (872-50) / 2, (872+50) / 2);
var c = Cv2.HoughCircles(org, HoughModes.Gradient, 1, 100, 80, 80, 1100 / 2, 1200 / 2); foreach (var circle in a)
{
// 画圆
Cv2.Circle(org, circle.Center.ToPoint(), (int)circle.Radius, new Scalar(0, 255, 0), 2); // 最后一个参数是线条宽度
}
if (isdebug)
ImShow("cycle", org);
//Cv2.WaitKey(100000);
var c = Cv2.HoughCircles(org, HoughModes.Gradient, 1, 100, 80, 80, (1150-50) / 2, (1150+50) / 2);
if (c.Length == 0) if (c.Length == 0)
{ {
result.msg = "未找到圆形"; result.msg = "未找到圆形";
return result; return result;
} }
var radius = (int)c[0].Radius - 40; var radius = (int)c[0].Radius - 50;
Cv2.Circle(org, c[0].Center.ToPoint(), radius, new Scalar(125), 5); Cv2.Circle(org, c[0].Center.ToPoint(), radius, new Scalar(125), 5);
var newp = PointWithAngle(c[0].Center.ToPoint(), 45 + 180, radius); var newp = PointWithAngle(c[0].Center.ToPoint(), 45 + 180, radius);
Cv2.Circle(org, newp, 10, new Scalar(255), 5); Cv2.Circle(org, newp, 10, new Scalar(255), 5);
//ImShow("org", org);
//Cv2.WaitKey(10000);
var sl = CalculateShortSideLength(radius); var sl = CalculateShortSideLength(radius);
var rect = new Rect(newp, new OpenCvSharp.Size(sl * 2, sl * 2)); var rect = new Rect(newp, new OpenCvSharp.Size(sl * 2, sl * 2));
Cv2.Rectangle(org, rect, new Scalar(255), 5);
if (isdebug)
ImShow("cycle", org);
if (org.Width < rect.Width + rect.X if (org.Width < rect.Width + rect.X
|| org.Height < rect.Height + rect.Y) || org.Height < rect.Height + rect.Y)
{ {
...@@ -49,7 +63,7 @@ namespace wafer_die_counter ...@@ -49,7 +63,7 @@ namespace wafer_die_counter
var temp = new Mat(rect.Size, MatType.CV_8U, 0); var temp = new Mat(rect.Size, MatType.CV_8U, 0);
Cv2.Threshold(org[rect], temp, i, 255, ThresholdTypes.Binary); Cv2.Threshold(org[rect], temp, i, 255, ThresholdTypes.Binary);
var avg = temp.Mean().Val0; var avg = temp.Mean().Val0;
if (avg == 255) if (avg >= 254)
{ {
i++; i++;
continue; continue;
...@@ -68,7 +82,7 @@ namespace wafer_die_counter ...@@ -68,7 +82,7 @@ namespace wafer_die_counter
{// 获得分割阈值方法2 {// 获得分割阈值方法2
for (int i = 35; i < 50; i++) for (int i = 35; i < 50; i++)
{ {
var rect2 = new Rect(0, 0, 100, 100);//截取左上角100x100范围 var rect2 = new Rect(0, 0, 110, 110);//截取左上角100x100范围
var temp2 = new Mat(rect2.Size, MatType.CV_8U, 0); var temp2 = new Mat(rect2.Size, MatType.CV_8U, 0);
//获取左上角白色区域二值化后的平均值 //获取左上角白色区域二值化后的平均值
Cv2.Threshold(org[rect][rect2], temp2, i, 255, ThresholdTypes.Binary); Cv2.Threshold(org[rect][rect2], temp2, i, 255, ThresholdTypes.Binary);
...@@ -77,7 +91,7 @@ namespace wafer_die_counter ...@@ -77,7 +91,7 @@ namespace wafer_die_counter
if (avg2 == 0) if (avg2 == 0)
continue; continue;
if (avg2 < 254) if (avg2 < 254.3)
{ {
Threshold2 = i - 1; Threshold2 = i - 1;
break; break;
...@@ -85,7 +99,7 @@ namespace wafer_die_counter ...@@ -85,7 +99,7 @@ namespace wafer_die_counter
} }
} }
Threshold = Math.Max(Threshold1, Threshold2); Threshold = Math.Min(Threshold1, Threshold2);
//Mat output=new Mat(); //Mat output=new Mat();
//Cv2.CalcHist(org[rect].Split(), new int[] { 0}, null, output, 1, new int[] { 255 }, new Rangef[] { new Rangef(0, 255) }); //Cv2.CalcHist(org[rect].Split(), new int[] { 0}, null, output, 1, new int[] { 255 }, new Rangef[] { new Rangef(0, 255) });
//var ii = new float[output.Col(0).Rows]; //var ii = new float[output.Col(0).Rows];
...@@ -106,13 +120,15 @@ namespace wafer_die_counter ...@@ -106,13 +120,15 @@ namespace wafer_die_counter
string txt = $"Threshold:{Threshold1},{Threshold2},C:{c[0].Center.ToPoint()},R:{c[0].Radius}"; string txt = $"Threshold:{Threshold1},{Threshold2},C:{c[0].Center.ToPoint()},R:{c[0].Radius}";
//BlockTester.FindBlock(org[rect]);
#region SimpleBlobDetector.Params #region SimpleBlobDetector.Params
var cparams = new SimpleBlobDetector.Params(); var cparams = new SimpleBlobDetector.Params();
cparams.ThresholdStep = 10; cparams.ThresholdStep = 10;
cparams.FilterByColor = true; cparams.FilterByColor = true;
cparams.BlobColor = 0; cparams.BlobColor = 0;
cparams.MinRepeatability = 1; cparams.MinRepeatability = 1;
cparams.MinDistBetweenBlobs = 1f; cparams.MinDistBetweenBlobs = 0.1f;
// 改变阈值 // 改变阈值
//cparams.MinThreshold = 0; //cparams.MinThreshold = 0;
//cparams.MaxThreshold = 255; //cparams.MaxThreshold = 255;
...@@ -141,16 +157,27 @@ namespace wafer_die_counter ...@@ -141,16 +157,27 @@ namespace wafer_die_counter
var tw = t.Wait(30 * 1000); var tw = t.Wait(30 * 1000);
if (tw) if (tw)
{ {
var rkeypoints = DBSCAN(keypoints.ToList(), 7,3);
var disrkeypoints = new List<KeyPoint>();
var green = new Scalar(0, 255, 0); var green = new Scalar(0, 255, 0);
for (int i = 0; i < keypoints.Length; i++) for (int i = 0; i < rkeypoints.Count; i++)
{ {
//keypoints[i].Size = 1; //keypoints[i].Size = 1;
Cv2.Circle(bgimg, keypoints[i].Pt.ToPoint(), 1, green, 1, LineTypes.Link8); for (int j = 0; j < rkeypoints[i].Count; j++)
{
if (!disrkeypoints.Contains(rkeypoints[i][j])) {
disrkeypoints.Add(rkeypoints[i][j]);
} }
}
}
for (int j = 0; j < disrkeypoints.Count; j++)
Cv2.Circle(bgimg, disrkeypoints[j].Pt.ToPoint(), 1, green, 1, LineTypes.Link8);
//Cv2.DrawKeypoints(org, keypoints, org, Scalar.FromRgb(255, 0, 0), DrawMatchesFlags.NotDrawSinglePoints); //Cv2.DrawKeypoints(org, keypoints, org, Scalar.FromRgb(255, 0, 0), DrawMatchesFlags.NotDrawSinglePoints);
Cv2.PutText(bgimg[rect], $"{keypoints.Length}", new Point(bgimg[rect].Width / 2 - 20, 30), HersheyFonts.HersheySimplex, 1, green, 2); Cv2.PutText(bgimg[rect], $"{disrkeypoints.Count}", new Point(bgimg[rect].Width / 2 - 20, 30), HersheyFonts.HersheySimplex, 1, green, 2);
result.success = true; result.success = true;
result.qty = keypoints.Length; result.qty = disrkeypoints.Count;
if (isdebug) if (isdebug)
ImShow("org1", bgimg[rect]); ImShow("org1", bgimg[rect]);
} }
...@@ -159,7 +186,7 @@ namespace wafer_die_counter ...@@ -159,7 +186,7 @@ namespace wafer_die_counter
txt += " Time out"; txt += " Time out";
} }
result.msg = txt; result.msg = txt+","+ sw.ElapsedMilliseconds;
Cv2.PutText(bgimg, txt, new Point(5, bgimg.Height - 40), HersheyFonts.HersheySimplex, 1, Scalar.Blue, 2); Cv2.PutText(bgimg, txt, new Point(5, bgimg.Height - 40), HersheyFonts.HersheySimplex, 1, Scalar.Blue, 2);
Cv2.ImWrite(resultfile, bgimg[rect]); Cv2.ImWrite(resultfile, bgimg[rect]);
} }
...@@ -169,6 +196,8 @@ namespace wafer_die_counter ...@@ -169,6 +196,8 @@ namespace wafer_die_counter
} }
return result; return result;
} }
static int FindMinValueGreater(int[] arr) static int FindMinValueGreater(int[] arr)
{ {
int maxDiff = 0; int maxDiff = 0;
...@@ -204,6 +233,75 @@ namespace wafer_die_counter ...@@ -204,6 +233,75 @@ namespace wafer_die_counter
return shortSideLength; return shortSideLength;
} }
static List<List<KeyPoint>> DBSCAN(List<KeyPoint> points, double epsilon, int minPoints)
{
List<List<KeyPoint>> clusters = new List<List<KeyPoint>>();
HashSet<KeyPoint> visited = new HashSet<KeyPoint>();
foreach (var point in points)
{
if (visited.Contains(point))
continue;
visited.Add(point);
List<KeyPoint> neighbors = GetNeighbors(point, points, epsilon);
if (neighbors.Count < minPoints)
continue;
List<KeyPoint> cluster = new List<KeyPoint> { point };
visited.Add(point);
ExpandCluster(cluster, point, neighbors, visited, points, epsilon, minPoints);
if (cluster.Count >= minPoints)
clusters.Add(cluster);
}
return clusters;
}
// 获取邻近点
static List<KeyPoint> GetNeighbors(KeyPoint point, List<KeyPoint> points, double epsilon)
{
List<KeyPoint> neighbors = new List<KeyPoint>();
foreach (var otherPoint in points)
{
if (CalculateDistance(point.Pt, otherPoint.Pt) <= epsilon)
neighbors.Add(otherPoint);
}
return neighbors;
}
// 扩展群体
static void ExpandCluster(List<KeyPoint> cluster, KeyPoint point, List<KeyPoint> neighbors, HashSet<KeyPoint> visited, List<KeyPoint> points, double epsilon, int minPoints)
{
foreach (var neighbor in neighbors.ToArray())
{
if (!visited.Contains(neighbor))
{
visited.Add(neighbor);
List<KeyPoint> neighborNeighbors = GetNeighbors(neighbor, points, epsilon);
if (neighborNeighbors.Count >= minPoints)
neighbors.AddRange(neighborNeighbors);
}
if (!cluster.Contains(neighbor))
cluster.Add(neighbor);
}
}
// 计算两点之间的距离
static double CalculateDistance(Point2f p1, Point2f p2)
{
return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
}
} }
[Serializable] [Serializable]
public class Result { public class Result {
......
...@@ -43,7 +43,7 @@ namespace wafer_die_counter ...@@ -43,7 +43,7 @@ namespace wafer_die_counter
if (File.Exists(openFileDialog.FileName)) { if (File.Exists(openFileDialog.FileName)) {
string srcfile = openFileDialog.FileName; string srcfile = openFileDialog.FileName;
string resultfile = Path.GetFileNameWithoutExtension(srcfile)+"_Mark.png"; string resultfile = Path.GetDirectoryName(srcfile) +"\\"+Path.GetFileNameWithoutExtension(srcfile)+"_Mark.png";
var res = Counter.docount(srcfile, resultfile, true); var res = Counter.docount(srcfile, resultfile, true);
Console.WriteLine(JsonConvert.SerializeObject(res)); Console.WriteLine(JsonConvert.SerializeObject(res));
Cv2.WaitKey(100000); Cv2.WaitKey(100000);
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BlockTester.cs" />
<Compile Include="Counter.cs" /> <Compile Include="Counter.cs" />
<Compile Include="Form1.cs"> <Compile Include="Form1.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!