Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
张士柳
/
eyemLib
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
图表
网络
创建新的问题
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit c28b0fea
由
张士柳
编写于
2021-07-12 16:11:41 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
无
1 个父辈
87a1305d
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
625 行增加
和
1115 行删除
eyemLib-Sharp/EyemLib.cs
eyemLib-Sharp/EyemLibDemo.cs
eyemLib/eyemDataCode.cpp
eyemLib/eyemDataCode.h
eyemLib/eyemLib.h
eyemLib/eyemLib.rc
eyemLib/eyemMisc.cpp
eyemLib/eyemMisc.h
eyemLib/nnDetector.cpp
eyemLib/nnDetector.h
eyemLib-Sharp/EyemLib.cs
查看文件 @
c28b0fe
...
@@ -1021,18 +1021,18 @@ namespace eyemLib_Sharp
...
@@ -1021,18 +1021,18 @@ namespace eyemLib_Sharp
#
endregion
#
endregion
#
region
项目
#
region
项目
//普通器件
//普通器件
(仍采用旧的算法)
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemCountObject
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
double
dOffset
,
int
iMinArea
,
int
iMaxArea
,
int
iWinSize
,
ref
string
pNumObj
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemCountObject
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
[
MarshalAs
(
UnmanagedType
.
LPArray
)]
int
[]
ipReelNum
,
out
EyemImage
tpDstImg
);
//异型器件
//异型器件
(新版本新算法)
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemCountObjectIrregularParts
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
string
strType
,
ref
string
pNumObj
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemCountObjectIrregularParts
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
string
strType
,
[
MarshalAs
(
UnmanagedType
.
LPArray
)]
int
[]
ipReelNum
,
out
EyemImage
tpDstImg
);
//普通器件(新版本)
//普通器件(新版本
新算法
)
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemCountObjectE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
ref
string
pNumObj
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemCountObjectE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
[
MarshalAs
(
UnmanagedType
.
LPArray
)]
int
[]
ipReelNum
,
out
EyemImage
tpDstImg
);
//异型器件(新版本)
//异型器件(新版本
模板匹配
)
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemCountObjectIrregularPartsE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
string
ccTplName
,
IntPtr
hModelID
,
ref
string
pNumObj
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemCountObjectIrregularPartsE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
fileName
,
string
ccTplName
,
IntPtr
hModelID
,
[
MarshalAs
(
UnmanagedType
.
LPArray
)]
int
[]
ipReelNum
,
out
EyemImage
tpDstImg
);
//创建模板匹配模型
//创建模板匹配模型
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemCreateTemplateModel
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
double
dMinScore
,
string
ccTplName
);
private
static
extern
int
eyemCreateTemplateModel
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
double
dMinScore
,
string
ccTplName
);
...
@@ -1129,6 +1129,7 @@ namespace eyemLib_Sharp
...
@@ -1129,6 +1129,7 @@ namespace eyemLib_Sharp
//记录日志
//记录日志
private
static
void
EyemLib_OnNewLogCallback
(
string
msg
)
private
static
void
EyemLib_OnNewLogCallback
(
string
msg
)
{
{
//算法里输出的一切日志都会在这里
logcpp
.
WriteLog
(
"["
+
Thread
.
CurrentThread
.
ManagedThreadId
.
ToString
(
"X16"
)
+
"]"
+
msg
);
logcpp
.
WriteLog
(
"["
+
Thread
.
CurrentThread
.
ManagedThreadId
.
ToString
(
"X16"
)
+
"]"
+
msg
);
}
}
...
@@ -1363,14 +1364,13 @@ namespace eyemLib_Sharp
...
@@ -1363,14 +1364,13 @@ namespace eyemLib_Sharp
//flag = eyemMulFuncTool(image, tpRoi, "__func1", 65, 75, ref tpCircle, out tpDstImg);
//flag = eyemMulFuncTool(image, tpRoi, "__func1", 65, 75, ref tpCircle, out tpDstImg);
string
pNumObj
=
""
;
int
[]
ipReelNum
=
new
int
[
4
]
;
string
file
=
fileName
.
Split
(
new
string
[]
{
"\\"
},
StringSplitOptions
.
RemoveEmptyEntries
)[
2
];
string
file
=
fileName
.
Split
(
new
string
[]
{
"\\"
},
StringSplitOptions
.
RemoveEmptyEntries
)[
2
];
//获取用于制作模板的图像
//获取用于制作模板的图像
//flag = eyemAchvTemplateImage(image, tpRoi, out tpDstImg);
//flag = eyemAchvTemplateImage(image, tpRoi, out tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//if (bitmap != null)
//{
//{
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
...
@@ -1423,10 +1423,10 @@ namespace eyemLib_Sharp
...
@@ -1423,10 +1423,10 @@ namespace eyemLib_Sharp
//eyemImageFree(ref tpDstImg);
//eyemImageFree(ref tpDstImg);
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS","IP_LOWCONTRAST_PARTS"
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS","IP_LOWCONTRAST_PARTS"
//eyemCountObject(image, tpRoi, file.Replace(".png", ""),
35, 0, 100, 5, ref pNumObj
, out tpDstImg);
//eyemCountObject(image, tpRoi, file.Replace(".png", ""),
ipReelNum
, out tpDstImg);
//eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_LONG_PARTS", ref pNumObj
, out tpDstImg);
eyemCountObjectIrregularParts
(
image
,
tpRoi
,
file
.
Replace
(
".png"
,
""
),
"IP_LARGE_PARTS"
,
ipReelNum
,
out
tpDstImg
);
eyemCountObjectE
(
image
,
tpRoi
,
fileName
,
ref
pNumObj
,
out
tpDstImg
);
//eyemCountObjectE(image, tpRoi, fileName, ipReelNum
, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), tpModels[0], hModelID,
ref pNumObj
, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), tpModels[0], hModelID,
ipReelNum
, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "D:\\模板文件\\" + /*file.Replace(".png", ".tpl")*/"74d571ed-9fd4-4959-85dd-3195261e4b48.tpl", ref pNumObj, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "D:\\模板文件\\" + /*file.Replace(".png", ".tpl")*/"74d571ed-9fd4-4959-85dd-3195261e4b48.tpl", ref pNumObj, out tpDstImg);
//移除模板
//移除模板
...
@@ -1435,8 +1435,8 @@ namespace eyemLib_Sharp
...
@@ -1435,8 +1435,8 @@ namespace eyemLib_Sharp
Bitmap
bitmap
=
eyemCvtToBitmap
(
tpDstImg
);
Bitmap
bitmap
=
eyemCvtToBitmap
(
tpDstImg
);
if
(
bitmap
!=
null
)
if
(
bitmap
!=
null
)
{
{
bitmap
.
Save
(
"D:\\ResOut\\"
+
file
);
//
bitmap.Save("D:\\ResOut\\" + file);
//
bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
bitmap
.
Save
(
System
.
Windows
.
Forms
.
Application
.
StartupPath
+
"\\ResOut\\"
+
file
);
}
}
//< 解码测试
//< 解码测试
...
@@ -1449,16 +1449,19 @@ namespace eyemLib_Sharp
...
@@ -1449,16 +1449,19 @@ namespace eyemLib_Sharp
// Marshal.FreeCoTaskMem(tpResults[i].hText); Marshal.FreeCoTaskMem(tpResults[i].hType);
// Marshal.FreeCoTaskMem(tpResults[i].hText); Marshal.FreeCoTaskMem(tpResults[i].hType);
//}
//}
//hObject.Dispose();
//hObject.Dispose();
//flag = eyemDetectAndDecodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
//flag = eyemDetectAndDecodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
//flag = eyemDetectAndDecodeBarcodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
//flag = eyemDetectAndDecodeBarcodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
string
strReelNum
=
""
;
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
strReelNum
+=
ipReelNum
[
i
].
ToString
()
+
","
;
}
sw
.
Stop
();
sw
.
Stop
();
Console
.
WriteLine
(
file
+
"--->"
+
"耗时:"
+
sw
.
ElapsedMilliseconds
.
ToString
()
+
"
毫秒"
+
",结果:"
+
pNumObj
);
Console
.
WriteLine
(
file
+
"--->"
+
"耗时:"
+
sw
.
ElapsedMilliseconds
.
ToString
()
+
"
ms"
+
",结果:"
+
strReelNum
);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//if (bitmap != null)
//{
//{
// bitmap.Save("D:\\ResOut\\" + file);
// bitmap.Save("D:\\ResOut\\" + file);
...
@@ -1498,7 +1501,7 @@ namespace eyemLib_Sharp
...
@@ -1498,7 +1501,7 @@ namespace eyemLib_Sharp
tpRoi
.
iHeight
=
image
.
iHeight
-
100
;
tpRoi
.
iHeight
=
image
.
iHeight
-
100
;
//
//
string
pNumObj
=
""
;
int
[]
pNumObj
=
new
int
[
4
]
;
string
file
=
fileName
.
Split
(
new
string
[]
{
"\\"
},
StringSplitOptions
.
RemoveEmptyEntries
)[
2
];
string
file
=
fileName
.
Split
(
new
string
[]
{
"\\"
},
StringSplitOptions
.
RemoveEmptyEntries
)[
2
];
//获取用于制作模板的图像
//获取用于制作模板的图像
...
@@ -1537,7 +1540,7 @@ namespace eyemLib_Sharp
...
@@ -1537,7 +1540,7 @@ namespace eyemLib_Sharp
eyemImageFree
(
ref
tpDstImg
);
eyemImageFree
(
ref
tpDstImg
);
//点料
//点料
eyemCountObjectIrregularPartsE
(
image
,
tpRoi
,
file
.
Replace
(
".png"
,
""
),
selectModel
.
Split
(
new
char
[]
{
','
},
StringSplitOptions
.
RemoveEmptyEntries
)[
0
],
hModelID
,
ref
pNumObj
,
out
tpDstImg
);
eyemCountObjectIrregularPartsE
(
image
,
tpRoi
,
file
.
Replace
(
".png"
,
""
),
selectModel
.
Split
(
new
char
[]
{
','
},
StringSplitOptions
.
RemoveEmptyEntries
)[
0
],
hModelID
,
pNumObj
,
out
tpDstImg
);
//测试移除模板
//测试移除模板
//eyemRemoveModelByName(hModelID, "D:\\模板文件及图像\\df871193-6632-48f9-abfe-540c3fc49c3f.tpl");
//eyemRemoveModelByName(hModelID, "D:\\模板文件及图像\\df871193-6632-48f9-abfe-540c3fc49c3f.tpl");
...
...
eyemLib-Sharp/EyemLibDemo.cs
查看文件 @
c28b0fe
using
Microsoft.Win32.SafeHandles
;
using
System
;
using
System
;
using
System.Runtime.InteropServices
;
using
System.Runtime.InteropServices
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Collections.Generic
;
using
System.Drawing
;
using
System.Drawing
;
using
System.Drawing.Imaging
;
using
System.Drawing.Imaging
;
...
@@ -323,8 +319,41 @@ namespace eyemLib_Sharp
...
@@ -323,8 +319,41 @@ namespace eyemLib_Sharp
//释放图像资源
//释放图像资源
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
void
eyemImageFree
(
ref
EyemImage
tpImage
);
private
static
extern
void
eyemImageFree
(
ref
EyemImage
tpImage
);
// 设定日志回调
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
void
setLogCallback
(
TCallBack
cb
);
#
endregion
#
endregion
// 日志
public
delegate
void
TCallBack
(
string
msg
);
public
static
TCallBack
sld
=
new
TCallBack
(
TLogCallback
);
public
static
event
TCallBack
OnNewLogCallback
;
public
static
void
TLogCallback
(
string
msg
)
{
OnNewLogCallback
?.
Invoke
(
msg
);
}
//程序启动时初始化一次
public
static
void
Init
()
{
setLogCallback
(
sld
);
OnNewLogCallback
+=
new
TCallBack
(
EyemLib_OnNewLogCallback
);
}
//程序结束时释放
public
static
void
Free
()
{
setLogCallback
(
null
);
sld
=
null
;
}
//记录算法日志
private
static
void
EyemLib_OnNewLogCallback
(
string
msg
)
{
//算法里输出的一切日志都会在这里
}
//例程
//例程
public
static
void
eyeyTestTemplateModelMethod
(
string
fileName
)
public
static
void
eyeyTestTemplateModelMethod
(
string
fileName
)
{
{
...
@@ -355,7 +384,6 @@ namespace eyemLib_Sharp
...
@@ -355,7 +384,6 @@ namespace eyemLib_Sharp
#
endregion
#
endregion
}
}
#
region
EyemImage
与
Bitmap
相互转换
#
region
EyemImage
与
Bitmap
相互转换
public
static
Bitmap
eyemCvtToBitmap
(
EyemImage
tpImage
)
public
static
Bitmap
eyemCvtToBitmap
(
EyemImage
tpImage
)
{
{
...
...
eyemLib/eyemDataCode.cpp
查看文件 @
c28b0fe
...
@@ -516,8 +516,10 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
...
@@ -516,8 +516,10 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
{
{
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
image
.
empty
())
{
if
(
image
.
empty
())
{
logger
.
t
(
"__eyemDetectAndDecodeUseNN__:图像文件不存在"
);
return
FUNC_IMAGE_NOT_EXIST
;
return
FUNC_IMAGE_NOT_EXIST
;
}
}
logger
.
t
(
"__eyemDetectAndDecodeUseNN__:开始识别并解码二维码"
);
//识别并解码
//识别并解码
std
::
vector
<
cv
::
Rect
>
points
;
std
::
vector
<
cv
::
Rect
>
__points
;
std
::
vector
<
cv
::
Rect
>
points
;
std
::
vector
<
cv
::
Rect
>
__points
;
auto
results
=
detector
->
detectAndDecode
(
image
,
points
,
__points
);
auto
results
=
detector
->
detectAndDecode
(
image
,
points
,
__points
);
...
@@ -569,6 +571,7 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
...
@@ -569,6 +571,7 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
//}
//}
#pragma endregion
#pragma endregion
logger
.
t
(
"__eyemDetectAndDecodeUseNN__:输出结果"
);
//解码结果
//解码结果
std
::
vector
<
EyemBarCode
>
*
tpResults
=
new
std
::
vector
<
EyemBarCode
>
();
std
::
vector
<
EyemBarCode
>
*
tpResults
=
new
std
::
vector
<
EyemBarCode
>
();
for
(
int
n
=
0
;
n
<
results
.
size
();
n
++
)
{
for
(
int
n
=
0
;
n
<
results
.
size
();
n
++
)
{
...
...
eyemLib/eyemDataCode.h
查看文件 @
c28b0fe
...
@@ -5,6 +5,13 @@
...
@@ -5,6 +5,13 @@
#ifndef __EYEM_DATACODE_H
#ifndef __EYEM_DATACODE_H
#define __EYEM_DATACODE_H
#define __EYEM_DATACODE_H
#ifdef _WIN32
#include <io.h>
#include <Windows.h>
#elif __linux__
#include <sys/stat.h>
#endif
#include "eyemLib.h"
#include "eyemLib.h"
#include "nnDetector.h"
#include "nnDetector.h"
...
@@ -12,6 +19,8 @@ std::mutex mtx;
...
@@ -12,6 +19,8 @@ std::mutex mtx;
cv
::
Ptr
<
NNDetector
>
detector
;
cv
::
Ptr
<
NNDetector
>
detector
;
extern
Logger
logger
;
//预处理区域
//预处理区域
struct
WaitArea
struct
WaitArea
{
{
...
...
eyemLib/eyemLib.h
查看文件 @
c28b0fe
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
#ifndef __EYEM_LIB_H
#ifndef __EYEM_LIB_H
#define __EYEM_LIB_H
#define __EYEM_LIB_H
#include <Windows.h>
#include <opencv.hpp>
#include <opencv.hpp>
...
@@ -662,7 +661,7 @@ extern "C" {
...
@@ -662,7 +661,7 @@ extern "C" {
// 函数接口
// 函数接口
EXPORTS
int
eyemEdgesPixel
(
EyemImage
tpImage
,
double
dThresh
);
EXPORTS
int
eyemEdgesPixel
(
EyemImage
tpImage
,
double
dThresh
);
EXPORTS
int
eyemEdgesSubpixel
(
EyemImage
tpImage
,
IntPtr
*
hObject
,
EyemOcsDXY
**
tpEdges
,
int
iFilter
,
int
iLow
,
int
iHigh
);
EXPORTS
int
eyemEdgesSubpixel
(
EyemImage
tpImage
,
IntPtr
*
hObject
,
EyemOcsDXY
**
tpEdges
,
int
iFilter
,
int
iLow
,
int
iHigh
);
EXPORTS
int
eyemSkeleton
(
EyemImage
tpImage
,
cv
::
Mat
&
skeleton
);
EXPORTS
int
eyemSkeleton
(
EyemImage
tpImage
,
EyemImage
&
skeleton
);
EXPORTS
int
eyemSobelAmp
(
EyemImage
tpImage
,
EyemImage
&
ImaAmp
);
EXPORTS
int
eyemSobelAmp
(
EyemImage
tpImage
,
EyemImage
&
ImaAmp
);
EXPORTS
int
eyemAutoCanny
(
EyemImage
tpImage
,
float
dSigma
=
0
.
33
);
EXPORTS
int
eyemAutoCanny
(
EyemImage
tpImage
,
float
dSigma
=
0
.
33
);
...
@@ -799,8 +798,8 @@ typedef struct {
...
@@ -799,8 +798,8 @@ typedef struct {
double
dAngle
;
// 角度
double
dAngle
;
// 角度
int
iCenterX
;
// y坐标
int
iCenterX
;
// y坐标
int
iCenterY
;
// y坐标
int
iCenterY
;
// y坐标
LPSTR
lpszType
;
// 码类型
char
*
lpszType
;
// 码类型
LPSTR
lpszText
;
// 码内容
char
*
lpszText
;
// 码内容
}
EyemBarCode
;
}
EyemBarCode
;
typedef
struct
{
typedef
struct
{
...
@@ -810,7 +809,7 @@ typedef struct {
...
@@ -810,7 +809,7 @@ typedef struct {
int
iWidth
;
// 图像内存X方向大小
int
iWidth
;
// 图像内存X方向大小
int
iHeight
;
// 图像内存Y方向大小
int
iHeight
;
// 图像内存Y方向大小
double
dMatchDeg
;
// 匹配度
double
dMatchDeg
;
// 匹配度
LPSTR
lpszName
;
// 名称
char
*
lpszName
;
// 名称
}
EyemModelID
;
}
EyemModelID
;
...
@@ -822,13 +821,13 @@ extern "C" {
...
@@ -822,13 +821,13 @@ extern "C" {
EXPORTS
int
eyemInitNNDataCodeModel
(
const
char
*
detectorConfigPath
,
const
char
*
detectorModelPath
,
const
char
*
superResolutionConfigPath
,
const
char
*
superResolutionModelPath
);
EXPORTS
int
eyemInitNNDataCodeModel
(
const
char
*
detectorConfigPath
,
const
char
*
detectorModelPath
,
const
char
*
superResolutionConfigPath
,
const
char
*
superResolutionModelPath
);
EXPORTS
int
eyemDetectAndDecodeBarcodeUseNN
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
IntPtr
*
hObject
,
EyemBarCode
**
hResults
,
int
*
ipNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemDetectAndDecodeBarcodeUseNN
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
IntPtr
*
hObject
,
EyemBarCode
**
hResults
,
int
*
ipNum
,
EyemImage
*
tpDstImg
);
EXPORTS
bool
eyemDetectAndDecodeFree
(
IntPtr
hObject
);
EXPORTS
bool
eyemDetectAndDecodeFree
(
IntPtr
hObject
);
EXPORTS
int
eyemCountObject
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
LPSTR
*
lpszNumObj
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObject
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
int
*
ipReelNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObjectE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
LPSTR
*
lpsz
ReelNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObjectE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
int
*
ip
ReelNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObjectIrregularParts
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccSubType
,
LPSTR
*
lpszNumObj
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObjectIrregularParts
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccSubType
,
int
*
ipReelNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObjectIrregularPartsE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccTplName
,
IntPtr
hModelID
,
LPSTR
*
lpsz
ReelNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCountObjectIrregularPartsE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccTplName
,
IntPtr
hModelID
,
int
*
ip
ReelNum
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemAchvTemplateImage
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemAchvTemplateImage
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemCreateTemplateModel
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
double
dMinScore
,
const
char
*
ccTplName
);
EXPORTS
int
eyemCreateTemplateModel
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
double
dMinScore
,
const
char
*
ccTplName
);
EXPORTS
int
eyemMatchTemplateModel
(
EyemImage
tpImage
,
IntPtr
hModelID
,
LPSTR
*
lpszTplName
);
EXPORTS
int
eyemMatchTemplateModel
(
EyemImage
tpImage
,
IntPtr
hModelID
,
char
*
*
lpszTplName
);
EXPORTS
int
eyemInitModel
(
const
char
*
ccTplName
,
IntPtr
*
hModelID
);
EXPORTS
int
eyemInitModel
(
const
char
*
ccTplName
,
IntPtr
*
hModelID
);
EXPORTS
int
eyemAchvModelByName
(
const
char
*
ccTplName
,
IntPtr
hModelID
,
EyemModelID
&
tpModelID
);
EXPORTS
int
eyemAchvModelByName
(
const
char
*
ccTplName
,
IntPtr
hModelID
,
EyemModelID
&
tpModelID
);
EXPORTS
int
eyemInsertModel
(
IntPtr
hModelID
,
const
char
*
ccTplName
);
EXPORTS
int
eyemInsertModel
(
IntPtr
hModelID
,
const
char
*
ccTplName
);
...
...
eyemLib/eyemLib.rc
查看文件 @
c28b0fe
此文件类型无法预览
eyemLib/eyemMisc.cpp
查看文件 @
c28b0fe
#ifdef _WIN32
#include <io.h>
#include <Windows.h>
#elif __linux__
#include <sys/stat.h>
#endif
#include <fstream>
#include "eyemMisc.h"
#include "eyemMisc.h"
#pragma region 一些参数计算公式
#pragma region 一些参数计算公式
...
@@ -655,7 +663,7 @@ static bool checkSize(cv::Mat &srcPrev, cv::Mat &mask, int &partSize)
...
@@ -655,7 +663,7 @@ static bool checkSize(cv::Mat &srcPrev, cv::Mat &mask, int &partSize)
#pragma endregion
#pragma endregion
int
eyemCountObject
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
LPSTR
*
lpszNumObj
,
EyemImage
*
tpDstImg
)
int
eyemCountObject
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
int
*
ipReelNum
,
EyemImage
*
tpDstImg
)
{
{
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
src
.
empty
())
{
if
(
src
.
empty
())
{
...
@@ -781,10 +789,8 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
...
@@ -781,10 +789,8 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
if
(
trays
.
size
()
<
1
)
if
(
trays
.
size
()
<
1
)
{
{
std
::
string
strTrayNum
=
"无料,"
;
std
::
string
strTrayNum
=
"无料,"
;
*
lpszNumObj
=
(
char
*
)
CoTaskMemAlloc
(
strTrayNum
.
size
());
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
if
(
NULL
!=
*
lpszNumObj
)
ipReelNum
[
i
]
=
0
;
{
strcpy
(
*
lpszNumObj
,
strTrayNum
.
c_str
());
}
}
return
FUNC_CANNOT_CALC
;
return
FUNC_CANNOT_CALC
;
}
}
...
@@ -1107,220 +1113,107 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
...
@@ -1107,220 +1113,107 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
});
});
//去掉中心1/3区域
//去掉中心1/3区域
cv
::
circle
(
image
,
reelCenter
,
cvRound
(
tFRadius
/
3
),
cv
::
Scalar
(
0
),
-
1
);
cv
::
circle
(
image
,
reelCenter
,
cvRound
(
tFRadius
/
3
),
cv
::
Scalar
(
0
),
-
1
);
struct
TracingAnchor
//追踪直至没有单个元件存在
{
bool
bExistSingle
=
true
;
float
Size
;
//用于计数
float
Length
,
Height
;
cv
::
Mat
lb4Count
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
Point2f
Anchor
;
cv
::
RotatedRect
RBox
;
TracingAnchor
(
cv
::
Point2f
Anchor
,
float
Length
,
float
Height
,
float
Size
,
cv
::
RotatedRect
RBox
)
:
Anchor
(
Anchor
),
Length
(
Length
),
Height
(
Height
),
Size
(
Size
),
RBox
(
RBox
)
{}
bool
operator
>
(
const
TracingAnchor
&
te
)
const
{
return
Size
>
te
.
Size
;
}
bool
operator
<
(
const
TracingAnchor
&
te
)
const
{
return
Size
<
te
.
Size
;
}
};
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contourTracing
;
cv
::
findContours
(
image
,
contourTracing
,
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_NONE
);
//所有追踪锚点
std
::
vector
<
TracingAnchor
>
tracingAnchors
;
for
(
auto
&
contour
:
contourTracing
)
{
cv
::
RotatedRect
rbox
=
cv
::
minAreaRect
(
contour
);
if
(
cv
::
min
(
rbox
.
size
.
width
,
rbox
.
size
.
height
)
>
2.0
f
)
{
tracingAnchors
.
push_back
(
TracingAnchor
(
rbox
.
center
,
cv
::
max
(
rbox
.
size
.
width
,
rbox
.
size
.
height
),
cv
::
min
(
rbox
.
size
.
width
,
rbox
.
size
.
height
),
rbox
.
size
.
area
(),
rbox
));
}
}
//不存在独立元件
if
(
tracingAnchors
.
empty
())
{
return
FUNC_CANNOT_CALC
;
}
//尺寸只计算一次
std
::
sort
(
tracingAnchors
.
begin
(),
tracingAnchors
.
end
(),
std
::
greater
<
TracingAnchor
>
());
//
struct
Track
{
int
iLimit
,
iPartSize
;
double
dMatchDeg
=
0.0
;
cv
::
Point2f
Pos
;
std
::
vector
<
cv
::
Point2f
>
Rect
;
Track
()
{};
Track
(
int
iLimit
,
int
iPartSize
,
double
dMatchDeg
,
cv
::
Point2f
Pos
,
std
::
vector
<
cv
::
Point2f
>
Rect
)
:
iLimit
(
iLimit
),
iPartSize
(
iPartSize
),
dMatchDeg
(
dMatchDeg
),
Pos
(
Pos
),
Rect
(
Rect
)
{};
bool
operator
>
(
const
Track
&
te
)
const
{
return
dMatchDeg
>
te
.
dMatchDeg
;
}
bool
operator
<
(
const
Track
&
te
)
const
{
return
dMatchDeg
<
te
.
dMatchDeg
;
}
};
//缩放比例
float
coeff
=
1.0
f
;
//填充值
const
int
fillVal
=
255
-
backThresh
;
//元件尺寸
const
double
taLength
=
tracingAnchors
[
tracingAnchors
.
size
()
/
2
].
Length
;
const
double
taHeight
=
tracingAnchors
[
tracingAnchors
.
size
()
/
2
].
Height
;
//元件灰度值
double
taMaxGray
=
0.0
;
//标签图
//标签图
unsigned
char
*
ucpTrackLabel
=
new
unsigned
char
[
Y
*
X
]();
unsigned
char
*
ucpTrackLabel
=
new
unsigned
char
[
Y
*
X
]();
cv
::
Mat
trackMat
(
Y
,
X
,
CV_8UC1
,
ucpTrackLabel
);
cv
::
Mat
trackMat
(
Y
,
X
,
CV_8UC1
,
ucpTrackLabel
);
//计数图像
do
cv
::
Mat
lbMat
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
{
//定位图像
cv
::
Mat
srcPrevS
,
tplMat
;
//模板文件
srcPrev
.
convertTo
(
srcPrevS
,
CV_32F
);
//随机打乱顺序(降低计算错误dChordL的可能性,也为了测试在起点信息不同时的稳定性)
std
::
random_shuffle
(
tracingAnchors
.
begin
(),
tracingAnchors
.
end
());
//开始确定起点(现在是用圆轨迹来追踪,不排除用螺旋线轨迹来追踪)
for
(
std
::
vector
<
TracingAnchor
>::
iterator
itvx
=
tracingAnchors
.
begin
();
itvx
!=
tracingAnchors
.
end
();
++
itvx
)
{
//跳过执行
//跳过执行
if
(
killProcessID
==
0
)
{
if
(
killProcessID
==
0
)
{
logger
.
t
(
"eyemCountObjectIrregularParts 点料阶段被跳过执行..."
);
logger
.
t
(
"eyemCountObjectIrregularParts
E
点料阶段被跳过执行..."
);
break
;
break
;
}
}
//起始位置信息
TracingAnchor
ta
=
(
*
itvx
);
//起始位置坐标
cv
::
Point2f
startCenter
(
ta
.
Anchor
.
x
,
ta
.
Anchor
.
y
);
//最小外包矩形
cv
::
Point2f
_pts
[
4
];
ta
.
RBox
.
points
(
_pts
);
//已做标记(TODO:考虑增加判断哪些是起点哪些不是)
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
startCenter
.
y
))[
cvRound
(
startCenter
.
x
)]
==
255
)
{
continue
;
}
//获取模板图像(是否每次起点都计算模板,如果元件变形过大是否还会有用?)
if
(
tplMat
.
empty
())
{
float
tDist
=
ta
.
Height
/
2.0
f
;
//理论范围扩展
cv
::
Rect
_rLimits
=
cv
::
Rect
(
cv
::
Point2i
(
cvRound
((
float
)
ta
.
RBox
.
boundingRect2f
().
tl
().
x
-
tDist
),
cvRound
((
float
)
ta
.
RBox
.
boundingRect2f
().
tl
().
y
-
tDist
)),
cv
::
Point2i
(
cvRound
((
float
)
ta
.
RBox
.
boundingRect2f
().
br
().
x
+
tDist
),
cvRound
((
float
)
ta
.
RBox
.
boundingRect2f
().
br
().
y
+
tDist
))
)
&
cv
::
Rect
(
0
,
0
,
X
,
Y
);
//确定元件位置根据旋转后的位置确定(前提是料盘中心定位的准确)
double
t
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180.0
/
PI
;
//计算旋转角度
cv
::
Mat
traceMat
=
srcPrev
(
_rLimits
);
//这里计算得出的模板不是很对
float
matx
[
6
];
tplMat
=
getTrackMat
(
traceMat
,
t
+
90.0
,
0
,
matx
);
//变换后的坐标
cv
::
Point2f
__pts
[
4
];
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
__pts
[
j
].
x
=
matx
[
0
]
*
(
_pts
[
j
].
x
-
(
float
)
_rLimits
.
x
)
+
matx
[
1
]
*
(
_pts
[
j
].
y
-
(
float
)
_rLimits
.
y
)
+
matx
[
2
];
__pts
[
j
].
y
=
matx
[
3
]
*
(
_pts
[
j
].
x
-
(
float
)
_rLimits
.
x
)
+
matx
[
4
]
*
(
_pts
[
j
].
y
-
(
float
)
_rLimits
.
y
)
+
matx
[
5
];
}
cv
::
Point2f
__ptsc
((
__pts
[
0
].
x
+
__pts
[
1
].
x
+
__pts
[
2
].
x
+
__pts
[
3
].
x
)
/
4.0
f
,
(
__pts
[
0
].
y
+
__pts
[
1
].
y
+
__pts
[
2
].
y
+
__pts
[
3
].
y
)
/
4.0
f
);
//确定各顶点方位
struct
DIR
{
int
i
=
-
1
;
cv
::
Point2f
pt
;
DIR
()
{};
DIR
(
int
i
,
cv
::
Point2f
pt
)
:
i
(
i
),
pt
(
pt
)
{};
//不随机挑选起点(考虑换成面积最小的那个)
};
std
::
vector
<
cv
::
Point
>
contourMin
;
auto
_dir_l
=
std
::
vector
<
DIR
>
();
auto
_dir_r
=
std
::
vector
<
DIR
>
();
cv
::
findContours
(
image
,
contoursFilter
,
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_NONE
);
for
(
int
j
=
0
;
j
<
4
;
j
++
)
//终止追踪
if
(
contoursFilter
.
size
()
<=
0
)
break
;
//大于等于1个随机挑选
if
(
contoursFilter
.
size
()
>
1
)
{
//随机数生成
srand
((
unsigned
)
time
(
NULL
));
contourMin
=
contoursFilter
[
rand
()
%
(
contoursFilter
.
size
()
-
1
)];
for
(
int
fc
=
0
;
fc
<
contoursFilter
.
size
();
fc
++
)
{
{
if
(
__pts
[
j
].
x
<
__ptsc
.
x
)
{
if
(
cv
::
contourArea
(
contoursFilter
[
fc
])
>
0.4
*
sinPartSize
)
_dir_l
.
push_back
(
DIR
(
j
,
__pts
[
j
]));
{
}
if
(
cv
::
contourArea
(
contoursFilter
[
fc
])
<
cv
::
contourArea
(
contourMin
))
else
{
{
_dir_r
.
push_back
(
DIR
(
j
,
__pts
[
j
]));
contourMin
=
contoursFilter
[
fc
];
}
}
}
}
}
//重新选点计算模板
}
if
(
_dir_l
.
size
()
!=
_dir_r
.
size
())
{
else
if
(
contoursFilter
.
size
()
==
1
)
continue
;
{
}
contourMin
=
contoursFilter
[
0
];
//确定顶点方向
}
cv
::
Point2f
p0
,
p1
,
p2
,
p3
;
//去掉起始位置
if
(
_dir_l
[
0
].
pt
.
y
<
_dir_l
[
1
].
pt
.
y
)
{
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
vTempRect
;
p0
=
_pts
[
_dir_l
[
0
].
i
];
vTempRect
.
push_back
(
contourMin
);
p1
=
_pts
[
_dir_l
[
1
].
i
];
cv
::
drawContours
(
image
,
vTempRect
,
0
,
cv
::
Scalar
(
0
),
-
1
);
}
//最小外包矩形
else
{
cv
::
RotatedRect
rect
=
cv
::
minAreaRect
(
contourMin
);
p0
=
_pts
[
_dir_l
[
1
].
i
];
cv
::
Point2f
points
[
4
];
p1
=
_pts
[
_dir_l
[
0
].
i
];
rect
.
points
(
points
);
}
//画图
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, points[j], points[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
//}
//追踪起点
cv
::
Point2f
startCenter
((
points
[
0
].
x
+
points
[
1
].
x
+
points
[
2
].
x
+
points
[
3
].
x
)
/
4.
f
,
(
points
[
0
].
y
+
points
[
1
].
y
+
points
[
2
].
y
+
points
[
3
].
y
)
/
4.
f
);
//打标签
cv
::
Mat
labels
;
nccomps
=
cv
::
connectedComponents
(
image
,
labels
);
//去掉已处理的分离器件
std
::
vector
<
uchar
>
labeled
(
nccomps
+
1
,
0
);
//标记为已追踪过
std
::
vector
<
cv
::
Point
>
vT
=
{
cv
::
Point
(
points
[
0
]),
cv
::
Point
(
points
[
1
])
,
cv
::
Point
(
points
[
2
])
,
cv
::
Point
(
points
[
3
])
};
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//起点加入计数
cv
::
circle
(
lb4Count
,
cv
::
Point
(
startCenter
),
0
,
cv
::
Scalar
(
255
),
1
);
cv
::
circle
(
cc
,
cv
::
Point
(
startCenter
),
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
///<追踪元件算法
struct
Track
{
int
iLimit
,
iPartSize
;
double
dMatchDeg
;
cv
::
Point
Pos
;
std
::
vector
<
cv
::
Point2f
>
Rect
;
if
(
_dir_r
[
0
].
pt
.
y
>
_dir_r
[
1
].
pt
.
y
)
{
Track
()
{};
p2
=
_pts
[
_dir_r
[
0
].
i
];
p3
=
_pts
[
_dir_r
[
1
].
i
];
}
else
{
p2
=
_pts
[
_dir_r
[
1
].
i
];
p3
=
_pts
[
_dir_r
[
0
].
i
];
}
//计算精确角度
cv
::
Point2f
p01
((
p0
.
x
+
p1
.
x
)
/
2.0
f
,
(
p0
.
y
+
p1
.
y
)
/
2.0
f
),
p23
((
p2
.
x
+
p3
.
x
)
/
2.0
f
,
(
p2
.
y
+
p3
.
y
)
/
2.0
f
);
double
realT
=
atan2
((
double
)
p23
.
y
-
(
double
)
p01
.
y
,
(
double
)
p23
.
x
-
(
double
)
p01
.
x
)
*
180.0
/
PI
;
Track
(
int
iLimit
,
int
iPartSize
,
double
dMatchDeg
,
cv
::
Point
Pos
,
std
::
vector
<
cv
::
Point2f
>
Rect
)
:
iLimit
(
iLimit
),
iPartSize
(
iPartSize
),
dMatchDeg
(
dMatchDeg
),
Pos
(
Pos
),
Rect
(
Rect
)
{};
cv
::
Mat
realTplMat
=
getTrackMat
(
traceMat
,
realT
,
0
,
matx
);
cv
::
Point2f
__mpts
[
4
];
bool
operator
>
(
const
Track
&
te
)
const
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
__mpts
[
j
].
x
=
matx
[
0
]
*
(
_pts
[
j
].
x
-
(
float
)
_rLimits
.
x
)
+
matx
[
1
]
*
(
_pts
[
j
].
y
-
(
float
)
_rLimits
.
y
)
+
matx
[
2
];
return
dMatchDeg
>
te
.
dMatchDeg
;
__mpts
[
j
].
y
=
matx
[
3
]
*
(
_pts
[
j
].
x
-
(
float
)
_rLimits
.
x
)
+
matx
[
4
]
*
(
_pts
[
j
].
y
-
(
float
)
_rLimits
.
y
)
+
matx
[
5
];
}
cv
::
Rect
_rr
(
cvFloor
(
std
::
min
(
std
::
min
(
std
::
min
(
__mpts
[
0
].
x
,
__mpts
[
1
].
x
),
__mpts
[
2
].
x
),
__mpts
[
3
].
x
)),
cvFloor
(
std
::
min
(
std
::
min
(
std
::
min
(
__mpts
[
0
].
y
,
__mpts
[
1
].
y
),
__mpts
[
2
].
y
),
__mpts
[
3
].
y
)),
cvCeil
(
std
::
max
(
std
::
max
(
std
::
max
(
__mpts
[
0
].
x
,
__mpts
[
1
].
x
),
__mpts
[
2
].
x
),
__mpts
[
3
].
x
)),
cvCeil
(
std
::
max
(
std
::
max
(
std
::
max
(
__mpts
[
0
].
y
,
__mpts
[
1
].
y
),
__mpts
[
2
].
y
),
__mpts
[
3
].
y
)));
_rr
.
width
-=
_rr
.
x
-
1
;
_rr
.
height
-=
_rr
.
y
-
1
;
//最终模板
tplMat
=
realTplMat
(
_rr
).
clone
();
//缩放比例
if
(
MIN
(
tplMat
.
size
().
width
,
tplMat
.
size
().
height
)
<
12.0
)
{
coeff
=
2.0
f
;
}
}
//最大值
};
cv
::
minMaxLoc
(
tplMat
,
NULL
,
&
taMaxGray
);
}
//标记为已追踪过
std
::
vector
<
cv
::
Point
>
vT
=
{
cv
::
Point
(
_pts
[
0
]),
cv
::
Point
(
_pts
[
1
])
,
cv
::
Point
(
_pts
[
2
])
,
cv
::
Point
(
_pts
[
3
])
};
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//标记计数
lbMat
.
ptr
<
uint8_t
>
(
cvRound
(
startCenter
.
y
))[
cvRound
(
startCenter
.
x
)]
=
255
;
//标记当前位置
cv
::
drawMarker
(
cc
,
cv
::
Point
(
startCenter
),
cv
::
Scalar
(
0
,
255
,
0
,
255
),
cv
::
MARKER_DIAMOND
,
5
);
//扫描步长
//扫描步长
const
double
dMinorStep
=
0.1
;
const
double
dMinorStep
=
0.1
;
//追踪长宽
//追踪长宽
const
double
trackLength
=
taLength
/
2.0
,
trackWidth
=
taHeight
/
4.0
;
//是否用较小尺寸的窗口
const
double
trackLength
=
std
::
max
(
rect
.
size
.
width
/
2
,
rect
.
size
.
height
/
2
),
trackWidth
=
std
::
min
(
rect
.
size
.
width
/
4
,
rect
.
size
.
height
/
4
);
//起始扫描角度
//起始扫描角度
const
double
startAngle
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180
.0
/
PI
;
const
double
startAngle
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180
/
PI
;
//起始扫描半径
//起始扫描半径
const
double
startRadius
=
cv
::
norm
(
startCenter
-
reelCenter
);
const
double
startRadius
=
cv
::
norm
(
startCenter
-
reelCenter
);
//偏移角度(元件尺寸)
//偏移角度(元件尺寸)
const
double
dOffset
=
(
2
.0
*
asin
(
2.0
*
trackLength
/
(
2.0
*
startRadius
)))
*
180.
0
/
PI
;
const
double
dOffset
=
(
2
*
asin
(
2
*
trackLength
/
(
2
*
startRadius
)))
*
18
0
/
PI
;
//
扫描角度(默认15度范围内存在元件
)
//
偏移角度(元件间距
)
const
double
dScanRange
=
15
.0
;
const
double
dScanRange
=
15
;
//追踪元件间距(弦长,可以尽量避免因个别器件偏离导致的追踪中断)
//追踪元件间距(弦长,可以尽量避免因个别器件偏离导致的追踪中断)
double
dChordL
=
.0
;
double
dChordL
=
.0
;
for
(
double
t
=
startAngle
+
dOffset
/
1.5
;
t
<
startAngle
+
dScanRange
;
t
+=
dMinorStep
)
for
(
double
t
=
startAngle
+
dOffset
/
1.5
;
t
<
startAngle
+
d
Offset
/
1.5
+
d
ScanRange
;
t
+=
dMinorStep
)
{
{
float
x
=
float
(
reelCenter
.
x
+
startRadius
*
cos
(
t
*
c
));
float
x
=
float
(
reelCenter
.
x
+
startRadius
*
cos
(
t
*
c
));
float
y
=
float
(
reelCenter
.
y
+
startRadius
*
sin
(
t
*
c
));
float
y
=
float
(
reelCenter
.
y
+
startRadius
*
sin
(
t
*
c
));
//防止超出图像范围
if
(
cvRound
(
x
)
<
0
||
(
cvRound
(
x
)
>
X
-
1
)
||
cvRound
(
y
)
<
0
||
(
cvRound
(
y
)
>
Y
-
1
))
{
break
;
}
//确定是否是下一个元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
y
))[
cvRound
(
x
)]
==
255
)
{
continue
;
}
//初次确定元件间距
//初次确定元件间距
const
double
angle
=
atan2
((
double
)
reelCenter
.
y
-
y
,
(
double
)
reelCenter
.
x
-
x
);
const
double
angle
=
atan2
((
double
)
reelCenter
.
y
-
y
,
(
double
)
reelCenter
.
x
-
x
);
...
@@ -1329,726 +1222,423 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
...
@@ -1329,726 +1222,423 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
//#ifdef _DEBUG
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
//#endif
cv
::
LineIterator
it
(
sinParts
,
p1
,
p2
,
4
);
cv
::
LineIterator
it
(
sinParts
,
p1
,
p2
,
4
);
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
{
if
(
sinParts
.
ptr
<
uint8_t
>
(
it
.
pos
().
y
)[
it
.
pos
().
x
]
==
255
)
if
(
(
sinParts
.
data
)[(
it
.
pos
().
x
)
+
(
it
.
pos
().
y
)
*
X
]
==
255
)
{
{
//计算元件间距(弦长)
//计算元件间距(弦长)
dChordL
=
2.0
*
startRadius
*
sin
(((
2.0
*
asin
((
cv
::
norm
(
startCenter
-
cv
::
Point2f
(
x
,
y
)))
/
(
2.0
*
startRadius
)))
*
180.0
/
PI
-
dOffset
/
2.0
)
*
PI
/
180.0
/
2.0
);
dChordL
=
2.0
*
startRadius
*
sin
(((
2.0
*
asin
((
cv
::
norm
(
startCenter
-
cv
::
Point2f
(
x
,
y
)))
/
(
2.0
*
startRadius
)))
*
180.0
/
PI
-
dOffset
/
2.0
)
*
PI
/
180.0
/
2.0
);
break
;
break
;
}
}
}
}
if
(
dChordL
>
2.1
)
if
(
dChordL
>
0
)
break
;
break
;
}
}
//没确定出元件间距一般为结尾或单个元件,继续从下一个起点计算弦长并开始追踪
//并行处理
if
(
dChordL
<=
2.1
)
{
//#pragma omp parallel sections
continue
;
}
//顺时针(是否并行取决于在windows下运行还是树莓派上)
{
{
//追踪中心
//(顺时针)
cv
::
Point2f
trackCenter
=
cv
::
Point2f
(
startCenter
.
x
,
startCenter
.
y
);
//#pragma omp section
//追踪角度、半径
double
trackAngle
=
startAngle
,
trackRadius
=
startRadius
;
//元件本身所占角度
double
trackOffset
=
dOffset
;
//元件间间距
double
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//开始追踪
bool
trackEnd
=
true
;
do
{
{
bool
found
=
true
;
bool
trayEnd
=
false
;
//追踪中心
std
::
vector
<
Track
>
vParts
;
cv
::
Point2f
trackCenter
=
cv
::
Point2f
(
startCenter
.
x
,
startCenter
.
y
);
for
(
double
t
=
trackAngle
+
(
trackOffset
+
partDist
-
trackOffset
/
12.0
);
t
<
trackAngle
+
(
trackOffset
+
partDist
-
trackOffset
/
12.0
)
+
trackOffset
/
6.0
;
t
+=
dMinorStep
)
//追踪角度、半径
double
trackAngle
=
startAngle
,
trackRadius
=
startRadius
;
//元件本身角度
double
trackOffset
=
dOffset
;
//元件间间距
double
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180
/
PI
;
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
//结束位置
Track
trackEndPos
;
//开始追踪
bool
trackEnd
=
true
;
do
{
{
cv
::
Point2f
predicPos
;
bool
found
=
true
;
predicPos
.
x
=
reelCenter
.
x
+
(
float
)
trackRadius
*
(
float
)
cos
((
trackAngle
+
(
trackOffset
+
partDist
))
*
c
);
std
::
vector
<
Track
>
vParts
;
predicPos
.
y
=
reelCenter
.
y
+
(
float
)
trackRadius
*
(
float
)
sin
((
trackAngle
+
(
trackOffset
+
partDist
))
*
c
);
for
(
double
t
=
trackAngle
+
(
trackOffset
/
2.0
+
partDist
);
t
<
trackAngle
+
(
trackOffset
/
2.0
+
partDist
)
+
trackOffset
;
t
+=
dMinorStep
)
//如果追踪到图像外则追踪终止
{
if
(
cvRound
(
predicPos
.
x
)
<
0
||
(
cvRound
(
predicPos
.
x
)
>
X
-
1
)
||
cvRound
(
predicPos
.
y
)
<
0
||
(
cvRound
(
predicPos
.
y
)
>
Y
-
1
))
{
trackCenter
.
x
=
reelCenter
.
x
+
(
float
)
trackRadius
*
(
float
)
cos
(
t
*
c
);
trayEnd
=
true
;
trackCenter
.
y
=
reelCenter
.
y
+
(
float
)
trackRadius
*
(
float
)
sin
(
t
*
c
);
break
;
float
b
=
(
float
)
cos
(
t
*
c
)
*
0.5
f
;
float
a
=
(
float
)
sin
(
t
*
c
)
*
0.5
f
;
pts
[
0
].
x
=
float
(
trackCenter
.
x
-
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
pts
[
0
].
y
=
float
(
trackCenter
.
y
+
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
1
].
x
=
float
(
trackCenter
.
x
+
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
pts
[
1
].
y
=
float
(
trackCenter
.
y
-
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
2
].
x
=
float
(
2
*
trackCenter
.
x
-
pts
[
0
].
x
);
pts
[
2
].
y
=
float
(
2
*
trackCenter
.
y
-
pts
[
0
].
y
);
pts
[
3
].
x
=
float
(
2
*
trackCenter
.
x
-
pts
[
1
].
x
);
pts
[
3
].
y
=
float
(
2
*
trackCenter
.
y
-
pts
[
1
].
y
);
std
::
vector
<
cv
::
Point
>
vPoints
;
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
//获取内部坐标
calcRotateRect
(
vRect
,
vPoints
);
//计算灰度值
double
dMatch
=
0
;
for
(
int
v
=
0
;
v
<
vPoints
.
size
();
v
++
)
{
if
(
vPoints
[
v
].
x
>=
0
&&
vPoints
[
v
].
x
<=
X
&&
vPoints
[
v
].
y
>=
0
&&
vPoints
[
v
].
y
<=
Y
)
{
dMatch
+=
(
srcPrev
.
data
)[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
];
}
}
dMatch
/=
(
double
)
vPoints
.
size
();
//仅扫描一个元件的角度
vParts
.
push_back
(
Track
(
0
,
0
,
dMatch
,
cv
::
Point
(
cvRound
(
trackCenter
.
x
),
cvRound
(
trackCenter
.
y
)),
vRect
));
//cv::circle(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), 0, cv::Scalar(0, 255, 255, 255), 1);
}
}
//感兴趣区域(向外扩展了一个元件,防止中心定位出现偏差或者料盘本身变形导致的偏差)
if
(
vParts
.
size
()
==
0
)
continue
;
cv
::
Point2f
predictBox
[
4
];
//
calcRotateRect
(
predicPos
,
(
float
)(
trackAngle
+
(
trackOffset
+
partDist
)),
(
float
)
trackLength
+
(
float
)
trackLength
,
(
float
)
trackWidth
+
(
float
)
trackWidth
,
predictBox
);
trackEndPos
=
vParts
[
vParts
.
size
()
/
2
];
//灰度极值认为是元件
cv
::
RotatedRect
r
(
predictBox
[
0
],
predictBox
[
1
],
predictBox
[
2
]);
std
::
sort
(
vParts
.
begin
(),
vParts
.
end
(),
std
::
greater
<
Track
>
());
cv
::
Rect
rLimits
=
r
.
boundingRect
()
&
cv
::
Rect
(
0
,
0
,
X
,
Y
);
//更新位置
trackCenter
=
cv
::
Point
(
vParts
[
0
].
Pos
.
x
,
vParts
[
0
].
Pos
.
y
);
//获取感兴趣区域
//更新扫描角度
float
matx
[
6
];
trackAngle
=
atan2
((
double
)
trackCenter
.
y
-
reelCenter
.
y
,
(
double
)
trackCenter
.
x
-
reelCenter
.
x
)
*
180
/
PI
;
cv
::
Mat
traceMat
=
getTrackMat
(
srcPrevS
(
rLimits
).
clone
()
//纵向扫描
,
(
trackAngle
+
(
trackOffset
+
partDist
))
+
90.0
,
fillVal
,
matx
);
vParts
.
clear
();
std
::
vector
<
cv
::
Point
>
trackLine
;
//计算原图中的点在旋转后的位置(即在traceMat中的精确位置)
drawLine
(
cc
,
reelCenter
,
trackCenter
,
cv
::
Scalar
(
0
,
255
,
255
,
255
),
1
,
trackLength
,
trackWidth
*
2
,
trackLine
);
cv
::
Point2f
predictBoxR
[
4
];
//更改纵向扫描方向,分两个方向?
for
(
int
j
=
0
;
j
<
4
;
j
++
)
cv
::
LineIterator
it
(
sinParts
,
trackLine
[
0
],
trackLine
[
1
],
4
);
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
{
predictBoxR
[
j
].
x
=
matx
[
0
]
*
(
predictBox
[
j
].
x
-
(
float
)
rLimits
.
x
)
+
matx
[
1
]
*
(
predictBox
[
j
].
y
-
(
float
)
rLimits
.
y
)
+
matx
[
2
];
float
b
=
(
float
)
cos
(
trackAngle
*
PI
/
180.
)
*
0.5
f
;
predictBoxR
[
j
].
y
=
matx
[
3
]
*
(
predictBox
[
j
].
x
-
(
float
)
rLimits
.
x
)
+
matx
[
4
]
*
(
predictBox
[
j
].
y
-
(
float
)
rLimits
.
y
)
+
matx
[
5
];
float
a
=
(
float
)
sin
(
trackAngle
*
PI
/
180.
)
*
0.5
f
;
}
pts
[
0
].
x
=
(
float
)(
it
.
pos
().
x
-
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
//中点
pts
[
0
].
y
=
(
float
)(
it
.
pos
().
y
+
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
cv
::
Point2f
predicPosR
((
predictBoxR
[
0
].
x
+
predictBoxR
[
1
].
x
+
predictBoxR
[
2
].
x
+
predictBoxR
[
3
].
x
)
/
4.0
f
,
pts
[
1
].
x
=
(
float
)(
it
.
pos
().
x
+
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
(
predictBoxR
[
0
].
y
+
predictBoxR
[
1
].
y
+
predictBoxR
[
2
].
y
+
predictBoxR
[
3
].
y
)
/
4.0
f
);
pts
[
1
].
y
=
(
float
)(
it
.
pos
().
y
-
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
2
].
x
=
(
float
)(
2
*
it
.
pos
().
x
-
pts
[
0
].
x
);
//理论区域
pts
[
2
].
y
=
(
float
)(
2
*
it
.
pos
().
y
-
pts
[
0
].
y
);
cv
::
Rect
tRec
=
cv
::
Rect
(
cv
::
Point
(
cvRound
((
predicPosR
.
x
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
pts
[
3
].
x
=
(
float
)(
2
*
it
.
pos
().
x
-
pts
[
1
].
x
);
cvRound
((
predicPosR
.
y
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
pts
[
3
].
y
=
(
float
)(
2
*
it
.
pos
().
y
-
pts
[
1
].
y
);
cv
::
Size
(
cvRound
(
trackLength
*
2.0
),
cvRound
(
trackWidth
*
4.0
)))
&
cv
::
Rect
(
0
,
0
,
traceMat
.
cols
,
traceMat
.
rows
);
std
::
vector
<
cv
::
Point
>
vPoints
;
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
//高精度理论区域
//获取内部坐标
cv
::
Rect_
<
float
>
tRecF
=
cv
::
Rect_
<
float
>
(
cv
::
Point2f
((
predicPosR
.
x
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
,
calcRotateRect
(
vRect
,
vPoints
);
(
predicPosR
.
y
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
),
//计算灰度值
cv
::
Size2f
((
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
4.0
f
))
int
iLimit
=
0
,
iPartSize
=
0
;
&
cv
::
Rect_
<
float
>
(
0.0
f
,
0.0
f
,
(
float
)
traceMat
.
cols
,
(
float
)
traceMat
.
rows
);
double
dMatch
=
0
;
for
(
int
v
=
0
;
v
<
vPoints
.
size
();
v
++
)
//理论区域向外扩展(即predictBox范围)
{
cv
::
Rect
rr
=
cv
::
Rect
(
cv
::
Point
(
cvRound
((
double
)
predicPosR
.
x
-
trackLength
*
2.0
),
if
(
vPoints
[
v
].
x
>=
0
&&
vPoints
[
v
].
x
<=
X
&&
vPoints
[
v
].
y
>=
0
&&
vPoints
[
v
].
y
<=
Y
)
cvRound
((
double
)
predicPosR
.
y
-
trackWidth
*
4.0
)),
cv
::
Size
(
cvRound
(
trackLength
*
2.0
*
2.0
),
cvRound
(
trackWidth
*
4.0
*
2.0
)))
&
cv
::
Rect
(
0
,
0
,
traceMat
.
cols
,
traceMat
.
rows
);
cv
::
Rect_
<
float
>
rrf
=
cv
::
Rect2f
(
cv
::
Point2f
((
predicPosR
.
x
*
2.0
f
-
(
float
)
trackLength
*
4.0
f
)
/
2.0
f
,
(
predicPosR
.
y
*
2.0
f
-
(
float
)
trackWidth
*
8.0
f
)
/
2.0
f
),
cv
::
Size2f
((
float
)
trackLength
*
4.0
f
,
(
float
)
trackWidth
*
8.0
f
))
&
cv
::
Rect2f
(
0.0
f
,
0.0
f
,
(
float
)
traceMat
.
cols
,
(
float
)
traceMat
.
rows
);
//元件尺寸太小放大N倍处理,这样坐标会精细些,考虑元件的80%尺寸作为kernel,防止元件尺寸变化太大
cv
::
Mat
kernel
=
cv
::
Mat
::
ones
(
cv
::
Size
(
cv
::
max
(
cvRound
((
float
)(
trackLength
*
2.0
)
*
coeff
),
cvRound
((
float
)(
trackWidth
*
4.0
)
*
coeff
)),
cv
::
min
(
cvRound
((
float
)(
trackLength
*
2.0
)
*
coeff
),
cvRound
((
float
)(
trackWidth
*
4.0
)
*
coeff
))),
CV_32FC1
);
cv
::
Mat
_traceMat
=
traceMat
.
clone
();
//放大
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_traceMat
,
_traceMat
,
cv
::
Size
(
cvRound
(
traceMat
.
size
().
width
*
coeff
),
cvRound
(
traceMat
.
size
().
height
*
coeff
)));
}
//计算最大值(当_traceMat尺寸小于kernel会报错)
cv
::
Mat
dst
;
cv
::
filter2D
(
_traceMat
,
dst
,
CV_32F
,
kernel
);
//归一化
cv
::
Mat
mmRescaling
;
cv
::
normalize
(
dst
,
mmRescaling
,
1.0
,
0.0
,
cv
::
NORM_MINMAX
);
//模板匹配做辅助判断,为了尽量避免定位出错
cv
::
Mat
_tplMat
;
tplMat
.
convertTo
(
_tplMat
,
CV_32FC1
);
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
}
//考虑并行计算两个模板结果
cv
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
int
modx
=
_tplMat
.
cols
%
2
,
mody
=
_tplMat
.
rows
%
2
;
cv
::
Mat
tplResultMap
;
cv
::
copyMakeBorder
(
tplResult0
,
tplResultMap
,
(
_tplMat
.
rows
-
mody
)
/
2
,
_traceMat
.
rows
-
tplResult0
.
rows
-
(
_tplMat
.
rows
-
mody
)
/
2
,
(
_tplMat
.
cols
-
modx
)
/
2
,
_traceMat
.
cols
-
tplResult0
.
cols
-
(
_tplMat
.
cols
-
modx
)
/
2
,
cv
::
BORDER_REPLICATE
);
//减去模板匹配的结果
mmRescaling
-=
tplResultMap
;
//非极大值抑制
cv
::
Mat
mask
;
cv
::
dilate
(
mmRescaling
,
mask
,
cv
::
Mat
());
cv
::
compare
(
mmRescaling
,
mask
,
mask
,
cv
::
CMP_GE
);
cv
::
Mat
non_plateau_mask
;
cv
::
erode
(
mmRescaling
,
non_plateau_mask
,
cv
::
Mat
());
cv
::
compare
(
mmRescaling
,
non_plateau_mask
,
non_plateau_mask
,
cv
::
CMP_GT
);
cv
::
bitwise_and
(
mask
,
non_plateau_mask
,
mask
);
//去掉分数过低的
mask
&=
cv
::
Mat
(
mmRescaling
>
0.36
);
//限定区域(mmRescaling范围内)
cv
::
Rect
_rr
=
cv
::
Rect
(
cvRound
(
rr
.
x
*
coeff
),
cvRound
(
rr
.
y
*
coeff
),
cvRound
(
rr
.
width
*
coeff
),
cvRound
(
rr
.
height
*
coeff
));
//候选元件位置
std
::
vector
<
cv
::
Point
>
candidates
;
cv
::
findNonZero
(
mask
(
_rr
),
candidates
);
//过滤
std
::
vector
<
Track
>
_vParts
;
for
(
auto
&
candidate
:
candidates
)
{
cv
::
Point
pt
(
candidate
.
x
+
_rr
.
x
,
candidate
.
y
+
_rr
.
y
);
float
confidence
=
mmRescaling
.
ptr
<
float
>
(
pt
.
y
)[
pt
.
x
];
if
(
confidence
>
0.5
f
)
{
_vParts
.
push_back
(
Track
(
0
,
0
,
confidence
,
cv
::
Point2f
((
float
)
pt
.
x
,
(
float
)
pt
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
}
}
//目标元件在小图中的位置
cv
::
Point2f
maxLox
;
//元件位置判断
if
(
_vParts
.
size
()
<=
0
)
{
//大概率终止
trayEnd
=
true
;
}
else
if
(
_vParts
.
size
()
==
1
)
{
//有可能会出错
maxLox
=
cv
::
Point2f
(
_vParts
[
0
].
Pos
.
x
/
coeff
,
_vParts
[
0
].
Pos
.
y
/
coeff
);
if
(
tRecF
.
contains
(
maxLox
))
{
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
+
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
}
else
{
//这里负责处理意外情况(极大可能是元件偏离过多或者料盘中心定位不准确导致的),
//采用距离理论位置最近的点(两种方式都失效的概率比较低,如果真的失效那就听天由命吧)
cv
::
Mat
_mmRescaling
,
_tplResultMap
;
_mmRescaling
=
mmRescaling
.
clone
();
_tplResultMap
=
tplResultMap
.
clone
();
//累加的方式
double
maxVal
;
cv
::
Point
maxLoc
;
cv
::
minMaxLoc
(
_mmRescaling
(
_rr
),
NULL
,
&
maxVal
,
NULL
,
&
maxLoc
);
maxLoc
+=
_rr
.
tl
();
//模板匹配的方式
double
minVal
;
cv
::
Point
minLoc
;
cv
::
minMaxLoc
(
_tplResultMap
(
_rr
),
&
minVal
,
NULL
,
&
minLoc
,
NULL
);
minLoc
+=
_rr
.
tl
();
std
::
vector
<
Track
>
__vParts
;
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
//排序
std
::
sort
(
__vParts
.
begin
(),
__vParts
.
end
(),
std
::
less
<
Track
>
());
//在小图中的位置
maxLox
=
cv
::
Point2f
(
__vParts
[
0
].
Pos
.
x
/
coeff
,
__vParts
[
0
].
Pos
.
y
/
coeff
);
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
+
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
iLimit
+=
ucpTrackLabel
[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
];
dMatch
+=
(
srcPrev
.
data
)[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
];
if
((
sinParts
.
data
)[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
]
==
255
)
iPartSize
++
;
}
}
}
}
vParts
.
push_back
(
Track
(
iLimit
,
iPartSize
,
dMatch
,
it
.
pos
(),
vRect
));
//cv::circle(cc, it.pos(), 0, cv::Scalar(255, 0, 0, 255), 1);
}
}
else
{
if
(
vParts
.
size
()
==
0
)
continue
;
//存在多个峰值,先判断分数最高是否位于理论位置
//方案二每个点以当前半径画圆,看下个点偏离圆多少
std
::
sort
(
_vParts
.
begin
(),
_vParts
.
end
(),
std
::
greater
<
Track
>
());
//灰度极值认为是元件(最多问题出现在这里,加个条件判断矩形内是否存在已标记像素)
for
(
auto
&
_vPart
:
_vParts
)
{
std
::
sort
(
vParts
.
begin
(),
vParts
.
end
(),
std
::
greater
<
Track
>
());
maxLox
=
cv
::
Point2f
(
_vPart
.
Pos
.
x
/
coeff
,
_vPart
.
Pos
.
y
/
coeff
);
//更新当前元件位置(必须不与已有元件重合)
if
(
tRecF
.
contains
(
maxLox
))
{
Track
mac
=
vParts
[
0
];
//计算旋转前的坐标(即匹配的最终坐标)
if
(
mac
.
iLimit
!=
0
)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
{
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
for
(
int
cc
=
1
;
cc
<
vParts
.
size
();
cc
++
)
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
{
if
(
vParts
[
cc
].
iLimit
<
mac
.
iLimit
)
//外包矩形顶点
mac
=
vParts
[
cc
];
cv
::
Point2f
pts
[
4
];
if
(
mac
.
iLimit
==
0
)
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
+
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
break
;
break
;
}
}
//如果不在则选取距离理论位置最近的
if
(
vParts
.
empty
())
{
//这里负责处理意外情况(极大可能是元件偏离过多或者中心定位不准确)
//,采用距离理论位置最近的点(两种方式都失效的概率比较低)
cv
::
Mat
_mmRescaling
,
_tplResultMap
;
_mmRescaling
=
mmRescaling
.
clone
();
_tplResultMap
=
tplResultMap
.
clone
();
//累加的方式
double
maxVal
;
cv
::
Point
maxLoc
;
cv
::
minMaxLoc
(
_mmRescaling
(
_rr
),
NULL
,
&
maxVal
,
NULL
,
&
maxLoc
);
maxLoc
+=
_rr
.
tl
();
//模板匹配的方式
double
minVal
;
cv
::
Point
minLoc
;
cv
::
minMaxLoc
(
_tplResultMap
(
_rr
),
&
minVal
,
NULL
,
&
minLoc
,
NULL
);
minLoc
+=
_rr
.
tl
();
std
::
vector
<
Track
>
__vParts
;
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
//排序
std
::
sort
(
__vParts
.
begin
(),
__vParts
.
end
(),
std
::
less
<
Track
>
());
//在小图中的位置
maxLox
=
cv
::
Point2f
(
__vParts
[
0
].
Pos
.
x
/
coeff
,
__vParts
[
0
].
Pos
.
y
/
coeff
);
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
+
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
}
}
}
trackCenter
=
mac
.
Pos
;
if
(
!
vParts
.
empty
())
{
//更新扫描半径
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
trackRadius
=
cv
::
norm
(
trackCenter
-
reelCenter
);
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
//更新扫描角度
cv
::
Size
(
cvRound
(
trackLength
*
2.0
)
+
2
,
cvRound
(
trackWidth
*
4.0
)
+
2
))
trackAngle
=
atan2
((
double
)
trackCenter
.
y
-
reelCenter
.
y
,
(
double
)
trackCenter
.
x
-
reelCenter
.
x
)
*
180
/
PI
;
&
cv
::
Rect
(
0
,
0
,
traceMat
.
cols
,
traceMat
.
rows
);
//更新偏移量(元件大小)
//当作一种辅助手段,无需设置太严格
trackOffset
=
(
2
*
asin
(
2
*
trackLength
/
(
2
*
trackRadius
)))
*
180
/
PI
;
double
dmax
;
//更新元件间角度
cv
::
minMaxLoc
(
traceMat
(
tRec_
).
clone
(),
NULL
,
&
dmax
);
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180
/
PI
;
if
(
dmax
<
0.7
*
taMaxGray
)
{
//判断是否结束
trayEnd
=
true
;
if
((
mac
.
iPartSize
<
sinPartSize
/
4
)
||
(
trackMat
.
at
<
uchar
>
((
cvRound
(
trackCenter
.
y
)),
(
cvRound
(
trackCenter
.
x
)))
==
255
)
||
(
mac
.
iLimit
/
255
)
>
(
rect
.
size
.
area
()
/
4
)
||
(
sinParts
.
at
<
uchar
>
((
cvRound
(
trackCenter
.
y
)),
(
cvRound
(
trackCenter
.
x
)))
==
0
))
}
{
found
=
false
;
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, trackEndPos.Rect[j], trackEndPos.Rect[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//}
//cv::circle(cc, trackCenter, 1, cv::Scalar(0, 255, 0, 255), 1);
}
}
break
;
else
}
//追踪终止,选取下一个起点
if
(
trayEnd
)
{
break
;
}
//更新位置
trackCenter
=
cv
::
Point2f
(
vParts
[
0
].
Pos
.
x
,
vParts
[
0
].
Pos
.
y
);
//更新扫描半径
trackRadius
=
cv
::
norm
(
trackCenter
-
reelCenter
);
//更新扫描角度
trackAngle
=
atan2
((
double
)
trackCenter
.
y
-
(
double
)
reelCenter
.
y
,
(
double
)
trackCenter
.
x
-
(
double
)
reelCenter
.
x
)
*
180.0
/
PI
;
//更新偏移量(元件角度大小)
trackOffset
=
(
2
*
asin
(
2
*
trackLength
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
//更新元件间角度
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
}
else
{
//计算元件位置
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
trackCenter
,
(
float
)
trackAngle
,
(
float
)
trackLength
,
(
float
)
trackWidth
,
pts
);
//标记计数
lbMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
=
255
;
//标记为已追踪过
std
::
vector
<
cv
::
Point
>
vT
=
{
cv
::
Point
(
pts
[
0
]),
cv
::
Point
(
pts
[
1
])
,
cv
::
Point
(
pts
[
2
])
,
cv
::
Point
(
pts
[
3
])
};
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//用于显示
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
14
,
173
,
238
,
255
),
1
);
//画出最终位置
}
std
::
vector
<
cv
::
Point
>
ptPoly
;
//#endif
for
(
int
j
=
0
;
j
<
4
;
j
++
)
}
{
//清空下一个
ptPoly
.
push_back
(
cv
::
Point
(
cvRound
(
mac
.
Rect
[
j
].
x
),
cvRound
(
mac
.
Rect
[
j
].
y
)));
vParts
.
resize
(
0
);
//cv::line(cc, mac.Rect[j], mac.Rect[(j + 1) % 4], cv::Scalar(0, 255, 0, 255), 1);
//跳过执行
if
(
killProcessID
==
0
)
{
logger
.
t
(
"eyemCountObjectIrregularPartsE 追踪阶段被跳过执行..."
);
found
=
false
;
}
trackEnd
=
(
!
found
);
}
while
(
!
trackEnd
);
}
//逆时针
{
//追踪起点
cv
::
Point2f
trackCenter
(
startCenter
.
x
,
startCenter
.
y
);
//追踪角度、半径
double
trackAngle
=
startAngle
,
trackRadius
=
startRadius
;
//元件本身角度
double
trackOffset
=
dOffset
;
//元件间间距
double
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//开始追踪
bool
trackEnd
=
true
;
//
do
{
bool
found
=
true
;
bool
trayEnd
=
false
;
std
::
vector
<
Track
>
vParts
;
for
(
double
t
=
trackAngle
-
(
trackOffset
+
partDist
-
trackOffset
/
12.0
);
t
>
trackAngle
-
(
trackOffset
+
partDist
-
trackOffset
/
12.0
)
-
trackOffset
/
6.0
;
t
-=
dMinorStep
)
{
cv
::
Point2f
predicPos
;
predicPos
.
x
=
reelCenter
.
x
+
(
float
)
trackRadius
*
(
float
)
cos
((
trackAngle
-
(
trackOffset
+
partDist
))
*
c
);
predicPos
.
y
=
reelCenter
.
y
+
(
float
)
trackRadius
*
(
float
)
sin
((
trackAngle
-
(
trackOffset
+
partDist
))
*
c
);
//如果追踪到图像外追踪终止
if
(
cvRound
(
predicPos
.
x
)
<
0
||
(
cvRound
(
predicPos
.
x
)
>
X
-
1
)
||
cvRound
(
predicPos
.
y
)
<
0
||
(
cvRound
(
predicPos
.
y
)
>
Y
-
1
))
{
trayEnd
=
true
;
break
;
}
//感兴趣区域(向外扩展了一个元件,防止中心定位出现偏差或者料盘本身变形导致的偏差)
cv
::
Point2f
predicBox
[
4
];
calcRotateRect
(
predicPos
,
(
float
)(
trackAngle
-
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
predicBox
);
cv
::
RotatedRect
r
(
predicBox
[
0
],
predicBox
[
1
],
predicBox
[
2
]);
cv
::
Rect
rLimits
=
r
.
boundingRect
()
&
cv
::
Rect
(
0
,
0
,
X
,
Y
);
//获取感兴趣区域
float
matx
[
6
];
cv
::
Mat
traceMat
=
getTrackMat
(
srcPrevS
(
rLimits
).
clone
()
,
(
trackAngle
-
(
trackOffset
+
partDist
))
+
90.0
,
fillVal
,
matx
);
//计算原图中的点在旋转后的位置(即在traceMat中的精确位置)
cv
::
Point2f
predictBoxR
[
4
];
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
predictBoxR
[
j
].
x
=
matx
[
0
]
*
(
predicBox
[
j
].
x
-
(
float
)
rLimits
.
x
)
+
matx
[
1
]
*
(
predicBox
[
j
].
y
-
(
float
)
rLimits
.
y
)
+
matx
[
2
];
predictBoxR
[
j
].
y
=
matx
[
3
]
*
(
predicBox
[
j
].
x
-
(
float
)
rLimits
.
x
)
+
matx
[
4
]
*
(
predicBox
[
j
].
y
-
(
float
)
rLimits
.
y
)
+
matx
[
5
];
}
//中点
cv
::
Point2f
predicPosR
((
predictBoxR
[
0
].
x
+
predictBoxR
[
1
].
x
+
predictBoxR
[
2
].
x
+
predictBoxR
[
3
].
x
)
/
4.0
f
,
(
predictBoxR
[
0
].
y
+
predictBoxR
[
1
].
y
+
predictBoxR
[
2
].
y
+
predictBoxR
[
3
].
y
)
/
4.0
f
);
//理论区域
cv
::
Rect
tRec
=
cv
::
Rect
(
cv
::
Point
(
cvRound
((
predicPosR
.
x
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cvRound
((
predicPosR
.
y
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
cv
::
Size
(
cvRound
(
trackLength
*
2.0
),
cvRound
(
trackWidth
*
4.0
)))
&
cv
::
Rect
(
0
,
0
,
traceMat
.
cols
,
traceMat
.
rows
);
//高精度理论区域
cv
::
Rect_
<
float
>
tRecF
=
cv
::
Rect_
<
float
>
(
cv
::
Point2f
((
predicPosR
.
x
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
,
(
predicPosR
.
y
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
),
cv
::
Size2f
((
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
4.0
f
))
&
cv
::
Rect_
<
float
>
(
0.0
f
,
0.0
f
,
(
float
)
traceMat
.
cols
,
(
float
)
traceMat
.
rows
);
//理论区域向外扩展(即predictBox范围)
cv
::
Rect
rr
=
cv
::
Rect
(
cv
::
Point
(
cvRound
((
double
)
predicPosR
.
x
-
trackLength
*
2.0
),
cvRound
((
double
)
predicPosR
.
y
-
trackWidth
*
4.0
)),
cv
::
Size
(
cvRound
(
trackLength
*
2.0
*
2.0
),
cvRound
(
trackWidth
*
4.0
*
2.0
)))
&
cv
::
Rect
(
0
,
0
,
traceMat
.
cols
,
traceMat
.
rows
);
cv
::
Rect_
<
float
>
rrf
=
cv
::
Rect2f
(
cv
::
Point2f
((
predicPosR
.
x
*
2.0
f
-
(
float
)
trackLength
*
4.0
f
)
/
2.0
f
,
(
predicPosR
.
y
*
2.0
f
-
(
float
)
trackWidth
*
8.0
f
)
/
2.0
f
),
cv
::
Size2f
((
float
)
trackLength
*
4.0
f
,
(
float
)
trackWidth
*
8.0
f
))
&
cv
::
Rect2f
(
0.0
f
,
0.0
f
,
(
float
)
traceMat
.
cols
,
(
float
)
traceMat
.
rows
);
//元件尺寸太小放大N倍处理,这样坐标会精细些,元件的80%尺寸作为kernel,防止元件尺寸变化太大
cv
::
Mat
kernel
=
cv
::
Mat
::
ones
(
cv
::
Size
(
cv
::
max
(
cvRound
((
float
)(
trackLength
*
2.0
)
*
coeff
),
cvRound
((
float
)(
trackWidth
*
4.0
)
*
coeff
)),
cv
::
min
(
cvRound
((
float
)(
trackLength
*
2.0
)
*
coeff
),
cvRound
((
float
)(
trackWidth
*
4.0
)
*
coeff
))),
CV_32FC1
);
cv
::
Mat
_traceMat
=
traceMat
.
clone
();
//放大
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_traceMat
,
_traceMat
,
cv
::
Size
(
cvRound
(
traceMat
.
size
().
width
*
coeff
),
cvRound
(
traceMat
.
size
().
height
*
coeff
)));
}
//计算最大值(当_traceMat尺寸小于kernel会报错)
cv
::
Mat
dst
;
cv
::
filter2D
(
_traceMat
,
dst
,
CV_32F
,
kernel
);
//归一化
cv
::
Mat
mmRescaling
;
cv
::
normalize
(
dst
,
mmRescaling
,
1.0
,
0.0
,
cv
::
NORM_MINMAX
);
//模板匹配,为了尽量避免定位出错
cv
::
Mat
_tplMat
;
tplMat
.
convertTo
(
_tplMat
,
CV_32FC1
);
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
}
//考虑并行计算两个模板结果
cv
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
int
modx
=
_tplMat
.
cols
%
2
,
mody
=
_tplMat
.
rows
%
2
;
cv
::
Mat
tplResultMap
;
cv
::
copyMakeBorder
(
tplResult0
,
tplResultMap
,
(
_tplMat
.
rows
-
mody
)
/
2
,
_traceMat
.
rows
-
tplResult0
.
rows
-
(
_tplMat
.
rows
-
mody
)
/
2
,
(
_tplMat
.
cols
-
modx
)
/
2
,
_traceMat
.
cols
-
tplResult0
.
cols
-
(
_tplMat
.
cols
-
modx
)
/
2
,
cv
::
BORDER_REPLICATE
);
//减去模板匹配的结果
mmRescaling
-=
tplResultMap
;
//非极大值抑制
cv
::
Mat
mask
;
cv
::
dilate
(
mmRescaling
,
mask
,
cv
::
Mat
());
cv
::
compare
(
mmRescaling
,
mask
,
mask
,
cv
::
CMP_GE
);
cv
::
Mat
non_plateau_mask
;
cv
::
erode
(
mmRescaling
,
non_plateau_mask
,
cv
::
Mat
());
cv
::
compare
(
mmRescaling
,
non_plateau_mask
,
non_plateau_mask
,
cv
::
CMP_GT
);
cv
::
bitwise_and
(
mask
,
non_plateau_mask
,
mask
);
//去掉分数过低的
mask
&=
cv
::
Mat
(
mmRescaling
>
0.36
);
//限定区域(mmRescaling范围内)
cv
::
Rect
_rr
=
cv
::
Rect
(
cvRound
(
rr
.
x
*
coeff
),
cvRound
(
rr
.
y
*
coeff
),
cvRound
(
rr
.
width
*
coeff
),
cvRound
(
rr
.
height
*
coeff
));
//候选元件位置
std
::
vector
<
cv
::
Point
>
candidates
;
cv
::
findNonZero
(
mask
(
_rr
),
candidates
);
//过滤
std
::
vector
<
Track
>
_vParts
;
for
(
auto
&
candidate
:
candidates
)
{
cv
::
Point
pt
(
candidate
.
x
+
_rr
.
x
,
candidate
.
y
+
_rr
.
y
);
float
confidence
=
mmRescaling
.
ptr
<
float
>
(
pt
.
y
)[
pt
.
x
];
if
(
confidence
>
0.5
f
)
{
_vParts
.
push_back
(
Track
(
0
,
0
,
confidence
,
cv
::
Point2f
((
float
)
pt
.
x
,
(
float
)
pt
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
}
}
//目标元件在小图中的位置
cv
::
Point2f
maxLox
;
//元件位置判断
if
(
_vParts
.
size
()
<=
0
)
{
//大概率终止
trayEnd
=
true
;
}
else
if
(
_vParts
.
size
()
==
1
)
{
maxLox
=
cv
::
Point2f
(
_vParts
[
0
].
Pos
.
x
/
coeff
,
_vParts
[
0
].
Pos
.
y
/
coeff
);
//有可能会出错,当靠的太近可能只存在一个峰值
if
(
tRecF
.
contains
(
maxLox
))
{
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
+
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
}
}
else
{
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//这里负责处理意外情况(极大可能是元件偏离过多或者中心定位不准确),采用距离理论位置最近的点(两种方式都失效的概率比较低)
cv
::
circle
(
lb4Count
,
trackCenter
,
0
,
cv
::
Scalar
(
255
),
1
);
cv
::
Mat
_mmRescaling
,
_tplResultMap
;
//标记Label
_mmRescaling
=
mmRescaling
.
clone
();
_tplResultMap
=
tplResultMap
.
clone
();
cv
::
fillConvexPoly
(
trackMat
,
ptPoly
,
cv
::
Scalar
(
255
));
//获得已处理标签
//累加的方式
std
::
vector
<
cv
::
Point
>
vTemp
;
double
maxVal
;
cv
::
Point
maxLoc
;
calcRotateRect
(
mac
.
Rect
,
vTemp
);
cv
::
minMaxLoc
(
_mmRescaling
(
_rr
),
NULL
,
&
maxVal
,
NULL
,
&
maxLoc
);
for
(
int
p
=
0
;
p
<
vTemp
.
size
();
p
++
)
maxLoc
+=
_rr
.
tl
();
{
if
(
vTemp
[
p
].
x
>=
0
&&
vTemp
[
p
].
x
<=
X
&&
vTemp
[
p
].
y
>=
0
&&
vTemp
[
p
].
y
<=
Y
)
//模板匹配的方式
double
minVal
;
cv
::
Point
minLoc
;
cv
::
minMaxLoc
(
_tplResultMap
(
_rr
),
&
minVal
,
NULL
,
&
minLoc
,
NULL
);
minLoc
+=
_rr
.
tl
();
std
::
vector
<
Track
>
__vParts
;
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
//排序
std
::
sort
(
__vParts
.
begin
(),
__vParts
.
end
(),
std
::
less
<
Track
>
());
//小图中的定位坐标
maxLox
=
cv
::
Point2f
(
__vParts
[
0
].
Pos
.
x
/
coeff
,
__vParts
[
0
].
Pos
.
y
/
coeff
);
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
-
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
int
label
=
labels
.
at
<
int
>
(
vTemp
[
p
]);
}
if
(
label
!=
0
)
}
{
}
labeled
[
label
]
=
255
;
else
{
break
;
//存在定位出错的可能性,先判断分数最高是否位于理论位置
}
std
::
sort
(
_vParts
.
begin
(),
_vParts
.
end
(),
std
::
greater
<
Track
>
());
}
for
(
auto
&
_vPart
:
_vParts
)
{
}
maxLox
=
cv
::
Point2f
(
_vPart
.
Pos
.
x
/
coeff
,
_vPart
.
Pos
.
y
/
coeff
);
}
if
(
tRecF
.
contains
(
maxLox
))
{
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
-
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
break
;
}
}
//如果不在则选取距离理论位置最近的
if
(
vParts
.
empty
())
{
//这里负责处理意外情况(极大可能是元件偏离过多或者中心定位不准确),采用距离理论位置最近的点(两种方式都失效的概率比较低)
cv
::
Mat
_mmRescaling
,
_tplResultMap
;
_mmRescaling
=
mmRescaling
.
clone
();
_tplResultMap
=
tplResultMap
.
clone
();
//累加的方式
double
maxVal
;
cv
::
Point
maxLoc
;
cv
::
minMaxLoc
(
_mmRescaling
(
_rr
),
NULL
,
&
maxVal
,
NULL
,
&
maxLoc
);
maxLoc
+=
_rr
.
tl
();
//模板匹配的方式
double
minVal
;
cv
::
Point
minLoc
;
cv
::
minMaxLoc
(
_tplResultMap
(
_rr
),
&
minVal
,
NULL
,
&
minLoc
,
NULL
);
minLoc
+=
_rr
.
tl
();
std
::
vector
<
Track
>
__vParts
;
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
maxLoc
.
x
,
(
float
)
maxLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
__vParts
.
push_back
(
Track
(
0
,
0
,
cv
::
norm
(
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
)
-
cv
::
Point2f
(
floorf
((
float
)
_traceMat
.
cols
/
2.0
f
),
floorf
((
float
)
_traceMat
.
rows
/
2.0
f
))),
cv
::
Point2f
((
float
)
minLoc
.
x
,
(
float
)
minLoc
.
y
),
std
::
vector
<
cv
::
Point2f
>
()));
//排序
std
::
sort
(
__vParts
.
begin
(),
__vParts
.
end
(),
std
::
less
<
Track
>
());
//小图中的位置
maxLox
=
cv
::
Point2f
(
__vParts
[
0
].
Pos
.
x
/
coeff
,
__vParts
[
0
].
Pos
.
y
/
coeff
);
//计算旋转前的坐标(即匹配的最终坐标)
float
realX
=
0.0
f
,
realY
=
0.0
f
;
realX
=
(
float
)
rLimits
.
tl
().
x
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
4
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
1
])
/
(
matx
[
0
]
*
matx
[
4
]
-
matx
[
3
]
*
matx
[
1
]);
realY
=
(
float
)
rLimits
.
tl
().
y
+
((
maxLox
.
x
-
matx
[
2
])
*
matx
[
3
]
-
(
maxLox
.
y
-
matx
[
5
])
*
matx
[
0
])
/
(
matx
[
1
]
*
matx
[
3
]
-
matx
[
4
]
*
matx
[
0
]);
//外包矩形顶点
//跳过执行
cv
::
Point2f
pts
[
4
];
if
(
killProcessID
==
0
)
{
calcRotateRect
(
cv
::
Point2f
(
realX
,
realY
),
(
float
)(
trackAngle
-
(
trackOffset
+
partDist
)),
(
float
)
trackLength
*
2.0
f
,
(
float
)
trackWidth
*
2.0
f
,
pts
);
logger
.
t
(
"eyemCountObjectIrregularPartsE 追踪阶段被跳过执行..."
);
found
=
false
;
}
//
trackEnd
=
(
!
found
);
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
)
);
}
while
(
!
trackEnd
);
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
}
for
(
int
j
=
0
;
j
<
4
;
j
++
)
//#pragma omp section
//逆时针追踪
{
//追踪起点
cv
::
Point2f
trackCenter
(
startCenter
.
x
,
startCenter
.
y
);
//起始扫描角度、半径
double
trackAngle
=
startAngle
,
trackRadius
=
startRadius
;
//元件本身角度
double
trackOffset
=
dOffset
;
//元件间间距
double
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180
/
PI
;
//当扫描一圈后修正中心位置(待测试)
cv
::
Point2f
pts
[
4
];
//结束位置
Track
trackEndPos
;
//开始追踪
bool
trackEnd
=
true
;
//
do
{
bool
found
=
true
;
std
::
vector
<
Track
>
vParts
;
for
(
double
t
=
trackAngle
-
(
partDist
+
trackOffset
/
2.0
);
t
>
trackAngle
-
(
partDist
+
trackOffset
/
2.0
)
-
trackOffset
;
t
-=
dMinorStep
)
{
trackCenter
.
x
=
float
(
reelCenter
.
x
+
trackRadius
*
cos
(
t
*
c
));
trackCenter
.
y
=
float
(
reelCenter
.
y
+
trackRadius
*
sin
(
t
*
c
));
float
b
=
(
float
)
cos
(
t
*
c
)
*
0.5
f
;
float
a
=
(
float
)
sin
(
t
*
c
)
*
0.5
f
;
pts
[
0
].
x
=
(
float
)(
trackCenter
.
x
-
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
pts
[
0
].
y
=
(
float
)(
trackCenter
.
y
+
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
1
].
x
=
(
float
)(
trackCenter
.
x
+
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
pts
[
1
].
y
=
(
float
)(
trackCenter
.
y
-
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
2
].
x
=
(
float
)(
2
*
trackCenter
.
x
-
pts
[
0
].
x
);
pts
[
2
].
y
=
(
float
)(
2
*
trackCenter
.
y
-
pts
[
0
].
y
);
pts
[
3
].
x
=
(
float
)(
2
*
trackCenter
.
x
-
pts
[
1
].
x
);
pts
[
3
].
y
=
(
float
)(
2
*
trackCenter
.
y
-
pts
[
1
].
y
);
std
::
vector
<
cv
::
Point
>
vPoints
;
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
//获取内部坐标
calcRotateRect
(
vRect
,
vPoints
);
//计算灰度值
double
dMatch
=
0
;
for
(
int
v
=
0
;
v
<
vPoints
.
size
();
v
++
)
{
if
(
vPoints
[
v
].
x
>=
0
&&
vPoints
[
v
].
x
<=
X
&&
vPoints
[
v
].
y
>=
0
&&
vPoints
[
v
].
y
<=
Y
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
)
;
dMatch
+=
(
srcPrev
.
data
)[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
]
;
}
}
}
}
dMatch
/=
(
double
)
vPoints
.
size
();
//仅扫描一个元件的角度
vParts
.
push_back
(
Track
(
0
,
0
,
dMatch
,
cv
::
Point
(
cvRound
(
trackCenter
.
x
),
cvRound
(
trackCenter
.
y
)),
vRect
));
//cv::circle(cc, trackCenter, 0, cv::Scalar(0, 255, 255, 255), 1);
}
}
if
(
!
vParts
.
empty
())
{
if
(
vParts
.
size
()
==
0
)
continue
;
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
//
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
trackEndPos
=
vParts
[
vParts
.
size
()
/
2
];
cv
::
Size
(
cvRound
(
trackLength
*
2.0
)
+
2
,
cvRound
(
trackWidth
*
4.0
)
+
2
))
//灰度极值认为是元件
&
cv
::
Rect
(
0
,
0
,
traceMat
.
cols
,
traceMat
.
rows
);
std
::
sort
(
vParts
.
begin
(),
vParts
.
end
(),
std
::
greater
<
Track
>
());
//当作一种辅助手段,无需设置太严格
//更新位置
double
dmax
;
trackCenter
=
cv
::
Point
(
vParts
[
0
].
Pos
.
x
,
vParts
[
0
].
Pos
.
y
);
cv
::
minMaxLoc
(
traceMat
(
tRec_
).
clone
(),
NULL
,
&
dmax
);
//更新扫描角度
if
(
dmax
<
0.7
*
taMaxGray
)
{
trackAngle
=
atan2
((
double
)
trackCenter
.
y
-
reelCenter
.
y
,
(
double
)
trackCenter
.
x
-
reelCenter
.
x
)
*
180
/
PI
;
trayEnd
=
true
;
//纵向扫描
vParts
.
clear
();
std
::
vector
<
cv
::
Point
>
trackLine
;
drawLine
(
cc
,
reelCenter
,
trackCenter
,
cv
::
Scalar
(
0
,
255
,
255
,
255
),
1
,
trackLength
,
trackWidth
*
2
,
trackLine
);
//更改纵向扫描方向,分两个方向
cv
::
LineIterator
it
(
sinParts
,
trackLine
[
0
],
trackLine
[
1
],
4
);
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
float
b
=
(
float
)
cos
(
trackAngle
*
PI
/
180.
)
*
0.5
f
;
float
a
=
(
float
)
sin
(
trackAngle
*
PI
/
180.
)
*
0.5
f
;
pts
[
0
].
x
=
(
float
)(
it
.
pos
().
x
-
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
pts
[
0
].
y
=
(
float
)(
it
.
pos
().
y
+
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
1
].
x
=
(
float
)(
it
.
pos
().
x
+
a
*
trackLength
*
2
-
b
*
trackWidth
*
4
);
pts
[
1
].
y
=
(
float
)(
it
.
pos
().
y
-
b
*
trackLength
*
2
-
a
*
trackWidth
*
4
);
pts
[
2
].
x
=
(
float
)(
2
*
it
.
pos
().
x
-
pts
[
0
].
x
);
pts
[
2
].
y
=
(
float
)(
2
*
it
.
pos
().
y
-
pts
[
0
].
y
);
pts
[
3
].
x
=
(
float
)(
2
*
it
.
pos
().
x
-
pts
[
1
].
x
);
pts
[
3
].
y
=
(
float
)(
2
*
it
.
pos
().
y
-
pts
[
1
].
y
);
std
::
vector
<
cv
::
Point
>
vPoints
;
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
//获取内部坐标
calcRotateRect
(
vRect
,
vPoints
);
//计算灰度值
int
iLimit
=
0
,
iPartSize
=
0
;
double
dMatch
=
0
;
for
(
int
v
=
0
;
v
<
vPoints
.
size
();
v
++
)
{
if
(
vPoints
[
v
].
x
>=
0
&&
vPoints
[
v
].
x
<=
X
&&
vPoints
[
v
].
y
>=
0
&&
vPoints
[
v
].
y
<=
Y
)
{
iLimit
+=
ucpTrackLabel
[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
];
dMatch
+=
(
srcPrev
.
data
)[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
];
if
((
sinParts
.
data
)[(
vPoints
[
v
].
x
)
+
(
vPoints
[
v
].
y
)
*
X
]
==
255
)
iPartSize
++
;
}
}
}
vParts
.
push_back
(
Track
(
iLimit
,
iPartSize
,
dMatch
,
it
.
pos
(),
vRect
));
//cv::circle(cc, it.pos(), 0, cv::Scalar(255, 0, 0, 255), 1);
}
}
break
;
if
(
vParts
.
size
()
==
0
)
continue
;
}
//灰度极值认为是元件
//接着下一个起点
std
::
sort
(
vParts
.
begin
(),
vParts
.
end
(),
std
::
greater
<
Track
>
());
if
(
trayEnd
)
{
//更新当前元件位置
break
;
Track
mac
=
vParts
[
0
];
}
if
(
mac
.
iLimit
!=
0
)
//更新位置
trackCenter
=
cv
::
Point2f
(
vParts
[
0
].
Pos
.
x
,
vParts
[
0
].
Pos
.
y
);
//更新扫描半径
trackRadius
=
cv
::
norm
(
trackCenter
-
reelCenter
);
//更新扫描角度
trackAngle
=
atan2
((
double
)
trackCenter
.
y
-
(
double
)
reelCenter
.
y
,
(
double
)
trackCenter
.
x
-
(
double
)
reelCenter
.
x
)
*
180.0
/
PI
;
//更新偏移量(元件角度大小)
trackOffset
=
(
2.0
*
asin
(
2.0
*
trackLength
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//更新元件间角度
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
}
else
{
//计算元件位置
cv
::
Point2f
pts
[
4
];
calcRotateRect
(
trackCenter
,
(
float
)
trackAngle
,
(
float
)
trackLength
,
(
float
)
trackWidth
,
pts
);
//标记计数
lbMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
=
255
;
//标记为已追踪过
std
::
vector
<
cv
::
Point
>
vT
=
{
cv
::
Point
(
pts
[
0
]),
cv
::
Point
(
pts
[
1
])
,
cv
::
Point
(
pts
[
2
])
,
cv
::
Point
(
pts
[
3
])
};
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//用于显示
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
102
,
205
,
0
,
255
),
1
);
for
(
int
cc
=
1
;
cc
<
vParts
.
size
();
cc
++
)
{
if
(
vParts
[
cc
].
iLimit
<
mac
.
iLimit
)
mac
=
vParts
[
cc
];
if
(
mac
.
iLimit
==
0
)
break
;
}
}
}
//#endif
trackCenter
=
mac
.
Pos
;
}
//更新扫描半径
//继续下一个起点
trackRadius
=
cv
::
norm
(
trackCenter
-
reelCenter
);
vParts
.
resize
(
0
);
//更新扫描角度
//跳过执行
trackAngle
=
atan2
((
double
)
trackCenter
.
y
-
reelCenter
.
y
,
(
double
)
trackCenter
.
x
-
reelCenter
.
x
)
*
180
/
PI
;
if
(
killProcessID
==
0
)
{
//更新偏移量
logger
.
t
(
"eyemCountObjectIrregularParts 追踪阶段被跳过执行..."
);
trackOffset
=
(
2
*
asin
(
2
*
trackLength
/
(
2
*
trackRadius
)))
*
180
/
PI
;
found
=
false
;
//更新追踪角度
}
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180
/
PI
;
trackEnd
=
(
!
found
);
//绕完一周后更新料盘中心试试?
}
while
(
!
trackEnd
);
//判断是否结束
if
(
mac
.
iPartSize
<
sinPartSize
/
4
||
(
trackMat
.
at
<
uchar
>
((
cvRound
(
trackCenter
.
y
)),
(
cvRound
(
trackCenter
.
x
)))
==
255
)
||
(
mac
.
iLimit
/
255
)
>
(
rect
.
size
.
area
()
/
4
)
||
(
sinParts
.
at
<
uchar
>
((
cvRound
(
trackCenter
.
y
)),
(
cvRound
(
trackCenter
.
x
)))
==
0
))
{
found
=
false
;
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, trackEndPos.Rect[j], trackEndPos.Rect[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//}
//cv::circle(cc, trackCenter, 1, cv::Scalar(0, 255, 0, 255), 1);
}
else
{
//画出最终位置
std
::
vector
<
cv
::
Point
>
ptPoly
;
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
ptPoly
.
push_back
(
cv
::
Point
(
cvRound
(
mac
.
Rect
[
j
].
x
),
cvRound
(
mac
.
Rect
[
j
].
y
)));
//cv::line(cc, mac.Rect[j], mac.Rect[(j + 1) % 4], cv::Scalar(0, 255, 0, 255), 1);
}
//
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
cv
::
circle
(
lb4Count
,
trackCenter
,
0
,
cv
::
Scalar
(
255
),
1
);
//标记Label
cv
::
fillConvexPoly
(
trackMat
,
ptPoly
,
cv
::
Scalar
(
255
));
//获得已处理标签
std
::
vector
<
cv
::
Point
>
vTemp
;
calcRotateRect
(
mac
.
Rect
,
vTemp
);
for
(
int
p
=
0
;
p
<
vTemp
.
size
();
p
++
)
{
if
(
vTemp
[
p
].
x
>=
0
&&
vTemp
[
p
].
x
<=
X
&&
vTemp
[
p
].
y
>=
0
&&
vTemp
[
p
].
y
<=
Y
)
{
int
label
=
labels
.
at
<
int
>
(
vTemp
[
p
]);
if
(
label
!=
0
)
{
labeled
[
label
]
=
255
;
break
;
}
}
}
}
//跳过执行
if
(
killProcessID
==
0
)
{
logger
.
t
(
"eyemCountObjectIrregularPartsE 追踪阶段被跳过执行..."
);
found
=
false
;
}
trackEnd
=
(
!
found
);
}
while
(
!
trackEnd
);
}
}
}
}
//去掉已标记处理的
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
++
)
{
int
label
=
((
int
*
)
labels
.
data
)[(
x
)
+
(
y
)
*
labels
.
cols
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
if
(
labeled
[
label
])
{
((
int
*
)(
labels
.
data
))[(
x
)
+
(
y
)
*
X
]
=
0
;
}
}
}
});
image
=
labels
>
0
;
//判断是否存在未追踪单个料
bExistSingle
=
(
cv
::
countNonZero
(
image
)
==
0
);
}
while
(
!
bExistSingle
);
//标记料盘编号
//标记料盘编号
//cv::putText(cc, std::to_string(sortedTrays[i].iDir), cv::Point(cvRound(reelCenter.x), cvRound(reelCenter.y) - 50), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
//cv::putText(cc, std::to_string(sortedTrays[i].iDir), cv::Point(cvRound(reelCenter.x), cvRound(reelCenter.y) - 50), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
//计数
//计数
int
reelNum
=
cv
::
countNonZero
(
lbMa
t
);
int
numObj
=
cv
::
countNonZero
(
lb4Coun
t
);
std
::
string
text
=
std
::
to_string
(
i
+
1
)
+
": Reel Number = "
;
std
::
string
text
=
std
::
to_string
(
i
+
1
)
+
": Reel Number = "
;
text
+=
std
::
to_string
(
reelNum
);
text
+=
std
::
to_string
(
numObj
);
text
+=
" ; PartSize = "
+
std
::
to_string
(
sinPartSize
);
text
+=
" ; PartSize = "
+
std
::
to_string
(
sinPartSize
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
+
i
*
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
+
i
*
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
//输出
//输出
trayNum
[
sortedTrays
[
i
].
iDir
]
=
reelNum
;
trayNum
[
sortedTrays
[
i
].
iDir
]
=
numObj
;
//释放资源
//释放资源
delete
[]
ucpTrackLabel
;
delete
[]
ucpTrackLabel
;
ucpTrackLabel
=
NULL
;
ucpTrackLabel
=
NULL
;
}
}
}
}
//输出结果
//输出结果
const
int
bufSize
=
64
;
const
int
SizeConst
=
4
;
char
cTrayNum
[
bufSize
*
4
]
=
{
0
};
for
(
int
i
=
0
;
i
<
trayNum
.
size
();
i
++
)
{
char
cTemp
[
bufSize
]
=
{
0
};
sprintf_s
(
cTemp
,
bufSize
,
"%d,"
,
trayNum
[
i
]);
strcat
(
cTrayNum
,
cTemp
);
}
//拷贝std::string拼接的字符串会莫名的报错??
*
lpszNumObj
=
(
char
*
)
CoTaskMemAlloc
(
bufSize
*
4
);
memset
(
*
lpszNumObj
,
0
,
bufSize
*
4
);
if
(
NULL
!=
*
lpszNumObj
)
{
strcpy
(
*
lpszNumObj
,
cTrayNum
);
}
//<输出计数结果标记图像
//<输出计数结果标记图像
{
{
for
(
int
i
=
0
;
i
<
SizeConst
;
i
++
)
{
ipReelNum
[
i
]
=
trayNum
[
i
];
}
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
//内存尺寸
//内存尺寸
...
@@ -2066,7 +1656,7 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
...
@@ -2066,7 +1656,7 @@ int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPS
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemCountObjectIrregularParts
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccSubType
,
LPSTR
*
lpsz
ReelNum
,
EyemImage
*
tpDstImg
)
int
eyemCountObjectIrregularParts
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccSubType
,
int
*
ip
ReelNum
,
EyemImage
*
tpDstImg
)
{
{
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
src
.
empty
())
{
if
(
src
.
empty
())
{
...
@@ -2781,9 +2371,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -2781,9 +2371,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
//
#ifdef _DEBUG
#ifdef _DEBUG
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
//
#endif
#endif
cv
::
LineIterator
it
(
binary
,
p1
,
p2
,
4
);
cv
::
LineIterator
it
(
binary
,
p1
,
p2
,
4
);
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
{
...
@@ -3001,11 +2591,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3001,11 +2591,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -3071,11 +2662,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3071,11 +2662,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
#endif
}
}
}
}
...
@@ -3122,12 +2714,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3122,12 +2714,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//用于显示
//用于显示
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//
#ifdef _DEBUG
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
14
,
173
,
238
,
255
),
1
);
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
14
,
173
,
238
,
255
),
1
);
}
}
//
#endif
#endif
}
}
//清空下一个
//清空下一个
vParts
.
resize
(
0
);
vParts
.
resize
(
0
);
...
@@ -3334,11 +2926,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3334,11 +2926,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -3402,23 +2995,15 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3402,23 +2995,15 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
}
}
#endif
}
}
}
}
if
(
!
vParts
.
empty
())
{
if
(
!
vParts
.
empty
())
{
#pragma region 测试用
////显示用
//cv::Mat traceMat4, traceMat5;
//_traceMat.convertTo(traceMat4, CV_8U);
//traceMat.convertTo(traceMat5, CV_8U);
//cv::rectangle(traceMat5, rr, cv::Scalar(0));
//cv::rectangle(traceMat4, _rr, cv::Scalar(0));
#pragma endregion
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
cv
::
Size
(
cvRound
(
trackLength
*
2.0
)
+
2
,
cvRound
(
trackWidth
*
4.0
)
+
2
))
cv
::
Size
(
cvRound
(
trackLength
*
2.0
)
+
2
,
cvRound
(
trackWidth
*
4.0
)
+
2
))
...
@@ -3461,12 +3046,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3461,12 +3046,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//用于显示
//用于显示
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//
#ifdef _DEBUG
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
102
,
205
,
0
,
255
),
1
);
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
102
,
205
,
0
,
255
),
1
);
}
}
//
#endif
#endif
}
}
//继续下一个起点
//继续下一个起点
vParts
.
resize
(
0
);
vParts
.
resize
(
0
);
...
@@ -3820,9 +3405,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3820,9 +3405,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
//
#ifdef _DEBUG
#ifdef _DEBUG
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
//
#endif
#endif
cv
::
LineIterator
it
(
binary
,
p1
,
p2
,
4
);
cv
::
LineIterator
it
(
binary
,
p1
,
p2
,
4
);
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
{
...
@@ -4040,11 +3625,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4040,11 +3625,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -4110,11 +3696,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4110,11 +3696,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
#endif
}
}
}
}
...
@@ -4373,11 +3960,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4373,11 +3960,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -4441,11 +4029,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4441,11 +4029,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
}
}
#endif
}
}
}
}
if
(
!
vParts
.
empty
())
{
if
(
!
vParts
.
empty
())
{
...
@@ -4646,47 +4235,15 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4646,47 +4235,15 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
else
else
{
{
//先用自动算法点,如果不行判断为散料
//先用自动算法点,如果不行判断为散料
LPSTR
trayNum
=
""
;
int
trayNum
[
4
]
;
int
iRet
=
eyemCountObjectE
(
tpImage
,
tpRoi
,
""
,
&
trayNum
,
tpDstImg
);
int
iRet
=
eyemCountObjectE
(
tpImage
,
tpRoi
,
""
,
trayNum
,
tpDstImg
);
if
(
iRet
==
FUNC_OK
)
{
if
(
iRet
==
FUNC_OK
)
{
cv
::
Mat
showCC
=
cv
::
Mat
(
tpDstImg
->
iHeight
,
tpDstImg
->
iWidth
,
MAKETYPE
(
tpDstImg
->
iDepth
,
tpDstImg
->
iChannels
),
tpDstImg
->
vpImage
);
std
::
vector
<
std
::
string
>
trayNums
;
split
(
trayNum
,
","
,
trayNums
);
//输出结果
//输出结果
std
::
string
tTrayNum
=
""
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
//输出结果
for
(
int
i
=
0
;
i
<
4
;
i
++
)
ipReelNum
[
i
]
=
trayNum
[
i
];
{
break
;
if
(
trayNums
[
i
]
!=
"0"
)
{
//输出结果
tTrayNum
=
trayNums
[
i
];
break
;
}
}
*
lpszReelNum
=
(
char
*
)
CoTaskMemAlloc
(
tTrayNum
.
size
()
+
1
);
if
(
NULL
!=
lpszReelNum
)
{
strcpy
(
*
lpszReelNum
,
tTrayNum
.
c_str
());
}
}
//获取当前运行目录
char
buf
[
128
];
_getcwd
(
buf
,
sizeof
(
buf
));
////不存在则创建
std
::
string
filePath
(
buf
);
filePath
+=
"
\\
ResOut"
;
if
(
_access
(
filePath
.
c_str
(),
0
)
==
-
1
)
_mkdir
(
filePath
.
c_str
());
//格式化文件名
char
file
[
256
];
sprintf_s
(
file
,
"%s
\\
%s-Mark.png"
,
filePath
.
c_str
(),
fileName
);
cv
::
imwrite
(
file
,
showCC
);
return
FUNC_OK
;
return
FUNC_OK
;
}
}
else
{
else
{
...
@@ -4755,17 +4312,13 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4755,17 +4312,13 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
std
::
string
text
=
"Reel Number = "
+
std
::
to_string
(
trayNum
);
std
::
string
text
=
"Reel Number = "
+
std
::
to_string
(
trayNum
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
//<输出结果
//<输出结果
const
int
bufSize
=
16
;
const
int
SizeConst
=
4
;
char
cReelNum
[
bufSize
]
=
{
0
};
sprintf_s
(
cReelNum
,
bufSize
,
"%d,"
,
trayNum
);
//拷贝std::string拼接的字符串会莫名的报错??
*
lpszReelNum
=
(
char
*
)
CoTaskMemAlloc
(
bufSize
);
memset
(
*
lpszReelNum
,
0
,
bufSize
);
if
(
NULL
!=
*
lpszReelNum
)
{
strcpy
(
*
lpszReelNum
,
cReelNum
);
}
//<输出计数结果标记图像
//<输出计数结果标记图像
{
{
memset
(
ipReelNum
,
0
,
SizeConst
);
ipReelNum
[
0
]
=
trayNum
;
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
//内存尺寸
//内存尺寸
...
@@ -4783,7 +4336,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4783,7 +4336,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemCountObjectE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
LPSTR
*
lpszNumObj
,
EyemImage
*
tpDstImg
)
int
eyemCountObjectE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
int
*
ipReelNum
,
EyemImage
*
tpDstImg
)
{
{
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
src
.
empty
())
{
if
(
src
.
empty
())
{
...
@@ -4903,13 +4456,9 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -4903,13 +4456,9 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
trays
.
push_back
(
TrayPos
(
reelCenter
,
tray
,
false
,
backThresh
));
trays
.
push_back
(
TrayPos
(
reelCenter
,
tray
,
false
,
backThresh
));
}
}
//判断可能无料,不能100%判断
//判断可能无料,不能100%判断
if
(
trays
.
size
()
<
1
)
if
(
trays
.
size
()
<
1
)
{
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
std
::
string
strTrayNum
=
"无料,"
;
ipReelNum
[
i
]
=
0
;
*
lpszNumObj
=
(
char
*
)
CoTaskMemAlloc
(
strTrayNum
.
size
());
if
(
NULL
!=
*
lpszNumObj
)
{
strcpy
(
*
lpszNumObj
,
strTrayNum
.
c_str
());
}
}
return
FUNC_CANNOT_CALC
;
return
FUNC_CANNOT_CALC
;
}
}
...
@@ -4975,8 +4524,10 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -4975,8 +4524,10 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
//分料盘计数
//分料盘计数
for
(
int
i
=
0
;
i
<
sortedTrays
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
sortedTrays
.
size
();
i
++
)
{
{
cv
::
Mat
srcPrev
;
cv
::
Mat
srcPrev
,
srcPrevB
;
cv
::
bitwise_not
(
sortedTrays
[
i
].
Tray
,
srcPrev
);
cv
::
bitwise_not
(
sortedTrays
[
i
].
Tray
,
srcPrev
);
//备份
srcPrevB
=
srcPrev
.
clone
();
//二值化可以分别放在两个算法里
//二值化可以分别放在两个算法里
cv
::
Mat
sinParts
;
cv
::
Mat
sinParts
;
cv
::
threshold
(
srcPrev
,
sinParts
,
(
255
-
sortedTrays
[
i
].
dBackThresh
),
255
,
cv
::
THRESH_BINARY
);
cv
::
threshold
(
srcPrev
,
sinParts
,
(
255
-
sortedTrays
[
i
].
dBackThresh
),
255
,
cv
::
THRESH_BINARY
);
...
@@ -5297,7 +4848,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5297,7 +4848,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
cv
::
Mat
lbMat
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
Mat
lbMat
(
Y
,
X
,
CV_8UC1
,
cv
::
Scalar
(
0
));
//定位图像
//定位图像
cv
::
Mat
srcPrevS
,
tplMat
;
//模板文件
cv
::
Mat
srcPrevS
,
tplMat
;
//模板文件
srcPrev
.
convertTo
(
srcPrevS
,
CV_32F
);
srcPrev
B
.
convertTo
(
srcPrevS
,
CV_32F
);
//随机打乱顺序(降低计算错误dChordL的可能性,也为了测试在起点信息不同时的稳定性)
//随机打乱顺序(降低计算错误dChordL的可能性,也为了测试在起点信息不同时的稳定性)
std
::
random_shuffle
(
tracingAnchors
.
begin
(),
tracingAnchors
.
end
());
std
::
random_shuffle
(
tracingAnchors
.
begin
(),
tracingAnchors
.
end
());
//开始确定起点(现在是用圆轨迹来追踪,不排除用螺旋线轨迹来追踪)
//开始确定起点(现在是用圆轨迹来追踪,不排除用螺旋线轨迹来追踪)
...
@@ -5331,7 +4882,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5331,7 +4882,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
//确定元件位置根据旋转后的位置确定(前提是料盘中心定位的准确)
//确定元件位置根据旋转后的位置确定(前提是料盘中心定位的准确)
double
t
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180.0
/
PI
;
double
t
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180.0
/
PI
;
//计算旋转角度
//计算旋转角度
cv
::
Mat
traceMat
=
srcPrev
(
_rLimits
);
cv
::
Mat
traceMat
=
srcPrev
B
(
_rLimits
);
//这里计算得出的模板不是很对
//这里计算得出的模板不是很对
float
matx
[
6
];
float
matx
[
6
];
tplMat
=
getTrackMat
(
traceMat
,
t
+
90.0
,
0
,
matx
);
tplMat
=
getTrackMat
(
traceMat
,
t
+
90.0
,
0
,
matx
);
...
@@ -5422,7 +4973,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5422,7 +4973,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
const
double
dMinorStep
=
0.1
;
const
double
dMinorStep
=
0.1
;
//追踪长宽
//追踪长宽
const
double
trackLength
=
taLength
/
2.0
,
trackWidth
=
taHeight
/
4.0
;
//是否用较小尺寸的窗口
const
double
trackLength
=
taLength
/
2.0
,
trackWidth
=
taHeight
/
4.0
;
//是否用较小尺寸的窗口
//起始扫描角度
//起始扫描角度
const
double
startAngle
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180.0
/
PI
;
const
double
startAngle
=
atan2
((
double
)
startCenter
.
y
-
reelCenter
.
y
,
(
double
)
startCenter
.
x
-
reelCenter
.
x
)
*
180.0
/
PI
;
//起始扫描半径
//起始扫描半径
const
double
startRadius
=
cv
::
norm
(
startCenter
-
reelCenter
);
const
double
startRadius
=
cv
::
norm
(
startCenter
-
reelCenter
);
...
@@ -5452,9 +5003,9 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5452,9 +5003,9 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cv
::
Point
p2
=
cv
::
Point
(
cvRound
(
x
+
trackWidth
*
cos
(
angle
+
CV_PI
)),
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
cvRound
(
y
+
trackWidth
*
sin
(
angle
+
CV_PI
)));
//
#ifdef _DEBUG
#ifdef _DEBUG
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
cv
::
line
(
cc
,
p1
,
p2
,
cv
::
Scalar
(
0
,
215
,
255
,
255
),
1
);
//
#endif
#endif
cv
::
LineIterator
it
(
sinParts
,
p1
,
p2
,
4
);
cv
::
LineIterator
it
(
sinParts
,
p1
,
p2
,
4
);
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
for
(
int
n
=
0
;
n
<
it
.
count
;
n
++
,
++
it
)
{
{
...
@@ -5672,11 +5223,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5672,11 +5223,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -5742,14 +5294,14 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5742,14 +5294,14 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
cv
::
line
(
cc
,
predictBox
[
j
],
predictBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
#endif
}
}
}
}
if
(
!
vParts
.
empty
())
{
if
(
!
vParts
.
empty
())
{
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
...
@@ -5793,12 +5345,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -5793,12 +5345,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//用于显示
//用于显示
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//
#ifdef _DEBUG
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
14
,
173
,
238
,
255
),
1
);
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
14
,
173
,
238
,
255
),
1
);
}
}
//
#endif
#endif
}
}
//清空下一个
//清空下一个
vParts
.
resize
(
0
);
vParts
.
resize
(
0
);
...
@@ -6005,11 +5557,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -6005,11 +5557,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -6073,13 +5626,15 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -6073,13 +5626,15 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
//
//
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
std
::
vector
<
cv
::
Point2f
>
vRect
(
pts
,
pts
+
sizeof
(
pts
)
/
sizeof
(
cv
::
Point2f
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
vParts
.
push_back
(
Track
(
0
,
0
,
0
,
cv
::
Point2f
(
realX
,
realY
),
vRect
));
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
cv
::
line
(
cc
,
predicBox
[
j
],
predicBox
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
0
,
238
,
255
),
1
);
}
}
#endif
}
}
}
}
if
(
!
vParts
.
empty
())
{
if
(
!
vParts
.
empty
())
{
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cv
::
Rect
tRec_
=
cv
::
Rect
(
cv
::
Point
(
cvFloor
((((
float
)
maxLox
.
x
)
*
2.0
f
-
(
float
)
trackLength
*
2.0
f
)
/
2.0
f
),
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
cvFloor
((((
float
)
maxLox
.
y
)
*
2.0
f
-
(
float
)
trackWidth
*
4.0
f
)
/
2.0
f
)),
...
@@ -6123,12 +5678,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -6123,12 +5678,12 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
cv
::
fillConvexPoly
(
trackMat
,
vT
,
cv
::
Scalar
(
255
));
//用于显示
//用于显示
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
cv
::
circle
(
cc
,
trackCenter
,
2
,
cv
::
Scalar
(
0
,
255
,
0
,
255
),
1
);
//
#ifdef _DEBUG
#ifdef _DEBUG
for
(
int
j
=
0
;
j
<
4
;
j
++
)
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
{
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
102
,
205
,
0
,
255
),
1
);
cv
::
line
(
cc
,
pts
[
j
],
pts
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
102
,
205
,
0
,
255
),
1
);
}
}
//
#endif
#endif
}
}
//继续下一个起点
//继续下一个起点
vParts
.
resize
(
0
);
vParts
.
resize
(
0
);
...
@@ -6157,21 +5712,13 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -6157,21 +5712,13 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
}
}
}
}
//输出结果
//输出结果
const
int
bufSize
=
64
;
const
int
SizeConst
=
4
;
char
cTrayNum
[
bufSize
*
4
]
=
{
0
};
for
(
int
i
=
0
;
i
<
trayNum
.
size
();
i
++
)
{
char
cTemp
[
bufSize
]
=
{
0
};
sprintf_s
(
cTemp
,
bufSize
,
"%d,"
,
trayNum
[
i
]);
strcat
(
cTrayNum
,
cTemp
);
}
//拷贝std::string拼接的字符串会莫名的报错??
*
lpszNumObj
=
(
char
*
)
CoTaskMemAlloc
(
bufSize
*
4
);
memset
(
*
lpszNumObj
,
0
,
bufSize
*
4
);
if
(
NULL
!=
*
lpszNumObj
)
{
strcpy
(
*
lpszNumObj
,
cTrayNum
);
}
//<输出计数结果标记图像
//<输出计数结果标记图像
{
{
for
(
int
i
=
0
;
i
<
SizeConst
;
i
++
)
{
ipReelNum
[
i
]
=
trayNum
[
i
];
}
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
//内存尺寸
//内存尺寸
...
@@ -6189,7 +5736,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
...
@@ -6189,7 +5736,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LP
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemCountObjectIrregularPartsE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccTplName
,
IntPtr
hModelID
,
LPSTR
*
lpsz
ReelNum
,
EyemImage
*
tpDstImg
)
int
eyemCountObjectIrregularPartsE
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
fileName
,
const
char
*
ccTplName
,
IntPtr
hModelID
,
int
*
ip
ReelNum
,
EyemImage
*
tpDstImg
)
{
{
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
src
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
...
@@ -7097,22 +6644,14 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -7097,22 +6644,14 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, EyemRect tpRoi, const char
std
::
string
text
=
"Reel Number = "
+
std
::
to_string
(
reelNum
);
std
::
string
text
=
"Reel Number = "
+
std
::
to_string
(
reelNum
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
///<输出结果
//<输出结果
const
int
bufSize
=
16
;
const
int
SizeConst
=
4
;
//<输出计数结果标记图像
char
cReelNum
[
bufSize
]
=
{
0
};
sprintf_s
(
cReelNum
,
bufSize
,
"%d,"
,
reelNum
);
//拷贝std::string拼接的字符串会莫名的报错??
*
lpszReelNum
=
(
char
*
)
CoTaskMemAlloc
(
bufSize
);
memset
(
*
lpszReelNum
,
0
,
bufSize
);
if
(
NULL
!=
*
lpszReelNum
)
{
{
strcpy
(
*
lpszReelNum
,
cReelNum
);
memset
(
ipReelNum
,
0
,
SizeConst
);
}
ipReelNum
[
0
]
=
reelNum
;
///<输出计数结果标记图像
{
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
tpDstImg
->
iWidth
=
cc
.
cols
;
tpDstImg
->
iHeight
=
cc
.
rows
;
tpDstImg
->
iDepth
=
cc
.
depth
();
tpDstImg
->
iChannels
=
cc
.
channels
();
//内存尺寸
//内存尺寸
...
@@ -7502,7 +7041,13 @@ int eyemRemoveModelByName(IntPtr hModelID, const char *ccTplName)
...
@@ -7502,7 +7041,13 @@ int eyemRemoveModelByName(IntPtr hModelID, const char *ccTplName)
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemMatchTemplateModel
(
EyemImage
tpImage
,
IntPtr
hModelID
,
LPSTR
*
lpszTplName
)
int
eyemRemoveModelByID
(
IntPtr
hModelID
,
const
int
iTplID
)
{
return
FUNC_OK
;
}
int
eyemMatchTemplateModel
(
EyemImage
tpImage
,
IntPtr
hModelID
,
char
**
lpszTplName
)
{
{
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
...
@@ -7617,93 +7162,6 @@ int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, LPSTR *lpszTplNam
...
@@ -7617,93 +7162,6 @@ int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, LPSTR *lpszTplNam
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemUpdateModel
(
const
char
*
ccTplPath
)
{
//获取文件路径
std
::
vector
<
std
::
string
>
fileNames
;
cv
::
glob
(
ccTplPath
,
fileNames
);
//判断文件
if
(
fileNames
.
size
()
<=
0
)
return
FUNC_CANNOT_CALC
;
for
(
std
::
vector
<
std
::
string
>::
iterator
it
=
fileNames
.
begin
();
it
!=
fileNames
.
end
();
++
it
)
{
std
::
string
fileName
=
(
*
it
);
struct
stat
_Stat
;
if
(
stat
(
fileName
.
c_str
(),
&
_Stat
)
!=
0
)
return
FUNC_CANNOT_CALC
;
FILE
*
fps
=
NULL
;
fopen_s
(
&
fps
,
fileName
.
c_str
(),
"r"
);
//判断文件是否打开
if
(
NULL
==
fps
)
return
FUNC_CANNOT_CALC
;
//获取文件大小
const
int
_Size
=
(
int
)
_Stat
.
st_size
;
//分配内存
unsigned
char
*
_Data
=
(
unsigned
char
*
)
malloc
(
_Size
);
if
(
NULL
==
_Data
)
return
FUNC_CANNOT_CALC
;
//初始化
memset
(
_Data
,
0
,
_Size
);
//读取数据
fread
(
_Data
,
sizeof
(
uint8_t
),
_Size
,
fps
);
//关闭文件
fclose
(
fps
);
////获取图像数据大小
//unsigned char _SizeData[8];
//memcpy(_SizeData, _Data, 8);
////有效信息长度
//const int valSize = std::atoi((const char *)_SizeData);
////文件信息
//const int tplSize = _Size - valSize - 8;
////拷贝文件信息
//char *tplInfo = new char[tplSize];
//memcpy(tplInfo, _Data + valSize + 8, tplSize);
////获取文件信息
//std::string line(tplInfo);
//std::vector<std::string> hints;
//split(line, ",", hints);
////宽,高,坐标,匹配度
//int X = std::atoi(hints[2].c_str()), Y = std::atoi(hints[3].c_str());
//double dMatchDeg = std::atof(hints[4].substr(0, 4).c_str()); pt = cv::Point(std::atoi(hints[0].c_str()), std::atoi(hints[1].c_str()));
//////创建图像文件
////cv::Mat tplMat= tplMat.create(Y, X, CV_8UC1, -1, true);
//////拷贝数据
////cv::Mat _tplMat = tplMat.getMat();
////memcpy(_tplMat.data, _Data + 8, valSize);
////释放内存
//delete[] tplInfo;
//tplInfo = NULL;
////释放文件内存
//free(_Data);
//_Data = NULL;
}
return
FUNC_OK
;
}
int
eyemReleaseModel
(
IntPtr
&
hModelID
)
int
eyemReleaseModel
(
IntPtr
&
hModelID
)
{
{
if
(
NULL
==
hModelID
)
if
(
NULL
==
hModelID
)
...
@@ -7803,7 +7261,6 @@ int eyemTrackFeature(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois,
...
@@ -7803,7 +7261,6 @@ int eyemTrackFeature(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois,
int
eyemAOIForTSAV
(
EyemImage
tpRefImg
,
EyemImage
tpNextImg
,
EyemRect3
*
tpRois
,
int
iRoiNum
)
int
eyemAOIForTSAV
(
EyemImage
tpRefImg
,
EyemImage
tpNextImg
,
EyemRect3
*
tpRois
,
int
iRoiNum
)
{
{
return
FUNC_OK
;
return
FUNC_OK
;
}
}
...
...
eyemLib/eyemMisc.h
查看文件 @
c28b0fe
...
@@ -5,17 +5,12 @@
...
@@ -5,17 +5,12 @@
#ifndef __EYEM_MISC_H
#ifndef __EYEM_MISC_H
#define __EYEM_MISC_H
#define __EYEM_MISC_H
#include <io.h>
#include <fstream>
#include <direct.h>
#include "eyemLib.h"
#include "eyemLib.h"
#include <tbb\tbb.h>
#include <tbb\tbb.h>
extern
Logger
logger
;
constexpr
double
c
=
PI
/
180
.;
constexpr
double
c
=
PI
/
180
.;
extern
Logger
logger
;
extern
int
killProcessID
;
extern
int
killProcessID
;
#endif
/* __EYEM_MISC_H */
#endif
/* __EYEM_MISC_H */
eyemLib/nnDetector.cpp
查看文件 @
c28b0fe
...
@@ -48,6 +48,7 @@ std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::ve
...
@@ -48,6 +48,7 @@ std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::ve
if
(
img
.
cols
()
<=
20
||
img
.
rows
()
<=
20
)
{
if
(
img
.
cols
()
<=
20
||
img
.
rows
()
<=
20
)
{
return
std
::
vector
<
std
::
string
>
();
return
std
::
vector
<
std
::
string
>
();
}
}
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__:开始图像格式转换"
);
cv
::
Mat
input
;
cv
::
Mat
input
;
int
incn
=
img
.
channels
();
int
incn
=
img
.
channels
();
if
(
incn
==
4
)
{
if
(
incn
==
4
)
{
...
@@ -59,14 +60,20 @@ std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::ve
...
@@ -59,14 +60,20 @@ std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::ve
else
{
else
{
input
=
img
.
getMat
();
input
=
img
.
getMat
();
}
}
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__:图像格式转换完成"
);
_mtx
.
lock
();
_mtx
.
lock
();
//识别
//识别
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__:开始识别二维码"
);
std
::
vector
<
cv
::
Rect
>
bboxes
=
p
->
detect
(
input
);
std
::
vector
<
cv
::
Rect
>
bboxes
=
p
->
detect
(
input
);
for
(
auto
&
bbox
:
bboxes
)
{
for
(
auto
&
bbox
:
bboxes
)
{
__points
.
push_back
(
bbox
);
__points
.
push_back
(
bbox
);
}
}
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__:识别二维码结束"
);
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__:开始解码"
);
//解码
//解码
std
::
vector
<
std
::
string
>
results
=
p
->
decode
(
input
,
bboxes
,
points
);
std
::
vector
<
std
::
string
>
results
=
p
->
decode
(
input
,
bboxes
,
points
);
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__:解码完成"
);
_mtx
.
unlock
();
_mtx
.
unlock
();
return
results
;
return
results
;
}
}
...
@@ -77,12 +84,14 @@ std::vector<cv::Rect> NNDetector::Impl::detect(const cv::Mat& img) {
...
@@ -77,12 +84,14 @@ std::vector<cv::Rect> NNDetector::Impl::detect(const cv::Mat& img) {
std
::
vector
<
std
::
string
>
NNDetector
::
Impl
::
decode
(
const
cv
::
Mat
&
img
,
std
::
vector
<
cv
::
Rect
>&
bboxes
,
std
::
vector
<
cv
::
Rect
>&
points
)
{
std
::
vector
<
std
::
string
>
NNDetector
::
Impl
::
decode
(
const
cv
::
Mat
&
img
,
std
::
vector
<
cv
::
Rect
>&
bboxes
,
std
::
vector
<
cv
::
Rect
>&
points
)
{
if
(
bboxes
.
size
()
==
0
)
{
if
(
bboxes
.
size
()
==
0
)
{
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:未识别到二维码"
);
return
std
::
vector
<
std
::
string
>
();
return
std
::
vector
<
std
::
string
>
();
}
}
std
::
vector
<
std
::
string
>
decode_results
;
std
::
vector
<
std
::
string
>
decode_results
;
//限定框,防止越界
//限定框,防止越界
for
(
auto
&
bbox
:
bboxes
)
{
for
(
auto
&
bbox
:
bboxes
)
{
if
(
bbox
.
height
>
1000
||
bbox
.
width
>
1000
)
{
if
(
bbox
.
height
>
1000
||
bbox
.
width
>
1000
)
{
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:识别尺寸太大,判断不是二维码"
);
continue
;
continue
;
}
}
float
padding_w
=
0.1
f
,
padding_h
=
0.1
f
;
float
padding_w
=
0.1
f
,
padding_h
=
0.1
f
;
...
@@ -95,10 +104,12 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
...
@@ -95,10 +104,12 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
int
end_x
=
cv
::
min
(
bbox
.
br
().
x
+
padx
,
img
.
cols
-
1
);
int
end_x
=
cv
::
min
(
bbox
.
br
().
x
+
padx
,
img
.
cols
-
1
);
int
end_y
=
cv
::
min
(
bbox
.
br
().
y
+
pady
,
img
.
rows
-
1
);
int
end_y
=
cv
::
min
(
bbox
.
br
().
y
+
pady
,
img
.
rows
-
1
);
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:裁剪图像"
);
cv
::
Rect
crop_roi
(
crop_x_
,
crop_y_
,
end_x
-
crop_x_
+
1
,
end_y
-
crop_y_
+
1
);
cv
::
Rect
crop_roi
(
crop_x_
,
crop_y_
,
end_x
-
crop_x_
+
1
,
end_y
-
crop_y_
+
1
);
cv
::
Mat
cropped_img
=
img
(
crop_roi
);
cv
::
Mat
cropped_img
=
img
(
crop_roi
);
//转单通道
//转单通道
cv
::
cvtColor
(
cropped_img
,
cropped_img
,
cv
::
COLOR_BGR2GRAY
);
cv
::
cvtColor
(
cropped_img
,
cropped_img
,
cv
::
COLOR_BGR2GRAY
);
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:获取多尺度信息"
);
auto
scale_list
=
getScaleList
(
cropped_img
.
cols
,
cropped_img
.
rows
);
auto
scale_list
=
getScaleList
(
cropped_img
.
cols
,
cropped_img
.
rows
);
for
(
auto
cur_scale
:
scale_list
)
{
for
(
auto
cur_scale
:
scale_list
)
{
cv
::
Mat
scaled_img
=
cv
::
Mat
scaled_img
=
...
@@ -109,12 +120,14 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
...
@@ -109,12 +120,14 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
auto
ret
=
decodeImage
(
scaled_img
,
result
,
false
,
0
,
_points
);
auto
ret
=
decodeImage
(
scaled_img
,
result
,
false
,
0
,
_points
);
if
(
ret
!=
-
1
)
{
if
(
ret
!=
-
1
)
{
//恢复真实尺度
//恢复真实尺度
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:恢复真实尺度"
);
for
(
auto
&
_point
:
_points
)
{
for
(
auto
&
_point
:
_points
)
{
_point
.
x
=
cvRound
((
float
)
_point
.
x
/
cur_scale
);
_point
.
x
=
cvRound
((
float
)
_point
.
x
/
cur_scale
);
_point
.
x
+=
crop_roi
.
tl
().
x
;
_point
.
x
+=
crop_roi
.
tl
().
x
;
_point
.
y
=
cvRound
((
float
)
_point
.
y
/
cur_scale
);
_point
.
y
=
cvRound
((
float
)
_point
.
y
/
cur_scale
);
_point
.
y
+=
crop_roi
.
tl
().
y
;
_point
.
y
+=
crop_roi
.
tl
().
y
;
}
}
logger
.
t
(
"__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:解码成功"
);
cv
::
Rect
br
=
cv
::
boundingRect
(
_points
);
cv
::
Rect
br
=
cv
::
boundingRect
(
_points
);
points
.
push_back
(
br
);
points
.
push_back
(
br
);
decode_results
.
push_back
(
result
);
decode_results
.
push_back
(
result
);
...
...
eyemLib/nnDetector.h
查看文件 @
c28b0fe
...
@@ -7,6 +7,9 @@
...
@@ -7,6 +7,9 @@
#include "opencv2/core.hpp"
#include "opencv2/core.hpp"
#include "libdecode.h"
#include "libdecode.h"
#include "eyemLib.h"
extern
Logger
logger
;
class
NNDetector
{
class
NNDetector
{
public
:
public
:
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论