Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
ReelCounter
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit b290e77b
由
SK
编写于
2019-04-28 17:31:24 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
分组算法优化
1 个父辈
bf447aef
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
293 行增加
和
155 行删除
AccImage/AccUtil.cs
AccImage/SplitItem.cs
AccImage/AccUtil.cs
查看文件 @
b290e77
...
...
@@ -3,11 +3,13 @@ using OpenCvSharp;
using
OpenCvSharp.Blob
;
using
OpenCvSharp.Extensions
;
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
System.Drawing
;
using
System.Drawing.Imaging
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Acc.Img
...
...
@@ -60,7 +62,14 @@ namespace Acc.Img
Cv2
.
CvtColor
(
imageMat
,
imageMat
,
ColorConversionCodes
.
RGBA2BGR
);
Mat
grayMat
=
BitmapConverter
.
ToMat
(
bitmap
);
Cv2
.
CvtColor
(
grayMat
,
grayMat
,
ColorConversionCodes
.
RGB2GRAY
);
Console
.
WriteLine
(
"Start Thresh"
);
Stopwatch
sw
=
new
Stopwatch
();
sw
.
Start
();
CvBlobs
blobs
=
AutoThreshBlobs
(
ref
grayMat
,
itemArea
);
//CvBlobs blobs = AutoThreshBlobsTask(ref grayMat, itemArea);
sw
.
Stop
();
Console
.
WriteLine
(
"Thresh End: "
+
sw
.
ElapsedMilliseconds
+
" ms"
);
int
totalCount
=
findCircles
(
ref
imageMat
,
grayMat
,
blobs
,
itemArea
);
//imageMat = grayMat;
//int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
...
...
@@ -79,16 +88,16 @@ namespace Acc.Img
/// <returns></returns>
public
static
int
findCircles
(
ref
Mat
srcMat
,
Mat
threshMat
,
CvBlobs
blobs
,
int
avgArea
)
{
Stopwatch
sw
=
new
Stopwatch
();
sw
.
Start
();
double
[,]
distanceArr
=
new
double
[
threshMat
.
Cols
,
threshMat
.
Rows
];
Task
distanceTask
=
Task
.
Factory
.
StartNew
(
delegate
{
Mat
distanceMat
=
new
Mat
();
Cv2
.
DistanceTransform
(
threshMat
,
distanceMat
,
DistanceTypes
.
L2
,
DistanceMaskSize
.
Mask3
);
double
[,]
distanceArr
=
new
double
[
threshMat
.
Cols
,
threshMat
.
Rows
];
Console
.
WriteLine
(
"Start to distance array"
);
unsafe
{
Stopwatch
sw
=
new
Stopwatch
();
sw
.
Start
();
for
(
int
y
=
0
;
y
<
threshMat
.
Rows
;
y
++)
{
for
(
int
x
=
0
;
x
<
threshMat
.
Cols
;
x
++)
...
...
@@ -97,41 +106,29 @@ namespace Acc.Img
distanceArr
[
x
,
y
]
=
dd
[
0
];
}
}
sw
.
Stop
();
Console
.
WriteLine
(
"="
+
sw
.
ElapsedMilliseconds
+
" ms"
);
}
});
Dictionary
<
int
,
SplitItem
>
blobCircles
=
new
Dictionary
<
int
,
SplitItem
>();
Console
.
WriteLine
(
"Start find reel center"
);
RediusPt
rediusPt
,
rediusPtOut
;
GetCenter
(
srcMat
,
out
rediusPt
);
GetOutContour
(
srcMat
,
out
rediusPtOut
);
Point2d
reelCenter
=
new
Point2d
(
0
,
0
);
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
);
srcMat
.
Circle
(
rediusPt
.
pt
,
(
int
)
rediusPt
.
radius
-
10
,
Scalar
.
Red
);
srcMat
.
Circle
(
rediusPtOut
.
pt
,
(
int
)
rediusPtOut
.
radius
-
10
,
Scalar
.
Red
);
List
<
Circle
>
resultCircles
=
new
List
<
Circle
>();
int
totalCount
=
0
;
List
<
CvBlob
>
bigBlobs
=
new
List
<
CvBlob
>();
double
maxWidth
=
0
;
double
maxHeight
=
0
;
double
maxRadius
=
0
;
Task
findOneBlobTask
=
Task
.
Factory
.
StartNew
(
delegate
{
Console
.
WriteLine
(
"Start find reel Max Radius, max Width"
);
List
<
double
>
widths
=
new
List
<
double
>();
List
<
double
>
heights
=
new
List
<
double
>();
List
<
double
>
radiusList
=
new
List
<
double
>();
List
<
Task
>
oneBlobTasks
=
new
List
<
Task
>();
foreach
(
CvBlob
blob
in
blobs
.
Values
)
{
Task
task
=
Task
.
Factory
.
StartNew
(
delegate
{
int
count
=
BlobHasItem
(
avgArea
,
blob
);
if
(
count
==
1
)
{
//结果数量+1
Interlocked
.
Increment
(
ref
totalCount
);
var
list
=
blob
.
Contour
.
ConvertToPolygon
().
ToList
();
var
minRect
=
Cv2
.
MinAreaRect
(
list
);
var
width
=
minRect
.
Size
.
Width
;
...
...
@@ -143,90 +140,111 @@ namespace Acc.Img
}
widths
.
Add
(
width
);
heights
.
Add
(
height
);
}
else
if
(
count
>
1
)
{
bigBlobs
.
Add
(
blob
);
}
}
maxWidth
=
GetStandardMax
(
widths
);
maxHeight
=
GetStandardMax
(
heights
);
});
RediusPt
rediusPt
,
rediusPtOut
;
Console
.
WriteLine
(
"Start find reel center"
);
GetCenter
(
srcMat
,
out
rediusPt
);
GetOutContour
(
srcMat
,
out
rediusPtOut
);
Point2d
reelCenter
=
new
Point2d
(
0
,
0
);
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
);
Task
.
WaitAll
(
distanceTask
);
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
);
Task
findMaxRadius
=
Task
.
Factory
.
StartNew
(
delegate
{
List
<
double
>
radiusList
=
new
List
<
double
>();
foreach
(
CvBlob
blob
in
blobs
.
Values
)
{
int
count
=
BlobHasItem
(
avgArea
,
blob
);
if
(
count
==
1
)
{
//这里只会找一个最大的圆
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
);
Scalar
color
=
Scalar
.
LightGreen
;
foreach
(
Circle
c
in
item
.
circles
)
{
radiusList
.
Add
(
c
.
radius
);
c
.
color
=
color
;
resultCircles
.
Add
(
c
);
}
}
});
oneBlobTasks
.
Add
(
task
);
}
Task
.
WaitAll
(
oneBlobTasks
.
ToArray
());
maxRadius
=
GetStandardMax
(
radiusList
);
});
Task
.
WaitAll
(
findMaxRadius
,
findOneBlobTask
);
var
maxWidth
=
GetStandardMax
(
widths
);
var
maxHeight
=
GetStandardMax
(
heights
);
var
maxRadius
=
GetStandardMax
(
radiusList
);
Console
.
WriteLine
(
maxWidth
+
" = "
+
maxHeight
+
" R="
+
maxRadius
);
//放大宽度,防止误判断
maxWidth
=
maxWidth
*
1.6
;
Console
.
WriteLine
(
"Start count"
);
List
<
Circle
>
resultCircles
=
new
List
<
Circle
>();
List
<
Task
>
countTasks
=
new
List
<
Task
>()
;
foreach
(
CvBlob
blob
in
blobs
.
Values
)
//
SplitItem
.
DIFF_PERCENT
=
0.4
;
if
(
maxHeight
<
maxRadius
*
2
)
{
maxHeight
=
maxRadius
*
2
;
}
maxWidth
=
maxWidth
*
1.5
;
Console
.
WriteLine
(
"Start count"
);
Scalar
color
=
Scalar
.
RandomColor
();
if
(
blob
.
Area
>
1000
)
{
blob
.
Contour
.
Render
(
srcMat
,
color
);
Cv2
.
PutText
(
srcMat
,
blob
.
Label
+
""
,
new
OpenCvSharp
.
Point
(
blob
.
Centroid
.
X
-
40
,
blob
.
Centroid
.
Y
+
30
),
HersheyFonts
.
HersheyComplex
,
1.0
,
color
);
}
//从大到小排序 ,大的先执行
bigBlobs
.
OrderByDescending
(
b
=>
b
.
Area
);
Task
countTask
=
Task
.
Factory
.
StartNew
(
delegate
{
int
count
=
BlobHasItem
(
avgArea
,
blob
);
if
(
count
>=
1
)
List
<
Task
>
countTasks
=
new
List
<
Task
>();
foreach
(
CvBlob
blob
in
bigBlobs
)
{
bool
isReelCenter
=
blob
.
Centroid
.
DistanceTo
(
new
Point2d
(
rediusPt
.
pt
.
X
,
rediusPt
.
pt
.
Y
))
<
rediusPt
.
radius
-
10
;
if
(!
isReelCenter
)
{
if
(
count
==
1
)
{
Circle
c
=
new
Circle
();
c
.
radius
=
maxRadius
;
c
.
x
=
(
int
)
blob
.
Centroid
.
X
;
c
.
y
=
(
int
)
blob
.
Centroid
.
Y
;
resultCircles
.
Add
(
c
);
}
else
{
Task
countTask
=
Task
.
Factory
.
StartNew
(
delegate
{
//多个元器件,查找 所有圆
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
,
maxWidth
,
maxRadius
);
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
maxWidth
,
maxRadius
);
//对所有圆进行分组
List
<
List
<
Circle
>>
groupCircles
=
item
.
groupCircles
(
maxWidth
,
2
*
maxRadius
,
reelCenter
);
List
<
List
<
Circle
>>
groupCircles
=
item
.
groupCircles
(
maxWidth
,
maxHeight
,
reelCenter
);
foreach
(
List
<
Circle
>
groupCircle
in
groupCircles
)
{
if
(
groupCircle
.
Count
==
0
)
{
continue
;
}
Circle
c
=
groupCircle
[
0
];
c
.
color
=
color
;
resultCircles
.
Add
(
c
);
}
}
//resultCircles.AddRange(groupCircle);
Interlocked
.
Increment
(
ref
totalCount
);
resultCircles
.
Add
(
groupCircle
[
0
]);
}
}
});
countTasks
.
Add
(
countTask
);
}
}
Task
.
WaitAll
(
countTasks
.
ToArray
());
int
index
=
0
;
foreach
(
var
c
in
resultCircles
)
{
if
(
c
==
null
)
{
continue
;
}
index
++;
srcMat
.
Circle
(
c
.
x
,
c
.
y
,
(
int
)
c
.
radius
,
c
.
color
);
}
int
totalCount
=
resultCircles
.
Count
;
Cv2
.
PutText
(
srcMat
,
totalCount
+
""
,
new
OpenCvSharp
.
Point
(
reelCenter
.
X
-
40
,
reelCenter
.
Y
+
30
),
HersheyFonts
.
HersheyComplex
,
1.0
,
Scalar
.
LightGreen
);
Console
.
WriteLine
(
"==========="
+
totalCount
);
sw
.
Stop
();
Console
.
WriteLine
(
"Count: "
+
totalCount
+
" Time:"
+
sw
.
ElapsedMilliseconds
+
" ms"
);
return
totalCount
;
}
...
...
@@ -280,6 +298,7 @@ namespace Acc.Img
Mat
resultMat
=
new
Mat
();
for
(
int
index
=
startIndex
;
index
<
endIndex
;
index
++)
{
Console
.
WriteLine
(
" Thresh Task "
+
index
);
Mat
threshMat
=
new
Mat
();
Cv2
.
Threshold
(
imageMat
,
threshMat
,
index
,
255
,
ThresholdTypes
.
BinaryInv
);
CvBlobs
blobs
=
new
CvBlobs
();
...
...
@@ -298,6 +317,90 @@ namespace Acc.Img
return
resultBlobs
;
}
private
static
CvBlobs
AutoThreshBlobsTask
(
ref
Mat
grayMat
,
int
blobArea
)
{
Mat
[]
mats
=
new
Mat
[]
{
grayMat
};
//一张图片,初始化
Mat
hist
=
new
Mat
();
//用来接收直方图
int
[]
channels
=
new
int
[]
{
0
};
//一个通道,初始化为通道0
int
[]
histsize
=
new
int
[]
{
256
};
//一个通道,初始化为256箱子
Rangef
[]
range
=
new
Rangef
[
1
];
//一个通道,值范围
range
[
0
].
Start
=
0.0F
;
//从0开始(含)
range
[
0
].
End
=
256.0F
;
//到256结束(不含)
Mat
mask
=
new
Mat
();
//不做掩码
Cv2
.
CalcHist
(
mats
,
channels
,
mask
,
hist
,
1
,
histsize
,
range
);
//计算灰度图,dim为1 1维
double
total
=
0
;
for
(
int
i
=
0
;
i
<
256
;
i
++)
//灰度值总数量
{
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
)
{
//灰度值的像素数小于100的忽略
if
(
startIndex
==
-
1
)
{
startIndex
=
i
;
}
endIndex
=
i
-
1
;
percent
=
percent
+
len
/
total
;
//近似的认为元器件的灰度值 数量占总数的百分比小于10%
if
(
percent
>
0.1
)
{
break
;
}
}
}
int
avgIndex
=
(
startIndex
+
endIndex
)
/
2
;
int
threshIndex
=
avgIndex
;
double
theArea
=
blobArea
*
0.8
;
if
(
theArea
<
1
)
theArea
=
1
;
Console
.
WriteLine
(
" Thresh Task Start.. "
);
Mat
srcMat
=
grayMat
;
List
<
Task
>
tasks
=
new
List
<
Task
>();
int
index
=
startIndex
;
object
lockObj
=
new
object
();
int
maxBlobCount
=
0
;
int
bestThreshIndex
=
0
;
CvBlobs
resultBlobs
=
new
CvBlobs
();
Mat
resultMat
=
new
Mat
();
for
(
int
i
=
0
;
i
<
2
;
i
++)
{
Task
task
=
Task
.
Factory
.
StartNew
(
delegate
{
while
(
index
<
endIndex
)
{
index
=
Interlocked
.
Increment
(
ref
index
);
;
Console
.
WriteLine
(
" Thresh Task "
+
index
);
Mat
threshMat
=
new
Mat
();
Cv2
.
Threshold
(
srcMat
,
threshMat
,
index
,
255
,
ThresholdTypes
.
BinaryInv
);
CvBlobs
blobs
=
new
CvBlobs
();
blobs
.
Label
(
threshMat
);
List
<
CvBlob
>
blobList
=
blobs
.
Values
.
Where
(
b
=>
b
.
Area
>
theArea
).
ToList
();
lock
(
lockObj
)
{
if
(
blobList
.
Count
>
maxBlobCount
)
{
maxBlobCount
=
blobList
.
Count
;
bestThreshIndex
=
index
;
resultBlobs
=
blobs
;
resultMat
=
threshMat
;
}
}
}
});
tasks
.
Add
(
task
);
}
Task
.
WaitAll
(
tasks
.
ToArray
());
Console
.
WriteLine
(
"best thresh= "
+
bestThreshIndex
+
" Blob: "
+
resultBlobs
.
Count
+
"middle thresh= "
+
threshIndex
+
" Area:"
+
theArea
);
return
resultBlobs
;
}
//获取圆心半径
public
struct
RediusPt
{
...
...
@@ -448,7 +551,7 @@ namespace Acc.Img
/// <param name="oneBlobWidth"></param>
/// <param name="oneBlobRadius"></param>
/// <returns></returns>
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
,
double
oneBlobWidth
=
-
1
,
double
oneBlobRadius
=
-
1
)
{
SplitItem
item
=
new
SplitItem
();
while
(
true
)
...
...
@@ -459,7 +562,7 @@ namespace Acc.Img
{
for
(
int
y
=
blob
.
MinY
;
y
<
blob
.
MaxY
;
y
++)
{
double
distance
=
matDistanceArr
[
x
,
y
];
double
distance
=
matDistanceArr
[
x
,
y
];
if
(
distance
>
0
)
{
int
label
=
blobs
.
GetLabel
(
x
,
y
);
...
...
@@ -471,22 +574,22 @@ namespace Acc.Img
hasPixToHandle
=
true
;
if
(!
item
.
isEnd
)
{
if
(
distance
<
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
)
if
(
distance
<
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
)
{
matDistanceArr
[
x
,
y
]
=
0
;
matDistanceArr
[
x
,
y
]
=
0
;
continue
;
}
//点到圆心的距离
double
distanceToCircle
=
item
.
minDistanceToCircles
(
x
,
y
,
reelCenter
,
oneBlobWidth
,
oneBlobRadius
);
double
distanceToCircle
=
item
.
minDistanceToCircles
(
x
,
y
,
oneBlobWidth
,
oneBlobRadius
);
if
(
distanceToCircle
==
0
)
{
matDistanceArr
[
x
,
y
]
=
0
;
matDistanceArr
[
x
,
y
]
=
0
;
continue
;
}
if
(
distanceToCircle
>
0
&&
distanceToCircle
<
distance
)
{
distance
=
distanceToCircle
;
matDistanceArr
[
x
,
y
]
=
distance
;
matDistanceArr
[
x
,
y
]
=
distance
;
}
if
(
distance
>
item
.
currentMaxRadius
)
{
...
...
@@ -495,41 +598,12 @@ namespace Acc.Img
item
.
centerY
=
y
;
if
(
oneBlobRadius
!=
-
1
&&
distance
>=
oneBlobRadius
)
{
item
.
calOneItem
(
oneBlobRadius
);
//填充1.5倍的方框
int
left
=
(
int
)
(
x
-
oneBlobRadius
-
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
);
if
(
left
<
0
)
{
left
=
0
;
}
int
right
=
(
int
)(
x
+
oneBlobRadius
+
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
);
int
top
=
(
int
)(
y
-
oneBlobRadius
-
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
);
if
(
top
<
0
)
{
top
=
0
;
}
int
bottom
=
(
int
)(
y
+
oneBlobRadius
+
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
);
for
(
int
rectX
=
left
;
rectX
<
right
;
rectX
++)
{
if
(
right
>=
matDistanceArr
.
GetLength
(
1
))
{
break
;
}
int
len
=
matDistanceArr
.
GetLength
(
0
);
for
(
int
rectY
=
top
;
rectY
<
bottom
;
rectY
++)
{
if
(
rectY
>=
len
)
{
break
;
}
int
pixLabel
=
blobs
.
GetLabel
(
rectX
,
rectY
);
if
(
pixLabel
==
blob
.
Label
)
hasFind
=
true
;
Circle
circle
=
item
.
calOneItem
(
oneBlobRadius
);
if
(
circle
!=
null
)
{
matDistanceArr
[
rectX
,
rectY
]
=
0
;
}
}
removeCircleFromDistanceArr
(
ref
matDistanceArr
,
circle
.
x
,
circle
.
y
,
circle
.
radius
,
blob
.
Label
,
blobs
);
}
hasFind
=
true
;
break
;
}
}
...
...
@@ -542,28 +616,50 @@ namespace Acc.Img
break
;
}
}
if
(!
hasFind
)
{
item
.
calOneItem
(
oneBlobRadius
);
}
if
(
item
.
isEnd
||
!
hasPixToHandle
)
Circle
circle
=
item
.
calOneItem
(
oneBlobRadius
);
if
(
circle
!=
null
)
{
break
;
removeCircleFromDistanceArr
(
ref
matDistanceArr
,
circle
.
x
,
circle
.
y
,
circle
.
radius
,
blob
.
Label
,
blobs
);
}
}
//if(item.circles.Count > 3000)
//{
// return item;
//}
//单个Blob只查找 最大的一个
if
(
oneBlobRadius
==
-
1
&&
item
.
circles
.
Count
==
1
)
if
(
oneBlobRadius
==
-
1
&&
item
.
circles
.
Count
==
1
)
{
return
item
;
}
if
(
item
.
isEnd
||
!
hasPixToHandle
)
{
break
;
}
}
return
item
;
}
private
static
void
removeCircleFromDistanceArr
(
ref
double
[,]
distanceArr
,
int
x
,
int
y
,
double
radius
,
int
label
,
CvBlobs
blobs
)
{
//填充外接正方形
for
(
int
rectX
=
(
int
)(
x
-
radius
);
rectX
<
(
int
)(
x
+
radius
);
rectX
++)
{
// int len = distanceArr.GetLength(0);
for
(
int
rectY
=
(
int
)(
y
-
radius
);
rectY
<
(
int
)(
y
+
radius
);
rectY
++)
{
// int pixLabel = blobs.GetLabel(rectX, rectY);
//if (pixLabel == label)
{
distanceArr
[
rectX
,
rectY
]
=
0
;
}
}
}
}
public
static
double
GetStandardMax
(
List
<
double
>
datas
)
{
int
count
=
datas
.
Count
;
...
...
@@ -576,9 +672,16 @@ namespace Acc.Img
// 除以数量,然后开方
double
std
=
Math
.
Sqrt
(
sum
/
count
);
List
<
double
>
list
=
datas
.
Where
(
d
=>
Math
.
Abs
(
d
-
avg
)
<
std
).
ToList
();
if
(
list
.
Count
>
0
)
{
return
list
.
Max
();
}
else
{
return
avg
;
}
}
return
0
;
}
...
...
AccImage/SplitItem.cs
查看文件 @
b290e77
...
...
@@ -9,7 +9,7 @@ namespace AccImage
{
public
class
SplitItem
{
public
static
double
DIFF_PERCENT
=
0.
5
;
public
static
double
DIFF_PERCENT
=
0.
4
;
public
bool
isEnd
=
false
;
public
double
avgRadius
=
0
;
public
int
centerX
=
0
;
...
...
@@ -17,12 +17,10 @@ namespace AccImage
public
double
currentMaxRadius
=
0
;
public
List
<
Circle
>
circles
=
new
List
<
Circle
>();
private
List
<
Circle
>
nearbyCircles
=
new
List
<
Circle
>();
/// <summary>
/// 一遍结束后调用
/// 一遍结束后调用
, 返回当前圆是否有效
/// </summary>
public
void
calOneItem
(
double
theFixRadius
=-
1
)
public
Circle
calOneItem
(
double
theFixRadius
=-
1
)
{
//该半径是否有效
bool
isValid
=
false
;
...
...
@@ -44,7 +42,7 @@ namespace AccImage
if
(
currentMaxRadius
==
0
)
{
isEnd
=
true
;
return
;
return
null
;
}
Circle
circle
=
new
Circle
();
if
(
theFixRadius
!=
-
1
&&
currentMaxRadius
>
theFixRadius
)
...
...
@@ -55,11 +53,6 @@ namespace AccImage
circle
.
x
=
centerX
;
circle
.
y
=
centerY
;
circles
.
Add
(
circle
);
if
(
nearbyCircles
.
Count
%
50
==
0
)
{
nearbyCircles
=
nearbyCircles
.
Where
(
c
=>
centerX
-
c
.
x
<
2
*
currentMaxRadius
).
ToList
();
}
nearbyCircles
.
Add
(
circle
);
currentMaxRadius
=
0
;
centerX
=
0
;
centerY
=
0
;
...
...
@@ -67,13 +60,14 @@ namespace AccImage
{
avgRadius
=
circle
.
radius
;
}
return
circle
;
}
else
{
isEnd
=
true
;
}
return
null
;
}
...
...
@@ -84,45 +78,86 @@ namespace AccImage
{
c
.
calDistanceToCenter
(
center
);
}
List
<
List
<
Circle
>>
allGroupCircle
=
new
List
<
List
<
Circle
>>();
List
<
int
>
allreadyGroup
=
new
List
<
int
>();
//List<Circle> groupCircle = new List<Circle>();
//groupCircle.Clear();
//排序
circles
.
OrderBy
(
c
=>
c
.
distanceToCenter
);
List
<
List
<
Circle
>>
lineCircles
=
new
List
<
List
<
Circle
>>();
List
<
int
>
allreadyLabel
=
new
List
<
int
>();
//与圆心距离在h范围内的分为一组
while
(
true
)
{
List
<
Circle
>
group
Circle
=
new
List
<
Circle
>();
Circle
label
Circle
=
null
;
for
(
int
i
=
0
;
i
<
circles
.
Count
;
i
++)
List
<
Circle
>
line
Circle
=
new
List
<
Circle
>();
Circle
firstLine
Circle
=
null
;
for
(
int
i
=
0
;
i
<
circles
.
Count
;
i
++)
{
if
(!
allready
Group
.
Contains
(
i
))
if
(!
allready
Label
.
Contains
(
i
))
{
Circle
c
=
circles
[
i
];
if
(
label
Circle
==
null
)
if
(
firstLine
Circle
==
null
)
{
label
Circle
=
c
;
allready
Group
.
Add
(
i
);
group
Circle
.
Add
(
c
);
firstLine
Circle
=
c
;
allready
Label
.
Add
(
i
);
line
Circle
.
Add
(
c
);
}
else
{
//到圆心的距离差小于H
if
(
Math
.
Abs
(
c
.
distanceToCenter
-
label
Circle
.
distanceToCenter
)
<
h
)
if
(
Math
.
Abs
(
c
.
distanceToCenter
-
firstLine
Circle
.
distanceToCenter
)
<
h
)
{
//两圆心之间的距离+直径小于W认为是同一个元器件
if
(
c
.
distanceToCircle
(
labelCircle
)
<
w
+
h
*
2
/
3
)
lineCircle
.
Add
(
c
);
allreadyLabel
.
Add
(
i
);
}
}
}
}
lineCircles
.
Add
(
lineCircle
);
if
(
allreadyLabel
.
Count
==
circles
.
Count
)
{
groupCircle
.
Add
(
c
);
allreadyGroup
.
Add
(
i
);
break
;
}
}
//再按长度划分
List
<
List
<
Circle
>>
allGroupCircle
=
new
List
<
List
<
Circle
>>();
foreach
(
var
lineCircle
in
lineCircles
)
{
//排序
lineCircle
.
OrderBy
(
c
=>
c
.
x
);
List
<
int
>
lineAllreadyLabel
=
new
List
<
int
>();
while
(
true
)
{
List
<
Circle
>
groupCircle
=
new
List
<
Circle
>();
Scalar
color
=
Scalar
.
Yellow
;
for
(
int
i
=
0
;
i
<
lineCircle
.
Count
;
i
++)
{
if
(!
lineAllreadyLabel
.
Contains
(
i
))
{
Circle
c
=
lineCircle
[
i
];
//圆心之间的距离+直径小于W认为是同一个元器件
bool
inGroup
=
true
;
foreach
(
var
gCircle
in
groupCircle
)
{
if
(
c
.
distanceToCircle
(
gCircle
)
>
w
)
{
inGroup
=
false
;
}
}
if
(
inGroup
)
{
c
.
color
=
color
;
groupCircle
.
Add
(
c
);
lineAllreadyLabel
.
Add
(
i
);
}
}
}
allGroupCircle
.
Add
(
groupCircle
);
if
(
allreadyGroup
.
Count
==
circles
.
Count
)
if
(
lineAllreadyLabel
.
Count
==
lineCircle
.
Count
)
{
break
;
}
}
}
return
allGroupCircle
;
}
...
...
@@ -133,14 +168,14 @@ namespace AccImage
/// <param name="px"></param>
/// <param name="py"></param>
/// <returns></returns>
public
double
minDistanceToCircles
(
int
px
,
int
py
,
Point2d
reelCenter
,
double
oneBlobWidth
=-
1
,
double
oneBlobRadius
=
-
1
)
public
double
minDistanceToCircles
(
int
px
,
int
py
,
double
oneBlobWidth
=-
1
,
double
oneBlobRadius
=
-
1
)
{
Point2d
point
=
new
Point2d
(
px
,
py
);
double
minDistanceToCircle
=
-
1
;
List
<
Circle
>
neighbourCircles
=
nearbyC
ircles
;
List
<
Circle
>
neighbourCircles
=
c
ircles
;
if
(
oneBlobRadius
>
0
)
{
neighbourCircles
=
ne
arby
Circles
.
Where
(
c
=>
Math
.
Abs
(
c
.
x
-
px
)
<=
2
*
oneBlobRadius
&&
Math
.
Abs
(
c
.
y
-
py
)
<=
2
*
oneBlobRadius
).
ToList
();
neighbourCircles
=
ne
ighbour
Circles
.
Where
(
c
=>
Math
.
Abs
(
c
.
x
-
px
)
<=
2
*
oneBlobRadius
&&
Math
.
Abs
(
c
.
y
-
py
)
<=
2
*
oneBlobRadius
).
ToList
();
}
foreach
(
Circle
c
in
neighbourCircles
)
{
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论