Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
张士柳
/
eyemLib
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
图表
网络
创建新的问题
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 88e2a6de
由
张士柳
编写于
2021-01-15 17:26:03 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
无
1 个父辈
1352ebcf
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
307 行增加
和
294 行删除
eyemLib-Sharp/EyemLib.cs
eyemLib/eyemBarCode.cpp
eyemLib-Sharp/EyemLib.cs
查看文件 @
88e2a6d
...
@@ -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
,
1
1
,
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
,
2
1
,
5
,
128
,
215
,
1d
);
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
)
+
""
);
...
@@ -658,7 +658,7 @@ namespace eyemLib_Sharp
...
@@ -658,7 +658,7 @@ namespace eyemLib_Sharp
if
(
tpPoints
==
null
)
if
(
tpPoints
==
null
)
throw
new
ArgumentNullException
(
"cvPoint2D32f"
);
throw
new
ArgumentNullException
(
"cvPoint2D32f"
);
//分配结构体需要的内存
//分配结构体需要的内存
IntPtr
memory
=
(
IntPtr
)
Marshal
.
AllocHGlobal
(
checked
(
Marshal
.
SizeOf
(
typeof
(
EyemOcsDXY
))
*
iLength
));
IntPtr
memory
=
Marshal
.
AllocHGlobal
(
checked
(
Marshal
.
SizeOf
(
typeof
(
EyemOcsDXY
))
*
iLength
));
for
(
int
index
=
0
;
index
<
iLength
;
index
++)
for
(
int
index
=
0
;
index
<
iLength
;
index
++)
{
{
Marshal
.
StructureToPtr
(
tpPoints
[
index
],
(
IntPtr
)(
checked
((
long
)
memory
+
index
*
Marshal
.
SizeOf
(
typeof
(
EyemOcsDXY
)))),
false
);
Marshal
.
StructureToPtr
(
tpPoints
[
index
],
(
IntPtr
)(
checked
((
long
)
memory
+
index
*
Marshal
.
SizeOf
(
typeof
(
EyemOcsDXY
)))),
false
);
...
...
eyemLib/eyemBarCode.cpp
查看文件 @
88e2a6d
...
@@ -560,6 +560,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -560,6 +560,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//用于显示
//用于显示
cv
::
Mat
showMat
;
cv
::
Mat
showMat
;
cv
::
cvtColor
(
src
,
showMat
,
cv
::
COLOR_GRAY2BGR
);
cv
::
cvtColor
(
src
,
showMat
,
cv
::
COLOR_GRAY2BGR
);
//
//图像尺寸
//图像尺寸
int
X
=
src
.
cols
,
Y
=
src
.
rows
;
int
X
=
src
.
cols
,
Y
=
src
.
rows
;
//解码结果
//解码结果
...
@@ -583,31 +584,9 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -583,31 +584,9 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
cv
::
threshold
(
srcPrev
,
binary
,
0
,
255
,
cv
::
THRESH_BINARY
|
cv
::
THRESH_OTSU
);
cv
::
threshold
(
srcPrev
,
binary
,
0
,
255
,
cv
::
THRESH_BINARY
|
cv
::
THRESH_OTSU
);
//膨胀
//膨胀
cv
::
morphologyEx
(
binary
,
binary
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
cvRound
(
iBlockSize
*
dScaleUpAndDown
/
3.
),
cvRound
(
iBlockSize
*
dScaleUpAndDown
/
3.
))));
cv
::
morphologyEx
(
binary
,
binary
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
cvRound
(
iBlockSize
*
dScaleUpAndDown
/
3.
),
cvRound
(
iBlockSize
*
dScaleUpAndDown
/
3.
))));
//图像增强
//double min, max;
//cv::minMaxLoc(src, &min, &max, NULL, NULL, binary);
////条码测试用
//cv::Mat xDer, yDer;
//cv::normalize(dx, dx, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
//cv::convertScaleAbs(dx, xDer);
//cv::normalize(dy, dy, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
//cv::convertScaleAbs(dy, yDer);
cv
::
Mat
mphyEx
;
cv
::
morphologyEx
(
src
,
mphyEx
,
cv
::
MORPH_BLACKHAT
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
cvRound
(
iBlockSize
*
dScaleUpAndDown
)
*
2
+
1
,
cvRound
(
iBlockSize
*
dScaleUpAndDown
)
*
2
+
1
)));
//确定背景
//cv::Mat binary4;
//cv::threshold(mphyEx, binary4, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//double min, max;
//cv::minMaxLoc(src, &min, &max, NULL, NULL, mphyEx);
//cv::Mat background(Y, X, CV_8UC1, max);
//src.copyTo(background, binary4);
//计算角点响应
//计算角点响应
cv
::
Mat
harMap
;
cv
::
Mat
harMap
;
cv
::
cornerHarris
(
src
,
harMap
,
cvRound
(
iBlockSize
*
dScaleUpAndDown
),
3
,
0.04
);
//对二维码效果比较好
cv
::
cornerHarris
(
src
,
harMap
,
cvRound
(
iBlockSize
*
dScaleUpAndDown
),
3
,
0.04
);
// 归一化与转换
// 归一化与转换
cv
::
normalize
(
harMap
,
harMap
,
0
,
255
,
cv
::
NORM_MINMAX
,
CV_32FC1
,
cv
::
Mat
());
cv
::
normalize
(
harMap
,
harMap
,
0
,
255
,
cv
::
NORM_MINMAX
,
CV_32FC1
,
cv
::
Mat
());
cv
::
convertScaleAbs
(
harMap
,
harMap
);
cv
::
convertScaleAbs
(
harMap
,
harMap
);
...
@@ -639,13 +618,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -639,13 +618,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
}
}
}
}
});
});
//测试用
return
FUNC_OK
;
//确定识别类型
//确定识别类型
std
::
vector
<
std
::
string
>
hints_
;
std
::
vector
<
std
::
string
>
hints_
;
split
(
ccCodeType
,
"|"
,
hints_
);
split
(
ccCodeType
,
"|"
,
hints_
);
...
@@ -661,9 +633,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -661,9 +633,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"ITF"
)
!=
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_14"
)
!=
hints_
.
end
()
||
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"RSS_EXPANDED"
)
!=
hints_
.
end
();
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"RSS_EXPANDED"
)
!=
hints_
.
end
();
//是否添加二维码检测
//是否添加二维码检测
bool
addTwoDReader
=
std
::
find
(
hints_
.
begin
(),
hints_
.
end
(),
"QR_CODE"
)
!=
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
(),
"DATA_MATRIX"
)
!=
hints_
.
end
()
||
...
@@ -671,7 +640,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -671,7 +640,6 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//未设置识别类型
//未设置识别类型
if
(
!
addOneDReader
&&
!
addTwoDReader
)
if
(
!
addOneDReader
&&
!
addTwoDReader
)
return
FUNC_CANNOT_CALC
;
return
FUNC_CANNOT_CALC
;
//所有解码内容
//所有解码内容
std
::
vector
<
DecodeResult
>
decodeResults
;
std
::
vector
<
DecodeResult
>
decodeResults
;
//待解码区域,区分条码类型来识别
//待解码区域,区分条码类型来识别
...
@@ -835,14 +803,14 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -835,14 +803,14 @@ 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);
waitAreas
.
push_back
(
WaitArea
(
cv
::
Mat
(),
ptMid
,
getThreshVal_Otsu_8u
(
oneDMats
[
0
]),
_angle
*
180.
/
PI
,
true
,
oneDMats
));
waitAreas
.
push_back
(
WaitArea
(
cv
::
Mat
(),
ptMid
,
getThreshVal_Otsu_8u
(
oneDMats
[
0
]),
_angle
*
180.
/
PI
,
true
,
oneDMats
));
}
}
}
}
...
@@ -904,47 +872,12 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -904,47 +872,12 @@ 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
=
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
();
////获取起始阈值
//double threshVal = getThreshVal_Otsu_8u(waitArea);
////去掉背景
//cv::parallel_for_(cv::Range(0, waitArea.rows), [&](const cv::Range range)->void {
// for (int y = range.start; y < range.end; y++)
// {
// for (int x = 0; x < waitArea.cols; x++)
// {
// if (waitArea.ptr<uint8_t>(y)[x] > threshVal + 7)
// {
// waitArea.ptr<uint8_t>(y)[x] = cvRound(threshVal);
// }
// }
// }
//});
////处理后再压入识别
//cv::Mat locHarMap;
//cv::cornerHarris(waitArea, locHarMap, cvRound(iBlockSize*dScaleUpAndDown), 3, 0.04);
//// 归一化与转换
//cv::normalize(locHarMap, locHarMap, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
//cv::convertScaleAbs(locHarMap, locHarMap);
////二值化
//cv::Mat binary;
//cv::threshold(locHarMap, binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//处理后再压入识别
//处理后再压入识别
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
>
()));
//画图
//画图
cv
::
rectangle
(
showMat
,
rect
,
cv
::
Scalar
(
0
,
255
,
0
),
1
);
cv
::
rectangle
(
showMat
,
rect
,
cv
::
Scalar
(
0
,
255
,
0
),
1
);
}
}
////绘制图形
//for (int j = 0; j < contourFilter.size(); j++)
//{
// cv::Point2f pts[4];
// cv::minAreaRect(contourFilter[j]).points(pts);
// //画透明蒙版
// std::vector<cv::Point> vT = { cv::Point(pts[0]),cv::Point(pts[1]) ,cv::Point(pts[2]) ,cv::Point(pts[3]) };
// cv::fillConvexPoly(showMat, vT, cv::Scalar(0, 255, 255));
//}
}
}
//cv::Mat dst;
//showMat.copyTo(dst);
//解码
//解码
decodeMul
(
waitAreas
,
hints_
,
showMat
,
decodeResults
,
iBlockSize
,
iRangeC
,
dMinorStep
);
decodeMul
(
waitAreas
,
hints_
,
showMat
,
decodeResults
,
iBlockSize
,
iRangeC
,
dMinorStep
);
//输出结果
//输出结果
...
@@ -978,220 +911,15 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
...
@@ -978,220 +911,15 @@ 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
);
//cv::addWeighted(dst, 0.7, showMat, 0.3, 0, dst);
//showMat = dst;
//格式化文件名
//格式化文件名
const
int
bufSize
=
32
;
//const int bufSize = 32;
char
file
[
bufSize
*
4
]
=
{
0
};
//char file[bufSize * 4] = { 0 };
sprintf_s
(
file
,
"D:
\\
ResOut
\\
%s-Mark.png"
,
ccFileName
);
//sprintf_s(file, "D:\\ResOut\\%s-Mark.png", ccFileName);
cv
::
imwrite
(
file
,
showMat
);
//cv::imwrite(file, showMat);
return
FUNC_OK
;
////局部二值化
//cv::adaptiveThreshold(src, binary, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, iBlockSize, 2);
////去掉大部分干扰项
//binary &= mask;
////对二值图像过滤
//cv::Mat labels, stats, centroids;
//int nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids, 4);
////过滤连通域面积及长/宽比例不符合的,允许50%误差
//std::vector<uchar> colors(nccomps + 1, 0);
//for (int i = 1; i < nccomps; i++) {
// colors[i] = 255;
// if ((stats.ptr<int>(i)[cv::CC_STAT_WIDTH] > iBlockSize * 15 * 1.414*(1. + dToleErr)) | (stats.ptr<int>(i)[cv::CC_STAT_HEIGHT] > iBlockSize * 15 * 1.414*(1. + dToleErr))\
// | (false))
// {
// colors[i] = 0;
// }
//}
////第一次过滤
//cv::parallel_for_(cv::Range(0, Y), [&](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 < X; x++)
// {
// int label = labels.ptr<int>(y)[x];
// CV_Assert(0 <= label && label <= nccomps);
// ptrRow[x] = colors[label];
// }
// }
//});
////cv::cvtColor(binary, showMat, cv::COLOR_GRAY2BGR);
//const int iScanRadius = 35;
////最好还是用线扫描的方法,具体扫描全图还是按照中心点来扫看时间
////指定长度十字网格遍历是否满足条件黑白比例在1:1,考虑其他方式去扫描,可能速度上会慢一些,如果区分满足各自条件可能会好一些
////,这样可以将其他不必要的过滤掉,最后再合成一张图;2,扫描宽度,根据宽度流来确定是否属于条码、qr、datamatrix,黑白宽度;
////宽度打开都在一个很小变动范围内,允许50%的误差,宽度密度相较目前判断方式可也确定是否是黑白格分布,考虑到一维条码,八个方向只需满足一个方向即可
////这样可以过滤掉一些孤立长条
////vPts[0].Pt = cv::Point(3610, 2433);
//cv::Mat label(Y, X, CV_8UC1, cv::Scalar(0));
//cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void {
// for (int y = range.start; y < range.end; y++)
// {
// for (int x = 0; x < X; x++)
// {
// uint8_t future_pixel = binary.ptr<uint8_t>(y)[x];
// if (!future_pixel)
// {
// continue;
// }
// bool iFlag = 0;
// //判断白色像素部分占整条线的比例
// for (double t = -180; t < 180; t += 45)
// {
// float xx = float(x + iScanRadius * cos(t* 0.01745));
// float yy = float(y + iScanRadius * sin(t* 0.01745));
// //防止越界
// if (xx < 0) xx = 0; if (xx >= X - 1) xx = X - 1; if (yy < 0) yy = 0; if (yy >= Y - 1) yy = Y - 1;
// cv::LineIterator it(binary, cv::Point(x, y), cv::Point(cvRound(xx), cvRound(yy)), 4);
// //扫描像素密度,比例接近1:1记录下来
// int length = 0;
// std::vector<double> test_lines;
// double test_line[2]{ 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[next_pixel % 254]++;
// length++;
// if (next_pixel != future_pixel)
// {
// if (!next_pixel)
// {
// test_lines.push_back(length);
// }
// future_pixel = 255 - future_pixel;
// length = 0;
// }
// }
// if (cv::max(test_line[0], test_line[1]) <= 0) continue;
// //至少存在l个方向满足黑白1:1比例,并且满足黑白交替比例大概在1:1
// double dRate = cv::min(test_line[0], test_line[1]) / cv::max(test_line[0], test_line[1]);
// if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr))
// {
// //满足条件,再判断当前方向的宽度是否
// iFlag = true;
// //cv::putText(showMat, "OK", vPts[c].Pt, cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(0, 0, 255));
// //showMat.at<cv::Vec3b>(cv::Point(x, y)) = cv::Vec3b(0, 255, 0);
// label.ptr<uint8_t>(y)[x] = 255;
// break;
// }
// }
// }
// }
//});
//for (int c = 0; c < (int)vPts.size(); c++)
//{
// bool iFlag = 0;
// uint8_t future_pixel = binary.ptr<uint8_t>(vPts[c].Pt.y)[vPts[c].Pt.x];
// //判断白色像素部分占整条线的比例
// for (double t = -180; t < 180; t += 45)
// {
// float x = float(vPts[c].Pt.x + iScanRadius * cos(t* 0.01745));
// float y = float(vPts[c].Pt.y + iScanRadius * sin(t* 0.01745));
// //防止越界
// if (x < 0) x = 0; if (x >= X - 1) x = X - 1; if (y < 0) y = 0; if (y >= Y - 1) y = Y - 1;
// cv::LineIterator it(binary, vPts[c].Pt, cv::Point(cvRound(x), cvRound(y)), 4);
// //扫描像素密度,比例接近1:1记录下来
// //测试用
// std::vector<cv::Point> test_point;
// int length = 0;
// std::vector<double> test_lines;
// double test_line[2]{ 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[next_pixel % 254]++;
// length++;
// if (next_pixel != future_pixel)
// {
// if (length > 1)
// {
// test_lines.push_back(length);
// }
// future_pixel = 255 - future_pixel;
// length = 0;
// }
// //test_point.push_back(it.pos());
// //showMat.at<cv::Vec3b>(it.pos()) = cv::Vec3b(0, 255, 0);
// }
// //至少存在l个方向满足黑白1:1比例,并且满足黑白交替比例大概在1:1
// double dRate = cv::min(test_line[0], test_line[1]) / cv::max(test_line[0], test_line[1]);
// if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && (test_lines.size() >= T))
// {
// //满足条件,再判断当前方向的宽度是否
// iFlag = true;
// //cv::putText(showMat, "OK", vPts[c].Pt, cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(0, 0, 255));
// //for (int n = 0; n < test_point.size(); n++)
// //{
// // showMat.at<cv::Vec3b>(test_point[n]) = cv::Vec3b(0, 0, 255);
// //}
// //std::cout << "xx" << std::endl;
// }
// }
// //对四个方向进行进一步进行过滤,黑白间隔跨度阈值限定
// if ((!iFlag))
// {
// colors[vPts[c].Label] = 0;
// }
//}
//二次过滤
//cv::parallel_for_(cv::Range(0, Y), [&](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 < X; x++)
// {
// int label = labels.ptr<int>(y)[x];
// CV_Assert(0 <= label && label <= nccomps);
// ptrRow[x] = colors[label];
// }
// }
//});
//cv::Mat binPrev;
//cv::morphologyEx(label, binPrev, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(iBlockSize, iBlockSize)));
////用于轮廓检测(最终过滤过的图)
//std::vector<cv::Vec4i> hierarchy;
//std::vector<std::vector<cv::Point>> contourAll, contourFilter;
//findContours(binPrev, contourAll, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
//for (int i = 0; i < static_cast<int>(contourAll.size()); i++)
//{
// cv::RotatedRect rect = cv::minAreaRect(contourAll[i]);
// double dRate = rect.size.width / rect.size.height;
// std::vector<cv::Point> approx;
// cv::approxPolyDP(cv::Mat(contourAll[i]), approx, cv::arcLength(cv::Mat(contourAll[i]), true)*0.02, true);
// //满足四边形条件
// if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && (approx.size() >= 4 && approx.size() < 8) && (cv::contourArea(contourAll[i]) > std::pow(iBlockSize * 12 * (1. - dToleErr), 2)))
// {
// contourFilter.push_back(contourAll[i]);
// }
//}
//if (contourFilter.size() < 1)
//{
// return FUNC_CANNOT_CALC;
//}
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemCalcDetectParameter
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
ccFileName
,
int
*
ipNum
,
int
iBlockSize
,
const
int
iRangeC
,
int
*
iSymbolMin
,
int
*
iSymbolMax
,
double
dScaleUpAndDown
,
double
dMinorStep
)
int
eyemCalcDetectParameter
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
ccFileName
,
bool
bTrainOneD
,
int
iBlockSize
,
int
*
ipNum
,
int
*
iSymbolMin
,
int
*
iSymbolMax
)
{
{
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
);
if
(
src
.
empty
())
{
if
(
src
.
empty
())
{
...
@@ -1199,9 +927,6 @@ int eyemCalcDetectParameter(EyemImage tpImage, EyemRect tpRoi, const char *ccFil
...
@@ -1199,9 +927,6 @@ int eyemCalcDetectParameter(EyemImage tpImage, EyemRect tpRoi, const char *ccFil
}
}
//提取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
));
//降采样
if
(
dScaleUpAndDown
!=
1.
)
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
);
...
@@ -1209,8 +934,296 @@ int eyemCalcDetectParameter(EyemImage tpImage, EyemRect tpRoi, const char *ccFil
...
@@ -1209,8 +934,296 @@ int eyemCalcDetectParameter(EyemImage tpImage, EyemRect tpRoi, const char *ccFil
int
X
=
src
.
cols
,
Y
=
src
.
rows
;
int
X
=
src
.
cols
,
Y
=
src
.
rows
;
//高斯滤波去噪
//高斯滤波去噪
cv
::
Mat
srcPrev
,
binary
;
cv
::
Mat
srcPrev
,
binary
;
int
ksize
=
cvRound
((
iBlockSize
+
1
)
*
dScaleUpAndDown
)
%
2
==
0
?
cvRound
((
iBlockSize
+
1
)
*
dScaleUpAndDown
)
+
1
:
cvRound
((
iBlockSize
+
1
)
*
dScaleUpAndDown
);
cv
::
GaussianBlur
(
src
,
srcPrev
,
cv
::
Size
(
iBlockSize
,
iBlockSize
),
0.3
);
cv
::
GaussianBlur
(
src
,
srcPrev
,
cv
::
Size
(
ksize
,
ksize
),
0.3
);
//计算角点响应
cv
::
Mat
harMap
;
cv
::
cornerHarris
(
src
,
harMap
,
iBlockSize
,
3
,
0.04
);
// 归一化与转换
cv
::
normalize
(
harMap
,
harMap
,
0
,
255
,
cv
::
NORM_MINMAX
,
CV_32FC1
,
cv
::
Mat
());
cv
::
convertScaleAbs
(
harMap
,
harMap
);
//计算背景像素
const
int
histSize
=
256
;
float
range
[]
=
{
0
,
255
};
const
float
*
histRange
=
{
range
};
//calculate the histogram
cv
::
Mat
hist
;
cv
::
calcHist
(
&
harMap
,
1
,
0
,
cv
::
Mat
(),
hist
,
1
,
&
histSize
,
&
histRange
);
//calculate the background pixels
int
maxIdx
[
2
]
=
{
255
,
255
};
cv
::
minMaxIdx
(
hist
,
NULL
,
NULL
,
NULL
,
maxIdx
);
//m1用于检测一维码;m2用于检测二维码
cv
::
Mat
m1
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
)),
m2
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
for
(
int
x
=
0
;
x
<
X
;
x
++
)
{
if
(
harMap
.
ptr
<
uint8_t
>
(
y
)[
x
]
<
maxIdx
[
0
])
{
m1
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
255
;
}
else
if
(
harMap
.
ptr
<
uint8_t
>
(
y
)[
x
]
>
maxIdx
[
0
])
{
m2
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
255
;
}
}
}
});
//允许误差
const
double
dToleErr
=
0.35
;
//所有解码内容
std
::
vector
<
DecodeResult
>
decodeResults
;
//待解码区域,区分条码类型来识别
std
::
vector
<
WaitArea
>
waitAreas
;
//是否是计算一维码参数
if
(
bTrainOneD
)
{
//对于一维码如何确定参数,暂时按照能识别到的个数来判断
cv
::
Mat
labels
,
stats
,
centroids
;
int
nccomps
=
cv
::
connectedComponentsWithStats
(
m1
,
labels
,
stats
,
centroids
,
4
);
//过滤连通域面积及长/宽比例不符合的,允许50%误差
std
::
vector
<
uchar
>
colors
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors
[
i
]
=
255
;
if
((
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
<
20
)
|
(
m1
.
ptr
<
uint8_t
>
(
cvRound
(
centroids
.
ptr
<
double
>
(
i
)[
1
]))[
cvRound
(
centroids
.
ptr
<
double
>
(
i
)[
0
])]
==
0
))
{
colors
[
i
]
=
0
;
}
}
//过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
uint8_t
*
ptrRow
=
m1
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
X
;
x
++
)
{
int
label
=
labels
.
ptr
<
int
>
(
y
)[
x
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
ptrRow
[
x
]
=
colors
[
label
];
}
}
});
//用于过滤非条码部分
cv
::
Mat
binFilter
;
cv
::
adaptiveThreshold
(
src
,
binFilter
,
255
,
cv
::
ADAPTIVE_THRESH_GAUSSIAN_C
,
cv
::
THRESH_BINARY_INV
,
iBlockSize
,
5
);
//处理断裂一维码
cv
::
morphologyEx
(
m1
,
m1
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
iBlockSize
,
iBlockSize
)));
//用于轮廓检测
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contourAll
,
contourFilter
;
findContours
(
m1
,
contourAll
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
contourAll
.
size
());
i
++
)
{
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourAll
[
i
]);
//最大宽度限制
double
minLen
=
cv
::
min
(
rect
.
size
.
height
,
rect
.
size
.
width
);
if
(
minLen
<
8.
*
iBlockSize
*
(
1.
+
dToleErr
))
{
//增加比例过滤条件
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
;
cv
::
LineIterator
it
(
binFilter
,
(
ptMid
+
ptEnd
)
/
2
,
(
ptMid
+
ptStart
)
/
2
,
4
);
double
dis
=
cv
::
norm
((
ptMid
+
ptEnd
)
/
2
-
(
ptMid
+
ptStart
)
/
2
);
uint8_t
future_pixel
=
255
;
//扫描像素密度,比例接近1:1记录下来,并且黑白间隔数目小大于长度的一半
int
flag
=
0
;
double
test_line
[
2
]{
0
};
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
if
(
m1
.
ptr
<
uint8_t
>
(
cvRound
(
it
.
pos
().
y
))[
cvRound
(
it
.
pos
().
x
)]
==
0
)
continue
;
//统计均匀性
uint8_t
next_pixel
=
binFilter
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
test_line
[
next_pixel
%
254
]
++
;
if
(
next_pixel
!=
future_pixel
)
{
flag
++
;
future_pixel
=
255
-
future_pixel
;
}
}
//满足比例
double
dRate
=
cv
::
min
(
test_line
[
0
],
test_line
[
1
])
/
cv
::
max
(
test_line
[
0
],
test_line
[
1
]);
if
(
dRate
>=
(
1.
-
dToleErr
)
&&
dRate
<=
(
1.
+
dToleErr
)
&&
flag
>
cvRound
((
dis
/
4.
)
*
(
1.
-
dToleErr
)))
{
cv
::
Point2f
pt
[
4
];
cv
::
Size
size
(
cvRound
(
cv
::
max
(
rect
.
size
.
height
,
rect
.
size
.
width
)
+
iBlockSize
/
4.
),
cvRound
(
cv
::
min
(
rect
.
size
.
height
,
rect
.
size
.
width
)));
//获取roi位置
double
_angle
=
std
::
atan2
((
ptEnd
.
y
-
ptStart
.
y
),
(
ptEnd
.
x
-
ptStart
.
x
));
float
b
=
(
float
)
cos
(
_angle
)
*
0.5
f
;
float
a
=
(
float
)
sin
(
_angle
)
*
0.5
f
;
pt
[
0
].
x
=
rect
.
center
.
x
-
a
*
size
.
height
-
b
*
size
.
width
;
pt
[
0
].
y
=
rect
.
center
.
y
+
b
*
size
.
height
-
a
*
size
.
width
;
pt
[
1
].
x
=
rect
.
center
.
x
+
a
*
size
.
height
-
b
*
size
.
width
;
pt
[
1
].
y
=
rect
.
center
.
y
-
b
*
size
.
height
-
a
*
size
.
width
;
pt
[
2
].
x
=
2
*
rect
.
center
.
x
-
pt
[
0
].
x
;
pt
[
2
].
y
=
2
*
rect
.
center
.
y
-
pt
[
0
].
y
;
pt
[
3
].
x
=
2
*
rect
.
center
.
x
-
pt
[
1
].
x
;
pt
[
3
].
y
=
2
*
rect
.
center
.
y
-
pt
[
1
].
y
;
//防止越界
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
);
}
//用采样的方式提取待解码区域
cv
::
LineIterator
itStHeight
(
src
,
pt
[
0
],
pt
[
1
],
4
);
cv
::
LineIterator
itEdHeight
(
src
,
pt
[
3
],
pt
[
2
],
4
);
cv
::
LineIterator
itStWidth
(
src
,
pt
[
0
],
pt
[
3
],
4
);
cv
::
LineIterator
itEdWidth
(
src
,
pt
[
1
],
pt
[
2
],
4
);
struct
Track
{
cv
::
Point
PosS
;
cv
::
Point
PosE
;
Track
()
{};
Track
(
cv
::
Point
PosS
,
cv
::
Point
PosE
)
:
PosS
(
PosS
),
PosE
(
PosE
)
{};
};
std
::
vector
<
Track
>
pairStEd
(
cv
::
min
(
itStHeight
.
count
,
itEdHeight
.
count
));
for
(
int
n
=
0
;
n
<
pairStEd
.
size
();
n
++
,
++
itStHeight
,
++
itEdHeight
)
{
pairStEd
[
n
]
=
Track
(
itStHeight
.
pos
(),
itEdHeight
.
pos
());
}
int
iSamplingStep
=
int
(
pairStEd
.
size
())
/
4
;
//线采样
cv
::
Mat
srcSampling
(
cv
::
Size
(
cv
::
max
(
itStWidth
.
count
,
itEdWidth
.
count
),
1
),
CV_8UC1
,
cv
::
Scalar
(
255
));
//
std
::
vector
<
cv
::
Mat
>
oneDMats
;
//行
for
(
int
n
=
0
;
n
<
(
int
)
pairStEd
.
size
();
n
+=
iSamplingStep
)
{
cv
::
LineIterator
it
(
src
,
pairStEd
[
n
].
PosS
,
pairStEd
[
n
].
PosE
,
4
);
for
(
int
nn
=
0
;
nn
<
it
.
count
;
nn
++
,
++
it
)
//列
{
srcSampling
.
ptr
<
uint8_t
>
(
0
)[
nn
]
=
src
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
];
}
//判断是否为二维码
cv
::
Mat
testMat
;
cv
::
threshold
(
srcSampling
,
testMat
,
0
,
255
,
cv
::
THRESH_BINARY_INV
|
cv
::
THRESH_OTSU
);
//
cv
::
Mat
testLabels
;
if
(
cv
::
connectedComponents
(
testMat
,
testLabels
)
<
6
)
{
//判断非二维码
break
;
}
//扩展
cv
::
Mat
waitArea
;
cv
::
copyMakeBorder
(
srcSampling
,
waitArea
,
0
,
1
,
60
,
60
,
cv
::
BORDER_REPLICATE
);
oneDMats
.
push_back
(
waitArea
);
}
//存储一维码待解码区域
if
((
int
)
oneDMats
.
size
()
>
0
)
{
waitAreas
.
push_back
(
WaitArea
(
cv
::
Mat
(),
ptMid
,
getThreshVal_Otsu_8u
(
oneDMats
[
0
]),
_angle
*
180.
/
PI
,
true
,
oneDMats
));
}
}
}
}
}
else
{
//按照识别到码的定位块尺寸来确定参数,如果是DM码该如何确定参数?
//断裂处连接在一起
cv
::
morphologyEx
(
m2
,
m2
,
cv
::
MORPH_DILATE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
iBlockSize
,
iBlockSize
)));
//去掉无关区域
cv
::
bitwise_and
(
binary
,
m2
,
m2
);
//对二值图像过滤
cv
::
Mat
labels
,
stats
,
centroids
;
int
nccomps
=
cv
::
connectedComponentsWithStats
(
m2
,
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
)))
|
(
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
]
>
iBlockSize
*
15
*
1.414
*
(
1.
+
dToleErr
))
|
(
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]
>
iBlockSize
*
15
*
1.414
*
(
1.
+
dToleErr
))
\
|
((
double
)
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
<
std
::
pow
(
iBlockSize
/
2
,
2
)
*
15
))
{
colors
[
i
]
=
0
;
}
}
//第一次过滤
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
uint8_t
*
ptrRow
=
m2
.
ptr
<
uint8_t
>
(
y
);
for
(
int
x
=
0
;
x
<
X
;
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
(
m2
,
contourAll
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
contourAll
.
size
());
i
++
)
{
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourAll
[
i
]);
//满足矩形条件与面积条件
double
dRate
=
cv
::
min
(
rect
.
size
.
width
,
rect
.
size
.
height
)
/
cv
::
max
(
rect
.
size
.
height
,
rect
.
size
.
width
);
if
(
dRate
>=
(
1.
-
dToleErr
)
&&
dRate
<=
(
1.
+
dToleErr
)
&&
((
double
)
rect
.
size
.
width
>
double
(
8.
*
iBlockSize
))
&&
((
double
)
rect
.
size
.
height
>
double
(
8.
*
iBlockSize
)))
{
contourFilter
.
push_back
(
contourAll
[
i
]);
}
}
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
,
(
double
)
rect
.
size
().
width
));
//疑似二维码区域
cv
::
Mat
waitArea
=
src
(
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rRect
.
center
.
y
)
-
cvRound
(
4.
*
(
double
)
iBlockSize
+
dynSize
/
2
)),
cv
::
min
(
Y
-
1
,
cvRound
(
rRect
.
center
.
y
)
+
cvRound
(
4.
*
(
double
)
iBlockSize
+
dynSize
/
2
))),
cv
::
Range
(
cv
::
max
(
0
,
cvRound
(
rRect
.
center
.
x
)
-
cvRound
(
4.
*
(
double
)
iBlockSize
+
dynSize
/
2
)),
cv
::
min
(
X
-
1
,
cvRound
(
rRect
.
center
.
x
)
+
cvRound
(
4.
*
(
double
)
iBlockSize
+
dynSize
/
2
)))).
clone
();
//处理后再压入识别
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"
};
//解码
decodeMul
(
waitAreas
,
hints_
,
showMat
,
decodeResults
,
iBlockSize
,
10
,
1.0
);
return
FUNC_OK
;
return
FUNC_OK
;
}
}
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论