Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
ReelCounter
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 0524be05
由
cuiyadong
编写于
2019-04-19 09:31:23 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
提高检测精度
1 个父辈
9e086d51
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
438 行增加
和
160 行删除
AccImage/ImageUtil.cs
AccImage/SplitItem.cs
AccImage/ImageUtil.cs
查看文件 @
0524be0
...
@@ -77,7 +77,7 @@ namespace Acc.Img
...
@@ -77,7 +77,7 @@ namespace Acc.Img
Mat
threshMat
=
Threshhold
(
imageMat
,
thresh
);
Mat
threshMat
=
Threshhold
(
imageMat
,
thresh
);
return
BitmapConverter
.
ToBitmap
(
threshMat
);
return
BitmapConverter
.
ToBitmap
(
threshMat
);
}
}
/// <summary>
/// <summary>
/// 获取鼠标位置的元器件特征值
/// 获取鼠标位置的元器件特征值
/// </summary>
/// </summary>
...
@@ -205,13 +205,14 @@ namespace Acc.Img
...
@@ -205,13 +205,14 @@ namespace Acc.Img
/// <returns></returns>
/// <returns></returns>
public
static
int
CountItems
(
ref
Image
image
,
int
itemArea
)
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
);
Cv2
.
CvtColor
(
imageMat
,
imageMat
,
ColorConversionCodes
.
RGBA2BGR
);
Mat
grayMat
=
BitmapConverter
.
ToMat
(
new
Bitmap
(
image
)
);
Mat
grayMat
=
BitmapConverter
.
ToMat
(
bitmap
);
Cv2
.
CvtColor
(
grayMat
,
grayMat
,
ColorConversionCodes
.
RGB2GRAY
);
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
);
int
totalCount
=
findCircles
(
ref
imageMat
,
grayMat
,
blobs
,
itemArea
);
//imageMat = grayMat;
//int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
//int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
image
=
BitmapConverter
.
ToBitmap
(
imageMat
);
image
=
BitmapConverter
.
ToBitmap
(
imageMat
);
return
totalCount
;
return
totalCount
;
...
@@ -381,9 +382,67 @@ namespace Acc.Img
...
@@ -381,9 +382,67 @@ namespace Acc.Img
}
}
return
Math
.
Sqrt
(
avgArea
);
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
[]
mats
=
new
Mat
[]
{
imageMat
};
//一张图片,初始化为panda
Mat
hist
=
new
Mat
();
//用来接收直方图
Mat
hist
=
new
Mat
();
//用来接收直方图
...
@@ -399,14 +458,13 @@ namespace Acc.Img
...
@@ -399,14 +458,13 @@ namespace Acc.Img
{
{
total
=
total
+
hist
.
Get
<
double
>(
i
);
total
=
total
+
hist
.
Get
<
double
>(
i
);
}
}
double
percent
=
0
;
double
percent
=
0
;
int
startIndex
=
-
1
;
int
startIndex
=
-
1
;
int
endIndex
=
-
1
;
int
endIndex
=
-
1
;
for
(
int
i
=
0
;
i
<
256
;
i
++)
//直方图
for
(
int
i
=
0
;
i
<
256
;
i
++)
//直方图
{
{
double
len
=
hist
.
Get
<
double
>(
i
);
double
len
=
hist
.
Get
<
double
>(
i
);
if
(
len
>
100
)
if
(
len
>
100
)
{
//灰度值的像素数小于100的忽略
{
//灰度值的像素数小于100的忽略
percent
=
percent
+
len
/
total
;
percent
=
percent
+
len
/
total
;
if
(
startIndex
==
-
1
)
if
(
startIndex
==
-
1
)
...
@@ -423,8 +481,13 @@ namespace Acc.Img
...
@@ -423,8 +481,13 @@ namespace Acc.Img
}
}
int
avgIndex
=
(
startIndex
+
endIndex
)
/
2
;
int
avgIndex
=
(
startIndex
+
endIndex
)
/
2
;
//avgIndex = GetIntermodesThreshold(hist);
Mat
threshMat
=
new
Mat
();
Mat
threshMat
=
new
Mat
();
Cv2
.
Threshold
(
imageMat
,
threshMat
,
avgIndex
,
255
,
ThresholdTypes
.
BinaryInv
);
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
();
CvBlobs
resultBlobs
=
new
CvBlobs
();
resultBlobs
.
Label
(
threshMat
);
resultBlobs
.
Label
(
threshMat
);
List
<
CvBlob
>
autoBlobList
=
resultBlobs
.
Values
.
Where
(
b
=>
b
.
Area
>
blobArea
).
ToList
();
List
<
CvBlob
>
autoBlobList
=
resultBlobs
.
Values
.
Where
(
b
=>
b
.
Area
>
blobArea
).
ToList
();
...
@@ -432,12 +495,13 @@ namespace Acc.Img
...
@@ -432,12 +495,13 @@ namespace Acc.Img
int
threshIndex
=
avgIndex
;
int
threshIndex
=
avgIndex
;
double
theArea
=
blobArea
*
0.8
;
double
theArea
=
blobArea
*
0.8
;
if
(
theArea
<
1
)
theArea
=
1
;
if
(
theArea
<
1
)
theArea
=
1
;
while
(
true
)
while
(
true
)
{
{
//阈值向下走,找满足条件Blob数量最多的
//阈值向下走,找满足条件Blob数量最多的
threshIndex
=
threshIndex
-
1
;
threshIndex
=
threshIndex
-
1
;
Cv2
.
Threshold
(
imageMat
,
threshMat
,
threshIndex
,
255
,
ThresholdTypes
.
BinaryInv
);
Cv2
.
Threshold
(
imageMat
,
threshMat
,
threshIndex
,
255
,
ThresholdTypes
.
BinaryInv
);
//Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, erodeMat);
CvBlobs
blobs
=
new
CvBlobs
();
CvBlobs
blobs
=
new
CvBlobs
();
blobs
.
Label
(
threshMat
);
blobs
.
Label
(
threshMat
);
List
<
CvBlob
>
blobList
=
blobs
.
Values
.
Where
(
b
=>
b
.
Area
>
theArea
).
ToList
();
List
<
CvBlob
>
blobList
=
blobs
.
Values
.
Where
(
b
=>
b
.
Area
>
theArea
).
ToList
();
...
@@ -457,6 +521,7 @@ namespace Acc.Img
...
@@ -457,6 +521,7 @@ namespace Acc.Img
//阈值向上走,找满足条件Blob数量最多的
//阈值向上走,找满足条件Blob数量最多的
threshIndex
=
threshIndex
+
1
;
threshIndex
=
threshIndex
+
1
;
Cv2
.
Threshold
(
imageMat
,
threshMat
,
threshIndex
,
255
,
ThresholdTypes
.
BinaryInv
);
Cv2
.
Threshold
(
imageMat
,
threshMat
,
threshIndex
,
255
,
ThresholdTypes
.
BinaryInv
);
//Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, erodeMat);
CvBlobs
blobs
=
new
CvBlobs
();
CvBlobs
blobs
=
new
CvBlobs
();
blobs
.
Label
(
threshMat
);
blobs
.
Label
(
threshMat
);
List
<
CvBlob
>
blobList
=
blobs
.
Values
.
Where
(
b
=>
b
.
Area
>
theArea
).
ToList
();
List
<
CvBlob
>
blobList
=
blobs
.
Values
.
Where
(
b
=>
b
.
Area
>
theArea
).
ToList
();
...
@@ -470,6 +535,64 @@ namespace Acc.Img
...
@@ -470,6 +535,64 @@ namespace Acc.Img
break
;
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
;
imageMat
=
threshMat
;
Console
.
WriteLine
(
threshIndex
+
"==== Blob: "
+
blobCount
+
" Area:"
+
theArea
);
Console
.
WriteLine
(
threshIndex
+
"==== Blob: "
+
blobCount
+
" Area:"
+
theArea
);
return
resultBlobs
;
return
resultBlobs
;
...
@@ -486,7 +609,6 @@ namespace Acc.Img
...
@@ -486,7 +609,6 @@ namespace Acc.Img
{
{
Mat
dst
=
new
Mat
();
Mat
dst
=
new
Mat
();
Cv2
.
CvtColor
(
imageMat
,
dst
,
ColorConversionCodes
.
RGB2GRAY
);
Cv2
.
CvtColor
(
imageMat
,
dst
,
ColorConversionCodes
.
RGB2GRAY
);
if
(
thresh
==
-
1
)
if
(
thresh
==
-
1
)
{
{
//全局自动二值 化
//全局自动二值 化
...
@@ -530,11 +652,12 @@ namespace Acc.Img
...
@@ -530,11 +652,12 @@ namespace Acc.Img
{
{
int
blobArea
=
blob
.
Area
;
int
blobArea
=
blob
.
Area
;
double
minArea
=
0.5
*
averageArea
;
double
minArea
=
0.5
*
averageArea
;
double
k
=
1.5
;
if
(
averageArea
<
50
)
if
(
averageArea
<
50
)
{
{
minArea
=
0.2
*
averageArea
;
minArea
=
0.2
*
averageArea
;
}
}
if
(
blobArea
<
minArea
)
if
(
blobArea
<
minArea
*
2
/
3
)
{
{
return
0
;
return
0
;
}
}
...
@@ -550,8 +673,18 @@ namespace Acc.Img
...
@@ -550,8 +673,18 @@ namespace Acc.Img
//{
//{
// return 3;
// return 3;
//}
//}
int
count
=
(
int
)((
blobArea
+
1.5
*
averageArea
)
/
(
1.5
*
averageArea
));
int
count
=
0
;
if
(
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
;
count
=
1
;
}
}
...
@@ -559,7 +692,7 @@ namespace Acc.Img
...
@@ -559,7 +692,7 @@ namespace Acc.Img
{
{
return
count
;
return
count
;
}
}
return
1
;
return
0
;
}
}
/// <summary>
/// <summary>
...
@@ -712,10 +845,12 @@ namespace Acc.Img
...
@@ -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
)
public
static
SplitItem
findCircleInBlob
(
double
[,]
matDistanceArr
,
CvBlobs
blobs
,
CvBlob
blob
,
Point2d
reelCenter
,
double
oneBlobWidth
=
-
1
,
double
oneBlobRadius
=
-
1
)
{
{
SplitItem
item
=
new
SplitItem
();
SplitItem
item
=
new
SplitItem
();
int
ct
=
0
;
while
(
true
)
while
(
true
)
{
{
bool
hasFind
=
false
;
bool
hasFind
=
false
;
bool
hasPixToHandle
=
false
;
bool
hasPixToHandle
=
false
;
ct
+=
1
;
for
(
int
x
=
blob
.
MinX
;
x
<
blob
.
MaxX
;
x
++)
for
(
int
x
=
blob
.
MinX
;
x
<
blob
.
MaxX
;
x
++)
{
{
for
(
int
y
=
blob
.
MinY
;
y
<
blob
.
MaxY
;
y
++)
for
(
int
y
=
blob
.
MinY
;
y
<
blob
.
MaxY
;
y
++)
...
@@ -733,6 +868,7 @@ namespace Acc.Img
...
@@ -733,6 +868,7 @@ namespace Acc.Img
hasPixToHandle
=
true
;
hasPixToHandle
=
true
;
if
(!
item
.
isEnd
)
if
(!
item
.
isEnd
)
{
{
//点到圆心的距离
double
distanceToCircle
=
item
.
minDistanceToCircles
(
x
,
y
,
reelCenter
);
double
distanceToCircle
=
item
.
minDistanceToCircles
(
x
,
y
,
reelCenter
);
if
(
distanceToCircle
==
0
)
if
(
distanceToCircle
==
0
)
{
{
...
@@ -756,9 +892,19 @@ namespace Acc.Img
...
@@ -756,9 +892,19 @@ namespace Acc.Img
break
;
break
;
}
}
}
}
else
{
if
(
ct
>
100
)
{
////hasFind = true;
hasPixToHandle
=
false
;
break
;
}
}
}
}
}
}
}
}
if
(
hasFind
)
if
(
hasFind
)
{
{
break
;
break
;
...
@@ -767,11 +913,12 @@ namespace Acc.Img
...
@@ -767,11 +913,12 @@ namespace Acc.Img
if
(!
hasFind
)
if
(!
hasFind
)
{
{
item
.
calOneItem
(
oneBlobRadius
);
item
.
calOneItem
(
oneBlobRadius
);
}
}
if
(
item
.
isEnd
||
hasPixToHandle
)
if
(
item
.
isEnd
||
!
hasPixToHandle
)
{
{
break
;
break
;
}
}
}
}
return
item
;
return
item
;
}
}
...
@@ -787,6 +934,9 @@ namespace Acc.Img
...
@@ -787,6 +934,9 @@ namespace Acc.Img
public
static
int
findCircles
(
ref
Mat
srcMat
,
Mat
threshMat
,
CvBlobs
blobs
,
int
avgArea
)
public
static
int
findCircles
(
ref
Mat
srcMat
,
Mat
threshMat
,
CvBlobs
blobs
,
int
avgArea
)
{
{
Mat
distanceMat
=
new
Mat
();
Mat
distanceMat
=
new
Mat
();
RediusPt
rediusPt
,
rediusPtOut
;
GetCenter
(
srcMat
,
out
rediusPt
);
GetOutContour
(
srcMat
,
out
rediusPtOut
);
Cv2
.
DistanceTransform
(
threshMat
,
distanceMat
,
DistanceTypes
.
L2
,
DistanceMaskSize
.
Mask3
);
Cv2
.
DistanceTransform
(
threshMat
,
distanceMat
,
DistanceTypes
.
L2
,
DistanceMaskSize
.
Mask3
);
double
[,]
distanceArr
=
new
double
[
threshMat
.
Cols
,
threshMat
.
Rows
];
double
[,]
distanceArr
=
new
double
[
threshMat
.
Cols
,
threshMat
.
Rows
];
...
@@ -820,28 +970,36 @@ namespace Acc.Img
...
@@ -820,28 +970,36 @@ namespace Acc.Img
Console
.
WriteLine
(
"Start find reel center"
);
Console
.
WriteLine
(
"Start find reel center"
);
Point2d
reelCenter
=
new
Point2d
(
0
,
0
)
;
Point2d
reelCenter
=
new
Point2d
(
0
,
0
)
;
//查找中心
////查找中心
foreach
(
CvBlob
blob
in
blobs
.
Values
)
//foreach (CvBlob blob in blobs.Values)
{
//{
int
count
=
BlobHasItem
(
avgArea
,
blob
);
// int count = BlobHasItem(avgArea, blob);
if
(
count
>
10
&&
reelCenter
.
X
==
0
)
// if (count > 10 && reelCenter.X == 0)
{
// {
Point2d
center
=
blob
.
Centroid
;
// Point2d center = blob.Centroid;
//中间的圆,查找圆心
// //中间的圆,查找圆心
if
(
center
.
DistanceTo
(
new
Point2d
(
srcMat
.
Cols
/
2
,
srcMat
.
Rows
/
2
))
<
200
)
// if (center.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
{
// {
reelCenter
=
center
;
// 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 - 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
);
// srcMat.Line(new OpenCvSharp.Point(center.X, center.Y - 10), new OpenCvSharp.Point(center.X, center.Y + 10), Scalar.Blue);
break
;
// 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"
);
Console
.
WriteLine
(
"Start find reel Max Radius, max Width"
);
//最大
//最大
double
maxRadius
=
0
;
double
maxRadius
=
0
;
double
maxWidth
=
0
;
double
maxWidth
=
0
;
List
<
SplitItem
>
averItem
=
new
List
<
SplitItem
>();
averItem
.
Clear
();
foreach
(
CvBlob
blob
in
blobs
.
Values
)
foreach
(
CvBlob
blob
in
blobs
.
Values
)
{
{
...
@@ -852,13 +1010,13 @@ namespace Acc.Img
...
@@ -852,13 +1010,13 @@ namespace Acc.Img
{
{
maxWidth
=
blob
.
Rect
.
Width
;
maxWidth
=
blob
.
Rect
.
Width
;
}
}
if
(
blob
.
Rect
.
Height
>
maxWidth
)
if
(
blob
.
Rect
.
Height
>
maxWidth
)
{
{
maxWidth
=
blob
.
Rect
.
Height
;
maxWidth
=
blob
.
Rect
.
Height
;
}
}
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
);
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
);
averItem
.
Add
(
item
);
foreach
(
Circle
c
in
item
.
circles
)
foreach
(
Circle
c
in
item
.
circles
)
{
{
...
@@ -870,25 +1028,28 @@ namespace Acc.Img
...
@@ -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"
);
Console
.
WriteLine
(
"Start count"
);
int
totalCount
=
0
;
int
totalCount
=
0
;
foreach
(
CvBlob
blob
in
blobs
.
Values
)
foreach
(
CvBlob
blob
in
blobs
.
Values
)
{
{
int
count
=
BlobHasItem
(
avgArea
,
blob
);
int
count
=
BlobHasItem
(
avgArea
,
blob
);
if
(
count
==
1
)
if
(
count
==
1
)
{
{
//单个元器件
//单个元器件
totalCount
=
totalCount
+
1
;
totalCount
=
totalCount
+
1
;
srcMat
.
Circle
((
int
)
blob
.
Centroid
.
X
,
(
int
)
blob
.
Centroid
.
Y
,
(
int
)
maxRadius
/
2
,
Scalar
.
LightGreen
);
srcMat
.
Circle
((
int
)
blob
.
Centroid
.
X
,
(
int
)
blob
.
Centroid
.
Y
,
(
int
)
maxRadius
/
2
,
Scalar
.
LightGreen
);
}
}
else
if
(
count
>
1
)
else
if
(
count
>
1
)
{
{
if
(
count
>
20
)
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
;
continue
;
}
}
...
@@ -897,13 +1058,20 @@ namespace Acc.Img
...
@@ -897,13 +1058,20 @@ namespace Acc.Img
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
,
maxWidth
,
maxRadius
);
SplitItem
item
=
findCircleInBlob
(
distanceArr
,
blobs
,
blob
,
reelCenter
,
maxWidth
,
maxRadius
);
//对所有圆进行分组
//对所有圆进行分组
List
<
List
<
Circle
>>
groupCircles
=
item
.
groupCircles
(
maxWidth
,
maxRadius
,
reelCenter
);
List
<
List
<
Circle
>>
groupCircles
=
item
.
groupCircles
(
maxWidth
,
maxRadius
,
reelCenter
);
Scalar
color
=
Scalar
.
RandomColor
();
//Scalar color = Scalar.RandomColor();
blob
.
Contour
.
Render
(
srcMat
,
color
);
//blob.Contour.Render(srcMat, color);
foreach
(
List
<
Circle
>
groupCircle
in
groupCircles
)
foreach
(
List
<
Circle
>
groupCircle
in
groupCircles
)
{
{
if
(
groupCircle
.
Count
==
0
)
{
continue
;
}
Circle
c
=
groupCircle
[
0
];
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
;
totalCount
=
totalCount
+
1
;
//foreach (Circle cg in groupCircle)
//foreach (Circle cg in groupCircle)
//{
//{
...
@@ -919,128 +1087,128 @@ namespace Acc.Img
...
@@ -919,128 +1087,128 @@ namespace Acc.Img
}
}
//TODO: 测试距离变换,用后删除
//
//
TODO: 测试距离变换,用后删除
public
static
Image
DistanceTransform
(
Image
image
)
//
public static Image DistanceTransform(Image image)
{
//
{
Mat
imageMat
=
BitmapConverter
.
ToMat
(
new
Bitmap
(
image
));
//
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Mat
gray
=
new
Mat
();
//
Mat gray = new Mat();
Cv2
.
CvtColor
(
imageMat
,
gray
,
ColorConversionCodes
.
RGB2GRAY
);
//
Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY);
////开运算
//
////开运算
Mat
k1
=
Mat
.
Ones
(
new
OpenCvSharp
.
Size
(
1
,
1
),
MatType
.
CV_8UC1
);
//
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
);
//
Cv2.MorphologyEx(gray, gray, MorphTypes.Open, k1, new OpenCvSharp.Point(0, 0), 3);
Mat
distanceMat
=
new
Mat
();
//
Mat distanceMat = new Mat();
Mat
labels
=
new
Mat
()
;
//
Mat labels = new Mat() ;
Cv2
.
DistanceTransform
(
gray
,
distanceMat
,
DistanceTypes
.
L2
,
DistanceMaskSize
.
Mask3
)
;
//
Cv2.DistanceTransform(gray, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3) ;
Cv2
.
Normalize
(
distanceMat
,
gray
,
0
,
255
,
NormTypes
.
MinMax
);
//
Cv2.Normalize(distanceMat, gray, 0, 255, NormTypes.MinMax);
gray
.
ConvertTo
(
gray
,
MatType
.
CV_8UC1
);
//
gray.ConvertTo(gray, MatType.CV_8UC1);
Cv2
.
Threshold
(
gray
,
gray
,
0
,
255
,
ThresholdTypes
.
Otsu
);
//
Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu);
Mat
colorImg
=
Mat
.
Zeros
(
gray
.
Size
(),
MatType
.
CV_8UC3
);
//
Mat colorImg = Mat.Zeros(gray.Size(), MatType.CV_8UC3);
Cv2
.
ConnectedComponents
(
gray
,
labels
,
PixelConnectivity
.
Connectivity8
);
//
Cv2.ConnectedComponents(gray, labels, PixelConnectivity.Connectivity8);
Dictionary
<
int
,
SplitItem
>
blobCircles
=
new
Dictionary
<
int
,
SplitItem
>();
//
Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
for
(
int
y
=
0
;
y
<
labels
.
Rows
;
y
++)
//
for(int y=0;y<labels.Rows; y++)
{
//
{
for
(
int
x
=
0
;
x
<
labels
.
Cols
;
x
++)
//
for (int x = 0; x < labels.Cols; x++)
{
//
{
int
label
=
labels
.
At
<
int
>(
y
,
x
);
//
int label = labels.At<int>(y, x);
float
distance
=
distanceMat
.
At
<
float
>(
y
,
x
);
//
float distance = distanceMat.At<float>(y, x);
SplitItem
item
=
new
SplitItem
();
//
SplitItem item = new SplitItem();
if
(
blobCircles
.
ContainsKey
(
label
))
//
if (blobCircles.ContainsKey(label))
{
//
{
item
=
blobCircles
[
label
];
//
item = blobCircles[label];
}
//
}
if
(
distance
>
item
.
currentMaxRadius
)
//
if (distance > item.currentMaxRadius)
{
//
{
item
.
currentMaxRadius
=
distance
;
//
item.currentMaxRadius = distance;
item
.
centerX
=
x
;
//
item.centerX = x;
item
.
centerY
=
y
;
//
item.centerY = y;
}
//
}
blobCircles
[
label
]
=
item
;
//
blobCircles[label] = item;
byte
b
=
(
byte
)(
label
%
255
);
//
byte b = (byte)(label % 255);
byte
g
=
0
;
//
byte g = 0;
if
(
b
<
128
&&
b
>
0
)
//
if (b < 128 && b>0)
{
//
{
g
=
(
byte
)(
255
-
b
);
//
g = (byte)(255 - b);
}
//
}
Vec3b
color
=
new
Vec3b
(
b
,
g
,
0
);
//
Vec3b color = new Vec3b(b,g,0);
colorImg
.
Set
<
Vec3b
>(
y
,
x
,
color
);
//
colorImg.Set<Vec3b>(y, x, color);
}
//
}
}
//
}
foreach
(
SplitItem
circle
in
blobCircles
.
Values
)
//
foreach (SplitItem circle in blobCircles.Values)
{
//
{
circle
.
calOneItem
(-
1
);
//
circle.calOneItem(-1);
}
//
}
while
(
true
)
//
while (true)
{
//
{
for
(
int
y
=
0
;
y
<
labels
.
Rows
;
y
++)
//
for (int y = 0; y < labels.Rows; y++)
{
//
{
for
(
int
x
=
0
;
x
<
labels
.
Cols
;
x
++)
//
for (int x = 0; x < labels.Cols; x++)
{
//
{
int
label
=
labels
.
At
<
int
>(
y
,
x
);
//
int label = labels.At<int>(y, x);
if
(
label
==
0
)
continue
;
//
if (label == 0) continue;
SplitItem
item
=
new
SplitItem
();
//
SplitItem item = new SplitItem();
if
(
blobCircles
.
ContainsKey
(
label
))
//
if (blobCircles.ContainsKey(label))
{
//
{
item
=
blobCircles
[
label
];
//
item = blobCircles[label];
}
//
}
if
(!
item
.
isEnd
)
//
if (!item.isEnd)
{
//
{
double
distance
=
distanceMat
.
At
<
float
>(
y
,
x
);
//
double distance = distanceMat.At<float>(y, x);
//此Blob未结束
//
//此Blob未结束
// bool validPoint = item.isValidPoint(x, y);
//
// bool validPoint = item.isValidPoint(x, y);
bool
validPoint
=
false
;
//
bool validPoint = false;
if
(
validPoint
)
//
if (validPoint)
{
//
{
if
(
distance
>
item
.
currentMaxRadius
)
//
if (distance > item.currentMaxRadius)
{
//
{
item
.
currentMaxRadius
=
distance
;
//
item.currentMaxRadius = distance;
item
.
centerX
=
x
;
//
item.centerX = x;
item
.
centerY
=
y
;
//
item.centerY = y;
blobCircles
[
label
]
=
item
;
//
blobCircles[label] = item;
}
//
}
}
//
}
}
//
}
}
//
}
}
//
}
bool
needContinue
=
false
;
//
bool needContinue = false;
foreach
(
SplitItem
circle
in
blobCircles
.
Values
)
//
foreach (SplitItem circle in blobCircles.Values)
{
//
{
circle
.
calOneItem
();
//
circle.calOneItem();
if
(!
circle
.
isEnd
)
//
if (!circle.isEnd)
{
//
{
needContinue
=
true
;
//
needContinue = true;
}
//
}
}
//
}
if
(!
needContinue
)
//
if (!needContinue)
{
//
{
break
;
//
break;
}
//
}
}
//
}
int
totalCount
=
0
;
//
int totalCount = 0;
foreach
(
SplitItem
item
in
blobCircles
.
Values
)
//
foreach (SplitItem item in blobCircles.Values)
{
//
{
foreach
(
Circle
circle
in
item
.
circles
)
//
foreach(Circle circle in item.circles)
{
//
{
Cv2
.
Circle
(
colorImg
,
circle
.
x
,
circle
.
y
,
(
int
)
circle
.
radius
,
Scalar
.
White
);
//
Cv2.Circle(colorImg, circle.x, circle.y, (int)circle.radius,Scalar.White);
totalCount
++;
//
totalCount++;
}
//
}
}
//
}
Console
.
WriteLine
(
"Total: "
+
totalCount
);
//
Console.WriteLine("Total: " + totalCount);
return
BitmapConverter
.
ToBitmap
(
colorImg
);
//
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.Threshold(dist, dist, 79, 255, ThresholdTypes.Binary);
//Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR);
//
//Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR);
//dist.ConvertTo(dist, MatType.CV_8UC1);
//
//dist.ConvertTo(dist, MatType.CV_8UC1);
//image = BitmapConverter.ToBitmap(dist);
//
//image = BitmapConverter.ToBitmap(dist);
//return image;
//
//return image;
}
//
}
/// <summary>
/// <summary>
/// 获取单个元器件的特征
/// 获取单个元器件的特征
...
@@ -1071,5 +1239,108 @@ namespace Acc.Img
...
@@ -1071,5 +1239,108 @@ namespace Acc.Img
}
}
return
blobArea
;
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
;
}
}
}
}
}
}
AccImage/SplitItem.cs
查看文件 @
0524be0
...
@@ -31,13 +31,18 @@ namespace AccImage
...
@@ -31,13 +31,18 @@ namespace AccImage
{
{
//与平均半径差值在10%以内,认为OK
//与平均半径差值在10%以内,认为OK
double
diff
=
avgRadius
-
currentMaxRadius
;
double
diff
=
avgRadius
-
currentMaxRadius
;
if
(
diff
/
avgRadius
<=
0.
4
)
if
(
diff
/
avgRadius
<=
0.
5
)
{
{
isValid
=
true
;
isValid
=
true
;
}
}
}
}
if
(
isValid
)
if
(
isValid
)
{
{
if
(
currentMaxRadius
==
0
)
{
isEnd
=
true
;
return
;
}
Circle
circle
=
new
Circle
();
Circle
circle
=
new
Circle
();
if
(
theFixRadius
!=
-
1
&&
currentMaxRadius
>
theFixRadius
)
if
(
theFixRadius
!=
-
1
&&
currentMaxRadius
>
theFixRadius
)
{
{
...
@@ -78,6 +83,8 @@ namespace AccImage
...
@@ -78,6 +83,8 @@ namespace AccImage
}
}
List
<
List
<
Circle
>>
allGroupCircle
=
new
List
<
List
<
Circle
>>();
List
<
List
<
Circle
>>
allGroupCircle
=
new
List
<
List
<
Circle
>>();
List
<
int
>
allreadyGroup
=
new
List
<
int
>();
List
<
int
>
allreadyGroup
=
new
List
<
int
>();
//List<Circle> groupCircle = new List<Circle>();
//groupCircle.Clear();
while
(
true
)
while
(
true
)
{
{
List
<
Circle
>
groupCircle
=
new
List
<
Circle
>();
List
<
Circle
>
groupCircle
=
new
List
<
Circle
>();
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论