Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
张士柳
/
eyemLib
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
图表
网络
创建新的问题
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 299c004e
由
张士柳
编写于
2021-01-25 17:54:14 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
无
1 个父辈
88e2a6de
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
468 行增加
和
101 行删除
eyemLib-Sharp/EyemLib.cs
eyemLib/eyemBarCode.cpp
eyemLib/eyemLib.rc
eyemLib-Sharp/EyemLib.cs
查看文件 @
299c004
...
@@ -596,7 +596,7 @@ namespace eyemLib_Sharp
...
@@ -596,7 +596,7 @@ namespace eyemLib_Sharp
//eyemCountObjectIrregularParts(ucpImage, file.Replace(".png", ""), 0d, "IP_LONG_PARTS", 100, 5, ref pNumObj, out tpDstImg);
//eyemCountObjectIrregularParts(ucpImage, file.Replace(".png", ""), 0d, "IP_LONG_PARTS", 100, 5, ref pNumObj, out tpDstImg);
int
ipNum
;
EyemBarCode
*
tpResults
;
int
ipNum
;
EyemBarCode
*
tpResults
;
DataCodeHandle
hObject
;
DataCodeHandle
hObject
;
int
iRes
=
eyemDetectAndDecode
(
ucpImage
,
tpRoi
,
file
.
Replace
(
".png"
,
""
),
"QR_CODE|DATA_MATRIX|CODE_128|CODE_39"
,
out
hObject
,
out
tpResults
,
out
ipNum
,
false
,
21
,
5
,
128
,
215
,
1d
);
int
iRes
=
eyemDetectAndDecode
(
ucpImage
,
tpRoi
,
file
.
Replace
(
".png"
,
""
),
"QR_CODE|DATA_MATRIX|CODE_128|CODE_39"
,
out
hObject
,
out
tpResults
,
out
ipNum
,
false
,
11
,
5
,
128
,
215
);
for
(
int
i
=
0
;
i
<
ipNum
;
i
++)
for
(
int
i
=
0
;
i
<
ipNum
;
i
++)
{
{
Console
.
WriteLine
(
"类型:"
+
Marshal
.
PtrToStringAnsi
(
tpResults
[
i
].
hType
)
+
";坐标"
+
"["
+
tpResults
[
i
].
iCenterX
.
ToString
()
+
","
+
tpResults
[
i
].
iCenterY
.
ToString
()
+
"]"
+
";角度:"
+
tpResults
[
i
].
dAngle
.
ToString
(
"F4"
)
+
","
+
";内容:"
+
Marshal
.
PtrToStringAnsi
(
tpResults
[
i
].
hText
)
+
""
);
Console
.
WriteLine
(
"类型:"
+
Marshal
.
PtrToStringAnsi
(
tpResults
[
i
].
hType
)
+
";坐标"
+
"["
+
tpResults
[
i
].
iCenterX
.
ToString
()
+
","
+
tpResults
[
i
].
iCenterY
.
ToString
()
+
"]"
+
";角度:"
+
tpResults
[
i
].
dAngle
.
ToString
(
"F4"
)
+
","
+
";内容:"
+
Marshal
.
PtrToStringAnsi
(
tpResults
[
i
].
hText
)
+
""
);
...
...
eyemLib/eyemBarCode.cpp
查看文件 @
299c004
...
@@ -462,11 +462,6 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
...
@@ -462,11 +462,6 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
break
;
break
;
}
}
}
}
if
(
!
bDecode
)
{
//如果仍未解码
}
}
}
else
else
{
{
...
@@ -524,6 +519,10 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
...
@@ -524,6 +519,10 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
}
}
}
}
}
}
//解码成功
breakLoop:
breakLoop:
{
{
if
(
strResult
!=
std
::
string
())
if
(
strResult
!=
std
::
string
())
...
@@ -544,6 +543,20 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
...
@@ -544,6 +543,20 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
mtx
.
unlock
();
mtx
.
unlock
();
}
}
static
int
calcHist
(
cv
::
Mat
src
)
{
const
int
histSize
=
256
;
float
range
[]
=
{
0
,
255
};
const
float
*
histRange
=
{
range
};
//calculate the histogram
cv
::
Mat
hist
;
cv
::
calcHist
(
&
src
,
1
,
0
,
cv
::
Mat
(),
hist
,
1
,
&
histSize
,
&
histRange
);
//calculate the background pixels
int
maxIdx
[
2
]
=
{
255
,
255
};
cv
::
minMaxIdx
(
hist
,
NULL
,
NULL
,
NULL
,
maxIdx
);
return
maxIdx
[
0
];
}
int
eyemDetectAndDecode
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
ccFileName
,
const
char
*
ccCodeType
,
IntPtr
*
hObject
,
EyemBarCode
**
hResults
,
int
*
ipNum
,
bool
bUseNiBlack
,
int
iBlockSize
,
const
int
iRangeC
,
int
iSymbolMin
,
int
iSymbolMax
,
double
dScaleUpAndDown
,
double
dToleErr
,
double
dMinorStep
)
int
eyemDetectAndDecode
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
ccFileName
,
const
char
*
ccCodeType
,
IntPtr
*
hObject
,
EyemBarCode
**
hResults
,
int
*
ipNum
,
bool
bUseNiBlack
,
int
iBlockSize
,
const
int
iRangeC
,
int
iSymbolMin
,
int
iSymbolMax
,
double
dScaleUpAndDown
,
double
dToleErr
,
double
dMinorStep
)
{
{
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
tpImage
.
iDepth
,
tpImage
.
vpImage
);
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
tpImage
.
iDepth
,
tpImage
.
vpImage
);
...
@@ -552,25 +565,323 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -552,25 +565,323 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
}
}
//提取ROI
//提取ROI
src
=
src
(
cv
::
Rect
(
tpRoi
.
iXs
,
tpRoi
.
iYs
,
tpRoi
.
iWidth
,
tpRoi
.
iHeight
));
src
=
src
(
cv
::
Rect
(
tpRoi
.
iXs
,
tpRoi
.
iYs
,
tpRoi
.
iWidth
,
tpRoi
.
iHeight
));
//图像原图备份
//真实图像数据与尺寸
cv
::
Mat
backup
=
src
.
clone
();
cv
::
Mat
realSrc
=
src
.
clone
();
int
iRealX
=
realSrc
.
cols
,
iRealY
=
realSrc
.
rows
,
iRealBlockSize
=
iBlockSize
;
//降采样
//降采样
if
(
dScaleUpAndDown
!=
1.
)
if
(
dScaleUpAndDown
!=
1.
)
cv
::
pyrDown
(
src
,
src
,
cv
::
Size
(
cvRound
(
src
.
cols
*
dScaleUpAndDown
),
cvRound
(
src
.
rows
*
dScaleUpAndDown
)));
cv
::
pyrDown
(
src
,
src
,
cv
::
Size
(
cvRound
(
src
.
cols
*
dScaleUpAndDown
),
cvRound
(
src
.
rows
*
dScaleUpAndDown
)));
//用于显示
//用于显示
cv
::
Mat
showMat
;
cv
::
Mat
showMat
;
cv
::
cvtColor
(
src
,
showMat
,
cv
::
COLOR_GRAY2BGR
);
cv
::
cvtColor
(
src
,
showMat
,
cv
::
COLOR_GRAY2BGR
);
//
//图像尺寸,可能为缩放后尺寸
//图像尺寸
int
iX
=
src
.
cols
,
iY
=
src
.
rows
;
int
X
=
src
.
cols
,
Y
=
src
.
rows
;
//解码结果
std
::
vector
<
EyemBarCode
>
*
tpResults
=
new
std
::
vector
<
EyemBarCode
>
();
//测试用
//测试用
cv
::
Mat
srcPrev
,
binary
;
if
(
dScaleUpAndDown
!=
1.
)
{
//太小则不考虑缩小窗口尺寸
if
(
iBlockSize
>
3
)
{
iBlockSize
=
cvRound
((
double
)(
iBlockSize
+
1
)
*
dScaleUpAndDown
)
%
2
==
0
?
cvRound
((
double
)(
iBlockSize
+
1
)
*
dScaleUpAndDown
)
-
1
:
cvRound
((
double
)(
iBlockSize
+
1
)
*
dScaleUpAndDown
)
-
1
;
}
}
//高斯滤波去噪
//高斯滤波去噪
int
ksize
=
cvRound
((
iBlockSize
+
1
)
*
dScaleUpAndDown
)
%
2
==
0
?
cvRound
((
iBlockSize
+
1
)
*
dScaleUpAndDown
)
+
1
:
cvRound
((
iBlockSize
+
1
)
*
dScaleUpAndDown
);
cv
::
Mat
srcPrev
,
binary
,
mask
;
cv
::
GaussianBlur
(
src
,
srcPrev
,
cv
::
Size
(
ksize
,
ksize
),
0.3
);
//确定识别类型
//条码来说会比背景值小,二维码来说会比背景值大
std
::
vector
<
std
::
string
>
hints_
;
split
(
ccCodeType
,
"|"
,
hints_
);
//是否添加一维码检测
bool
addOneDReader
=
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"UPC_A"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"UPC_E"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"EAN_8"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"EAN_13"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODABAR"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODE_39"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODE_93"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODE_128"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"ITF"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"RSS_14"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"RSS_EXPANDED"
)
!=
hints_
.
end
();
//是否添加二维码检测
bool
addTwoDReader
=
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"QR_CODE"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"DATA_MATRIX"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"AZTEC"
)
!=
hints_
.
end
();
//未设置识别类型
if
(
!
addOneDReader
&&
!
addTwoDReader
)
return
FUNC_CANNOT_CALC
;
//检测热点图,s1用来检测一维码;s2用来检测二维码(条码来说会比背景值小,二维码来说会比背景值大)
cv
::
Mat
s1
(
iY
,
iX
,
CV_8UC1
,
cv
::
Scalar
(
0
)),
s2
(
iY
,
iX
,
CV_8UC1
,
cv
::
Scalar
(
0
));
//<//////////////////////通用预处理方式//////////////////////>//
cv
::
adaptiveThreshold
(
src
,
binary
,
255
,
cv
::
ADAPTIVE_THRESH_MEAN_C
,
cv
::
THRESH_BINARY_INV
,
iBlockSize
,
2
);
//突出条码部分
cv
::
morphologyEx
(
src
,
srcPrev
,
cv
::
MORPH_GRADIENT
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
3
,
3
)));
//二值化
cv
::
Mat
srcPrevBin
;
cv
::
threshold
(
srcPrev
,
srcPrevBin
,
0
,
255
,
cv
::
THRESH_BINARY
|
cv
::
THRESH_OTSU
);
//略微膨胀覆盖条码
cv
::
morphologyEx
(
srcPrevBin
,
srcPrevBin
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
iBlockSize
,
iBlockSize
)));
//尽量去掉无关区域
cv
::
bitwise_and
(
srcPrevBin
,
binary
,
binary
);
//连通域分析
cv
::
Mat
labels
,
stats
,
centroids
;
int
nccomps
=
cv
::
connectedComponentsWithStats
(
binary
,
labels
,
stats
,
centroids
);
//过滤连通域面积及长/宽比例不符合的,允许50%误差
std
::
vector
<
uchar
>
colors
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors
[
i
]
=
255
;
double
maxSize
=
cv
::
max
(
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
],
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]);
if
((
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
<
15
)
||
(
maxSize
<
((
double
)
iBlockSize
)
*
(
1.
-
dToleErr
))
||
(
maxSize
>
35
*
iBlockSize
))
{
colors
[
i
]
=
0
;
}
}
//过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
iY
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
uint8_t
*
ptrRow
=
binary
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
iX
;
x
++
)
{
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
ptrRow
[
x
]
=
colors
[
label
];
}
}
});
//膨胀区域
cv
::
Mat
binaryEx
;
cv
::
morphologyEx
(
binary
,
binaryEx
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
iBlockSize
*
2
,
iBlockSize
*
2
)));
//连通域分析
nccomps
=
cv
::
connectedComponentsWithStats
(
binaryEx
,
labels
,
stats
,
centroids
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
//角点响应图
cv
::
Mat
harMap
;
cv
::
Rect
rec
(
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_LEFT
],
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_TOP
],
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
],
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]);
if
((
cv
::
max
(
rec
.
size
().
width
,
rec
.
size
().
height
)
>
5
*
iBlockSize
)
&&
(
rec
.
area
()
>
5
*
std
::
pow
(
iBlockSize
,
2
)))
{
cv
::
cornerHarris
(
src
(
rec
),
harMap
,
iBlockSize
,
3
,
0.04
);
// 归一化与转换
cv
::
normalize
(
harMap
,
harMap
,
0
,
255
,
cv
::
NORM_MINMAX
,
CV_32FC1
,
cv
::
Mat
());
cv
::
convertScaleAbs
(
harMap
,
harMap
);
// 尺寸
cv
::
Size
sz
=
rec
.
size
();
// 用于一维码检测
cv
::
Mat
m1
=
harMap
<
calcHist
(
harMap
);
const
uchar
*
s1ptr
=
m1
.
data
;
uchar
*
d1ptr
=
s1
.
data
;
// 叠加图像
cv
::
parallel_for_
(
cv
::
Range
(
0
,
sz
.
height
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
for
(
int
x
=
0
;
x
<
sz
.
width
;
x
++
)
{
d1ptr
[(
x
+
rec
.
x
)
+
(
y
+
rec
.
y
)
*
iX
]
+=
s1ptr
[(
x
)
+
(
y
)
*
sz
.
width
];
}
}
});
// 用于二维码检测
cv
::
Mat
m2
=
harMap
>
calcHist
(
harMap
);
const
uchar
*
s2ptr
=
m2
.
data
;
uchar
*
d2ptr
=
s2
.
data
;
// 叠加图像
cv
::
parallel_for_
(
cv
::
Range
(
0
,
sz
.
height
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
for
(
int
x
=
0
;
x
<
sz
.
width
;
x
++
)
{
d2ptr
[(
x
+
rec
.
x
)
+
(
y
+
rec
.
y
)
*
iX
]
+=
s2ptr
[(
x
)
+
(
y
)
*
sz
.
width
];
}
}
});
}
}
//输出解码结果
std
::
vector
<
EyemBarCode
>
*
tpResults
=
new
std
::
vector
<
EyemBarCode
>
();
//解码内容
std
::
vector
<
DecodeResult
>
decodeResults
;
//待解码区域,区分条码类型来识别
std
::
vector
<
WaitArea
>
waitAreas
;
//判断要增加的识别,从这一步可以进行分开处理
if
(
addOneDReader
)
{
//添加一维码识别
cv
::
morphologyEx
(
binary
,
mask
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
2
*
iBlockSize
+
1
,
2
*
iBlockSize
+
1
)));
//去掉干扰
cv
::
bitwise_and
(
s1
,
mask
,
s1
);
///<进一步去除干扰
cv
::
morphologyEx
(
s1
,
s1
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
5
,
5
)));
//连通域分析
nccomps
=
cv
::
connectedComponentsWithStats
(
s1
,
labels
,
stats
,
centroids
);
std
::
vector
<
uchar
>
colors2
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors2
[
i
]
=
255
;
if
((
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
<
std
::
pow
(
iBlockSize
,
2
)))
{
colors2
[
i
]
=
0
;
}
}
//过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
iY
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
uint8_t
*
ptrRow
=
s1
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
iX
;
x
++
)
{
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
ptrRow
[
x
]
=
colors2
[
label
];
}
}
});
//后续识别
}
//添加二维码识别
if
(
addTwoDReader
)
{
//突出条码部分
cv
::
morphologyEx
(
src
,
srcPrev
,
cv
::
MORPH_BLACKHAT
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
2
*
iBlockSize
+
1
,
2
*
iBlockSize
+
1
)));
//二值化,用于分割粘连
cv
::
Mat
srcPrevBin
;
cv
::
threshold
(
srcPrev
,
srcPrevBin
,
0
,
255
,
cv
::
THRESH_BINARY
|
cv
::
THRESH_OTSU
);
//
cv
::
morphologyEx
(
srcPrevBin
,
srcPrevBin
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
cvRound
((
double
)
iBlockSize
/
3.
),
cvRound
((
double
)
iBlockSize
/
3.
))));
//断裂处连接在一起
cv
::
morphologyEx
(
s2
,
s2
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
2
*
iBlockSize
+
1
,
2
*
iBlockSize
+
1
)));
//去除干扰
cv
::
bitwise_and
(
srcPrevBin
,
s2
,
s2
);
//对图像过滤
cv
::
Mat
labels
,
stats
,
centroids
;
int
nccomps
=
cv
::
connectedComponentsWithStats
(
s2
,
labels
,
stats
,
centroids
,
4
);
//过滤连通域面积及长/宽比例不符合的,允许50%误差
std
::
vector
<
uchar
>
colors
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors
[
i
]
=
255
;
double
dRate
=
(
double
)
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
]
/
(
double
)
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
];
if
(
!
((
dRate
>=
(
1.
-
dToleErr
)
&&
dRate
<=
(
1.
+
dToleErr
))
&&
((
double
)
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
>
std
::
pow
(
20
*
1.414
*
dScaleUpAndDown
,
2
))))
{
colors
[
i
]
=
0
;
}
}
//第一次过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
iY
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
uint8_t
*
ptrRow
=
s2
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
iX
;
x
++
)
{
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
ptrRow
[
x
]
=
colors
[
label
];
}
}
});
//用于轮廓检测
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contourAll
,
contourFilter
;
findContours
(
s2
,
contourAll
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
contourAll
.
size
());
i
++
)
{
cv
::
RotatedRect
rec
=
cv
::
minAreaRect
(
contourAll
[
i
]);
//偏移量
cv
::
Point2f
pts
[
4
];
rec
.
points
(
pts
);
cv
::
Point
ptStart
,
ptEnd
;
ptStart
=
cv
::
Point
((
pts
[
0
]
+
pts
[
3
])
/
2.
);
ptEnd
=
cv
::
Point
((
pts
[
1
]
+
pts
[
2
])
/
2.
);
//满足矩形条件与面积条件
double
dRate
=
cv
::
min
(
rec
.
size
.
width
,
rec
.
size
.
height
)
/
cv
::
max
(
rec
.
size
.
height
,
rec
.
size
.
width
);
if
(
dRate
>=
(
1.
-
dToleErr
)
&&
dRate
<=
(
1.
+
dToleErr
)
&&
cv
::
min
(
rec
.
size
.
width
,
rec
.
size
.
height
)
>
20
)
{
int
dynSize
=
cvRound
(
cv
::
max
((
double
)
rec
.
boundingRect
().
size
().
height
,
(
double
)
rec
.
boundingRect
().
size
().
width
));
cv
::
Mat
waitArea
=
src
(
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rec
.
center
.
y
)
-
(
2
*
iBlockSize
+
dynSize
/
2
)),
cv
::
min
(
iY
-
1
,
cvRound
(
rec
.
center
.
y
)
+
(
2
*
iBlockSize
+
dynSize
/
2
))),
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rec
.
center
.
x
)
-
(
2
*
iBlockSize
+
dynSize
/
2
)),
cv
::
min
(
iX
-
1
,
cvRound
(
rec
.
center
.
x
)
+
(
2
*
iBlockSize
+
dynSize
/
2
))));
//计算响应图
cv
::
Mat
harMap
;
cv
::
cornerHarris
(
waitArea
,
harMap
,
iBlockSize
,
3
,
0.04
);
// 归一化与转换
cv
::
normalize
(
harMap
,
harMap
,
0
,
255
,
cv
::
NORM_MINMAX
,
CV_32FC1
,
cv
::
Mat
());
cv
::
convertScaleAbs
(
harMap
,
harMap
);
//进一步判断
cv
::
Mat
m2
=
harMap
>
calcHist
(
harMap
);
//用于轮廓检测
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contours
;
findContours
(
m2
,
contours
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
//最大轮廓
std
::
vector
<
cv
::
Point
>
contourMax
=
contours
[
0
];
for
(
int
cc
=
0
;
cc
<
contours
.
size
();
cc
++
)
{
if
(
cv
::
contourArea
(
contours
[
cc
])
>
cv
::
contourArea
(
contourMax
))
{
contourMax
=
contours
[
cc
];
}
}
//未过滤前
cv
::
rectangle
(
showMat
,
cv
::
minAreaRect
(
contourAll
[
i
]).
boundingRect
(),
cv
::
Scalar
(
0
,
0
,
255
),
1
);
rec
=
cv
::
minAreaRect
(
contourMax
);
dRate
=
cv
::
min
(
rec
.
size
.
width
,
rec
.
size
.
height
)
/
cv
::
max
(
rec
.
size
.
height
,
rec
.
size
.
width
);
//判断比例
if
(
dRate
>=
(
1.
-
dToleErr
)
&&
dRate
<=
(
1.
+
dToleErr
)
&&
cv
::
min
(
rec
.
size
.
width
,
rec
.
size
.
height
)
>
20
)
{
//按照比例过滤
int
flags
=
0
;
double
test_line
[
6
]{
0
};
cv
::
LineIterator
it
(
binary
,
ptStart
,
ptEnd
,
4
);
uint8_t
future_pixel
=
0
;
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
//统计均匀性
uint8_t
next_pixel
=
binary
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
//统计黑白像素
test_line
[
flags
]
++
;
if
(
next_pixel
!=
future_pixel
)
{
flags
++
;
future_pixel
=
255
-
future_pixel
;
if
(
flags
==
6
)
{
break
;
}
}
}
//满足比例
double
dRate
=
cv
::
min
((
test_line
[
0
]
+
test_line
[
2
]
+
test_line
[
4
]),
(
test_line
[
1
]
+
test_line
[
3
]
+
test_line
[
5
]))
/
cv
::
max
((
test_line
[
0
]
+
test_line
[
2
]
+
test_line
[
4
]),
(
test_line
[
1
]
+
test_line
[
3
]
+
test_line
[
5
]));
if
(
dRate
>=
(
1.
-
dToleErr
)
&&
dRate
<=
(
1.
+
dToleErr
)
&&
flags
>=
6
)
{
//符合特征
cv
::
line
(
showMat
,
ptStart
,
ptEnd
,
cv
::
Scalar
(
0
,
255
,
255
),
1
);
cv
::
rectangle
(
showMat
,
cv
::
minAreaRect
(
contourAll
[
i
]).
boundingRect
(),
cv
::
Scalar
(
0
,
255
,
0
),
1
);
}
}
}
}
//for (int i = 0; i < contourFilter.size(); i++)
//{
// cv::Rect rect = cv::minAreaRect(contourFilter[i]).boundingRect();
// cv::RotatedRect rRect = cv::minAreaRect(contourFilter[i]);
// //外包矩形
// int dynSize = cvRound(cv::max((double)rect.size().height / dScaleUpAndDown, (double)rect.size().width / dScaleUpAndDown));
// //疑似二维码区域
// cv::Mat waitArea = realSrc(cv::Range(cv::max(0, cvRound(rRect.center.y / dScaleUpAndDown) - cvRound(4.*(double)iBlockSize + dynSize / 2)), cv::min(realSrc.rows - 1, cvRound(rRect.center.y / dScaleUpAndDown) + cvRound(4.*(double)iBlockSize + dynSize / 2))), cv::Range(cv::max(0, cvRound(rRect.center.x / dScaleUpAndDown) - cvRound(4.*(double)iBlockSize + dynSize / 2)), cv::min(realSrc.cols - 1, cvRound(rRect.center.x / dScaleUpAndDown) + cvRound(4.*(double)iBlockSize + dynSize / 2))));
// //处理后再压入识别
// waitAreas.push_back(WaitArea(waitArea, cv::Point(cvRound(rRect.center.x / dScaleUpAndDown), cvRound(rRect.center.y / dScaleUpAndDown)), 0, 0, false, std::vector<cv::Mat>()));
// //画图
// cv::rectangle(showMat, rect, cv::Scalar(0, 255, 0), 1);
// //cv::Point2f points[4];
// //rec.points(points);
// //for (int j = 0; j < 4; j++)
// //{
// // cv::line(showMat, points[j], points[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
// //}
//}
}
//最后解码用原图来解码
//格式化文件名
const
int
bufSize
=
32
;
char
file
[
bufSize
*
4
]
=
{
0
};
sprintf_s
(
file
,
"D:
\\
ResOut
\\
%s-Mark.png"
,
ccFileName
);
cv
::
imwrite
(
file
,
showMat
);
return
FUNC_OK
;
//计算导数
//计算导数
cv
::
Mat
dx
,
dy
,
mag
;
cv
::
Mat
dx
,
dy
,
mag
;
cv
::
Sobel
(
srcPrev
,
dx
,
CV_32F
,
1
,
0
);
cv
::
Sobel
(
srcPrev
,
dx
,
CV_32F
,
1
,
0
);
...
@@ -601,68 +912,52 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -601,68 +912,52 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
int
maxIdx
[
2
]
=
{
255
,
255
};
int
maxIdx
[
2
]
=
{
255
,
255
};
cv
::
minMaxIdx
(
hist
,
NULL
,
NULL
,
NULL
,
maxIdx
);
cv
::
minMaxIdx
(
hist
,
NULL
,
NULL
,
NULL
,
maxIdx
);
//m1用于检测一维码;m2用于检测二维码
//m1用于检测一维码;m2用于检测二维码
cv
::
Mat
m1
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
)),
m2
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
Mat
/*m1(Y, X, CV_8UC1, cv::Scalar(0)),*/
m2
(
iY
,
i
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
cv
::
parallel_for_
(
cv
::
Range
(
0
,
i
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
{
for
(
int
x
=
0
;
x
<
X
;
x
++
)
for
(
int
x
=
0
;
x
<
i
X
;
x
++
)
{
{
if
(
harMap
.
ptr
<
uint8_t
>
(
y
)[
x
]
<
maxIdx
[
0
])
if
(
harMap
.
ptr
<
uint8_t
>
(
y
)[
x
]
<
maxIdx
[
0
])
{
{
m
1
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
255
;
s
1
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
255
;
}
}
else
if
(
harMap
.
ptr
<
uint8_t
>
(
y
)[
x
]
>
maxIdx
[
0
])
else
if
(
harMap
.
ptr
<
uint8_t
>
(
y
)[
x
]
>
maxIdx
[
0
])
{
{
m
2
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
255
;
s
2
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
255
;
}
}
}
}
}
}
});
});
//确定识别类型
std
::
vector
<
std
::
string
>
hints_
;
split
(
ccCodeType
,
"|"
,
hints_
);
//是否添加一维码检测
bool
addOneDReader
=
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"UPC_A"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"UPC_E"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"EAN_8"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"EAN_13"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODABAR"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODE_39"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODE_93"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"CODE_128"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"ITF"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"RSS_14"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"RSS_EXPANDED"
)
!=
hints_
.
end
();
//是否添加二维码检测
bool
addTwoDReader
=
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"QR_CODE"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"DATA_MATRIX"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"AZTEC"
)
!=
hints_
.
end
();
//未设置识别类型
if
(
!
addOneDReader
&&
!
addTwoDReader
)
return
FUNC_CANNOT_CALC
;
//所有解码内容
std
::
vector
<
DecodeResult
>
decodeResults
;
//待解码区域,区分条码类型来识别
std
::
vector
<
WaitArea
>
waitAreas
;
if
(
addOneDReader
)
if
(
addOneDReader
)
{
{
//测试用
cv
::
morphologyEx
(
binary
,
binary
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
iBlockSize
,
iBlockSize
)));
cv
::
Mat
binFilter
;
cv
::
adaptiveThreshold
(
realSrc
,
binFilter
,
255
,
cv
::
ADAPTIVE_THRESH_GAUSSIAN_C
,
cv
::
THRESH_BINARY_INV
,
iBlockSize
,
2
);
//去掉非条码部分
cv
::
bitwise_and
(
binFilter
,
binary
,
binFilter
);
//连通域分析
cv
::
Mat
labels
,
stats
,
centroids
;
cv
::
Mat
labels
,
stats
,
centroids
;
int
nccomps
=
cv
::
connectedComponentsWithStats
(
m1
,
labels
,
stats
,
centroids
,
4
);
int
nccomps
=
cv
::
connectedComponentsWithStats
(
binFilter
,
labels
,
stats
,
centroids
);
//过滤连通域面积及长/宽比例不符合的,允许50%误差
//过滤连通域面积及长/宽比例不符合的,允许50%误差
std
::
vector
<
uchar
>
colors
(
nccomps
+
1
,
0
);
std
::
vector
<
uchar
>
colors
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors
[
i
]
=
255
;
colors
[
i
]
=
255
;
if
((
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
<
std
::
pow
(
iBlockSize
*
dScaleUpAndDown
,
2
)
*
5
)
|
(
m1
.
ptr
<
uint8_t
>
(
cvRound
(
centroids
.
ptr
<
double
>
(
i
)[
1
]))[
cvRound
(
centroids
.
ptr
<
double
>
(
i
)[
0
])]
==
0
))
double
maxSize
=
cv
::
max
(
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
],
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]);
if
((
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
<
15
)
|
(
maxSize
<
iBlockSize
*
(
1.
+
dToleErr
))
|
(
maxSize
>
25
*
iBlockSize
))
{
{
colors
[
i
]
=
0
;
colors
[
i
]
=
0
;
}
}
}
}
//过滤
//过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
cv
::
parallel_for_
(
cv
::
Range
(
0
,
i
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
{
uint8_t
*
ptrRow
=
m1
.
ptr
<
uint8_t
>
(
y
);
uint8_t
*
ptrRow
=
binFilter
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
X
;
x
++
)
for
(
int
x
=
0
;
x
<
i
X
;
x
++
)
{
{
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
...
@@ -670,14 +965,112 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -670,14 +965,112 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
}
}
}
}
});
});
//用于过滤非条码部分
cv
::
Mat
back4Filter
=
binFilter
.
clone
();
cv
::
Mat
binFilter
;
//cv::cvtColor(back4Filter, showMat, cv::COLOR_GRAY2BGR);
cv
::
adaptiveThreshold
(
backup
,
binFilter
,
255
,
cv
::
ADAPTIVE_THRESH_GAUSSIAN_C
,
cv
::
THRESH_BINARY_INV
,
ksize
,
5
);
//处理断裂一维码
cv
::
morphologyEx
(
m1
,
m1
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
cvRound
(
iBlockSize
*
dScaleUpAndDown
),
cvRound
(
iBlockSize
*
dScaleUpAndDown
))));
//用于轮廓检测
//用于轮廓检测
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contourAll
,
contourFilter
;
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contourAll
,
contourFilter
;
findContours
(
m1
,
contourAll
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
findContours
(
binFilter
,
contourAll
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
//初步过滤
for
(
int
i
=
0
;
i
<
int
(
contourAll
.
size
());
i
++
)
{
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourAll
[
i
]);
double
dRate
=
(
double
)
cv
::
max
(
rect
.
size
.
height
,
rect
.
size
.
width
)
/
(
double
)
cv
::
min
(
rect
.
size
.
height
,
rect
.
size
.
width
),
rgt
=
cv
::
contourArea
(
contourAll
[
i
])
/
rect
.
size
.
area
();
if
(
!
(
cv
::
min
(
rect
.
size
.
height
,
rect
.
size
.
width
)
>
iBlockSize
*
4
)
&&
(
cv
::
contourArea
(
contourAll
[
i
])
/
rect
.
size
.
area
())
>
0.35
)
{
contourFilter
.
push_back
(
contourAll
[
i
]);
}
else
cv
::
drawContours
(
binFilter
,
contourAll
,
i
,
cv
::
Scalar
(
0
),
-
1
);
}
const
float
tipLength
=
128
;
for
(
int
c
=
0
;
c
<
8
;
c
++
)
{
std
::
vector
<
cv
::
Point
>
approx
;
//符合条件,继续增加比例过滤条件
for
(
int
i
=
0
;
i
<
int
(
contourFilter
.
size
());
i
++
)
{
//首先进行四边形过滤
cv
::
approxPolyDP
(
cv
::
Mat
(
contourFilter
[
i
]),
approx
,
cv
::
arcLength
(
cv
::
Mat
(
contourFilter
[
i
]),
true
)
*
0.02
,
true
);
if
(
approx
.
size
()
>
10
)
{
cv
::
drawContours
(
binFilter
,
contourFilter
,
i
,
cv
::
Scalar
(
0
),
-
1
);
continue
;
}
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourFilter
[
i
]);
cv
::
Point2f
pts
[
4
];
rect
.
points
(
pts
);
//起点、终点、中点
cv
::
Point
ptStart
,
ptEnd
,
ptMid
;
if
(
cv
::
norm
(
pts
[
0
]
-
pts
[
1
])
>
cv
::
norm
(
pts
[
1
]
-
pts
[
2
]))
{
ptStart
=
cv
::
Point
((
pts
[
0
]
+
pts
[
3
])
/
2.
);
ptEnd
=
cv
::
Point
((
pts
[
1
]
+
pts
[
2
])
/
2.
);
}
else
{
ptStart
=
cv
::
Point
((
pts
[
0
]
+
pts
[
1
])
/
2.
);
ptEnd
=
cv
::
Point
((
pts
[
2
]
+
pts
[
3
])
/
2.
);
}
ptMid
=
(
ptStart
+
ptEnd
)
/
2
;
double
_angle
=
std
::
atan2
(
-
(
ptEnd
.
x
-
ptStart
.
x
),
ptEnd
.
y
-
ptStart
.
y
);
cv
::
Point
pt
[
2
];
pt
[
0
]
=
cv
::
Point
(
cvRound
(
ptMid
.
x
+
tipLength
*
cos
(
_angle
)),
cvRound
(
ptMid
.
y
+
tipLength
*
sin
(
_angle
)));
pt
[
1
]
=
cv
::
Point
(
cvRound
(
ptMid
.
x
+
tipLength
*
cos
(
_angle
+
CV_PI
)),
cvRound
(
ptMid
.
y
+
tipLength
*
sin
(
_angle
+
CV_PI
)));
//防止越界
for
(
int
n
=
0
;
n
<
2
;
n
++
)
{
if
(
pt
[
n
].
x
<
0
)
pt
[
n
].
x
=
0.
f
;
if
(
pt
[
n
].
x
>=
iX
-
1
)
pt
[
n
].
x
=
float
(
iX
-
1
);
if
(
pt
[
n
].
y
<
0
)
pt
[
n
].
y
=
0.
f
;
if
(
pt
[
n
].
y
>=
iY
-
1
)
pt
[
n
].
y
=
float
(
iY
-
1
);
}
bool
bFit
=
false
;
//扫描像素密度,比例接近1:1记录下来,并且黑白间隔数目小大于长度的一半
for
(
int
ii
=
0
;
ii
<
2
;
ii
++
)
{
int
flags
=
0
;
double
test_line
[
6
]{
0
};
cv
::
LineIterator
it
(
back4Filter
,
ptMid
,
pt
[
ii
],
4
);
uint8_t
future_pixel
=
back4Filter
.
ptr
<
uint8_t
>
(
ptMid
.
y
)[
ptMid
.
x
];
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
//统计均匀性
uint8_t
next_pixel
=
back4Filter
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
//统计黑白像素
test_line
[
flags
]
++
;
if
(
next_pixel
!=
future_pixel
)
{
flags
++
;
future_pixel
=
255
-
future_pixel
;
if
(
flags
==
6
)
{
break
;
}
}
}
//满足比例
double
dRate
=
cv
::
min
((
test_line
[
0
]
+
test_line
[
2
]
+
test_line
[
4
]),
(
test_line
[
1
]
+
test_line
[
3
]
+
test_line
[
5
]))
/
cv
::
max
((
test_line
[
0
]
+
test_line
[
2
]
+
test_line
[
4
]),
(
test_line
[
1
]
+
test_line
[
3
]
+
test_line
[
5
]));
if
(
dRate
>=
(
1.
-
dToleErr
*
1.5
)
&&
dRate
<=
(
1.
+
dToleErr
*
1.5
)
&&
flags
>=
6
)
{
bFit
=
true
;
//符合条码特征
break
;
}
}
if
(
!
bFit
)
{
//不符合条码特征
cv
::
drawContours
(
binFilter
,
contourFilter
,
i
,
cv
::
Scalar
(
0
),
-
1
);
}
}
findContours
(
binFilter
,
contourFilter
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
back4Filter
=
binFilter
;
}
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
contourAll
.
size
());
i
++
)
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
contourAll
.
size
());
i
++
)
{
{
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourAll
[
i
]);
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourAll
[
i
]);
...
@@ -710,7 +1103,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -710,7 +1103,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
double
test_line
[
2
]{
0
};
double
test_line
[
2
]{
0
};
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
{
if
(
m
1
.
ptr
<
uint8_t
>
(
cvRound
(
it
.
pos
().
y
*
dScaleUpAndDown
))[
cvRound
(
it
.
pos
().
x
*
dScaleUpAndDown
)]
==
0
)
continue
;
if
(
s
1
.
ptr
<
uint8_t
>
(
cvRound
(
it
.
pos
().
y
*
dScaleUpAndDown
))[
cvRound
(
it
.
pos
().
x
*
dScaleUpAndDown
)]
==
0
)
continue
;
//统计均匀性
//统计均匀性
uint8_t
next_pixel
=
binFilter
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
uint8_t
next_pixel
=
binFilter
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
test_line
[
next_pixel
%
254
]
++
;
test_line
[
next_pixel
%
254
]
++
;
...
@@ -744,16 +1137,16 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -744,16 +1137,16 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//防止越界
//防止越界
for
(
int
n
=
0
;
n
<
4
;
n
++
)
for
(
int
n
=
0
;
n
<
4
;
n
++
)
{
{
if
(
pt
[
n
].
x
<
0
)
pt
[
n
].
x
=
0.
f
;
if
(
pt
[
n
].
x
>=
X
-
1
)
pt
[
n
].
x
=
float
(
X
-
1
);
if
(
pt
[
n
].
y
<
0
)
pt
[
n
].
y
=
0.
f
;
if
(
pt
[
n
].
y
>=
Y
-
1
)
pt
[
n
].
y
=
float
(
Y
-
1
);
if
(
pt
[
n
].
x
<
0
)
pt
[
n
].
x
=
0.
f
;
if
(
pt
[
n
].
x
>=
iX
-
1
)
pt
[
n
].
x
=
float
(
iX
-
1
);
if
(
pt
[
n
].
y
<
0
)
pt
[
n
].
y
=
0.
f
;
if
(
pt
[
n
].
y
>=
iY
-
1
)
pt
[
n
].
y
=
float
(
i
Y
-
1
);
}
}
//用采样的方式提取待解码区域
//用采样的方式提取待解码区域
cv
::
LineIterator
itStHeight
(
backup
,
pt
[
0
],
pt
[
1
],
4
);
cv
::
LineIterator
itStHeight
(
realSrc
,
pt
[
0
],
pt
[
1
],
4
);
cv
::
LineIterator
itEdHeight
(
backup
,
pt
[
3
],
pt
[
2
],
4
);
cv
::
LineIterator
itEdHeight
(
realSrc
,
pt
[
3
],
pt
[
2
],
4
);
cv
::
LineIterator
itStWidth
(
backup
,
pt
[
0
],
pt
[
3
],
4
);
cv
::
LineIterator
itStWidth
(
realSrc
,
pt
[
0
],
pt
[
3
],
4
);
cv
::
LineIterator
itEdWidth
(
backup
,
pt
[
1
],
pt
[
2
],
4
);
cv
::
LineIterator
itEdWidth
(
realSrc
,
pt
[
1
],
pt
[
2
],
4
);
struct
Track
struct
Track
{
{
...
@@ -779,11 +1172,11 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -779,11 +1172,11 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//行
//行
for
(
int
n
=
0
;
n
<
(
int
)
pairStEd
.
size
();
n
+=
iSamplingStep
)
for
(
int
n
=
0
;
n
<
(
int
)
pairStEd
.
size
();
n
+=
iSamplingStep
)
{
{
cv
::
LineIterator
it
(
backup
,
pairStEd
[
n
].
PosS
,
pairStEd
[
n
].
PosE
,
4
);
cv
::
LineIterator
it
(
realSrc
,
pairStEd
[
n
].
PosS
,
pairStEd
[
n
].
PosE
,
4
);
for
(
int
nn
=
0
;
nn
<
it
.
count
;
nn
++
,
++
it
)
//列
for
(
int
nn
=
0
;
nn
<
it
.
count
;
nn
++
,
++
it
)
//列
{
{
//showMat.at<cv::Vec3b>(it.pos()) = cv::Vec3b(0, 255, 0);
//showMat.at<cv::Vec3b>(it.pos()) = cv::Vec3b(0, 255, 0);
srcSampling
.
ptr
<
uint8_t
>
(
0
)[
nn
]
=
backup
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
srcSampling
.
ptr
<
uint8_t
>
(
0
)[
nn
]
=
realSrc
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
}
}
//判断是否为二维码
//判断是否为二维码
cv
::
Mat
testMat
;
cv
::
Mat
testMat
;
...
@@ -803,11 +1196,11 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -803,11 +1196,11 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//存储一维码待解码区域
//存储一维码待解码区域
if
((
int
)
oneDMats
.
size
()
>
0
)
if
((
int
)
oneDMats
.
size
()
>
0
)
{
{
//
//
画图
//画图
//
for (int j = 0; j < 4; j++)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
//
{
{
//
cv::line(showMat, pt[j], pt[(j + 1) % 4], cv::Scalar(0, 255, 255), 1);
cv
::
line
(
showMat
,
pt
[
j
],
pt
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
255
,
255
),
1
);
//
}
}
//cv::circle(showMat, pt[0], 2, cv::Scalar(255, 0, 0), -1);
//cv::circle(showMat, pt[0], 2, cv::Scalar(255, 0, 0), -1);
//cv::circle(showMat, pt[1], 2, cv::Scalar(0, 255, 0), -1);
//cv::circle(showMat, pt[1], 2, cv::Scalar(0, 255, 0), -1);
//cv::circle(showMat, pt[2], 2, cv::Scalar(0, 0, 255), -1);
//cv::circle(showMat, pt[2], 2, cv::Scalar(0, 0, 255), -1);
...
@@ -838,11 +1231,11 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -838,11 +1231,11 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
}
}
}
}
//第一次过滤
//第一次过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
cv
::
parallel_for_
(
cv
::
Range
(
0
,
i
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
{
uint8_t
*
ptrRow
=
m2
.
ptr
<
uint8_t
>
(
y
);
uint8_t
*
ptrRow
=
m2
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
X
;
x
++
)
for
(
int
x
=
0
;
x
<
i
X
;
x
++
)
{
{
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
...
@@ -871,7 +1264,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -871,7 +1264,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//外包矩形
//外包矩形
int
dynSize
=
cvRound
(
cv
::
max
((
double
)
rect
.
size
().
height
/
dScaleUpAndDown
,
(
double
)
rect
.
size
().
width
/
dScaleUpAndDown
));
int
dynSize
=
cvRound
(
cv
::
max
((
double
)
rect
.
size
().
height
/
dScaleUpAndDown
,
(
double
)
rect
.
size
().
width
/
dScaleUpAndDown
));
//疑似二维码区域
//疑似二维码区域
cv
::
Mat
waitArea
=
backup
(
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rRect
.
center
.
y
/
dScaleUpAndDown
)
-
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
)),
cv
::
min
(
backup
.
rows
-
1
,
cvRound
(
rRect
.
center
.
y
/
dScaleUpAndDown
)
+
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
))),
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rRect
.
center
.
x
/
dScaleUpAndDown
)
-
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
)),
cv
::
min
(
backup
.
cols
-
1
,
cvRound
(
rRect
.
center
.
x
/
dScaleUpAndDown
)
+
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
)))).
clone
();
cv
::
Mat
waitArea
=
realSrc
(
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rRect
.
center
.
y
/
dScaleUpAndDown
)
-
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
)),
cv
::
min
(
realSrc
.
rows
-
1
,
cvRound
(
rRect
.
center
.
y
/
dScaleUpAndDown
)
+
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
))),
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rRect
.
center
.
x
/
dScaleUpAndDown
)
-
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
)),
cv
::
min
(
realSrc
.
cols
-
1
,
cvRound
(
rRect
.
center
.
x
/
dScaleUpAndDown
)
+
cvRound
(
4.
*
(
double
)
iBlockSize
*
dScaleUpAndDown
+
dynSize
/
2
)))).
clone
();
//处理后再压入识别
//处理后再压入识别
waitAreas
.
push_back
(
WaitArea
(
waitArea
,
cv
::
Point
(
cvRound
(
rRect
.
center
.
x
/
dScaleUpAndDown
),
cvRound
(
rRect
.
center
.
y
/
dScaleUpAndDown
)),
0
,
0
,
false
,
std
::
vector
<
cv
::
Mat
>
()));
waitAreas
.
push_back
(
WaitArea
(
waitArea
,
cv
::
Point
(
cvRound
(
rRect
.
center
.
x
/
dScaleUpAndDown
),
cvRound
(
rRect
.
center
.
y
/
dScaleUpAndDown
)),
0
,
0
,
false
,
std
::
vector
<
cv
::
Mat
>
()));
//画图
//画图
...
@@ -911,11 +1304,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -911,11 +1304,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
*
hResults
=
tpResults
->
data
();
*
hResults
=
tpResults
->
data
();
*
ipNum
=
static_cast
<
int
>
(
tpResults
->
size
());
*
ipNum
=
static_cast
<
int
>
(
tpResults
->
size
());
*
hObject
=
reinterpret_cast
<
IntPtr
>
(
tpResults
);
*
hObject
=
reinterpret_cast
<
IntPtr
>
(
tpResults
);
//格式化文件名
//const int bufSize = 32;
//char file[bufSize * 4] = { 0 };
//sprintf_s(file, "D:\\ResOut\\%s-Mark.png", ccFileName);
//cv::imwrite(file, showMat);
return
FUNC_OK
;
return
FUNC_OK
;
}
}
...
@@ -1200,30 +1588,9 @@ int eyemCalcDetectParameter(EyemImage tpImage, EyemRect tpRoi, const char *ccFil
...
@@ -1200,30 +1588,9 @@ int eyemCalcDetectParameter(EyemImage tpImage, EyemRect tpRoi, const char *ccFil
waitAreas
.
push_back
(
WaitArea
(
waitArea
,
cv
::
Point
(
cvRound
(
rRect
.
center
.
x
),
cvRound
(
rRect
.
center
.
y
)),
0
,
0
,
false
,
std
::
vector
<
cv
::
Mat
>
()));
waitAreas
.
push_back
(
WaitArea
(
waitArea
,
cv
::
Point
(
cvRound
(
rRect
.
center
.
x
),
cvRound
(
rRect
.
center
.
y
)),
0
,
0
,
false
,
std
::
vector
<
cv
::
Mat
>
()));
}
}
}
}
enum
{
NONE
,
AZTEC
,
CODABAR
,
CODE_39
,
CODE_93
,
CODE_128
,
DATA_MATRIX
,
EAN_8
,
EAN_13
,
ITF
,
MAXICODE
,
PDF_417
,
QR_CODE
,
RSS_14
,
RSS_EXPANDED
,
UPC_A
,
UPC_E
,
UPC_EAN_EXTENSION
};
std
::
vector
<
std
::
string
>
hints_
=
{
"AZTEC"
,
"CODABAR"
,
"CODE_39"
,
"CODE_93"
,
"CODE_128"
,
"DATA_MATRIX"
,
"EAN_8"
,
"EAN_13"
,
"ITF"
,
"MAXICODE"
,
"PDF_417"
,
"QR_CODE"
,
"RSS_14"
,
"RSS_EXPANDED"
,
"UPC_A"
,
"UPC_E"
,
"UPC_EAN_EXTENSION"
};
std
::
vector
<
std
::
string
>
hints_
=
{
"AZTEC"
,
"CODABAR"
,
"CODE_39"
,
"CODE_93"
,
"CODE_128"
,
"DATA_MATRIX"
,
"EAN_8"
,
"EAN_13"
,
"ITF"
,
"MAXICODE"
,
"PDF_417"
,
"QR_CODE"
,
"RSS_14"
,
"RSS_EXPANDED"
,
"UPC_A"
,
"UPC_E"
,
"UPC_EAN_EXTENSION"
};
//解码
//解码
decodeMul
(
waitAreas
,
hints_
,
showMat
,
decodeResults
,
iBlockSize
,
10
,
1.0
);
decodeMul
(
waitAreas
,
hints_
,
showMat
,
decodeResults
,
iBlockSize
,
10
,
1.0
);
return
FUNC_OK
;
return
FUNC_OK
;
}
}
...
...
eyemLib/eyemLib.rc
查看文件 @
299c004
此文件类型无法预览
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论