Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
ReelCounter
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit dc4f85e6
由
SK
编写于
2019-04-25 17:07:11 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
优化粘连
1 个父辈
e7982bd2
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
610 行增加
和
26 行删除
AccImage/AccImage.csproj
AccImage/AccUtil.cs
AccImage/SplitItem.cs
AccImage/AccImage.csproj
查看文件 @
dc4f85e
...
@@ -63,6 +63,7 @@
...
@@ -63,6 +63,7 @@
<Reference Include="System.Xml" />
<Reference Include="System.Xml" />
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
<Compile Include="AccUtil.cs" />
<Compile Include="ImageUtil.cs" />
<Compile Include="ImageUtil.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SplitItem.cs" />
<Compile Include="SplitItem.cs" />
...
...
AccImage/AccUtil.cs
0 → 100644
查看文件 @
dc4f85e
using
AccImage
;
using
OpenCvSharp
;
using
OpenCvSharp.Blob
;
using
OpenCvSharp.Extensions
;
using
System
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
System.Drawing
;
using
System.Drawing.Imaging
;
using
System.Linq
;
using
System.Threading.Tasks
;
namespace
Acc.Img
{
public
class
AccUtil
{
/// <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
);
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
;
}
}
}
return
blobArea
;
}
/// <summary>
/// 根据元器件特征统计图片中的元器件数量
/// </summary>
/// <param name="image"></param>
/// <param name="itemFeature"></param>
/// <param name="thresh"></param>
/// <param name="inv"></param>
/// <returns></returns>
public
static
int
CountItems
(
ref
Image
image
,
int
itemArea
)
{
Bitmap
bitmap
=
new
Bitmap
(
image
);
Mat
imageMat
=
BitmapConverter
.
ToMat
(
bitmap
);
Cv2
.
CvtColor
(
imageMat
,
imageMat
,
ColorConversionCodes
.
RGBA2BGR
);
Mat
grayMat
=
BitmapConverter
.
ToMat
(
bitmap
);
Cv2
.
CvtColor
(
grayMat
,
grayMat
,
ColorConversionCodes
.
RGB2GRAY
);
CvBlobs
blobs
=
AutoThreshBlobs
(
ref
grayMat
,
itemArea
);
int
totalCount
=
findCircles
(
ref
imageMat
,
grayMat
,
blobs
,
itemArea
);
//imageMat = grayMat;
//int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
image
=
BitmapConverter
.
ToBitmap
(
imageMat
);
return
totalCount
;
}
/// <summary>
/// 查找Blobs包含的元器件数量
/// </summary>
/// <param name="srcMat"></param>
/// <param name="threshMat"></param>
/// <param name="blobs"></param>
/// <param name="avgArea"></param>
/// <returns></returns>
public
static
int
findCircles
(
ref
Mat
srcMat
,
Mat
threshMat
,
CvBlobs
blobs
,
int
avgArea
)
{
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
++)
{
float
*
dd
=
(
float
*)
distanceMat
.
Ptr
(
y
,
x
);
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
);
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
)
{
var
list
=
blob
.
Contour
.
ConvertToPolygon
().
ToList
();
var
minRect
=
Cv2
.
MinAreaRect
(
list
);
var
width
=
minRect
.
Size
.
Width
;
var
height
=
minRect
.
Size
.
Height
;
if
(
width
<
height
)
{
width
=
minRect
.
Size
.
Height
;
height
=
minRect
.
Size
.
Width
;
}
widths
.
Add
(
width
);
heights
.
Add
(
height
);
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
);
Scalar
color
=
Scalar
.
LightGreen
;
foreach
(
Circle
c
in
item
.
circles
)
{
radiusList
.
Add
(
c
.
radius
);
}
}
});
oneBlobTasks
.
Add
(
task
);
}
Task
.
WaitAll
(
oneBlobTasks
.
ToArray
());
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
)
{
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
);
}
Task
countTask
=
Task
.
Factory
.
StartNew
(
delegate
{
int
count
=
BlobHasItem
(
avgArea
,
blob
);
if
(
count
>=
1
)
{
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
{
//多个元器件,查找 所有圆
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
,
maxWidth
,
maxRadius
);
//对所有圆进行分组
List
<
List
<
Circle
>>
groupCircles
=
item
.
groupCircles
(
maxWidth
,
2
*
maxRadius
,
reelCenter
);
foreach
(
List
<
Circle
>
groupCircle
in
groupCircles
)
{
if
(
groupCircle
.
Count
==
0
)
{
continue
;
}
Circle
c
=
groupCircle
[
0
];
c
.
color
=
color
;
resultCircles
.
Add
(
c
);
}
}
}
}
});
countTasks
.
Add
(
countTask
);
}
Task
.
WaitAll
(
countTasks
.
ToArray
());
foreach
(
var
c
in
resultCircles
)
{
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
);
return
totalCount
;
}
private
static
CvBlobs
AutoThreshBlobs
(
ref
Mat
imageMat
,
int
blobArea
)
{
Mat
[]
mats
=
new
Mat
[]
{
imageMat
};
//一张图片,初始化为panda
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
blobCount
=
0
;
int
threshIndex
=
avgIndex
;
double
theArea
=
blobArea
*
0.8
;
if
(
theArea
<
1
)
theArea
=
1
;
CvBlobs
resultBlobs
=
new
CvBlobs
();
Mat
resultMat
=
new
Mat
();
for
(
int
index
=
startIndex
;
index
<
endIndex
;
index
++)
{
Mat
threshMat
=
new
Mat
();
Cv2
.
Threshold
(
imageMat
,
threshMat
,
index
,
255
,
ThresholdTypes
.
BinaryInv
);
CvBlobs
blobs
=
new
CvBlobs
();
blobs
.
Label
(
threshMat
);
List
<
CvBlob
>
blobList
=
blobs
.
Values
.
Where
(
b
=>
b
.
Area
>
theArea
).
ToList
();
if
(
blobList
.
Count
>
blobCount
)
{
threshIndex
=
index
;
resultMat
=
threshMat
;
resultBlobs
=
blobs
;
blobCount
=
blobList
.
Count
;
}
}
imageMat
=
resultMat
;
Console
.
WriteLine
(
"thresh: "
+
threshIndex
+
" Blob: "
+
resultBlobs
.
Count
+
" Area:"
+
theArea
);
return
resultBlobs
;
}
//获取圆心半径
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
=
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
;
}
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
;
}
}
/// <summary>
/// 给定Blob包含几个元器件
/// </summary>
/// <param name="averageArea"></param>
/// <param name="blob"></param>
/// <returns></returns>
public
static
int
BlobHasItem
(
int
averageArea
,
CvBlob
blob
)
{
int
blobArea
=
blob
.
Area
;
double
minArea
=
0.5
*
averageArea
;
double
k
=
1.5
;
if
(
averageArea
<
50
)
{
minArea
=
0.2
*
averageArea
;
}
if
(
blobArea
<
minArea
*
2
/
3
)
{
return
0
;
}
int
count
=
0
;
count
=
(
int
)((
blobArea
+
k
*
averageArea
)
/
(
k
*
averageArea
));
if
(
count
==
0
||
count
==
1
)
{
count
=
1
;
}
// if (count <= 5000)
{
return
count
;
}
// return 0;
}
/// <summary>
/// 查找Blob中包含的所有与给定半径差不多的内接圆
/// </summary>
/// <param name="matDistanceArr"></param>
/// <param name="blobs"></param>
/// <param name="blob"></param>
/// <param name="reelCenter"></param>
/// <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
)
{
SplitItem
item
=
new
SplitItem
();
while
(
true
)
{
bool
hasFind
=
false
;
bool
hasPixToHandle
=
false
;
for
(
int
x
=
blob
.
MinX
;
x
<
blob
.
MaxX
;
x
++)
{
for
(
int
y
=
blob
.
MinY
;
y
<
blob
.
MaxY
;
y
++)
{
double
distance
=
matDistanceArr
[
x
,
y
];
if
(
distance
>
0
)
{
int
label
=
blobs
.
GetLabel
(
x
,
y
);
if
(
label
!=
blob
.
Label
)
{
//不是当前Blob的像素
continue
;
}
hasPixToHandle
=
true
;
if
(!
item
.
isEnd
)
{
if
(
distance
<
SplitItem
.
DIFF_PERCENT
*
oneBlobRadius
)
{
matDistanceArr
[
x
,
y
]
=
0
;
continue
;
}
//点到圆心的距离
double
distanceToCircle
=
item
.
minDistanceToCircles
(
x
,
y
,
reelCenter
,
oneBlobWidth
,
oneBlobRadius
);
if
(
distanceToCircle
==
0
)
{
matDistanceArr
[
x
,
y
]
=
0
;
continue
;
}
if
(
distanceToCircle
>
0
&&
distanceToCircle
<
distance
)
{
distance
=
distanceToCircle
;
matDistanceArr
[
x
,
y
]
=
distance
;
}
if
(
distance
>
item
.
currentMaxRadius
)
{
item
.
currentMaxRadius
=
distance
;
item
.
centerX
=
x
;
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
)
{
matDistanceArr
[
rectX
,
rectY
]
=
0
;
}
}
}
hasFind
=
true
;
break
;
}
}
}
}
}
if
(
hasFind
)
{
break
;
}
}
if
(!
hasFind
)
{
item
.
calOneItem
(
oneBlobRadius
);
}
if
(
item
.
isEnd
||
!
hasPixToHandle
)
{
break
;
}
//if(item.circles.Count > 3000)
//{
// return item;
//}
//单个Blob只查找 最大的一个
if
(
oneBlobRadius
==
-
1
&&
item
.
circles
.
Count
==
1
)
{
return
item
;
}
}
return
item
;
}
public
static
double
GetStandardMax
(
List
<
double
>
datas
)
{
int
count
=
datas
.
Count
;
if
(
count
>
0
)
{
// 计算平均数
double
avg
=
datas
.
Average
();
// 计算各数值与平均数的差值的平方,然后求和
double
sum
=
datas
.
Sum
(
d
=>
Math
.
Pow
(
d
-
avg
,
2
));
// 除以数量,然后开方
double
std
=
Math
.
Sqrt
(
sum
/
count
);
List
<
double
>
list
=
datas
.
Where
(
d
=>
Math
.
Abs
(
d
-
avg
)
<
std
).
ToList
();
return
list
.
Max
();
}
return
0
;
}
}
}
AccImage/SplitItem.cs
查看文件 @
dc4f85e
...
@@ -9,6 +9,7 @@ namespace AccImage
...
@@ -9,6 +9,7 @@ namespace AccImage
{
{
public
class
SplitItem
public
class
SplitItem
{
{
public
static
double
DIFF_PERCENT
=
0.5
;
public
bool
isEnd
=
false
;
public
bool
isEnd
=
false
;
public
double
avgRadius
=
0
;
public
double
avgRadius
=
0
;
public
int
centerX
=
0
;
public
int
centerX
=
0
;
...
@@ -16,6 +17,8 @@ namespace AccImage
...
@@ -16,6 +17,8 @@ namespace AccImage
public
double
currentMaxRadius
=
0
;
public
double
currentMaxRadius
=
0
;
public
List
<
Circle
>
circles
=
new
List
<
Circle
>();
public
List
<
Circle
>
circles
=
new
List
<
Circle
>();
private
List
<
Circle
>
nearbyCircles
=
new
List
<
Circle
>();
/// <summary>
/// <summary>
/// 一遍结束后调用
/// 一遍结束后调用
/// </summary>
/// </summary>
...
@@ -29,9 +32,9 @@ namespace AccImage
...
@@ -29,9 +32,9 @@ namespace AccImage
}
}
else
else
{
{
//与平均半径差值在
1
0%以内,认为OK
//与平均半径差值在
5
0%以内,认为OK
double
diff
=
avgRadius
-
currentMaxRadius
;
double
diff
=
avgRadius
-
currentMaxRadius
;
if
(
diff
/
avgRadius
<=
0.5
)
if
(
diff
/
avgRadius
<=
DIFF_PERCENT
)
{
{
isValid
=
true
;
isValid
=
true
;
}
}
...
@@ -52,26 +55,26 @@ namespace AccImage
...
@@ -52,26 +55,26 @@ namespace AccImage
circle
.
x
=
centerX
;
circle
.
x
=
centerX
;
circle
.
y
=
centerY
;
circle
.
y
=
centerY
;
circles
.
Add
(
circle
);
circles
.
Add
(
circle
);
if
(
nearbyCircles
.
Count
%
50
==
0
)
{
nearbyCircles
=
nearbyCircles
.
Where
(
c
=>
centerX
-
c
.
x
<
2
*
currentMaxRadius
).
ToList
();
}
nearbyCircles
.
Add
(
circle
);
currentMaxRadius
=
0
;
currentMaxRadius
=
0
;
centerX
=
0
;
centerX
=
0
;
centerY
=
0
;
centerY
=
0
;
////平均半径
//double total = 0;
//foreach (Circle c in circles)
//{
// total = total + c.radius;
//}
//avgRadius = total / circles.Count;
if
(
circle
.
radius
>
avgRadius
)
if
(
circle
.
radius
>
avgRadius
)
{
{
avgRadius
=
circle
.
radius
;
avgRadius
=
circle
.
radius
;
}
}
}
}
else
else
{
{
isEnd
=
true
;
isEnd
=
true
;
}
}
}
}
...
@@ -134,31 +137,23 @@ namespace AccImage
...
@@ -134,31 +137,23 @@ namespace AccImage
{
{
Point2d
point
=
new
Point2d
(
px
,
py
);
Point2d
point
=
new
Point2d
(
px
,
py
);
double
minDistanceToCircle
=
-
1
;
double
minDistanceToCircle
=
-
1
;
foreach
(
Circle
c
in
circles
)
List
<
Circle
>
neighbourCircles
=
nearbyCircles
;
if
(
oneBlobRadius
>
0
)
{
neighbourCircles
=
nearbyCircles
.
Where
(
c
=>
Math
.
Abs
(
c
.
x
-
px
)
<=
2
*
oneBlobRadius
&&
Math
.
Abs
(
c
.
y
-
py
)
<=
2
*
oneBlobRadius
).
ToList
();
}
foreach
(
Circle
c
in
neighbourCircles
)
{
{
Point2d
circleCenter
=
new
Point2d
(
c
.
x
,
c
.
y
);
Point2d
circleCenter
=
new
Point2d
(
c
.
x
,
c
.
y
);
double
distanceToCircle
=
point
.
DistanceTo
(
circleCenter
);
double
distanceToCircle
=
point
.
DistanceTo
(
circleCenter
)
-
c
.
radius
;
if
(
distanceToCircle
<=
c
.
radius
)
if
(
distanceToCircle
<=
DIFF_PERCENT
*
c
.
radius
)
{
{
return
0
;
return
0
;
}
}
//当前点到料盘中心与圆心到料盘中心的距离在直径内,忽略
//if(oneBlobRadius != -1 && oneBlobWidth != -1)
//{
// double distanceToReelCenter = point.DistanceTo(reelCenter);
// double circleCenterToReelCenter = circleCenter.DistanceTo(reelCenter);
// if (Math.Abs(distanceToReelCenter - circleCenterToReelCenter) < oneBlobRadius)
// {
// if (distanceToCircle < oneBlobWidth)
// {
// return 0;
// }
// }
//}
if
(
minDistanceToCircle
==
-
1
||
distanceToCircle
<
minDistanceToCircle
)
if
(
minDistanceToCircle
==
-
1
||
distanceToCircle
<
minDistanceToCircle
)
{
{
minDistanceToCircle
=
distanceToCircle
-
c
.
radius
;
minDistanceToCircle
=
distanceToCircle
;
}
}
}
}
return
minDistanceToCircle
;
return
minDistanceToCircle
;
...
@@ -171,6 +166,7 @@ namespace AccImage
...
@@ -171,6 +166,7 @@ namespace AccImage
public
int
x
;
public
int
x
;
public
int
y
;
public
int
y
;
public
double
radius
;
public
double
radius
;
public
Scalar
color
=
Scalar
.
Green
;
public
double
distanceToCenter
=
0
;
public
double
distanceToCenter
=
0
;
public
double
distanceToCircle
(
Circle
c
)
public
double
distanceToCircle
(
Circle
c
)
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论