Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
AccAOI
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 6d28a16b
由
刘韬
编写于
2024-01-11 13:37:26 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
1
1 个父辈
e6b8ac30
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
198 行增加
和
16 行删除
园晶斑点分析测试/BlockTester.cs
园晶斑点分析测试/Counter.cs
园晶斑点分析测试/Program.cs
园晶斑点分析测试/园晶斑点分析测试.csproj
园晶斑点分析测试/BlockTester.cs
0 → 100644
查看文件 @
6d28a16
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
>();
}
}
}
园晶斑点分析测试/Counter.cs
查看文件 @
6d28a16
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
-
4
0
;
var
radius
=
(
int
)
c
[
0
].
Radius
-
5
0
;
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
,
1
00
,
10
0
);
//截取左上角100x100范围
var
rect2
=
new
Rect
(
0
,
0
,
1
10
,
11
0
);
//截取左上角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
.
M
ax
(
Threshold1
,
Threshold2
);
Threshold
=
Math
.
M
in
(
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
{
...
...
园晶斑点分析测试/Program.cs
查看文件 @
6d28a16
...
@@ -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
.
Get
DirectoryName
(
srcfile
)
+
"\\"
+
Path
.
Get
FileNameWithoutExtension
(
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
);
...
...
园晶斑点分析测试/园晶斑点分析测试.csproj
查看文件 @
6d28a16
...
@@ -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!
Cancel
请
注册
或
登录
后发表评论