Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
张士柳
/
eyemLib
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
图表
网络
创建新的问题
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 547390fb
由
张士柳
编写于
2021-08-27 17:33:59 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
无
1 个父辈
ae41cb88
隐藏空白字符变更
内嵌
并排
正在显示
16 个修改的文件
包含
2261 行增加
和
632 行删除
eyemLib-Sharp/EyemLib.cs
eyemLib-Sharp/EyemLibDemo.cs
eyemLib-Sharp/Program.cs
eyemLib/eyemBin.h
eyemLib/eyemClp2d.cpp
eyemLib/eyemEdge1d.cpp
eyemLib/eyemEdge1d.h
eyemLib/eyemLib.h
eyemLib/eyemLib.rc
eyemLib/eyemLib.vcxproj
eyemLib/eyemLib.vcxproj.filters
eyemLib/eyemMat.cpp
eyemLib/eyemMisc.cpp
eyemLib/eyemMisc.h
eyemLib/stegers.cpp
eyemLib/stegers.h
eyemLib-Sharp/EyemLib.cs
查看文件 @
547390f
...
...
@@ -61,40 +61,11 @@ namespace eyemLib_Sharp
COLOR_BGRA2GRAY
=
10
,
COLOR_RGBA2GRAY
=
11
,
COLOR_BGR2BGR565
=
12
,
//!< convert between RGB/BGR and BGR565 (16-bit images)
COLOR_RGB2BGR565
=
13
,
COLOR_BGR5652BGR
=
14
,
COLOR_BGR5652RGB
=
15
,
COLOR_BGRA2BGR565
=
16
,
COLOR_RGBA2BGR565
=
17
,
COLOR_BGR5652BGRA
=
18
,
COLOR_BGR5652RGBA
=
19
,
COLOR_GRAY2BGR565
=
20
,
//!< convert between grayscale to BGR565 (16-bit images)
COLOR_BGR5652GRAY
=
21
,
COLOR_BGR2BGR555
=
22
,
//!< convert between RGB/BGR and BGR555 (16-bit images)
COLOR_RGB2BGR555
=
23
,
COLOR_BGR5552BGR
=
24
,
COLOR_BGR5552RGB
=
25
,
COLOR_BGRA2BGR555
=
26
,
COLOR_RGBA2BGR555
=
27
,
COLOR_BGR5552BGRA
=
28
,
COLOR_BGR5552RGBA
=
29
,
COLOR_GRAY2BGR555
=
30
,
//!< convert between grayscale and BGR555 (16-bit images)
COLOR_BGR5552GRAY
=
31
,
COLOR_BGR2XYZ
=
32
,
//!< convert RGB/BGR to CIE XYZ, @ref color_convert_rgb_xyz "color conversions"
COLOR_RGB2XYZ
=
33
,
COLOR_XYZ2BGR
=
34
,
COLOR_XYZ2RGB
=
35
,
COLOR_BGR2YCrCb
=
36
,
//!< convert RGB/BGR to luma-chroma (aka YCC), @ref color_convert_rgb_ycrcb "color conversions"
COLOR_RGB2YCrCb
=
37
,
COLOR_YCrCb2BGR
=
38
,
COLOR_YCrCb2RGB
=
39
,
COLOR_BGR2HSV
=
40
,
//!< convert RGB/BGR to HSV (hue saturation value), @ref color_convert_rgb_hsv "color conversions"
COLOR_RGB2HSV
=
41
,
...
...
@@ -116,188 +87,10 @@ namespace eyemLib_Sharp
COLOR_HLS2BGR
=
60
,
COLOR_HLS2RGB
=
61
,
COLOR_BGR2HSV_FULL
=
66
,
COLOR_RGB2HSV_FULL
=
67
,
COLOR_BGR2HLS_FULL
=
68
,
COLOR_RGB2HLS_FULL
=
69
,
COLOR_HSV2BGR_FULL
=
70
,
COLOR_HSV2RGB_FULL
=
71
,
COLOR_HLS2BGR_FULL
=
72
,
COLOR_HLS2RGB_FULL
=
73
,
COLOR_LBGR2Lab
=
74
,
COLOR_LRGB2Lab
=
75
,
COLOR_LBGR2Luv
=
76
,
COLOR_LRGB2Luv
=
77
,
COLOR_Lab2LBGR
=
78
,
COLOR_Lab2LRGB
=
79
,
COLOR_Luv2LBGR
=
80
,
COLOR_Luv2LRGB
=
81
,
COLOR_BGR2YUV
=
82
,
//!< convert between RGB/BGR and YUV
COLOR_RGB2YUV
=
83
,
COLOR_YUV2BGR
=
84
,
COLOR_YUV2RGB
=
85
,
//! YUV 4:2:0 family to RGB
COLOR_YUV2RGB_NV12
=
90
,
COLOR_YUV2BGR_NV12
=
91
,
COLOR_YUV2RGB_NV21
=
92
,
COLOR_YUV2BGR_NV21
=
93
,
COLOR_YUV420sp2RGB
=
COLOR_YUV2RGB_NV21
,
COLOR_YUV420sp2BGR
=
COLOR_YUV2BGR_NV21
,
COLOR_YUV2RGBA_NV12
=
94
,
COLOR_YUV2BGRA_NV12
=
95
,
COLOR_YUV2RGBA_NV21
=
96
,
COLOR_YUV2BGRA_NV21
=
97
,
COLOR_YUV420sp2RGBA
=
COLOR_YUV2RGBA_NV21
,
COLOR_YUV420sp2BGRA
=
COLOR_YUV2BGRA_NV21
,
COLOR_YUV2RGB_YV12
=
98
,
COLOR_YUV2BGR_YV12
=
99
,
COLOR_YUV2RGB_IYUV
=
100
,
COLOR_YUV2BGR_IYUV
=
101
,
COLOR_YUV2RGB_I420
=
COLOR_YUV2RGB_IYUV
,
COLOR_YUV2BGR_I420
=
COLOR_YUV2BGR_IYUV
,
COLOR_YUV420p2RGB
=
COLOR_YUV2RGB_YV12
,
COLOR_YUV420p2BGR
=
COLOR_YUV2BGR_YV12
,
COLOR_YUV2RGBA_YV12
=
102
,
COLOR_YUV2BGRA_YV12
=
103
,
COLOR_YUV2RGBA_IYUV
=
104
,
COLOR_YUV2BGRA_IYUV
=
105
,
COLOR_YUV2RGBA_I420
=
COLOR_YUV2RGBA_IYUV
,
COLOR_YUV2BGRA_I420
=
COLOR_YUV2BGRA_IYUV
,
COLOR_YUV420p2RGBA
=
COLOR_YUV2RGBA_YV12
,
COLOR_YUV420p2BGRA
=
COLOR_YUV2BGRA_YV12
,
COLOR_YUV2GRAY_420
=
106
,
COLOR_YUV2GRAY_NV21
=
COLOR_YUV2GRAY_420
,
COLOR_YUV2GRAY_NV12
=
COLOR_YUV2GRAY_420
,
COLOR_YUV2GRAY_YV12
=
COLOR_YUV2GRAY_420
,
COLOR_YUV2GRAY_IYUV
=
COLOR_YUV2GRAY_420
,
COLOR_YUV2GRAY_I420
=
COLOR_YUV2GRAY_420
,
COLOR_YUV420sp2GRAY
=
COLOR_YUV2GRAY_420
,
COLOR_YUV420p2GRAY
=
COLOR_YUV2GRAY_420
,
//! YUV 4:2:2 family to RGB
COLOR_YUV2RGB_UYVY
=
107
,
COLOR_YUV2BGR_UYVY
=
108
,
//COLOR_YUV2RGB_VYUY = 109,
//COLOR_YUV2BGR_VYUY = 110,
COLOR_YUV2RGB_Y422
=
COLOR_YUV2RGB_UYVY
,
COLOR_YUV2BGR_Y422
=
COLOR_YUV2BGR_UYVY
,
COLOR_YUV2RGB_UYNV
=
COLOR_YUV2RGB_UYVY
,
COLOR_YUV2BGR_UYNV
=
COLOR_YUV2BGR_UYVY
,
COLOR_YUV2RGBA_UYVY
=
111
,
COLOR_YUV2BGRA_UYVY
=
112
,
//COLOR_YUV2RGBA_VYUY = 113,
//COLOR_YUV2BGRA_VYUY = 114,
COLOR_YUV2RGBA_Y422
=
COLOR_YUV2RGBA_UYVY
,
COLOR_YUV2BGRA_Y422
=
COLOR_YUV2BGRA_UYVY
,
COLOR_YUV2RGBA_UYNV
=
COLOR_YUV2RGBA_UYVY
,
COLOR_YUV2BGRA_UYNV
=
COLOR_YUV2BGRA_UYVY
,
COLOR_YUV2RGB_YUY2
=
115
,
COLOR_YUV2BGR_YUY2
=
116
,
COLOR_YUV2RGB_YVYU
=
117
,
COLOR_YUV2BGR_YVYU
=
118
,
COLOR_YUV2RGB_YUYV
=
COLOR_YUV2RGB_YUY2
,
COLOR_YUV2BGR_YUYV
=
COLOR_YUV2BGR_YUY2
,
COLOR_YUV2RGB_YUNV
=
COLOR_YUV2RGB_YUY2
,
COLOR_YUV2BGR_YUNV
=
COLOR_YUV2BGR_YUY2
,
COLOR_YUV2RGBA_YUY2
=
119
,
COLOR_YUV2BGRA_YUY2
=
120
,
COLOR_YUV2RGBA_YVYU
=
121
,
COLOR_YUV2BGRA_YVYU
=
122
,
COLOR_YUV2RGBA_YUYV
=
COLOR_YUV2RGBA_YUY2
,
COLOR_YUV2BGRA_YUYV
=
COLOR_YUV2BGRA_YUY2
,
COLOR_YUV2RGBA_YUNV
=
COLOR_YUV2RGBA_YUY2
,
COLOR_YUV2BGRA_YUNV
=
COLOR_YUV2BGRA_YUY2
,
COLOR_YUV2GRAY_UYVY
=
123
,
COLOR_YUV2GRAY_YUY2
=
124
,
//CV_YUV2GRAY_VYUY = CV_YUV2GRAY_UYVY,
COLOR_YUV2GRAY_Y422
=
COLOR_YUV2GRAY_UYVY
,
COLOR_YUV2GRAY_UYNV
=
COLOR_YUV2GRAY_UYVY
,
COLOR_YUV2GRAY_YVYU
=
COLOR_YUV2GRAY_YUY2
,
COLOR_YUV2GRAY_YUYV
=
COLOR_YUV2GRAY_YUY2
,
COLOR_YUV2GRAY_YUNV
=
COLOR_YUV2GRAY_YUY2
,
//! alpha premultiplication
COLOR_RGBA2mRGBA
=
125
,
COLOR_mRGBA2RGBA
=
126
,
//! RGB to YUV 4:2:0 family
COLOR_RGB2YUV_I420
=
127
,
COLOR_BGR2YUV_I420
=
128
,
COLOR_RGB2YUV_IYUV
=
COLOR_RGB2YUV_I420
,
COLOR_BGR2YUV_IYUV
=
COLOR_BGR2YUV_I420
,
COLOR_RGBA2YUV_I420
=
129
,
COLOR_BGRA2YUV_I420
=
130
,
COLOR_RGBA2YUV_IYUV
=
COLOR_RGBA2YUV_I420
,
COLOR_BGRA2YUV_IYUV
=
COLOR_BGRA2YUV_I420
,
COLOR_RGB2YUV_YV12
=
131
,
COLOR_BGR2YUV_YV12
=
132
,
COLOR_RGBA2YUV_YV12
=
133
,
COLOR_BGRA2YUV_YV12
=
134
,
//! Demosaicing
COLOR_BayerBG2BGR
=
46
,
COLOR_BayerGB2BGR
=
47
,
COLOR_BayerRG2BGR
=
48
,
COLOR_BayerGR2BGR
=
49
,
COLOR_BayerBG2RGB
=
COLOR_BayerRG2BGR
,
COLOR_BayerGB2RGB
=
COLOR_BayerGR2BGR
,
COLOR_BayerRG2RGB
=
COLOR_BayerBG2BGR
,
COLOR_BayerGR2RGB
=
COLOR_BayerGB2BGR
,
COLOR_BayerBG2GRAY
=
86
,
COLOR_BayerGB2GRAY
=
87
,
COLOR_BayerRG2GRAY
=
88
,
COLOR_BayerGR2GRAY
=
89
,
//! Demosaicing using Variable Number of Gradients
COLOR_BayerBG2BGR_VNG
=
62
,
COLOR_BayerGB2BGR_VNG
=
63
,
COLOR_BayerRG2BGR_VNG
=
64
,
COLOR_BayerGR2BGR_VNG
=
65
,
COLOR_BayerBG2RGB_VNG
=
COLOR_BayerRG2BGR_VNG
,
COLOR_BayerGB2RGB_VNG
=
COLOR_BayerGR2BGR_VNG
,
COLOR_BayerRG2RGB_VNG
=
COLOR_BayerBG2BGR_VNG
,
COLOR_BayerGR2RGB_VNG
=
COLOR_BayerGB2BGR_VNG
,
//! Edge-Aware Demosaicing
COLOR_BayerBG2BGR_EA
=
135
,
COLOR_BayerGB2BGR_EA
=
136
,
COLOR_BayerRG2BGR_EA
=
137
,
COLOR_BayerGR2BGR_EA
=
138
,
COLOR_BayerBG2RGB_EA
=
COLOR_BayerRG2BGR_EA
,
COLOR_BayerGB2RGB_EA
=
COLOR_BayerGR2BGR_EA
,
COLOR_BayerRG2RGB_EA
=
COLOR_BayerBG2BGR_EA
,
COLOR_BayerGR2RGB_EA
=
COLOR_BayerGB2BGR_EA
,
//! Demosaicing with alpha channel
COLOR_BayerBG2BGRA
=
139
,
COLOR_BayerGB2BGRA
=
140
,
COLOR_BayerRG2BGRA
=
141
,
COLOR_BayerGR2BGRA
=
142
,
COLOR_BayerBG2RGBA
=
COLOR_BayerRG2BGRA
,
COLOR_BayerGB2RGBA
=
COLOR_BayerGR2BGRA
,
COLOR_BayerRG2RGBA
=
COLOR_BayerBG2BGRA
,
COLOR_BayerGR2RGBA
=
COLOR_BayerGB2BGRA
,
COLOR_COLORCVT_MAX
=
143
};
#
endregion
...
...
@@ -1236,6 +1029,9 @@ namespace eyemLib_Sharp
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemLibImpl
(
EyemImage
tpImage
,
out
EyemImage
tpDstImg
);
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemEdge1dRidgeDetection
(
EyemImage
tpImage
);
#
endregion
#
region
日志功能
...
...
@@ -1317,6 +1113,12 @@ namespace eyemLib_Sharp
//flag = eyemCvtColor(tpDstImg, ColorConversionCodes.COLOR_GRAY2BGR, ref tpDstImg);
//flag = eyemLibImpl(image, out tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//{
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//}
//return;
//flag = eyemNormalize(ref image);
...
...
@@ -1324,10 +1126,9 @@ namespace eyemLib_Sharp
//eyemDecompose(image, out image1, out image2, out image3);
//flag = eyemBinThresholdC(image, new int[] { 55, 0, 0 }, new int[] { 135, 225, 225 }, out tpDstImg);
//sw.Restart();
//flag = eyemMarkerTracing(image, 120, ref tpCircle, out tpDstImg,
tru
e);
//flag = eyemMarkerTracing(image, 120, ref tpCircle, out tpDstImg,
fals
e);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
...
...
@@ -1339,28 +1140,31 @@ namespace eyemLib_Sharp
//Console.WriteLine("时间:" + sw.ElapsedMilliseconds.ToString());
//return;
//flag = eyemEdge1dRidgeDetection(image);
//return;
#
region
Test
Blob
sw
.
Restart
();
int
ipNum
;
BlobHandle
hObject
;
EyemBinBlob
*
tpResults
;
eyemBinBlob
(
image
,
out
hObject
,
100
,
out
tpResults
,
out
ipNum
,
out
tpDstImg
);
sw
.
Stop
();
for
(
int
i
=
0
;
i
<
ipNum
;
i
++)
{
Console
.
WriteLine
(
tpResults
[
i
].
iArea
);
}
Bitmap
bitmap
=
eyemCvtToBitmap
(
tpDstImg
);
if
(
bitmap
!=
null
)
{
bitmap
.
Save
(
System
.
Windows
.
Forms
.
Application
.
StartupPath
+
"\\ResOut\\"
+
file
);
}
//
sw.Restart();
//
int ipNum;
//
BlobHandle hObject;
//
EyemBinBlob* tpResults;
//
eyemBinBlob(image, out hObject, 100, out tpResults, out ipNum, out tpDstImg);
//
sw.Stop();
//
for (int i = 0; i < ipNum; i++)
//
{
//
Console.WriteLine(tpResults[i].iArea);
//
}
//
Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//
if (bitmap != null)
//
{
//
bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//
}
hObject
.
Dispose
();
eyemImageFree
(
ref
tpDstImg
);
eyemImageFree
(
ref
image
);
Console
.
WriteLine
(
"时间-:"
+
sw
.
ElapsedMilliseconds
.
ToString
());
return
;
//
hObject.Dispose();
//
eyemImageFree(ref tpDstImg);
//
eyemImageFree(ref image);
//
Console.WriteLine("时间-:" + sw.ElapsedMilliseconds.ToString());
//
return;
#
endregion
#
region
Test
1D
Edge
...
...
@@ -1368,7 +1172,7 @@ namespace eyemLib_Sharp
//tpLineSt.dX = 62;
//tpLineSt.dY = 62;
//EyemOcsDXY tpLineEd = new EyemOcsDXY();
//tpLineEd.dX =
3
23.5;
//tpLineEd.dX = 23.5;
//tpLineEd.dY = 40.5;
//MeasureHandle hObject;
...
...
@@ -1379,6 +1183,10 @@ namespace eyemLib_Sharp
////eyemEdge1dFindCircle(image, tpLineSt, 21, 12, 3, 10, 1, -1, 35, "negative", out hObject);
//sw.Stop();
//Console.WriteLine("时间:" + sw.ElapsedMilliseconds.ToString());
//eyemEdge1dGenMeasureRect(image, tpLineSt, tpLineEd, 1, "", 1, 0, 0, out hObject);
//eyemEdge1dGenPosRect(image, tpLineSt, tpLineEd, 1, 1, 1, 1, out hObject);
//return;
#
endregion
...
...
@@ -1566,9 +1374,9 @@ namespace eyemLib_Sharp
#
endregion
EyemRect
tpRoi
=
new
EyemRect
();
tpRoi
.
iXs
=
2
50
;
tpRoi
.
iYs
=
25
0
;
tpRoi
.
iWidth
=
image
.
iWidth
-
5
00
;
tpRoi
.
iHeight
=
image
.
iHeight
-
5
00
;
tpRoi
.
iXs
=
2
00
;
tpRoi
.
iYs
=
20
0
;
tpRoi
.
iWidth
=
image
.
iWidth
-
4
00
;
tpRoi
.
iHeight
=
image
.
iHeight
-
4
00
;
//flag = eyemMulFuncTool(image, tpRoi, "__func1", 65, 75, ref tpCircle, out tpDstImg);
...
...
@@ -1594,17 +1402,18 @@ namespace eyemLib_Sharp
//{
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//}
//return;
////创建模板匹配模型
//EyemRect tpRoi2 = new EyemRect();
//tpRoi2.iXs = 0; tpRoi2.iYs = 0;
//tpRoi2.iWidth = image.iWidth;
//tpRoi2.iHeight = image.iHeight;
//double matchDeg = 0.
7
5;
//double matchDeg = 0.
8
5;
//flag = eyemCreateTemplateModel(image, tpRoi2, matchDeg, "D:\\模板文件\\" + file.Replace(".png", ".tpl"));
//return;
//
//
加载模板到内存
//加载模板到内存
//IntPtr hModelID = IntPtr.Zero;
//flag = eyemInitModel("D:\\模板文件", out hModelID);
...
...
@@ -1643,20 +1452,20 @@ namespace eyemLib_Sharp
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS","IP_LOWCONTRAST_PARTS"
//eyemCountObject(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_LARGE
_PARTS", ipReelNum, out tpDstImg);
eyemCountObjectIrregularParts
(
image
,
tpRoi
,
file
.
Replace
(
".png"
,
""
),
"IP_SMALL
_PARTS"
,
ipReelNum
,
out
tpDstImg
);
//eyemCountObjectE(image, tpRoi, file.Replace(".png", ""), ipReelNum, 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", ""),
"20210825095751-1"
, hModelID, ipReelNum, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "D:\\模板文件\\" +
"20210825095751-1.tpl", hModelID, ipReelNum
, out tpDstImg);
//移除模板
//flag = eyemRemoveModelByName(hModelID, "D:\\模板文件及图像\\df871193-6632-48f9-abfe-540c3fc49c3f.tpl");
//
Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//
if (bitmap != null)
//
{
//
//bitmap.Save("D:\\ResOut\\" + file);
//
bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//
}
Bitmap
bitmap
=
eyemCvtToBitmap
(
tpDstImg
);
if
(
bitmap
!=
null
)
{
//bitmap.Save("D:\\ResOut\\" + file);
bitmap
.
Save
(
System
.
Windows
.
Forms
.
Application
.
StartupPath
+
"\\ResOut\\"
+
file
);
}
//< 解码测试
//int ipNum; EyemBarCode* tpResults;
...
...
@@ -1676,7 +1485,6 @@ namespace eyemLib_Sharp
//{
// strReelNum += ipReelNum[i].ToString() + ",";
//}
sw
.
Stop
();
Console
.
WriteLine
(
file
+
"--->"
+
"耗时:"
+
sw
.
ElapsedMilliseconds
.
ToString
()
+
"ms"
+
",结果:"
+
strReelNum
);
...
...
eyemLib-Sharp/EyemLibDemo.cs
查看文件 @
547390f
...
...
@@ -497,6 +497,5 @@ namespace eyemLib_Sharp
return
tpImage
;
}
#
endregion
}
}
eyemLib-Sharp/Program.cs
查看文件 @
547390f
...
...
@@ -24,7 +24,6 @@ namespace eyemLib_Sharp
{
EyemLib
.
eyemReadImageTool
(
item
);
}
EyemLib
.
Free
();
Console
.
Write
(
"请按任意键继续。。。"
);
Console
.
ReadKey
();
...
...
eyemLib/eyemBin.h
查看文件 @
547390f
...
...
@@ -8,44 +8,4 @@
#include "eyemLib.h"
typedef
unsigned
int
CvLabel
;
typedef
std
::
map
<
CvLabel
,
cv
::
Scalar
>
Palete
;
/// \def _HSV2RGB_(H, S, V, R, G, B)
/// \brief Color translation between HSV and RGB.
#define _HSV2RGB_(H, S, V, R, G, B) \
{ \
double _h = H/60.; \
int _hf = (int)floor(_h); \
int _hi = ((int)_h)%6; \
double _f = _h - _hf; \
\
double _p = V * (1. - S); \
double _q = V * (1. - _f * S); \
double _t = V * (1. - (1. - _f) * S); \
\
switch (_hi) \
{ \
case 0: \
R = 255.*V; G = 255.*_t; B = 255.*_p; \
break; \
case 1: \
R = 255.*_q; G = 255.*V; B = 255.*_p; \
break; \
case 2: \
R = 255.*_p; G = 255.*V; B = 255.*_t; \
break; \
case 3: \
R = 255.*_p; G = 255.*_q; B = 255.*V; \
break; \
case 4: \
R = 255.*_t; G = 255.*_p; B = 255.*V; \
break; \
case 5: \
R = 255.*V; G = 255.*_p; B = 255.*_q; \
break; \
} \
}
#endif
/* __EYEM_BIN_H */
\ No newline at end of file
eyemLib/eyemClp2d.cpp
查看文件 @
547390f
...
...
@@ -54,26 +54,12 @@ void eyemClp2dLinePointAndSlope(EyemOcsDXY tpPoint, double dSlope, EyemOcsDABC &
int
eyemClp2dIntersectionTwoLines
(
EyemOcsDABC
tpLine1
,
EyemOcsDABC
tpLine2
,
EyemOcsDXY
&
tpPoint
)
{
if
(
abs
(
tpLine1
.
dA
*
tpLine2
.
dB
-
tpLine2
.
dA
*
tpLine1
.
dB
)
<
EPS
)
{
double
det
=
tpLine1
.
dA
*
tpLine2
.
dB
-
tpLine2
.
dA
*
tpLine1
.
dB
;
if
(
abs
(
det
)
<
EPS
)
{
return
FUNC_CANNOT_CALC
;
}
//计算系数
double
sa
[
4
],
sb
[
2
],
sx
[
2
];
cv
::
Mat
a
=
cv
::
Mat
(
2
,
2
,
CV_64F
,
sa
),
b
=
cv
::
Mat
(
2
,
1
,
CV_64F
,
sb
);
//系数矩阵A*X=B;
cv
::
Mat
x
=
cv
::
Mat
(
2
,
1
,
CV_64F
,
sx
);
std
::
memset
(
sa
,
0
,
sizeof
(
sa
));
std
::
memset
(
sb
,
0
,
sizeof
(
sb
));
std
::
memset
(
sx
,
0
,
sizeof
(
sx
));
sa
[
0
]
=
tpLine1
.
dA
,
sa
[
1
]
=
tpLine1
.
dB
;
sa
[
2
]
=
tpLine2
.
dA
,
sa
[
3
]
=
tpLine2
.
dB
;
sb
[
0
]
=
-
tpLine1
.
dC
,
sb
[
1
]
=
-
tpLine2
.
dC
;
//solve
cv
::
solve
(
a
,
b
,
x
,
cv
::
DECOMP_SVD
);
tpPoint
.
dX
=
sx
[
0
];
tpPoint
.
dY
=
sx
[
1
];
tpPoint
.
dX
=
(
tpLine1
.
dB
*
tpLine2
.
dC
-
tpLine2
.
dB
*
tpLine1
.
dC
)
/
det
;
tpPoint
.
dY
=
(
tpLine2
.
dA
*
tpLine1
.
dC
-
tpLine1
.
dA
*
tpLine2
.
dC
)
/
det
;
return
FUNC_OK
;
}
...
...
eyemLib/eyemEdge1d.cpp
查看文件 @
547390f
...
...
@@ -60,326 +60,33 @@ void getSuperResolution(const cv::Mat &src, cv::Mat &dst, int size)
int
eyemEdge1dGenMeasureRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
const
char
*
ccSubType
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
IntPtr
*
hObject
)
{
cv
::
Mat
image
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
CV_8UC1
,
tpImage
.
vpImage
);
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
)
,
tpImage
.
vpImage
);
if
(
image
.
empty
())
{
return
FUNC_IMAGE_NOT_EXIST
;
}
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
if
(
tpLineSt
.
dX
<
0
||
tpLineSt
.
dY
<
0
||
tpLineSt
.
dX
>
tpImage
.
iWidth
||
tpLineSt
.
dY
>
tpImage
.
iHeight
\
||
tpLineEd
.
dX
<
0
||
tpLineEd
.
dY
<
0
||
tpLineEd
.
dX
>
tpImage
.
iWidth
||
tpLineEd
.
dY
>
tpImage
.
iHeight
)
return
FUNC_ILLEGAL_ARGUMENT
;
//主轴倾斜角
double
t
=
.0
;
t
=
atan2
(
tpLineEd
.
dY
-
tpLineSt
.
dY
,
tpLineEd
.
dX
-
tpLineSt
.
dX
)
*
180.
/
PI
;
double
rotWeight
=
tpImage
.
iHeight
*
abs
(
sin
(
t
*
CV_PI
/
180
))
+
tpImage
.
iWidth
*
abs
(
cos
(
t
*
CV_PI
/
180
));
double
rotHeight
=
ceil
(
tpImage
.
iWidth
*
abs
(
sin
(
t
*
CV_PI
/
180
))
+
tpImage
.
iHeight
*
abs
(
cos
(
t
*
CV_PI
/
180
)));
cv
::
RotatedRect
rotRect
(
cv
::
Point2f
((
float
)(
tpLineSt
.
dX
+
tpLineEd
.
dX
)
/
2.0
f
,
(
float
)(
tpLineSt
.
dY
+
tpLineEd
.
dY
)
/
2.0
f
),
\
cv
::
Size2f
((
float
)
std
::
sqrt
(
std
::
pow
(
tpLineSt
.
dX
-
tpLineEd
.
dX
,
2
)
+
(
float
)
std
::
pow
(
tpLineSt
.
dY
-
tpLineEd
.
dY
,
2
)),
(
float
)
iWhRoi
),
(
float
)
t
);
cv
::
Mat
rotM2d
(
2
,
3
,
CV_64F
);
rotM2d
=
cv
::
getRotationMatrix2D
(
cv
::
Point2f
(
tpImage
.
iWidth
/
2.0
f
-
0.5
f
,
tpImage
.
iHeight
/
2.0
f
-
0.5
f
),
t
,
1.0
);
#define COEFF_AT(x,y) ((double *)rotM2d.data)[(y)*rotM2d.cols + (x)]
COEFF_AT
(
2
,
0
)
+=
(
rotWeight
-
tpImage
.
iWidth
)
/
2.0
;
COEFF_AT
(
2
,
1
)
+=
(
rotHeight
-
tpImage
.
iHeight
)
/
2.0
;
cv
::
Point2d
rotedCenter
;
rotedCenter
.
x
=
rotRect
.
center
.
x
*
COEFF_AT
(
0
,
0
)
+
rotRect
.
center
.
y
*
COEFF_AT
(
1
,
0
)
+
COEFF_AT
(
2
,
0
);
rotedCenter
.
y
=
rotRect
.
center
.
x
*
COEFF_AT
(
0
,
1
)
+
rotRect
.
center
.
y
*
COEFF_AT
(
1
,
1
)
+
COEFF_AT
(
2
,
1
);
cv
::
Mat
rotImg
;
cv
::
warpAffine
(
image
,
rotImg
,
rotM2d
,
cv
::
Size
((
int
)
rotWeight
,
(
int
)
rotHeight
),
cv
::
INTER_LINEAR
);
//获取Roi区域
cv
::
Rect
roi
((
int
)
MAX
(
rotedCenter
.
x
-
rotRect
.
size
.
width
/
2
,
0
),
(
int
)
MAX
(
rotedCenter
.
y
-
rotRect
.
size
.
height
/
2
,
0
),
\
(
int
)
rotRect
.
size
.
width
,
(
int
)
rotRect
.
size
.
height
);
cv
::
Mat
filter
,
diffMat
,
one
;
diffMat
=
/*convert(rotImg(roi), CV_64F)*/
cv
::
Mat
();
//计算投影
cv
::
reduce
(
diffMat
,
one
,
0
,
cv
::
REDUCE_AVG
,
CV_64F
);
#ifdef _DEBUG
cv
::
Mat
map1
=
projectMap
(
one
,
30
);
#endif
//高斯滤波
cv
::
Mat
kernel
=
cv
::
getGaussianKernel
(
5
,
dSigma
).
t
();
cv
::
sepFilter2D
(
one
,
one
,
diffMat
.
depth
(),
kernel
,
cv
::
Mat
::
ones
(
1
,
1
,
CV_64F
));
#ifdef _DEBUG
cv
::
Mat
map2
=
projectMap
(
one
,
30
);
#endif
//默认过滤一半像素
const
cv
::
Mat
whalf
=
(
cv
::
Mat_
<
double
>
(
1
,
5
)
<<
-
1
,
-
1
,
0
,
1
,
1
);
cv
::
sepFilter2D
(
one
,
filter
,
diffMat
.
depth
(),
whalf
,
cv
::
Mat
::
ones
(
1
,
1
,
CV_64F
));
#ifdef _DEBUG
cv
::
Mat
map3
=
projectMap
(
filter
,
130
);
#endif
std
::
vector
<
double
>
v_filter
=
filter
.
reshape
(
0
,
1
);
std
::
vector
<
int
>
peeks
;
//findPeak(v_filter, peeks);
std
::
vector
<
EyemOcsDXY
>
*
tpEdges
=
new
std
::
vector
<
EyemOcsDXY
>
();
EyemOcsDXY
tpEdge
;
for
(
int
i
=
0
;
i
<
(
int
)
peeks
.
size
();
i
++
)
{
if
(
abs
(
v_filter
[
peeks
[
i
]])
>
dAmpThresh
)
{
double
a
,
b
,
c
;
a
=
v_filter
[
MAX
(
0
,
peeks
[
i
]
-
1
)];
b
=
v_filter
[
peeks
[
i
]];
c
=
v_filter
[
MIN
((
int
)
v_filter
.
size
()
-
1
,
peeks
[
i
]
+
1
)];
double
offset
=
0.5
*
(
a
-
c
)
/
(
a
-
b
-
b
+
c
);
if
(
abs
(
offset
)
<=
0.5
)
{
double
x
=
peeks
[
i
]
+
rotedCenter
.
x
-
rotRect
.
size
.
width
/
2
+
offset
+
0.5
;
double
y
=
iWhRoi
/
2
+
rotedCenter
.
y
-
rotRect
.
size
.
height
/
2
+
0.5
;
double
a1
,
b1
,
c1
,
a2
,
b2
,
c2
;
a1
=
COEFF_AT
(
0
,
0
);
b1
=
COEFF_AT
(
1
,
0
);
c1
=
x
-
COEFF_AT
(
2
,
0
);
a2
=
COEFF_AT
(
0
,
1
);
b2
=
COEFF_AT
(
1
,
1
);
c2
=
y
-
COEFF_AT
(
2
,
1
);
tpEdge
.
dX
=
(
c1
*
b2
-
c2
*
b1
)
/
(
a1
*
b2
-
a2
*
b1
);
tpEdge
.
dY
=
(
c1
*
a2
-
c2
*
a1
)
/
(
b1
*
a2
-
b2
*
a1
);
//all
if
(
iTransition
==
0
)
{
tpEdges
->
push_back
(
tpEdge
);
}
else
if
(
iTransition
==
1
)
{
//positive
if
(
b
<
0
)
{
tpEdges
->
push_back
(
tpEdge
);
}
}
else
if
(
iTransition
==
-
1
)
{
//negative
if
(
b
>
0
)
{
tpEdges
->
push_back
(
tpEdge
);
}
}
}
}
}
if
(
strcmp
(
ccSubType
,
"first"
)
==
0
)
{
tpEdge
=
tpEdges
->
front
();
tpEdges
->
clear
();
tpEdges
->
push_back
(
tpEdge
);
}
else
if
(
strcmp
(
ccSubType
,
"last"
)
==
0
)
{
tpEdge
=
tpEdges
->
back
();
tpEdges
->
clear
();
tpEdges
->
push_back
(
tpEdge
);
}
#ifdef _DEBUG
std
::
cout
<<
"Test 'eyemEdge1dGenRect' "
<<
std
::
endl
;
cv
::
Mat
showMat
,
showMat2
;
cv
::
cvtColor
(
image
,
showMat
,
cv
::
COLOR_GRAY2BGR
);
cv
::
Point2f
rect
[
4
];
rotRect
.
points
(
rect
);
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
cv
::
line
(
showMat
,
rect
[
j
],
rect
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
255
,
0
),
1
);
}
//获取ROI区域
cv
::
cvtColor
(
rotImg
.
clone
(),
showMat2
,
cv
::
COLOR_GRAY2BGR
);
cv
::
rectangle
(
showMat2
,
roi
,
cv
::
Scalar
(
0
,
255
,
0
),
1
);
cv
::
line
(
showMat
,
cv
::
Point
((
int
)
tpLineSt
.
dX
,
(
int
)
tpLineSt
.
dY
),
cv
::
Point
((
int
)
tpLineEd
.
dX
,
(
int
)
tpLineEd
.
dY
),
cv
::
Scalar
(
0
,
255
,
0
),
1
);
for
(
int
i
=
0
;
i
<
tpEdges
->
size
();
i
++
)
{
double
_angle
=
(
t
+
90.
)
*
CV_PI
/
180.
;
float
b
=
(
float
)
cos
(
_angle
)
*
0.5
f
;
float
a
=
(
float
)
sin
(
_angle
)
*
0.5
f
;
cv
::
Point2f
center
((
float
)
tpEdges
->
at
(
i
).
dX
,
(
float
)
tpEdges
->
at
(
i
).
dY
);
cv
::
Point
start
((
int
)(
center
.
x
-
b
*
iWhRoi
+
0.5
),
(
int
)(
center
.
y
-
a
*
iWhRoi
+
0.5
));
cv
::
Point
end
((
int
)(
center
.
x
+
b
*
iWhRoi
+
0.5
),
(
int
)(
center
.
y
+
a
*
iWhRoi
+
0.5
));
cv
::
line
(
showMat
,
start
,
end
,
cv
::
Scalar
(
0
,
0
,
255
),
1
);
}
#endif
*
hObject
=
reinterpret_cast
<
IntPtr
>
(
tpEdges
);
return
FUNC_OK
;
}
int
eyemEdge1dGenPosRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
IntPtr
*
hObject
)
{
cv
::
Mat
image
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
CV_8UC1
,
tpImage
.
vpImage
);
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
)
,
tpImage
.
vpImage
);
if
(
image
.
empty
())
{
return
FUNC_IMAGE_NOT_EXIST
;
}
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
if
(
tpLineSt
.
dX
<
0
||
tpLineSt
.
dY
<
0
||
tpLineSt
.
dX
>
tpImage
.
iWidth
||
tpLineSt
.
dY
>
tpImage
.
iHeight
\
||
tpLineEd
.
dX
<
0
||
tpLineEd
.
dY
<
0
||
tpLineEd
.
dX
>
tpImage
.
iWidth
||
tpLineEd
.
dY
>
tpImage
.
iHeight
)
return
FUNC_ILLEGAL_ARGUMENT
;
//主轴倾角
double
t
=
.0
;
t
=
atan2
(
tpLineEd
.
dY
-
tpLineSt
.
dY
,
tpLineEd
.
dX
-
tpLineSt
.
dX
)
*
180.
/
PI
;
double
rotWeight
=
tpImage
.
iHeight
*
abs
(
sin
(
t
*
CV_PI
/
180
))
+
tpImage
.
iWidth
*
abs
(
cos
(
t
*
CV_PI
/
180
));
double
rotHeight
=
ceil
(
tpImage
.
iWidth
*
abs
(
sin
(
t
*
CV_PI
/
180
))
+
tpImage
.
iHeight
*
abs
(
cos
(
t
*
CV_PI
/
180
)));
cv
::
RotatedRect
rotRect
(
cv
::
Point2f
((
float
)(
tpLineSt
.
dX
+
tpLineEd
.
dX
)
/
2.0
f
,
(
float
)(
tpLineSt
.
dY
+
tpLineEd
.
dY
)
/
2.0
f
),
\
cv
::
Size2f
((
float
)
std
::
sqrt
(
std
::
pow
(
tpLineSt
.
dX
-
tpLineEd
.
dX
,
2
)
+
(
float
)
std
::
pow
(
tpLineSt
.
dY
-
tpLineEd
.
dY
,
2
)),
(
float
)
iWhRoi
),
(
float
)
t
);
cv
::
Mat
rotM2d
(
2
,
3
,
CV_64F
);
rotM2d
=
cv
::
getRotationMatrix2D
(
cv
::
Point2f
(
tpImage
.
iWidth
/
2.0
f
-
0.5
f
,
tpImage
.
iHeight
/
2.0
f
-
0.5
f
),
t
,
1.0
);
#define COEFF_AT(x,y) ((double *)rotM2d.data)[(y)*rotM2d.cols + (x)]
COEFF_AT
(
2
,
0
)
+=
(
rotWeight
-
tpImage
.
iWidth
)
/
2.0
;
COEFF_AT
(
2
,
1
)
+=
(
rotHeight
-
tpImage
.
iHeight
)
/
2.0
;
cv
::
Point2d
rotedCenter
;
rotedCenter
.
x
=
rotRect
.
center
.
x
*
COEFF_AT
(
0
,
0
)
+
rotRect
.
center
.
y
*
COEFF_AT
(
1
,
0
)
+
COEFF_AT
(
2
,
0
);
rotedCenter
.
y
=
rotRect
.
center
.
x
*
COEFF_AT
(
0
,
1
)
+
rotRect
.
center
.
y
*
COEFF_AT
(
1
,
1
)
+
COEFF_AT
(
2
,
1
);
cv
::
Mat
rotImg
;
cv
::
warpAffine
(
image
,
rotImg
,
rotM2d
,
cv
::
Size
((
int
)
rotWeight
,
(
int
)
rotHeight
),
cv
::
INTER_LINEAR
);
//获取Roi区域
cv
::
Rect
roi
((
int
)
MAX
(
rotedCenter
.
x
-
rotRect
.
size
.
width
/
2
,
0
),
(
int
)
MAX
(
rotedCenter
.
y
-
rotRect
.
size
.
height
/
2
,
0
),
\
(
int
)
rotRect
.
size
.
width
,
(
int
)
rotRect
.
size
.
height
);
cv
::
Mat
F
,
G
;
//TODO:增加处理接口
F
=
/*convert(rotImg(roi), CV_64F)*/
cv
::
Mat
();
//高斯滤波
cv
::
GaussianBlur
(
F
,
G
,
cv
::
Size
(
3
,
3
),
dSigma
,
dSigma
);
//偏导
cv
::
Mat
dx
,
dy
;
spatialGradient
(
G
,
dx
,
dy
);
//梯度幅值
cv
::
Mat
mag
;
cv
::
magnitude
(
dx
,
dy
,
mag
);
#define FELEM_AT(x,y) ((double *)F.data)[(y)*F.cols + (x)]
#define FXELEM_AT(x,y) ((double *)dx.data)[(y)*dx.cols + (x)]
#define FYELEM_AT(x,y) ((double *)dy.data)[(y)*dy.cols + (x)]
#define MAGELEM_AT(x,y) ((double *)mag.data)[(y)*mag.cols + (x)]
//提取边缘
std
::
vector
<
cv
::
Point
>
edgePixel
;
cv
::
parallel_for_
(
cv
::
Range
(
5
,
F
.
rows
-
4
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
r
=
range
.
start
;
r
<
range
.
end
;
r
++
)
{
for
(
int
c
=
5
;
c
<
mag
.
cols
-
4
;
c
++
)
{
if
(
MAGELEM_AT
(
c
,
r
)
>
dAmpThresh
)
{
if
(
abs
(
FYELEM_AT
(
c
,
r
))
>=
abs
(
FXELEM_AT
(
c
,
r
)))
{
if
(
abs
(
FYELEM_AT
(
c
,
r
))
>=
abs
(
FYELEM_AT
(
c
,
r
-
1
))
\
&&
abs
(
FYELEM_AT
(
c
,
r
))
>=
abs
(
FYELEM_AT
(
c
,
r
+
1
)))
{
edgePixel
.
push_back
(
cv
::
Point
(
c
,
r
));
}
}
else
{
if
(
abs
(
FXELEM_AT
(
c
,
r
))
>=
abs
(
FXELEM_AT
(
c
-
1
,
r
))
\
&&
abs
(
FXELEM_AT
(
c
,
r
))
>=
abs
(
FXELEM_AT
(
c
+
1
,
r
)))
{
edgePixel
.
push_back
(
cv
::
Point
(
c
,
r
));
}
}
}
}
}
});
cv
::
Mat
showMat3
;
cv
::
cvtColor
(
/*convert(F, CV_8U)*/
cv
::
Mat
(),
showMat3
,
cv
::
COLOR_GRAY2BGR
);
EyemOcsDXY
tpEdge
;
std
::
vector
<
EyemOcsDXY
>
*
tpEdges
=
new
std
::
vector
<
EyemOcsDXY
>
();
for
(
int
i
=
0
;
i
<
(
int
)
edgePixel
.
size
();
i
++
)
{
double
x
=
edgePixel
[
i
].
x
+
rotedCenter
.
x
-
rotRect
.
size
.
width
/
2
+
0.5
;
double
y
=
edgePixel
[
i
].
y
+
rotedCenter
.
y
-
rotRect
.
size
.
height
/
2
+
0.5
;
double
a1
,
b1
,
c1
,
a2
,
b2
,
c2
;
a1
=
COEFF_AT
(
0
,
0
);
b1
=
COEFF_AT
(
1
,
0
);
c1
=
x
-
COEFF_AT
(
2
,
0
);
a2
=
COEFF_AT
(
0
,
1
);
b2
=
COEFF_AT
(
1
,
1
);
c2
=
y
-
COEFF_AT
(
2
,
1
);
tpEdge
.
dX
=
(
c1
*
b2
-
c2
*
b1
)
/
(
a1
*
b2
-
a2
*
b1
);
tpEdge
.
dY
=
(
c1
*
a2
-
c2
*
a1
)
/
(
b1
*
a2
-
b2
*
a1
);
tpEdges
->
push_back
(
tpEdge
);
}
#ifdef _DEBUG
std
::
cout
<<
"Test 'eyemEdge1dGenRect' "
<<
std
::
endl
;
cv
::
Mat
showMat
,
showMat2
;
cv
::
cvtColor
(
image
,
showMat
,
cv
::
COLOR_GRAY2BGR
);
cv
::
Point2f
rect
[
4
];
rotRect
.
points
(
rect
);
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
cv
::
line
(
showMat
,
rect
[
j
],
rect
[(
j
+
1
)
%
4
],
cv
::
Scalar
(
0
,
255
,
0
),
1
);
}
//获取ROI区域
cv
::
cvtColor
(
rotImg
.
clone
(),
showMat2
,
cv
::
COLOR_GRAY2BGR
);
cv
::
rectangle
(
showMat2
,
roi
,
cv
::
Scalar
(
0
,
255
,
0
),
1
);
cv
::
line
(
showMat
,
cv
::
Point
((
int
)
tpLineSt
.
dX
,
(
int
)
tpLineSt
.
dY
),
cv
::
Point
((
int
)
tpLineEd
.
dX
,
(
int
)
tpLineEd
.
dY
),
cv
::
Scalar
(
0
,
255
,
0
),
1
);
//for (int i = 0; i < edges.size(); i++)
//{
// showMat.at<cv::Vec3b>(cv::Point(edges[i].dX, edges[i].dY)) = cv::Vec3b(0, 0, 255);
// //cv::line(showMat, start, end, cv::Scalar(0, 0, 255), 1);
//}
#endif
*
hObject
=
reinterpret_cast
<
IntPtr
>
(
tpEdges
);
return
FUNC_OK
;
}
...
...
@@ -797,6 +504,89 @@ int eyemEdge1dGenArc(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLineEd
return
FUNC_OK
;
}
int
eyemEdge1dRidgeDetection
(
EyemImage
tpImage
)
{
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
image
.
empty
())
{
return
FUNC_IMAGE_NOT_EXIST
;
}
//灰度图
int
incn
=
image
.
channels
();
if
(
incn
>
3
)
{
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGRA2GRAY
);
}
else
if
(
incn
==
3
)
{
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGR2GRAY
);
}
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
auto
polarity
=
line_polarity
::
dark
;
float
sigma
=
1.832
,
low_thr
=
0.0
,
high_thr
=
0.05
;
cv
::
Mat
imageF
;
image
.
convertTo
(
imageF
,
CV_64F
);
std
::
vector
<
double
>
dimg
(
size_t
(
Y
*
X
));
std
::
memcpy
(
dimg
.
data
(),
imageF
.
ptr
(
0
),
image
.
total
()
*
sizeof
(
double
));
std
::
vector
<
std
::
vector
<
float
>>
out
;
get_all_derivatives
(
dimg
,
sigma
,
X
,
Y
,
out
);
std
::
vector
<
int32_t
>
ismax
;
std
::
vector
<
std
::
vector
<
double
>>
line_out
;
cv
::
Mat
esp
;
compute_line_points
(
out
,
X
,
Y
,
polarity
,
ismax
,
line_out
,
low_thr
,
high_thr
,
esp
);
std
::
map
<
int32_t
,
int32_t
>
lm
;
auto
results
=
compute_contours
(
ismax
,
line_out
[
0
],
line_out
[
5
],
line_out
[
6
],
line_out
[
1
],
line_out
[
2
],
line_out
[
3
],
line_out
[
5
],
X
,
Y
,
sigma
,
polarity
);
float
length_total
=
0
;
for
(
auto
cc
=
0
;
cc
<
results
.
size
();
cc
++
)
{
const
contour
&
ct
=
results
[
cc
];
auto
length
=
ct
.
compute_length
();
int
ilength
=
(
int
)
length
;
auto
miter
=
lm
.
find
(
ilength
);
if
(
miter
==
lm
.
end
())
lm
[
ilength
]
=
0
;
auto
current
=
lm
[
ilength
];
lm
[
ilength
]
=
current
+
1
;
length_total
+=
length
;
}
float
avg_node_count
=
results
.
empty
()
?
0
:
length_total
/
float
(
results
.
size
());
std
::
string
output
=
"AvgLength: "
+
std
::
to_string
(
avg_node_count
);
std
::
string
output2
=
"Count: "
+
std
::
to_string
(
results
.
size
());
cv
::
Mat
display
;
cv
::
cvtColor
(
image
,
display
,
cv
::
COLOR_GRAY2BGR
);
if
(
true
)
{
int
factor
=
8
;
for
(
auto
cc
=
0
;
cc
<
results
.
size
();
cc
++
)
{
const
contour
&
ct
=
results
[
cc
];
std
::
vector
<
cv
::
Point
>
pts
;
std
::
vector
<
float
>::
const_iterator
rowItr
=
ct
.
row
.
begin
();
std
::
vector
<
float
>::
const_iterator
colItr
=
ct
.
col
.
begin
();
for
(
auto
pp
=
0
;
pp
<
ct
.
row
.
size
();
pp
++
,
rowItr
++
,
colItr
++
)
{
pts
.
emplace_back
(
static_cast
<
int
>
(
*
colItr
*
factor
),
static_cast
<
int
>
(
*
rowItr
*
factor
));
}
polylines
(
display
,
pts
,
false
,
cv
::
Scalar
(
0
,
0
,
255
),
1
,
cv
::
LINE_AA
,
int
(
std
::
log2
(
factor
)));
}
int
start
=
100
;
auto
it
=
lm
.
begin
();
while
(
it
!=
lm
.
end
())
{
std
::
string
hout
=
"histogram ["
+
std
::
to_string
(
it
->
first
)
+
"] = "
+
std
::
to_string
(
it
->
second
);
cv
::
putText
(
display
,
hout
.
c_str
(),
cv
::
Point
(
500
,
start
),
cv
::
FONT_HERSHEY_SIMPLEX
,
1.0
,
cv
::
Scalar
(
255
,
0
,
0
),
2
);
start
+=
30
;
it
++
;
}
}
return
FUNC_OK
;
}
bool
eyemEdge1dGenMeasureFree
(
IntPtr
hObject
)
{
std
::
vector
<
EyemOcsDXY
>
*
tpEdges
=
reinterpret_cast
<
std
::
vector
<
EyemOcsDXY
>*>
(
hObject
);
...
...
eyemLib/eyemEdge1d.h
查看文件 @
547390f
...
...
@@ -5,8 +5,1443 @@
#ifndef __EYEM_EDGE1D_H
#define __EYEM_EDGE1D_H
#include <ostream>
#include "eyemLib.h"
#include "stegers.h"
static
constexpr
int
DERIV_R
=
1
;
/** Derivative in column direction */
static
constexpr
int
DERIV_C
=
2
;
/** Second derivative in row direction */
static
constexpr
int
DERIV_RR
=
3
;
/** Second derivative in row and column direction */
static
constexpr
int
DERIV_RC
=
4
;
/** Second derivative in column direction */
static
constexpr
int
DERIV_CC
=
5
;
#ifndef LCOR
#define LCOR(row,col,width) (row)*(width) + (col)
#endif
double
SQRT_2_PI_INV
=
0
.
398942280401432677939946059935
;
double
SQRTPI
=
1
.
772453850905516027
;
double
UPPERLIMIT
=
20
.
0
;
double
SQRT2
=
1
.
41421356237309504880
;
double
P10
=
242
.
66795523053175
;
double
P11
=
21
.
979261618294152
;
double
P12
=
6
.
9963834886191355
;
double
P13
=
-
0
.
03560
9843701815385
;
double
Q10
=
215
.
05
887586986120
;
double
Q11
=
91
.
164905404514901
;
double
Q12
=
15
.
082797630407787
;
double
Q13
=
1
.
0
;
double
P20
=
300
.
4592610201616005
;
double
P21
=
451
.
9189537118729422
;
double
P22
=
339
.
3208167343436870
;
double
P23
=
152
.
9892850469404039
;
double
P24
=
43
.
16222722205673530
;
double
P25
=
7
.
211758250883093659
;
double
P26
=
0
.
5641955174789739711
;
double
P27
=
-
0
.
000000136
8648573827167067
;
double
Q20
=
300
.
4592609569832933
;
double
Q21
=
790
.
9509253278980272
;
double
Q22
=
931
.
3540948506096211
;
double
Q23
=
638
.
9802644656311665
;
double
Q24
=
277
.
5854447439876434
;
double
Q25
=
77
.
000152
93522947295
;
double
Q26
=
12
.
78272731962942351
;
double
Q27
=
1
.
0
;
double
P30
=
-
0
.
002
99610707703542174
;
double
P31
=
-
0
.
04
94730910623250734
;
double
P32
=
-
0
.
226956593539686930
;
double
P33
=
-
0
.
278661308609647788
;
double
P34
=
-
0
.
02231
92459734184686
;
double
Q30
=
0
.
010620
9230528467918
;
double
Q31
=
0
.
191308926107829841
;
double
Q32
=
1
.
051675107067
93207
;
double
Q33
=
1
.
98733201817135256
;
double
Q34
=
1
.
0
;
double
MAX_SIZE_MASK_0
=
3
.
09023230616781
;
double
MAX_SIZE_MASK_1
=
3
.
46087178201605
;
double
MAX_SIZE_MASK_2
=
3
.
82922419517181
;
int
MASK_SIZE
(
double
MAX
,
double
sigma
)
{
return
static_cast
<
int
>
(
ceil
(
MAX
*
sigma
));
}
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
dirtab
{
{
{
1
,
0
},{
1
,
-
1
},{
1
,
1
}
},
{
{
1
,
1
},{
1
,
0
},{
0
,
1
}
},
{
{
0
,
1
},{
1
,
1
},{
-
1
,
1
}
},
{
{
-
1
,
1
},{
0
,
1
},{
-
1
,
0
}
},
{
{
-
1
,
0
},{
-
1
,
1
},{
-
1
,
-
1
}
},
{
{
-
1
,
-
1
},{
-
1
,
0
},{
0
,
-
1
}
},
{
{
0
,
-
1
},{
-
1
,
-
1
},{
1
,
-
1
}
},
{
{
1
,
-
1
},{
0
,
-
1
},{
1
,
0
}
}
};
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
cleartab
=
{
{
{
0
,
1
},{
0
,
-
1
}
},
{
{
-
1
,
1
},{
1
,
-
1
}
},
{
{
-
1
,
0
},{
1
,
0
}
},
{
{
-
1
,
-
1
},{
1
,
1
}
},
{
{
0
,
-
1
},{
0
,
1
}
},
{
{
1
,
-
1
},{
-
1
,
1
}
},
{
{
1
,
0
},{
-
1
,
0
}
},
{
{
1
,
1
},{
-
1
,
-
1
}
}
};
enum
line_polarity
{
light
,
dark
};
double
normal
(
double
x
)
{
int
sn
;
double
R1
,
R2
,
y
,
y2
,
y3
,
y4
,
y5
,
y6
,
y7
;
double
erf
,
erfc
,
z
,
z2
,
z3
,
z4
;
double
phi
;
if
(
x
<
-
UPPERLIMIT
)
return
0
.
0
;
if
(
x
>
UPPERLIMIT
)
return
1
.
0
;
y
=
x
/
SQRT2
;
if
(
y
<
0
)
{
y
=
-
y
;
sn
=
-
1
;
}
else
sn
=
1
;
y2
=
y
*
y
;
y4
=
y2
*
y2
;
y6
=
y4
*
y2
;
if
(
y
<
0
.
46875
)
{
R1
=
P10
+
P11
*
y2
+
P12
*
y4
+
P13
*
y6
;
R2
=
Q10
+
Q11
*
y2
+
Q12
*
y4
+
Q13
*
y6
;
erf
=
y
*
R1
/
R2
;
if
(
sn
==
1
)
phi
=
0
.
5
+
0
.
5
*
erf
;
else
phi
=
0
.
5
-
0
.
5
*
erf
;
}
else
if
(
y
<
4
.
0
)
{
y3
=
y2
*
y
;
y5
=
y4
*
y
;
y7
=
y6
*
y
;
R1
=
P20
+
P21
*
y
+
P22
*
y2
+
P23
*
y3
+
P24
*
y4
+
P25
*
y5
+
P26
*
y6
+
P27
*
y7
;
R2
=
Q20
+
Q21
*
y
+
Q22
*
y2
+
Q23
*
y3
+
Q24
*
y4
+
Q25
*
y5
+
Q26
*
y6
+
Q27
*
y7
;
erfc
=
exp
(
-
y2
)
*
R1
/
R2
;
if
(
sn
==
1
)
phi
=
1
.
0
-
0
.
5
*
erfc
;
else
phi
=
0
.
5
*
erfc
;
}
else
{
z
=
y4
;
z2
=
z
*
z
;
z3
=
z2
*
z
;
z4
=
z2
*
z2
;
R1
=
P30
+
P31
*
z
+
P32
*
z2
+
P33
*
z3
+
P34
*
z4
;
R2
=
Q30
+
Q31
*
z
+
Q32
*
z2
+
Q33
*
z3
+
Q34
*
z4
;
erfc
=
(
exp
(
-
y2
)
/
y
)
*
(
1
.
0
/
SQRTPI
+
R1
/
(
R2
*
y2
));
if
(
sn
==
1
)
phi
=
1
.
0
-
0
.
5
*
erfc
;
else
phi
=
0
.
5
*
erfc
;
}
return
phi
;
}
/** Integral of the Gaussian function */
double
phi0
(
double
x
,
double
sigma
)
{
return
normal
(
x
/
sigma
);
}
/** The Gaussian function */
double
phi1
(
double
x
,
double
sigma
)
{
double
t
;
t
=
x
/
sigma
;
return
SQRT_2_PI_INV
/
sigma
*
exp
(
-
0
.
5
*
t
*
t
);
}
/** First derivative of the Gaussian function */
double
phi2
(
double
x
,
double
sigma
)
{
double
t
;
t
=
x
/
sigma
;
return
-
x
*
SQRT_2_PI_INV
/
pow
(
sigma
,
3
.
0
)
*
exp
(
-
0
.
5
*
t
*
t
);
}
/** Gaussian smoothing mask */
void
compute_gauss_mask_0
(
double
sigma
,
std
::
vector
<
double
>
&
h
)
{
int
i
,
n
;
n
=
MASK_SIZE
(
MAX_SIZE_MASK_0
,
sigma
);
/* Error < 0.001 on each side */
h
.
resize
(
2
*
n
+
1
);
for
(
i
=
-
n
+
1
;
i
<=
n
-
1
;
i
++
)
h
[
i
+
n
]
=
phi0
(
-
i
+
0
.
5
,
sigma
)
-
phi0
(
-
i
-
0
.
5
,
sigma
);
h
[
0
]
=
1
.
0
-
phi0
(
n
-
0
.
5
,
sigma
);
h
[
2
*
n
]
=
phi0
(
-
n
+
0
.
5
,
sigma
);
}
/** First derivative of Gaussian smoothing mask */
void
compute_gauss_mask_1
(
double
sigma
,
std
::
vector
<
double
>
&
h
)
{
int
i
,
n
;
n
=
MASK_SIZE
(
MAX_SIZE_MASK_1
,
sigma
);
/* Error < 0.001 on each side */
h
.
resize
(
2
*
n
+
1
);
for
(
i
=
-
n
+
1
;
i
<=
n
-
1
;
i
++
)
h
[
i
+
n
]
=
phi1
(
-
i
+
0
.
5
,
sigma
)
-
phi1
(
-
i
-
0
.
5
,
sigma
);
h
[
0
]
=
-
phi1
(
n
-
0
.
5
,
sigma
);
h
[
2
*
n
]
=
phi1
(
-
n
+
0
.
5
,
sigma
);
}
/** Second derivative of Gaussian smoothing mask */
void
compute_gauss_mask_2
(
double
sigma
,
std
::
vector
<
double
>
&
h
)
{
int
i
,
n
;
n
=
MASK_SIZE
(
MAX_SIZE_MASK_2
,
sigma
);
/* Error < 0.001 on each side */
h
.
resize
(
2
*
n
+
1
);
for
(
i
=
-
n
+
1
;
i
<=
n
-
1
;
i
++
)
h
[
i
+
n
]
=
phi2
(
-
i
+
0
.
5
,
sigma
)
-
phi2
(
-
i
-
0
.
5
,
sigma
);
h
[
0
]
=
-
phi2
(
n
-
0
.
5
,
sigma
);
h
[
2
*
n
]
=
phi2
(
-
n
+
0
.
5
,
sigma
);
}
/** Convolve an image with a derivative of the Gaussian. */
void
convolve_gauss_opencv
(
std
::
vector
<
double
>&
image
,
int
width
,
int
height
,
double
sigma
,
int
deriv_type
,
std
::
vector
<
float
>&
out
)
{
std
::
vector
<
double
>
hr
;
std
::
vector
<
double
>
hc
;
switch
(
deriv_type
)
{
case
DERIV_R
:
compute_gauss_mask_1
(
sigma
,
hr
);
compute_gauss_mask_0
(
sigma
,
hc
);
break
;
case
DERIV_C
:
compute_gauss_mask_0
(
sigma
,
hr
);
compute_gauss_mask_1
(
sigma
,
hc
);
break
;
case
DERIV_RR
:
compute_gauss_mask_2
(
sigma
,
hr
);
compute_gauss_mask_0
(
sigma
,
hc
);
break
;
case
DERIV_RC
:
compute_gauss_mask_1
(
sigma
,
hr
);
compute_gauss_mask_1
(
sigma
,
hc
);
break
;
case
DERIV_CC
:
compute_gauss_mask_0
(
sigma
,
hr
);
compute_gauss_mask_2
(
sigma
,
hc
);
break
;
default:
// just a stub
assert
(
false
);
break
;
}
// @note: result is nearly identical to c version
// if sepFilter2D is operates on double input and the output is transformed to float
cv
::
Mat
image_m
(
height
,
width
,
cv
::
DataType
<
double
>::
type
,
image
.
data
());
cv
::
Mat
hr_m
(
hr
.
size
(),
1
,
cv
::
DataType
<
double
>::
type
,
hr
.
data
());
cv
::
Mat
hc_m
(
hc
.
size
(),
1
,
cv
::
DataType
<
double
>::
type
,
hc
.
data
());
cv
::
Mat
outm
;
cv
::
sepFilter2D
(
image_m
,
outm
,
-
1
,
hc_m
,
hr_m
,
cv
::
Point
(
-
1
,
-
1
),
0
,
CV_HAL_BORDER_REFLECT
);
std
::
vector
<
double
>
dimg
(
width
*
height
);
std
::
memcpy
(
dimg
.
data
(),
outm
.
ptr
(
0
),
outm
.
total
()
*
sizeof
(
double
));
std
::
transform
(
dimg
.
begin
(),
dimg
.
end
(),
out
.
begin
(),
[](
const
double
d
)
{
return
float
(
d
);
});
}
void
get_all_derivatives
(
std
::
vector
<
double
>&
image
,
double
sigma
,
int
width
,
int
height
,
std
::
vector
<
std
::
vector
<
float
>>&
k
)
{
static
double
zero_val
=
0
.
0
;
k
.
resize
(
0
);
for
(
int
i
=
0
;
i
<
5
;
i
++
)
k
.
emplace_back
(
width
*
height
,
zero_val
);
convolve_gauss_opencv
(
image
,
width
,
height
,
sigma
,
DERIV_R
,
k
[
0
]);
convolve_gauss_opencv
(
image
,
width
,
height
,
sigma
,
DERIV_C
,
k
[
1
]);
convolve_gauss_opencv
(
image
,
width
,
height
,
sigma
,
DERIV_RR
,
k
[
2
]);
convolve_gauss_opencv
(
image
,
width
,
height
,
sigma
,
DERIV_RC
,
k
[
3
]);
convolve_gauss_opencv
(
image
,
width
,
height
,
sigma
,
DERIV_CC
,
k
[
4
]);
}
std
::
vector
<
std
::
vector
<
double
>>
RectangularDoubleVector
(
int
size1
,
int
size2
)
{
static
double
zero
=
0
.
0
;
std
::
vector
<
std
::
vector
<
double
>>
newVector
(
size1
);
for
(
int
vector1
=
0
;
vector1
<
size1
;
vector1
++
)
{
newVector
[
vector1
]
=
std
::
vector
<
double
>
(
size2
,
zero
);
}
return
newVector
;
}
std
::
vector
<
std
::
vector
<
float
>>
RectangularFloatVector
(
int
size1
,
int
size2
)
{
std
::
vector
<
std
::
vector
<
float
>>
newVector
(
size1
);
for
(
int
vector1
=
0
;
vector1
<
size1
;
vector1
++
)
{
newVector
[
vector1
]
=
std
::
vector
<
float
>
(
size2
);
}
return
newVector
;
}
void
compute_eigenvals
(
double
dfdrr
,
double
dfdrc
,
double
dfdcc
,
std
::
vector
<
std
::
vector
<
double
>>&
eigenvalvect
)
{
double
theta
,
t
,
n1
,
n2
;
// , phi;
double
c
=
1
.
0
;
double
s
=
0
.
0
;
double
e1
=
dfdrr
;
double
e2
=
dfdcc
;
/* Compute the eigenvalues and eigenvectors of the Hessian matrix. */
if
(
dfdrc
!=
0
.
0
)
{
theta
=
0
.
5
*
(
dfdcc
-
dfdrr
)
/
dfdrc
;
t
=
1
.
0
/
(
std
::
abs
(
theta
)
+
std
::
sqrt
(
theta
*
theta
+
1
.
0
));
if
(
theta
<
0
.
0
)
{
t
=
-
t
;
}
c
=
1
.
0
/
std
::
sqrt
(
t
*
t
+
1
.
0
);
s
=
t
*
c
;
e1
=
dfdrr
-
t
*
dfdrc
;
e2
=
dfdcc
+
t
*
dfdrc
;
}
n1
=
c
;
n2
=
-
s
;
/* If the absolute value of an eigenvalue is larger than the other, put that
eigenvalue into first position. If both are of equal absolute value, put
the negative one first. */
if
(
std
::
abs
(
e1
)
>
std
::
abs
(
e2
))
{
eigenvalvect
[
0
][
0
]
=
e1
;
eigenvalvect
[
0
][
1
]
=
e2
;
eigenvalvect
[
1
][
0
]
=
n1
;
eigenvalvect
[
1
][
1
]
=
n2
;
eigenvalvect
[
2
][
0
]
=
-
n2
;
eigenvalvect
[
2
][
1
]
=
n1
;
}
else
if
(
std
::
abs
(
e1
)
<
std
::
abs
(
e2
))
{
eigenvalvect
[
0
][
0
]
=
e2
;
eigenvalvect
[
0
][
1
]
=
e1
;
eigenvalvect
[
1
][
0
]
=
-
n2
;
eigenvalvect
[
1
][
1
]
=
n1
;
eigenvalvect
[
2
][
0
]
=
n1
;
eigenvalvect
[
2
][
1
]
=
n2
;
}
else
{
if
(
e1
<
e2
)
{
eigenvalvect
[
0
][
0
]
=
e1
;
eigenvalvect
[
0
][
1
]
=
e2
;
eigenvalvect
[
1
][
0
]
=
n1
;
eigenvalvect
[
1
][
1
]
=
n2
;
eigenvalvect
[
2
][
0
]
=
-
n2
;
eigenvalvect
[
2
][
1
]
=
n1
;
}
else
{
eigenvalvect
[
0
][
0
]
=
e2
;
eigenvalvect
[
0
][
1
]
=
e1
;
eigenvalvect
[
1
][
0
]
=
-
n2
;
eigenvalvect
[
1
][
1
]
=
n1
;
eigenvalvect
[
2
][
0
]
=
n1
;
eigenvalvect
[
2
][
1
]
=
n2
;
}
}
}
int32_t
BR
(
int32_t
row
,
int
m_height
)
{
return
((
row
)
<
0
?
-
(
row
)
:
(
row
)
>=
m_height
?
m_height
-
(
row
)
+
m_height
-
2
:
(
row
));
}
/** Mirror the column coordinate at the borders of the image; width must be a
defined variable in the calling function containing the image width. */
int32_t
BC
(
int32_t
col
,
int
m_width
)
{
return
((
col
)
<
0
?
-
(
col
)
:
(
col
)
>=
m_width
?
m_width
-
(
col
)
+
m_width
-
2
:
(
col
));
}
double
interpolate_response
(
const
std
::
vector
<
double
>&
resp
,
int32_t
x
,
int32_t
y
,
double
px
,
double
py
,
int
width
,
int
height
)
{
double
i1
,
i2
,
i3
,
i4
,
i5
,
i6
,
i7
,
i8
,
i9
;
double
t1
,
t2
,
t3
,
t4
,
t5
,
t6
;
double
d
,
dr
,
dc
,
drr
,
drc
,
dcc
;
double
xx
,
yy
;
i1
=
resp
[
LCOR
(
BR
(
x
-
1
,
height
),
BC
(
y
-
1
,
width
),
width
)];
i2
=
resp
[
LCOR
(
BR
(
x
-
1
,
height
),
y
,
width
)];
i3
=
resp
[
LCOR
(
BR
(
x
-
1
,
height
),
BC
(
y
+
1
,
width
),
width
)];
i4
=
resp
[
LCOR
(
x
,
BC
(
y
-
1
,
width
),
width
)];
i5
=
resp
[
LCOR
(
x
,
y
,
width
)];
i6
=
resp
[
LCOR
(
x
,
BC
(
y
+
1
,
width
),
width
)];
i7
=
resp
[
LCOR
(
BR
(
x
+
1
,
height
),
BC
(
y
-
1
,
width
),
width
)];
i8
=
resp
[
LCOR
(
BR
(
x
+
1
,
height
),
y
,
width
)];
i9
=
resp
[
LCOR
(
BR
(
x
+
1
,
height
),
BC
(
y
+
1
,
width
),
width
)];
t1
=
i1
+
i2
+
i3
;
t2
=
i4
+
i5
+
i6
;
t3
=
i7
+
i8
+
i9
;
t4
=
i1
+
i4
+
i7
;
t5
=
i2
+
i5
+
i8
;
t6
=
i3
+
i6
+
i9
;
d
=
(
-
i1
+
2
*
i2
-
i3
+
2
*
i4
+
5
*
i5
+
2
*
i6
-
i7
+
2
*
i8
-
i9
)
/
9
;
dr
=
(
t3
-
t1
)
/
6
;
dc
=
(
t6
-
t4
)
/
6
;
drr
=
(
t1
-
2
*
t2
+
t3
)
/
6
;
dcc
=
(
t4
-
2
*
t5
+
t6
)
/
6
;
drc
=
(
i1
-
i3
-
i7
+
i9
)
/
4
;
xx
=
px
-
x
;
yy
=
py
-
y
;
return
d
+
xx
*
dr
+
yy
*
dc
+
xx
*
xx
*
drr
+
xx
*
yy
*
drc
+
yy
*
yy
*
dcc
;
}
void
interpolate_gradient
(
const
std
::
vector
<
double
>&
gradx
,
const
std
::
vector
<
double
>&
grady
,
double
px
,
double
py
,
doublepoint
&
gradxy
,
int
width
,
int
height
)
{
long
gix
,
giy
,
gpos
;
double
gfx
,
gfy
,
gx1
,
gy1
,
gx2
,
gy2
,
gx3
,
gy3
,
gx4
,
gy4
;
gix
=
(
long
)
std
::
floor
(
px
);
giy
=
(
long
)
std
::
floor
(
py
);
gfx
=
px
;
// % 1.0; //check whether it works as promised
gfy
=
py
;
// % 1.0;
gpos
=
LCOR
(
gix
,
giy
,
width
);
gx1
=
gradx
[(
int
)
gpos
];
gy1
=
grady
[(
int
)
gpos
];
gpos
=
LCOR
(
gix
+
1
,
giy
,
width
);
gx2
=
gradx
[(
int
)
gpos
];
gy2
=
grady
[(
int
)
gpos
];
gpos
=
LCOR
(
gix
,
giy
+
1
,
width
);
gx3
=
gradx
[(
int
)
gpos
];
gy3
=
grady
[(
int
)
gpos
];
gpos
=
LCOR
(
gix
+
1
,
giy
+
1
,
width
);
gx4
=
gradx
[(
int
)
gpos
];
gy4
=
grady
[(
int
)
gpos
];
gradxy
.
cx
=
(
1
-
gfy
)
*
((
1
-
gfx
)
*
gx1
+
gfx
*
gx2
)
+
gfy
*
((
1
-
gfx
)
*
gx3
+
gfx
*
gx4
);
gradxy
.
cy
=
(
1
-
gfy
)
*
((
1
-
gfx
)
*
gy1
+
gfx
*
gy2
)
+
gfy
*
((
1
-
gfx
)
*
gy3
+
gfx
*
gy4
);
}
// orintation from norms.
double
get_angle
(
const
std
::
vector
<
double
>&
nrmx
,
const
std
::
vector
<
double
>&
nrmy
,
int32_t
position
)
{
auto
nx
=
-
nrmy
[
position
];
auto
ny
=
nrmx
[
position
];
auto
alpha
=
std
::
atan2
(
ny
,
nx
);
if
(
alpha
<
0
.
0
)
alpha
+=
2
.
0
*
PI
;
if
(
alpha
>=
PI
)
alpha
-=
PI
;
return
alpha
;
}
template
<
typename
T
>
int
sgn
(
T
val
)
{
return
(
T
(
0
)
<
val
)
-
(
val
<
T
(
0
));
}
void
closest_point
(
double
lx
,
double
ly
,
double
dx
,
double
dy
,
double
px
,
double
py
,
doublepoint
&
out
)
{
double
mx
,
my
,
den
,
nom
,
tt
;
mx
=
px
-
lx
;
my
=
py
-
ly
;
den
=
dx
*
dx
+
dy
*
dy
;
nom
=
mx
*
dx
+
my
*
dy
;
if
(
den
!=
0
)
tt
=
nom
/
den
;
else
tt
=
0
;
out
.
cx
=
lx
+
tt
*
dx
;
out
.
cy
=
ly
+
tt
*
dy
;
out
.
t
=
tt
;
}
void
bresenham
(
double
nx
,
double
ny
,
double
px
,
double
py
,
double
length
,
std
::
vector
<
offset
>&
out
)
{
out
.
resize
(
0
);
int
i
,
x
,
y
,
s1
,
s2
,
xchg
,
maxit
;
double
e
,
dx
,
dy
,
t
;
x
=
0
;
y
=
0
;
dx
=
std
::
fabs
(
nx
);
dy
=
std
::
fabs
(
ny
);
s1
=
sgn
(
nx
);
s2
=
sgn
(
ny
);
px
*=
s1
;
py
*=
s2
;
if
(
dy
>
dx
)
{
t
=
dx
;
dx
=
dy
;
dy
=
t
;
t
=
px
;
px
=
py
;
py
=
t
;
xchg
=
1
;
}
else
{
xchg
=
0
;
}
maxit
=
(
int
)
std
::
ceil
(
length
*
dx
);
e
=
(
0
.
5
-
px
)
*
dy
/
dx
-
(
0
.
5
-
py
);
for
(
i
=
0
;
i
<=
maxit
;
i
++
)
{
out
.
emplace_back
(
x
,
y
);
while
(
e
>=
-
1e-8
)
{
if
(
std
::
fabs
(
xchg
)
>
0
)
x
+=
s1
;
else
y
+=
s2
;
e
--
;
if
(
e
>
-
1
)
{
out
.
emplace_back
(
x
,
y
);
}
}
if
(
std
::
fabs
(
xchg
)
>
0
)
y
+=
s2
;
else
x
+=
s1
;
e
+=
dy
/
dx
;
}
}
void
compute_line_points
(
const
std
::
vector
<
std
::
vector
<
float
>>&
derivs
,
int
width
,
int
height
,
line_polarity
lp
,
std
::
vector
<
int32_t
>&
ismax
,
std
::
vector
<
std
::
vector
<
double
>>&
ennpp
,
double
low
,
double
high
,
cv
::
Mat
&
espace
)
{
int
r
,
c
;
std
::
vector
<
std
::
vector
<
double
>>
line_points
=
RectangularDoubleVector
(
7
,
static_cast
<
int
>
(
width
*
height
));
std
::
vector
<
std
::
vector
<
double
>>
eigenvalvect
=
RectangularDoubleVector
(
3
,
2
);
ismax
.
resize
(
width
*
height
,
0
);
espace
=
cv
::
Mat
(
height
,
width
,
CV_32F
);
//all derivatives
int
l
;
double
a
,
b
,
n1
,
n2
,
t
;
/*compute eigenval and vectors */
for
(
r
=
0
;
r
<
height
;
r
++
)
{
float
*
row_ptr
=
(
float
*
)(
espace
.
ptr
(
r
));
for
(
c
=
0
;
c
<
width
;
c
++
,
row_ptr
++
)
{
l
=
r
*
width
+
c
;
compute_eigenvals
(
derivs
[
2
][
l
],
derivs
[
3
][
l
],
derivs
[
4
][
l
],
eigenvalvect
);
auto
val
=
lp
==
line_polarity
::
light
?
-
eigenvalvect
[
0
][
0
]
:
eigenvalvect
[
0
][
0
];
if
(
val
>
0
.
0
)
{
*
row_ptr
=
(
float
)
val
;
line_points
[
0
][
l
]
=
val
;
// first eigenvalue
n1
=
eigenvalvect
[
1
][
0
];
// igenvector coordinate y
n2
=
eigenvalvect
[
1
][
1
];
// eigenvector coordinate x
a
=
derivs
[
2
][
l
]
*
n1
*
n1
+
2
.
0
*
derivs
[
3
][
l
]
*
n1
*
n2
+
derivs
[
4
][
l
]
*
n2
*
n2
;
b
=
derivs
[
0
][
l
]
*
n1
+
derivs
[
1
][
l
]
*
n2
;
if
(
a
==
0
.
0
)
continue
;
t
=
(
-
1
)
*
b
/
a
;
auto
p1
=
t
*
n1
;
auto
p2
=
t
*
n2
;
if
(
std
::
fabs
(
p1
)
>
0
.
6
||
std
::
fabs
(
p2
)
>
0
.
6
)
continue
;
ismax
[
l
]
=
val
>=
high
?
2
:
val
>=
low
?
1
:
0
;
line_points
[
5
][
l
]
=
r
+
p1
;
line_points
[
6
][
l
]
=
c
+
p2
;
line_points
[
1
][
l
]
=
n1
;
// "super-resolved" y
line_points
[
2
][
l
]
=
n2
;
// "super-resolved" x
line_points
[
3
][
l
]
=
derivs
[
0
][
l
];
line_points
[
4
][
l
]
=
derivs
[
1
][
l
];
}
}
}
ennpp
=
line_points
;
}
std
::
vector
<
contour
>
compute_contours
(
std
::
vector
<
int32_t
>
ismax
,
const
std
::
vector
<
double
>&
eigval
,
const
std
::
vector
<
double
>&
posx
,
const
std
::
vector
<
double
>&
posy
,
const
std
::
vector
<
double
>&
normx
,
const
std
::
vector
<
double
>&
normy
,
const
std
::
vector
<
double
>&
gradx
,
const
std
::
vector
<
double
>&
grady
,
int
width
,
int
height
,
double
sigma
,
line_polarity
polarity
)
{
std
::
vector
<
contour
>
m_results
;
std
::
vector
<
junction
>
m_junctions
;
//parameter
int
m_total_cnt
=
width
*
height
;
// Parameters @todo move into params class
double
MAX_ANGLE_DIFFERENCE
=
PI
/
6
.
0
;
double
MAX_LINE_EXTENSION
=
sigma
*
2
.
5
;
double
MAX_LINE_WIDTH
=
(
2
.
5
*
sigma
);
double
LINE_WIDTH_COMPENSATION
=
1
.
05
;
double
MIN_LINE_WIDTH
=
0
.
1
;
double
m_pixel_boundary
=
0
.
6
;
double
m_spread_fraction
=
0
.
1
;
//m_espace = cv::Mat(m_height, m_width, CV_32F);
double
m_max_line_pts
=
(
width
*
height
)
/
(
sigma
*
9
);
m_max_line_pts
=
m_spread_fraction
*
m_max_line_pts
;
bool
m_crowded
=
false
;
long
area
;
int
i
,
k
,
l
,
pos
,
nexti
;
int
nextpos
;
int
it
;
long
num_pnt
,
num_cont
,
num_junc
;
long
x
,
y
;
long
begin
,
end
;
long
indx_max
;
double
max
;
long
maxx
,
maxy
,
nextx
,
nexty
;
double
nx
,
ny
,
mx
,
my
;
double
px
,
py
,
nextpx
,
nextpy
;
double
alpha
,
nextalpha
,
beta
,
last_beta
;
int
octant
,
last_octant
;
bool
nextismax
;
double
diff
,
mindiff
,
diff1
,
diff2
,
dist
,
mindist
;
double
dx
,
dy
;
double
s
,
t
,
gx
,
gy
;
double
length
,
response
;
int
num_add
;
int
m
=
0
;
int
j
=
0
;
double
end_angle
=
0
;
double
end_resp
=
0
;
contour
tmp_cont
;
bool
add_ext
;
doublepoint
closestpnt
;
//double MAX_ANGLE_DIFFERENCE = PI / 6.0;
std
::
vector
<
contour
>
cont
;
contour_class
cls
;
std
::
vector
<
float
>
row
;
std
::
vector
<
float
>
col
;
std
::
vector
<
float
>
angle
;
std
::
vector
<
float
>
resp
;
std
::
vector
<
float
>
extx
;
std
::
vector
<
float
>
exty
;
std
::
vector
<
offset
>
line
;
std
::
vector
<
float
>
trow
;
std
::
vector
<
float
>
tcol
;
std
::
vector
<
float
>
tangle
;
std
::
vector
<
float
>
tresp
;
std
::
vector
<
chord
>
rl
;
std
::
vector
<
short
>
label
(
m_total_cnt
,
0
);
std
::
vector
<
int32_t
>
indx
(
m_total_cnt
,
0
);
// Select all pixels that can be starting points for lines.
region
seg
(
ismax
,
2
,
width
,
height
);
// Count the number of possible starting points.
area
=
0
;
for
(
i
=
0
;
i
<
seg
.
num
;
i
++
)
{
area
+=
seg
.
rl
[
i
].
ce
-
seg
.
rl
[
i
].
cb
+
1
;
}
// Create the index of possible starting points.
std
::
vector
<
crossRef
>
cross
;
rl
=
seg
.
rl
;
for
(
i
=
0
;
i
<
seg
.
num
;
i
++
)
{
x
=
rl
[
i
].
r
;
for
(
y
=
rl
[
i
].
cb
;
y
<=
rl
[
i
].
ce
;
y
++
)
{
pos
=
(
int
)
LCOR
(
x
,
y
,
width
);
cross
.
emplace_back
((
short
)
x
,
(
short
)
y
,
std
::
fabs
(
eigval
[
pos
]),
false
);
}
}
sort
(
cross
.
begin
(),
cross
.
end
(),
std
::
greater
<
crossRef
>
());
if
(
area
>
m_max_line_pts
)
{
m_crowded
=
true
;
area
=
m_max_line_pts
;
}
for
(
i
=
0
;
i
<
area
;
i
++
)
indx
[
LCOR
(
cross
[
i
].
x
(),
cross
[
i
].
y
(),
width
)]
=
i
+
1
;
//reset everything
num_cont
=
0
;
num_junc
=
0
;
std
::
vector
<
junction
>
junc
;
// Link lines points.
indx_max
=
0
;
for
(;;)
{
// Contour class unknown at this point; therefore assume both ends free.
cls
=
contour_class
::
cont_no_junc
;
while
(
indx_max
<
area
&&
cross
[
indx_max
].
done
())
indx_max
++
;
// Stop if no feasible starting point exists.
if
(
indx_max
==
area
)
break
;
max
=
cross
[
indx_max
].
value
();
maxx
=
cross
[
indx_max
].
x
();
maxy
=
cross
[
indx_max
].
y
();
if
(
max
==
0
.
0
)
break
;
row
.
resize
(
0
);
col
.
resize
(
0
);
resp
.
resize
(
0
);
angle
.
resize
(
0
);
// Add starting point to the line.
num_pnt
=
0
;
pos
=
(
int
)
LCOR
(
maxx
,
maxy
,
width
);
label
[
pos
]
=
(
short
)(
num_cont
+
1
);
if
(
indx
[
pos
]
!=
0
)
cross
[
indx
[
pos
]
-
1
].
setDone
();
row
.
push_back
((
float
)
posx
[
pos
]);
col
.
push_back
((
float
)
posy
[
pos
]);
// Select line direction.
nx
=
-
normy
[
pos
];
ny
=
normx
[
pos
];
alpha
=
std
::
atan2
(
ny
,
nx
);
if
(
alpha
<
0
.
0
)
alpha
+=
2
.
0
*
PI
;
if
(
alpha
>=
PI
)
alpha
-=
PI
;
octant
=
(
int
)(
std
::
floor
(
4
.
0
/
PI
*
alpha
+
0
.
5
))
%
4
;
// Select normal to the line. The normal points to the right of the line
// as the line is traversed from 0 to num-1. Since the points are sorted
// in reverse order before the second iteration, the first beta actually
// has to point to the left of the line!
beta
=
alpha
+
PI
/
2
.
0
;
if
(
beta
>=
2
.
0
*
PI
)
beta
-=
2
.
0
*
PI
;
angle
.
push_back
((
float
)
beta
);
resp
.
push_back
((
float
)
interpolate_response
(
eigval
,
maxx
,
maxy
,
posx
[
pos
],
posy
[
pos
],
width
,
height
));
num_pnt
++
;
// Mark double responses as processed.
for
(
i
=
0
;
i
<
2
;
i
++
)
{
nextx
=
maxx
+
cleartab
[
octant
][
i
][
0
];
nexty
=
maxy
+
cleartab
[
octant
][
i
][
1
];
if
(
nextx
<
0
||
nextx
>=
height
||
nexty
<
0
||
nexty
>=
width
)
continue
;
nextpos
=
(
int
)
LCOR
(
nextx
,
nexty
,
width
);
if
(
ismax
[
nextpos
]
>
0
)
{
nextalpha
=
get_angle
(
normx
,
normy
,
nextpos
);
diff
=
std
::
abs
(
alpha
-
nextalpha
);
if
(
diff
>=
PI
/
2
.
0
)
diff
=
PI
-
diff
;
if
(
diff
<
MAX_ANGLE_DIFFERENCE
)
{
label
[
nextpos
]
=
(
short
)(
num_cont
+
1
);
if
(
indx
[
nextpos
]
!=
0
)
cross
[
indx
[
nextpos
]
-
1
].
setDone
();
}
}
}
for
(
it
=
1
;
it
<=
2
;
it
++
)
{
if
(
it
==
1
)
{
// Search along the initial line direction in the first iteration.
x
=
maxx
;
y
=
maxy
;
pos
=
(
int
)
LCOR
(
x
,
y
,
width
);
alpha
=
get_angle
(
normx
,
normy
,
pos
);
last_octant
=
(
int
)(
std
::
floor
(
4
.
0
/
PI
*
alpha
+
0
.
5
))
%
4
;
last_beta
=
alpha
+
PI
/
2
.
0
;
if
(
last_beta
>=
2
.
0
*
PI
)
last_beta
-=
2
.
0
*
PI
;
}
else
{
// Search in the opposite direction in the second iteration.
x
=
maxx
;
y
=
maxy
;
pos
=
(
int
)
LCOR
(
x
,
y
,
width
);
alpha
=
get_angle
(
normx
,
normy
,
pos
);
last_octant
=
(
int
)(
std
::
floor
(
4
.
0
/
PI
*
alpha
+
0
.
5
))
%
4
+
4
;
last_beta
=
alpha
+
PI
/
2
.
0
;
if
(
last_beta
>=
2
.
0
*
PI
)
last_beta
-=
2
.
0
*
PI
;
}
if
(
it
==
2
)
{
// Sort the points found in the first iteration in reverse.
std
::
reverse
(
row
.
begin
(),
row
.
end
());
std
::
reverse
(
col
.
begin
(),
col
.
end
());
std
::
reverse
(
angle
.
begin
(),
angle
.
end
());
std
::
reverse
(
resp
.
begin
(),
resp
.
end
());
}
// Now start adding appropriate neighbors to the line.
for
(;;)
{
pos
=
(
int
)
LCOR
(
x
,
y
,
width
);
px
=
posx
[
pos
];
py
=
posy
[
pos
];
// Orient line direction w.r.t. the last line direction.
alpha
=
get_angle
(
normx
,
normy
,
pos
);
octant
=
(
int
)(
std
::
floor
(
4
.
0
/
PI
*
alpha
+
0
.
5
))
%
4
;
switch
(
octant
)
{
case
0
:
if
(
last_octant
>=
3
&&
last_octant
<=
5
)
octant
=
4
;
break
;
case
1
:
if
(
last_octant
>=
4
&&
last_octant
<=
6
)
octant
=
5
;
break
;
case
2
:
if
(
last_octant
>=
4
&&
last_octant
<=
7
)
octant
=
6
;
break
;
case
3
:
if
(
last_octant
==
0
||
last_octant
>=
6
)
octant
=
7
;
break
;
}
last_octant
=
octant
;
// Determine appropriate neighbor.
nextismax
=
false
;
nexti
=
1
;
mindiff
=
std
::
numeric_limits
<
double
>::
max
();
for
(
i
=
0
;
i
<
3
;
i
++
)
{
nextx
=
x
+
dirtab
[
octant
][
i
][
0
];
nexty
=
y
+
dirtab
[
octant
][
i
][
1
];
if
(
nextx
<
0
||
nextx
>=
height
||
nexty
<
0
||
nexty
>=
width
)
continue
;
nextpos
=
(
int
)
LCOR
(
nextx
,
nexty
,
width
);
if
(
ismax
[
nextpos
]
==
0
)
continue
;
nextpx
=
posx
[
nextpos
];
nextpy
=
posy
[
nextpos
];
dx
=
nextpx
-
px
;
dy
=
nextpy
-
py
;
dist
=
std
::
sqrt
(
dx
*
dx
+
dy
*
dy
);
nextalpha
=
get_angle
(
normx
,
normy
,
nextpos
);
diff
=
std
::
abs
(
alpha
-
nextalpha
);
if
(
diff
>=
PI
/
2
.
0
)
diff
=
PI
-
diff
;
diff
=
dist
+
diff
;
if
(
diff
<
mindiff
)
{
mindiff
=
diff
;
nexti
=
i
;
}
if
(
!
ismax
[
nextpos
]
==
0
)
nextismax
=
true
;
}
// Mark double responses as processed.
for
(
i
=
0
;
i
<
2
;
i
++
)
{
nextx
=
x
+
cleartab
[
octant
][
i
][
0
];
nexty
=
y
+
cleartab
[
octant
][
i
][
1
];
if
(
nextx
<
0
||
nextx
>=
height
||
nexty
<
0
||
nexty
>=
width
)
continue
;
nextpos
=
(
int
)
LCOR
(
nextx
,
nexty
,
width
);
if
(
ismax
[
nextpos
]
>
0
)
{
nextalpha
=
get_angle
(
normx
,
normy
,
nextpos
);
diff
=
std
::
abs
(
alpha
-
nextalpha
);
if
(
diff
>=
PI
/
2
.
0
)
diff
=
PI
-
diff
;
if
(
diff
<
MAX_ANGLE_DIFFERENCE
)
{
label
[
nextpos
]
=
(
short
)(
num_cont
+
1
);
if
(
indx
[
nextpos
]
!=
0
)
cross
[
indx
[
nextpos
]
-
1
].
setDone
();
}
}
}
// Have we found the end of the line?
if
(
!
nextismax
)
break
;
// If not, add the neighbor to the line.
x
+=
dirtab
[
octant
][
nexti
][
0
];
y
+=
dirtab
[
octant
][
nexti
][
1
];
pos
=
(
int
)
LCOR
(
x
,
y
,
width
);
row
.
push_back
((
float
)
posx
[
pos
]);
col
.
push_back
((
float
)
posy
[
pos
]);
// Orient normal to the line direction w.r.t. the last normal.
beta
=
get_angle
(
normx
,
normy
,
pos
);
diff1
=
std
::
abs
(
beta
-
last_beta
);
if
(
diff1
>=
PI
)
diff1
=
2
.
0
*
PI
-
diff1
;
diff2
=
std
::
abs
(
beta
+
PI
-
last_beta
);
if
(
diff2
>=
PI
)
diff2
=
2
.
0
*
PI
-
diff2
;
if
(
diff1
<
diff2
)
{
angle
.
push_back
((
float
)
beta
);
last_beta
=
beta
;
}
else
{
angle
.
push_back
((
float
)(
beta
+
PI
));
last_beta
=
beta
+
PI
;
}
resp
.
push_back
((
float
)
interpolate_response
(
eigval
,
x
,
y
,
posx
[
pos
],
posy
[
pos
],
width
,
height
));
num_pnt
++
;
// If the appropriate neighbor is already processed a junction point is found.
if
(
label
[
pos
]
>
0
)
{
// Look for the junction point in the other line.
k
=
label
[
pos
]
-
1
;
if
(
k
==
num_cont
)
{
// Line intersects itself.
for
(
j
=
0
;
j
<
num_pnt
-
1
;
j
++
)
{
if
(
row
[
j
]
==
posx
[
pos
]
&&
col
[
j
]
==
posy
[
pos
])
{
if
(
j
==
0
)
{
// Contour is closed.
cls
=
contour_class
::
cont_closed
;
std
::
reverse
(
row
.
begin
(),
row
.
end
());
std
::
reverse
(
col
.
begin
(),
col
.
end
());
std
::
reverse
(
angle
.
begin
(),
angle
.
end
());
std
::
reverse
(
resp
.
begin
(),
resp
.
end
());
it
=
2
;
}
else
{
if
(
it
==
2
)
{
// Determine contour class.
if
(
cls
==
contour_class
::
cont_start_junc
)
cls
=
contour_class
::
cont_both_junc
;
else
cls
=
contour_class
::
cont_end_junc
;
// Index j is the correct index.
junc
.
emplace_back
(
num_cont
,
num_cont
,
j
,
(
float
)
posx
[
pos
],
(
float
)
posy
[
pos
]);
num_junc
++
;
}
else
{
// Determine contour class.
cls
=
contour_class
::
cont_start_junc
;
// Index num_pnt-1-j is the correct index since the line
// is going to be sorted in reverse.
junc
.
emplace_back
(
num_cont
,
num_cont
,
num_pnt
-
1
-
j
,
(
float
)
posx
[
pos
],
(
float
)
posy
[
pos
]);
num_junc
++
;
}
}
break
;
}
}
// Mark this case as being processed for the algorithm below.
j
=
-
1
;
}
else
{
for
(
j
=
0
;
j
<
cont
[
k
].
num
;
j
++
)
{
if
(
cont
[
k
].
row
[
j
]
==
posx
[
pos
]
&&
cont
[
k
].
col
[
j
]
==
posy
[
pos
])
break
;
mindist
=
std
::
sqrt
(
std
::
pow
(
cont
[
k
].
row
[
j
]
-
posx
[
pos
],
2
)
+
std
::
pow
(
cont
[
k
].
col
[
j
]
-
posy
[
pos
],
2
));
if
(
mindist
<
0
.
00001
)
break
;
}
// If no point can be found on the other line a double response
// must have occured. In this case, find the nearest point on
// the other line and add it to the current line.
if
(
j
==
cont
[
k
].
num
)
{
mindist
=
std
::
numeric_limits
<
double
>::
max
();
j
=
-
1
;
for
(
l
=
0
;
l
<
cont
[
k
].
num
;
l
++
)
{
dx
=
posx
[
pos
]
-
cont
[
k
].
row
[
l
];
dy
=
posy
[
pos
]
-
cont
[
k
].
col
[
l
];
dist
=
std
::
sqrt
(
dx
*
dx
+
dy
*
dy
);
if
(
dist
<
mindist
)
{
mindist
=
dist
;
j
=
l
;
}
}
// Add the point with index j to the current line.
row
.
push_back
(
cont
[
k
].
row
[
j
]);
col
.
push_back
(
cont
[
k
].
col
[
j
]);
beta
=
cont
[
k
].
angle
[
j
];
if
(
beta
>=
PI
)
beta
-=
PI
;
diff1
=
std
::
abs
(
beta
-
last_beta
);
if
(
diff1
>=
PI
)
diff1
=
2
.
0
*
PI
-
diff1
;
diff2
=
std
::
abs
(
beta
+
PI
-
last_beta
);
if
(
diff2
>=
PI
)
diff2
=
2
.
0
*
PI
-
diff2
;
if
(
diff1
<
diff2
)
angle
.
push_back
((
float
)
beta
);
else
angle
.
push_back
((
float
)(
beta
+
PI
));
resp
.
push_back
(
cont
[
k
].
response
[
j
]);
num_pnt
++
;
}
}
// Add the junction point only if it is not one of the other line's
// endpoints.
if
(
j
>
0
&&
j
<
cont
[
k
].
num
-
1
)
{
// Determine contour class.
if
(
it
==
1
)
cls
=
contour_class
::
cont_start_junc
;
else
if
(
cls
==
contour_class
::
cont_start_junc
)
cls
=
contour_class
::
cont_both_junc
;
else
cls
=
contour_class
::
cont_end_junc
;
// Add the new junction.
junc
.
emplace_back
(
k
,
num_cont
,
j
,
row
[(
int
)(
num_pnt
-
1
)],
col
[(
int
)(
num_pnt
-
1
)]);
num_junc
++
;
}
break
;
}
label
[
pos
]
=
(
short
)(
num_cont
+
1
);
if
(
indx
[
pos
]
!=
0
)
cross
[(
int
)(
indx
[
pos
]
-
1
)].
setDone
();
}
}
if
(
num_pnt
>
1
)
{
// Only add lines with at least two points.
cont
.
emplace_back
(
num_pnt
,
row
,
col
,
angle
,
resp
,
cls
);
num_cont
++
;
}
else
{
// Delete the point from the label image; we can use maxx and maxy
// as the coordinates in the label image in this case.
for
(
i
=
-
1
;
i
<=
1
;
i
++
)
{
for
(
j
=
-
1
;
j
<=
1
;
j
++
)
{
pos
=
(
int
)
LCOR
(
BR
(
maxx
+
i
,
height
),
BC
(
maxy
+
j
,
width
),
width
);
if
(
label
[
pos
]
==
num_cont
+
1
)
label
[
pos
]
=
0
;
}
}
}
}
// Now try to extend the lines at their ends to find additional junctions.
bool
extend_lines
=
true
;
if
(
extend_lines
)
{
// Sign by which the gradient has to be multiplied below.
s
=
polarity
==
line_polarity
::
light
?
1
:
-
1
;
length
=
MAX_LINE_EXTENSION
;
auto
max_line
=
(
int
)
ceil
(
length
*
3
);
std
::
vector
<
offset
>
line
(
max_line
);
std
::
vector
<
float
>
extx
(
max_line
);
std
::
vector
<
float
>
exty
(
max_line
);
for
(
i
=
0
;
i
<
num_cont
;
i
++
)
{
tmp_cont
=
cont
[
i
];
num_pnt
=
tmp_cont
.
num
;
if
(
num_pnt
==
1
)
continue
;
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_closed
)
continue
;
trow
=
tmp_cont
.
row
;
tcol
=
tmp_cont
.
col
;
tangle
=
tmp_cont
.
angle
;
tresp
=
tmp_cont
.
response
;
// Check both ends of the line (it==-1: start, it==1: end).
for
(
it
=
-
1
;
it
<=
1
;
it
+=
2
)
{
// Determine the direction of the search line. This is done by using
// the normal to the line (angle). Since this normal may point to
// the left of the line (see below) we have to check for this case by
// comparing the normal to the direction of the line at its respective
// end point.
if
(
it
==
-
1
)
{
// Start point of the line.
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_start_junc
||
tmp_cont
.
cont_class
==
contour_class
::
cont_both_junc
)
continue
;
dx
=
trow
[
1
]
-
trow
[
0
];
dy
=
tcol
[
1
]
-
tcol
[
0
];
alpha
=
tangle
[
0
];
nx
=
std
::
cos
(
alpha
);
ny
=
std
::
sin
(
alpha
);
if
(
nx
*
dy
-
ny
*
dx
<
0
)
{
// Turn the normal by +90 degrees.
mx
=
-
ny
;
my
=
nx
;
}
else
{
// Turn the normal by -90 degrees.
mx
=
ny
;
my
=
-
nx
;
}
px
=
trow
[
0
];
py
=
tcol
[
0
];
response
=
tresp
[
0
];
}
else
{
// End point of the line.
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_end_junc
||
tmp_cont
.
cont_class
==
contour_class
::
cont_both_junc
)
continue
;
dx
=
trow
[(
int
)(
num_pnt
-
1
)]
-
trow
[(
int
)(
num_pnt
-
2
)];
dy
=
tcol
[(
int
)(
num_pnt
-
1
)]
-
tcol
[(
int
)(
num_pnt
-
2
)];
alpha
=
tangle
[(
int
)(
num_pnt
-
1
)];
nx
=
std
::
cos
(
alpha
);
ny
=
std
::
sin
(
alpha
);
if
(
nx
*
dy
-
ny
*
dx
<
0
)
{
// Turn the normal by -90 degrees.
mx
=
ny
;
my
=
-
nx
;
}
else
{
// Turn the normal by +90 degrees.
mx
=
-
ny
;
my
=
nx
;
}
px
=
trow
[(
int
)(
num_pnt
-
1
)];
py
=
tcol
[(
int
)(
num_pnt
-
1
)];
response
=
tresp
[(
int
)(
num_pnt
-
1
)];
}
// Determine the current pixel and calculate the pixels on the search line.
x
=
(
long
)
std
::
floor
(
px
+
0
.
5
);
y
=
(
long
)
std
::
floor
(
py
+
0
.
5
);
dx
=
px
-
x
;
dy
=
py
-
y
;
bresenham
(
mx
,
my
,
dx
,
dy
,
length
,
line
);
// Now determine whether we can go only uphill (bright lines) or
// downhill (dark lines) until we hit another line.
num_add
=
0
;
add_ext
=
false
;
for
(
k
=
0
;
k
<
line
.
size
();
k
++
)
{
nextx
=
x
+
line
[
k
].
x
;
nexty
=
y
+
line
[
k
].
y
;
doublepoint
closestpnt
;
closest_point
(
px
,
py
,
mx
,
my
,
(
double
)
nextx
,
(
double
)
nexty
,
closestpnt
);
nextpx
=
closestpnt
.
cx
;
nextpy
=
closestpnt
.
cy
;
t
=
closestpnt
.
t
;
// Ignore points before or less than half a pixel away from the
// true end point of the line.
if
(
t
<=
0
.
5
)
continue
;
// Stop if the gradient can't be interpolated any more or if the
// next point lies outside the image.
if
(
nextpx
<
0
||
nextpy
<
0
||
nextpx
>=
height
-
1
||
nextpy
>=
width
-
1
||
nextx
<
0
||
nexty
<
0
||
nextx
>=
height
||
nexty
>=
width
)
break
;
doublepoint
interpoint
;
interpolate_gradient
(
gradx
,
grady
,
nextpx
,
nextpy
,
interpoint
,
width
,
height
);
gx
=
interpoint
.
cx
;
gy
=
interpoint
.
cy
;
// Stop if we can't go uphill anymore. This is determined by the
// dot product of the line direction and the gradient. If it is
// smaller than 0 we go downhill (reverse for dark lines).
nextpos
=
(
int
)
LCOR
(
nextx
,
nexty
,
width
);
if
(
s
*
(
mx
*
gx
+
my
*
gy
)
<
0
&&
label
[
nextpos
]
==
0
)
break
;
// Have we hit another line?
if
(
label
[
nextpos
]
>
0
)
{
m
=
label
[
nextpos
]
-
1
;
// Search for the junction point on the other line.
mindist
=
std
::
numeric_limits
<
double
>::
max
();
j
=
-
1
;
for
(
l
=
0
;
l
<
cont
[
m
].
num
;
l
++
)
{
dx
=
nextpx
-
cont
[
m
].
row
[
l
];
dy
=
nextpy
-
cont
[
m
].
col
[
l
];
dist
=
std
::
sqrt
(
dx
*
dx
+
dy
*
dy
);
if
(
dist
<
mindist
)
{
mindist
=
dist
;
j
=
l
;
}
}
// This should not happen... But better safe than sorry...
if
(
mindist
>
3
.
0
)
break
;
extx
.
push_back
(
cont
[
m
].
row
[
j
]);
exty
.
push_back
(
cont
[
m
].
col
[
j
]);
end_resp
=
cont
[
m
].
response
[
j
];
end_angle
=
cont
[
m
].
angle
[
j
];
beta
=
end_angle
;
if
(
beta
>=
PI
)
beta
-=
PI
;
diff1
=
std
::
abs
(
beta
-
alpha
);
if
(
diff1
>=
PI
)
diff1
=
2
.
0
*
PI
-
diff1
;
diff2
=
std
::
abs
(
beta
+
PI
-
alpha
);
if
(
diff2
>=
PI
)
diff2
=
2
.
0
*
PI
-
diff2
;
if
(
diff1
<
diff2
)
end_angle
=
beta
;
else
end_angle
=
beta
+
PI
;
num_add
++
;
/* if (DEBUG_show_extensions)
{
resolved_p = new OvalRoi(cont[m).col[j) - 0.25, cont[m).row[j) - 0.25, 0.5, 0.5);
resolved_p.setStrokeColor(Color.GREEN);
resolved_p.setPosition(nFrame + 1);
image_overlay.add(resolved_p);
imp.setOverlay(image_overlay);
imp.updateAndRepaintWindow();
imp.show();
}*/
add_ext
=
true
;
break
;
}
else
{
extx
.
push_back
((
float
)
nextpx
);
exty
.
push_back
((
float
)
nextpy
);
/* if (DEBUG_show_extensions)
{
resolved_p = new OvalRoi(nextpy - 0.25, nextpx - 0.25, 0.5, 0.5);
resolved_p.setStrokeColor(Color.GREEN);
resolved_p.setPosition(nFrame + 1);
image_overlay.add(resolved_p);
imp.setOverlay(image_overlay);
imp.updateAndRepaintWindow();
imp.show();
}*/
num_add
++
;
}
}
if
(
add_ext
)
{
// Make room for the new points.
num_pnt
+=
num_add
;
tmp_cont
.
row
=
trow
;
tmp_cont
.
col
=
tcol
;
tmp_cont
.
angle
=
tangle
;
tmp_cont
.
response
=
tresp
;
tmp_cont
.
num
=
num_pnt
;
if
(
it
==
-
1
)
{
// Move points on the line up num_add places.
// Insert points at the beginning of the line.
for
(
k
=
0
;
k
<
num_add
;
k
++
)
{
//cause order of insertion is different
trow
.
insert
(
trow
.
begin
(),
extx
[
k
]);
tcol
.
insert
(
tcol
.
begin
(),
exty
[
k
]);
tangle
.
insert
(
tangle
.
begin
(),
(
float
)
alpha
);
tresp
.
insert
(
tresp
.
begin
(),
(
float
)
response
);
}
tangle
[
0
]
=
(
float
)
end_angle
;
tresp
[
0
]
=
(
float
)
end_resp
;
// Adapt indices of the previously found junctions.
for
(
k
=
0
;
k
<
num_junc
;
k
++
)
{
if
(
junc
[
k
].
cont1
==
i
)
junc
[
k
].
pos
+=
num_add
;
}
}
else
{
// Insert points at the end of the line.
for
(
k
=
0
;
k
<
num_add
;
k
++
)
{
trow
.
push_back
(
extx
[
k
]);
tcol
.
push_back
(
exty
[
k
]);
tangle
.
push_back
((
float
)
alpha
);
tresp
.
push_back
((
float
)
response
);
}
tangle
[
num_pnt
-
1
]
=
(
float
)
end_angle
;
tresp
[
num_pnt
-
1
]
=
(
float
)
end_resp
;
}
// Add the junction point only if it is not one of the other line's
// endpoints.
if
(
j
>
0
&&
j
<
cont
[
m
].
num
-
1
)
{
if
(
it
==
-
1
)
{
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_end_junc
)
tmp_cont
.
cont_class
=
contour_class
::
cont_both_junc
;
else
tmp_cont
.
cont_class
=
contour_class
::
cont_start_junc
;
}
else
{
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_start_junc
)
tmp_cont
.
cont_class
=
contour_class
::
cont_both_junc
;
else
tmp_cont
.
cont_class
=
contour_class
::
cont_end_junc
;
}
junc
.
emplace_back
();
junc
[(
int
)
num_junc
].
cont1
=
m
;
junc
[(
int
)
num_junc
].
cont2
=
i
;
junc
[(
int
)
num_junc
].
pos
=
j
;
if
(
it
==
-
1
)
{
junc
[(
int
)
num_junc
].
x
=
trow
[
0
];
junc
[(
int
)
num_junc
].
y
=
tcol
[
0
];
}
else
{
junc
[(
int
)
num_junc
].
x
=
trow
[(
int
)(
num_pnt
-
1
)];
junc
[(
int
)
num_junc
].
y
=
tcol
[(
int
)(
num_pnt
-
1
)];
}
num_junc
++
;
}
}
}
}
}
// Done with linking. Now split the lines at the junction points.
sort
(
junc
.
begin
(),
junc
.
end
(),
std
::
greater
<
junction
>
());
m_junctions
=
junc
;
bool
split_lines
=
false
;
if
(
split_lines
)
{
for
(
i
=
0
;
i
<
num_junc
;
i
+=
k
)
{
j
=
(
int
)
junc
[
i
].
cont1
;
tmp_cont
=
cont
[
j
];
num_pnt
=
tmp_cont
.
num
;
// Count how often line j needs to be split.
auto
counter
=
0
;
for
(
auto
index
=
0
;
index
<
num_junc
;
index
++
)
{
if
((
i
+
k
)
<
num_junc
&&
junc
[(
i
+
k
)].
cont1
==
j
)
counter
++
;
}
if
(
counter
==
1
&&
tmp_cont
.
row
.
size
()
>
(
num_pnt
-
1
)
&&
tmp_cont
.
row
[
0
]
==
tmp_cont
.
row
[(
int
)(
num_pnt
-
1
)]
&&
tmp_cont
.
col
[
0
]
==
tmp_cont
.
col
[(
int
)(
num_pnt
-
1
)])
{
// If only one junction point is found and the line is closed it only
// needs to be rearranged cyclically, but not split.
begin
=
junc
[
i
].
pos
;
trow
=
tmp_cont
.
row
;
tcol
=
tmp_cont
.
col
;
tangle
=
tmp_cont
.
angle
;
tresp
=
tmp_cont
.
response
;
for
(
l
=
0
;
l
<
num_pnt
;
l
++
)
{
pos
=
(
int
)(
begin
+
l
);
// Skip starting point so that it is not added twice.
if
(
pos
>=
num_pnt
)
pos
=
(
int
)(
begin
+
l
-
num_pnt
+
1
);
tmp_cont
.
row
[
l
]
=
trow
[
pos
];
tmp_cont
.
col
[
l
]
=
tcol
[
pos
];
tmp_cont
.
angle
[
l
]
=
tangle
[
pos
];
tmp_cont
.
response
[
l
]
=
tresp
[
pos
];
}
// Modify contour class.
tmp_cont
.
cont_class
=
contour_class
::
cont_both_junc
;
}
else
{
// Otherwise the line has to be split.
for
(
l
=
0
;
l
<=
counter
;
l
++
)
{
begin
=
(
l
==
0
)
?
0
:
junc
[
i
+
l
-
1
].
pos
;
end
=
(
l
==
counter
)
?
(
tmp_cont
.
num
-
1
)
:
(
l
!=
counter
&&
(
i
+
l
)
>
0
)
?
junc
[
i
+
l
].
pos
:
0
;
if
(
end
==
begin
&&
counter
>
1
)
continue
;
#if 1
cont
.
emplace_back
();
//till begin+num_pnt, since last index is exclusive in subList function
cont
[
num_cont
].
row
=
std
::
vector
<
float
>
(
tmp_cont
.
row
.
begin
(),
tmp_cont
.
row
.
begin
()
+
num_pnt
);
cont
[
num_cont
].
col
=
std
::
vector
<
float
>
(
tmp_cont
.
col
.
begin
(),
tmp_cont
.
col
.
begin
()
+
num_pnt
);
cont
[
num_cont
].
angle
=
std
::
vector
<
float
>
(
tmp_cont
.
angle
.
begin
(),
tmp_cont
.
angle
.
begin
()
+
num_pnt
);
cont
[
num_cont
].
response
=
std
::
vector
<
float
>
(
tmp_cont
.
response
.
begin
(),
tmp_cont
.
response
.
begin
()
+
num_pnt
);
cont
[
num_cont
].
num
=
num_pnt
;
#endif
// Modify contour class.
if
(
l
==
0
)
{
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_start_junc
||
tmp_cont
.
cont_class
==
contour_class
::
cont_both_junc
)
cont
[(
int
)
num_cont
].
cont_class
=
contour_class
::
cont_both_junc
;
else
cont
[(
int
)
num_cont
].
cont_class
=
contour_class
::
cont_end_junc
;
}
else
if
(
l
==
counter
)
{
if
(
tmp_cont
.
cont_class
==
contour_class
::
cont_end_junc
||
tmp_cont
.
cont_class
==
contour_class
::
cont_both_junc
)
cont
[(
int
)
num_cont
].
cont_class
=
contour_class
::
cont_both_junc
;
else
cont
[(
int
)
num_cont
].
cont_class
=
contour_class
::
cont_start_junc
;
}
/* else {
cont[(int)num_cont].cont_class = contour_class::cont_both_junc;
}
num_cont++;
}
cont[j] = cont[--num_cont]; */
}
}
}
}
// Finally, check whether all angles point to the right of the line.
for
(
i
=
0
;
i
<
num_cont
;
i
++
)
{
tmp_cont
=
cont
[
i
];
if
(
tmp_cont
.
row
.
empty
())
continue
;
num_pnt
=
tmp_cont
.
num
;
trow
=
tmp_cont
.
row
;
tcol
=
tmp_cont
.
col
;
tangle
=
tmp_cont
.
angle
;
// One point of the contour is enough to determine the orientation.
k
=
(
int
)((
num_pnt
-
1
)
/
2
);
if
(
k
==
0
||
trow
.
size
()
==
1
||
k
>
(
trow
.
size
()
-
2
))
continue
;
// The next few lines are ok because lines have at least two points.
dx
=
trow
[
k
+
1
]
-
trow
[
k
];
dy
=
tcol
[
k
+
1
]
-
tcol
[
k
];
nx
=
std
::
cos
(
tangle
[
k
]);
ny
=
std
::
sin
(
tangle
[
k
]);
// If the angles point to the left of the line they have to be adapted.
// The orientation is determined by looking at the z-component of the
// cross-product of (dx,dy,0) and (nx,ny,0).
if
(
nx
*
dy
-
ny
*
dx
<
0
)
{
for
(
j
=
0
;
j
<
num_pnt
;
j
++
)
{
tangle
[
j
]
=
(
float
)(
tangle
[
j
]
+
PI
);
if
(
tangle
[
j
]
>=
2
*
PI
)
tangle
[
j
]
=
(
float
)(
tangle
[
j
]
-
2
*
PI
);
}
}
}
//Remove lines with number of points less than threshold
m_results
.
resize
(
0
);
int
min_node_count
=
5
;
int
nMinNumberOfNodes
=
min_node_count
;
for
(
auto
cc
=
0
;
cc
<
cont
.
size
();
cc
++
)
{
const
contour
&
ct
=
cont
[
cc
];
auto
len
=
ct
.
compute_length
();
if
(
nMinNumberOfNodes
>
0
&&
len
<
nMinNumberOfNodes
)
continue
;
auto
min_row
=
std
::
min_element
(
ct
.
row
.
begin
(),
ct
.
row
.
end
());
if
(
signbit
(
*
min_row
))
continue
;
auto
min_col
=
std
::
min_element
(
ct
.
col
.
begin
(),
ct
.
col
.
end
());
if
(
signbit
(
*
min_col
))
continue
;
m_results
.
emplace_back
(
ct
);
}
return
m_results
;
}
#endif
/* __EYEM_EDGE1D_H */
\ No newline at end of file
eyemLib/eyemLib.h
查看文件 @
547390f
...
...
@@ -102,6 +102,46 @@
typedef
intptr_t
IntPtr
;
#endif
typedef
unsigned
int
CvLabel
;
typedef
std
::
map
<
CvLabel
,
cv
::
Scalar
>
Palete
;
/// \def _HSV2RGB_(H, S, V, R, G, B)
/// \brief Color translation between HSV and RGB.
#define _HSV2RGB_(H, S, V, R, G, B) \
{ \
double _h = H/60.; \
int _hf = (int)floor(_h); \
int _hi = ((int)_h)%6; \
double _f = _h - _hf; \
\
double _p = V * (1. - S); \
double _q = V * (1. - _f * S); \
double _t = V * (1. - (1. - _f) * S); \
\
switch (_hi) \
{ \
case 0: \
R = 255.*V; G = 255.*_t; B = 255.*_p; \
break; \
case 1: \
R = 255.*_q; G = 255.*V; B = 255.*_p; \
break; \
case 2: \
R = 255.*_p; G = 255.*V; B = 255.*_t; \
break; \
case 3: \
R = 255.*_p; G = 255.*_q; B = 255.*V; \
break; \
case 4: \
R = 255.*_t; G = 255.*_p; B = 255.*V; \
break; \
case 5: \
R = 255.*V; G = 255.*_p; B = 255.*_q; \
break; \
} \
}
// 图像边界处理
#ifndef __EYEM_BORDER
...
...
@@ -149,6 +189,14 @@ typedef struct {
double
dVar
;
// 可能会使用的值
}
EyemRect3
;
// 旋转矩形定义
typedef
struct
{
double
dWidth
;
// 旋转矩形宽度
double
dHeight
;
// 旋转矩形高度
double
dAngle
;
// 旋转矩形角度(-90==>90)
EyemOcsDXY
tC
;
// 旋转矩形中心
}
EyemRotateRect
;
///////////////////////////////////////////////////////////////////////////////
// Orthogonal Coordinate System
...
...
@@ -621,6 +669,7 @@ extern "C" {
EXPORTS
int
eyemEdge1dGenPosRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
IntPtr
*
hObject
);
EXPORTS
int
eyemEdge1dFindCircle
(
EyemImage
tpImage
,
EyemOcsDXY
tpPoint
,
int
iRadius
,
int
iCapLength
,
int
iCapWidth
,
int
nCalipers
,
int
nFilterSize
,
int
iSearchDirec
,
double
dAmpThreshold
,
const
char
*
ccTransition
,
IntPtr
*
hObject
);
EXPORTS
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iCapLength
,
int
iCapWidth
,
int
nCalipers
,
int
iFilterSize
,
int
iSearchDirec
,
double
dAmpThreshold
,
const
char
*
ccTransition
,
IntPtr
*
hObject
);
EXPORTS
int
eyemEdge1dRidgeDetection
(
EyemImage
tpImage
);
EXPORTS
bool
eyemEdge1dGenMeasureFree
(
IntPtr
hObject
);
#ifdef __cplusplus
...
...
eyemLib/eyemLib.rc
查看文件 @
547390f
此文件类型无法预览
eyemLib/eyemLib.vcxproj
查看文件 @
547390f
...
...
@@ -182,6 +182,7 @@
<ClInclude Include="eyemSmooth.h" />
<ClInclude Include="eyemCodeDetector.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stegers.h" />
<ClInclude Include="yoloWrapper.h" />
</ItemGroup>
<ItemGroup>
...
...
@@ -205,6 +206,7 @@
<ClCompile Include="eyemSmooth.cpp" />
<ClCompile Include="eyemCodeDetector.cpp" />
<ClCompile Include="libopencv.cpp" />
<ClCompile Include="stegers.cpp" />
<ClCompile Include="yoloWrapper.cpp" />
</ItemGroup>
<ItemGroup>
...
...
eyemLib/eyemLib.vcxproj.filters
查看文件 @
547390f
...
...
@@ -69,6 +69,9 @@
<ClInclude Include="eyemNNDetector.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="stegers.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="eyemLib.cpp">
...
...
@@ -134,6 +137,9 @@
<ClCompile Include="eyemNNDetector.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="stegers.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="eyemLib.rc">
...
...
eyemLib/eyemMat.cpp
查看文件 @
547390f
...
...
@@ -617,6 +617,16 @@ int eyemDecompose(EyemImage tpImage, EyemImage *tpDstImgR, EyemImage *tpDstImgG,
return
FUNC_OK
;
}
int
eyemCopyRegion
(
EyemImage
tpImage
,
EyemRotateRect
tpRoi
,
EyemImage
*
tpDstImg
)
{
CV_Assert
(
NULL
!=
tpImage
.
vpImage
);
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
return
FUNC_OK
;
}
int
eyemNormalize
(
EyemImage
&
tpImage
)
{
CV_Assert
(
NULL
!=
tpImage
.
vpImage
);
...
...
eyemLib/eyemMisc.cpp
查看文件 @
547390f
...
...
@@ -1887,6 +1887,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
contourAll
.
resize
(
0
);
findContours
(
image
,
contourAll
,
cv
::
noArray
(),
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_SIMPLE
);
if
(
contourAll
.
empty
())
{
return
FUNC_CANNOT_CALC
;
}
//寻找最大轮廓
contourMax
=
contourAll
[
0
];
contourMaxArea
=
cv
::
contourArea
(
contourMax
);
for
(
int
i
=
1
;
i
<
contourAll
.
size
();
i
++
)
...
...
@@ -2105,6 +2109,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv
::
drawContours
(
image
,
contoursFilter
,
i
,
cv
::
Scalar
(
255
),
-
1
);
}
image
-=
srcPrevEx0
;
//2021/08/26增加测试用
cv
::
morphologyEx
(
image
,
image
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
45
,
45
)));
//获取最大轮廓
cv
::
findContours
(
image
,
contoursFilter
,
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_NONE
);
if
(
contoursFilter
.
size
()
<=
0
)
...
...
@@ -2487,6 +2494,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
}
if
(
_tplMat
.
cols
>
_traceMat
.
cols
||
_tplMat
.
rows
>
_traceMat
.
rows
)
{
return
FUNC_CANNOT_CALC
;
}
//考虑并行计算两个模板结果
cv
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
...
...
@@ -2826,6 +2836,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
}
if
(
_tplMat
.
cols
>
_traceMat
.
cols
||
_tplMat
.
rows
>
_traceMat
.
rows
)
{
return
FUNC_CANNOT_CALC
;
}
//考虑并行计算两个模板结果
cv
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
...
...
@@ -3185,6 +3198,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv
::
drawContours
(
image
,
contoursFilter
,
i
,
cv
::
Scalar
(
255
),
-
1
);
}
image
-=
srcPrevEx0
;
//2021/08/26增加测试用
cv
::
morphologyEx
(
image
,
image
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
45
,
45
)));
//获取最大轮廓
cv
::
findContours
(
image
,
contoursFilter
,
cv
::
RETR_EXTERNAL
,
cv
::
CHAIN_APPROX_NONE
);
if
(
contoursFilter
.
size
()
<=
0
)
...
...
@@ -4108,7 +4124,153 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
else
if
(
strcmp
(
ccSubType
,
"IP_SQUARE_PARTS"
)
==
0
)
{
//TODO:
//二值化
cv
::
threshold
(
srcPrev
,
binary
,
0
,
255
,
cv
::
THRESH_BINARY
|
cv
::
THRESH_OTSU
);
cv
::
morphologyEx
(
binary
,
binary
,
cv
::
MORPH_CLOSE
,
cv
::
getStructuringElement
(
cv
::
MORPH_RECT
,
cv
::
Size
(
75
,
75
)));
//计算直方图
int
hist_
[
256
];
for
(
int
y
=
0
;
y
<
256
;
y
++
)
hist_
[
y
]
=
0
;
for
(
int
y
=
0
;
y
<
Y
;
y
++
)
{
uchar
*
uPtr
=
srcPrev
.
data
+
y
*
X
;
for
(
int
x
=
0
;
x
<
srcPrev
.
cols
;
x
++
,
uPtr
++
)
{
if
(
binary
.
ptr
<
uint8_t
>
(
y
)[
x
]
==
255
)
{
hist_
[
*
uPtr
]
++
;
}
}
}
cv
::
threshold
(
srcPrev
,
binary
,
Otsu
(
hist_
),
255
,
cv
::
THRESH_BINARY
);
//计算元件大小
cv
::
Mat
m1
,
m2
,
m3
;
int
nccomps
=
cv
::
connectedComponentsWithStats
(
binary
,
m1
,
m2
,
m3
);
std
::
vector
<
uchar
>
colors0
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors0
[
i
]
=
255
;
if
((((
int
*
)
m2
.
data
)[(
cv
::
CC_STAT_AREA
)
+
(
i
)
*
m2
.
cols
]
<=
2
))
//经验值
{
colors0
[
i
]
=
0
;
}
}
//认为是干扰
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
&
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
for
(
int
x
=
0
;
x
<
X
;
x
++
)
{
int
label
=
((
int
*
)
m1
.
data
)[(
x
)
+
(
y
)
*
m1
.
cols
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
(
binary
.
data
)[(
x
)
+
(
y
)
*
X
]
=
colors0
[
label
];
}
}
});
nccomps
=
cv
::
connectedComponentsWithStats
(
binary
,
m1
,
m2
,
m3
,
4
);
//
if
(
nccomps
<=
1
)
return
FUNC_CANNOT_CALC
;
//统计元件面积
std
::
vector
<
int
>
vHist
(
nccomps
);
for
(
int
y
=
0
;
y
<
Y
;
y
++
)
{
int
*
uPtr
=
(
int
*
)
m1
.
data
+
y
*
X
;
for
(
int
x
=
0
;
x
<
X
;
x
++
,
uPtr
++
)
{
vHist
[
*
uPtr
]
++
;
}
}
//统计面积个数
std
::
map
<
int
,
int
>
cAreaMap
;
for
(
const
auto
&
v
:
vHist
)
{
std
::
map
<
int
,
int
>::
iterator
it
=
cAreaMap
.
find
(
v
);
if
(
it
!=
cAreaMap
.
end
())
{
it
->
second
++
;
continue
;
}
else
{
cAreaMap
.
insert
(
std
::
make_pair
(
v
,
1
));
};
}
struct
tMap
{
int
Key
;
int
Value
;
tMap
(
int
Key
,
int
Value
)
:
Key
(
Key
),
Value
(
Value
)
{}
bool
operator
>
(
const
tMap
&
te
)
const
{
return
Value
>
te
.
Value
;
}
};
//获得单个元器件面积(准确性待测试,假定不粘连占大多数!)
std
::
vector
<
tMap
>
tVector
;
std
::
map
<
int
,
int
>::
iterator
it
;
for
(
it
=
cAreaMap
.
begin
();
it
!=
cAreaMap
.
end
();
it
++
)
{
tVector
.
push_back
(
tMap
(
it
->
first
,
it
->
second
));
}
std
::
sort
(
tVector
.
begin
(),
tVector
.
end
(),
std
::
greater
<
tMap
>
());
if
(
tVector
.
size
()
<
2
)
{
return
false
;
}
//单个元件面积
int
sinPartSize
=
cvRound
((
tVector
[
0
].
Key
+
tVector
[
1
].
Key
)
/
2.
);
std
::
vector
<
uchar
>
colors
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors
[
i
]
=
255
;
if
((((
int
*
)
m2
.
data
)[(
cv
::
CC_STAT_AREA
)
+
(
i
)
*
m2
.
cols
]
>=
1.35
*
sinPartSize
)
||
(((
int
*
)
m2
.
data
)[(
cv
::
CC_STAT_AREA
)
+
(
i
)
*
m2
.
cols
]
<
0.45
*
sinPartSize
))
//经验值
{
colors
[
i
]
=
0
;
}
}
std
::
vector
<
int
>
trayCount
(
nccomps
+
1
,
0
);
Palete
pal
;
unsigned
int
colorCount
=
0
;
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colorCount
=
cvRound
((
float
)
m2
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_AREA
]
/
(
float
)
sinPartSize
);
CvLabel
_label
=
i
;
double
r
,
g
,
b
;
if
(
!
colors
[
_label
]
==
0
)
{
_HSV2RGB_
((
double
)((
colorCount
*
77
)
%
360
),
1.
,
1.
,
r
,
g
,
b
);
}
else
{
_HSV2RGB_
((
double
)(((
colorCount
+
2
)
*
77
)
%
360
),
1.
,
.5
,
r
,
g
,
b
);
}
pal
[
_label
]
=
CV_RGB
(
r
,
g
,
b
);
trayCount
[
_label
]
=
colorCount
;
}
//认为是粘连
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
*
)
m1
.
data
)[(
x
)
+
(
y
)
*
m1
.
cols
];
CV_Assert
(
0
<=
label
&&
label
<=
nccomps
);
if
(
binary
.
ptr
<
uint8_t
>
(
y
)[
x
])
{
cc
.
ptr
<
cv
::
Vec4b
>
(
y
)[
x
]
=
cv
::
Vec4b
((
uchar
)
pal
[
label
].
val
[
0
],
(
uchar
)
pal
[
label
].
val
[
1
],
(
uchar
)
pal
[
label
].
val
[
2
],
255
);
}
binary
.
ptr
<
uint8_t
>
(
y
)[
x
]
=
colors
[
label
];
}
}
});
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
CvLabel
_label
=
i
;
if
(
trayCount
[
_label
]
!=
1
)
{
cv
::
putText
(
cc
,
std
::
to_string
(
trayCount
[
_label
]),
cv
::
Point
(
cvRound
(
m3
.
ptr
<
double
>
(
i
)[
0
]),
cvRound
(
m3
.
ptr
<
double
>
(
i
)[
1
])),
cv
::
FONT_HERSHEY_PLAIN
,
1
,
cv
::
Scalar
(
0
,
0
,
255
,
255
),
1
);
}
}
//计数
int
totalCount
=
std
::
accumulate
(
trayCount
.
begin
(),
trayCount
.
end
(),
0
);
//画图显示
std
::
string
text
=
"Reel Number = "
+
std
::
to_string
(
totalCount
);
cv
::
putText
(
cc
,
text
,
cv
::
Point
(
35
,
35
),
0
,
1.0
,
cv
::
Scalar
(
0
,
140
,
255
,
255
),
2
);
//标记
binary
=
cv
::
Scalar
(
0
);
for
(
int
t
=
0
;
t
<
totalCount
;
t
++
)
{
binary
.
ptr
<
uint8_t
>
(
0
)[
t
]
=
255
;
}
}
else
if
(
strcmp
(
ccSubType
,
"IP_DYNAMIC_PARTS"
)
==
0
)
{
...
...
@@ -4303,7 +4465,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
}
}
}
//计数
std
::
vector
<
cv
::
Point
>
idx
;
cv
::
findNonZero
(
binary
,
idx
);
...
...
@@ -4315,25 +4476,24 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//<输出结果
const
int
SizeConst
=
4
;
//<输出计数结果标记图像
{
memset
(
ipReelNum
,
0
,
SizeConst
);
memset
(
ipReelNum
,
0
,
SizeConst
);
ipReelNum
[
0
]
=
trayNum
;
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
();
//内存尺寸
int
_Size
=
tpDstImg
->
iWidth
*
tpDstImg
->
iHeight
*
tpDstImg
->
iChannels
*
sizeof
(
uint8_t
);
//内存尺寸
int
_Size
=
tpDstImg
->
iWidth
*
tpDstImg
->
iHeight
*
tpDstImg
->
iChannels
*
sizeof
(
uint8_t
);
//分配/初始化内存
tpDstImg
->
vpImage
=
(
uint8_t
*
)
malloc
(
_Size
);
if
(
NULL
==
tpDstImg
->
vpImage
)
return
FUNC_NOT_ENOUGH_MEM
;
memset
(
tpDstImg
->
vpImage
,
0
,
_Size
);
//分配/初始化内存
tpDstImg
->
vpImage
=
(
uint8_t
*
)
malloc
(
_Size
);
if
(
NULL
==
tpDstImg
->
vpImage
)
return
FUNC_NOT_ENOUGH_MEM
;
memset
(
tpDstImg
->
vpImage
,
0
,
_Size
);
//拷贝数据
memcpy
(
tpDstImg
->
vpImage
,
cc
.
data
,
_Size
);
//拷贝数据
memcpy
(
tpDstImg
->
vpImage
,
cc
.
data
,
_Size
);
}
return
FUNC_OK
;
}
...
...
@@ -7452,7 +7612,7 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors
[
i
]
=
255
;
double
minSize
=
cv
::
min
(
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
],
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]);
double
dRate
=
(
double
)
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
]
/
(
double
)
stats
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
];
if
(
minSize
<
2
0
||
!
(
dRate
>
0.75
&&
dRate
<
1.25
))
if
(
minSize
<
2
4
||
!
(
dRate
>
0.75
&&
dRate
<
1.25
))
{
colors
[
i
]
=
0
;
}
...
...
@@ -7500,7 +7660,7 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
cv
::
approxPolyDP
(
cv
::
Mat
(
contour
),
approx
,
arcL
*
0.01
,
true
);
if
(
approx
.
size
()
>
5
)
{
cv
::
Rect
bbox
=
cv
::
boundingRect
(
contour
);
if
(
MIN
(
bbox
.
width
,
bbox
.
height
)
>
18
&&
((
float
)
bbox
.
width
/
(
float
)
bbox
.
height
)
>
0.75
&&
\
if
(
MIN
(
bbox
.
width
,
bbox
.
height
)
>
24
&&
((
float
)
bbox
.
width
/
(
float
)
bbox
.
height
)
>
0.75
&&
\
((
float
)
bbox
.
width
/
(
float
)
bbox
.
height
)
<
1.25
)
{
//圆度
double
afa
=
4.0
f
*
CV_PI
*
cv
::
contourArea
(
contour
,
false
)
/
std
::
pow
(
arcL
,
2
);
...
...
@@ -7556,14 +7716,15 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
//排序
std
::
sort
(
AFAs
.
begin
(),
AFAs
.
end
(),
std
::
less
<
AFA
>
());
//高精度定位
if
(
bHighAccuracy
)
{
if
(
false
)
{
EyemOcsDXY
tpPoint
;
IntPtr
hObject
;
tpPoint
.
dX
=
AFAs
[
0
].
tpCircle
.
dX
;
tpPoint
.
dY
=
AFAs
[
0
].
tpCircle
.
dY
;
//提取图像
std
::
vector
<
cv
::
Mat
>
mvx
;
cv
::
split
(
cc
,
mvx
);
EyemImage
imageRed
;
imageRed
.
iWidth
=
cc
.
cols
;
imageRed
.
iHeight
=
cc
.
rows
;
imageRed
.
iDepth
=
cc
.
depth
();
imageRed
.
iChannels
=
1
;
imageRed
.
vpImage
=
mvx
[
2
].
data
;
eyemEdge1dFindCircle
(
imageRed
,
tpPoint
,
13
,
4
,
2
,
19
,
2
,
1
,
35
,
"positive"
,
&
hObject
);
int
iRadius
=
27
,
iCapLength
=
9
,
iCapWidth
=
6
,
nCalipers
=
19
,
nFilterSize
=
2
,
iSearchDirec
=
1
;
eyemEdge1dFindCircle
(
imageRed
,
tpPoint
,
iRadius
,
iCapLength
,
iCapWidth
,
nCalipers
,
nFilterSize
,
iSearchDirec
,
35
,
"positive"
,
&
hObject
);
//拟合
std
::
vector
<
EyemOcsDXY
>
*
tpResults
=
reinterpret_cast
<
std
::
vector
<
EyemOcsDXY
>*>
(
hObject
);
double
rms
;
EyemOcsDXYR
_tpCircle
;
...
...
@@ -7776,18 +7937,37 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
const
int
X
=
image
.
cols
;
const
int
Y
=
image
.
rows
;
if
(
image
.
channels
()
>
3
)
{
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGRA2BGR
);
}
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGR2GRAY
);
cv
::
Mat
mask
;
cv
::
threshold
(
image
,
mask
,
0
,
255
,
cv
::
THRESH_BINARY_INV
|
cv
::
THRESH_OTSU
);
cv
::
Mat
showMat
;
cv
::
cvtColor
(
image
,
showMat
,
cv
::
COLOR_GRAY2BGRA
);
cv
::
Mat
judgeMat
;
judgeMat
=
image
(
cv
::
Rect
(
500
,
160
,
120
,
120
));
//设定bin数目
const
int
histSize
=
17
;
//设定取值范围
float
range
[]
=
{
0
,
255
};
const
float
*
histRange
=
{
range
};
//计算直方图
cv
::
Mat
hist
;
cv
::
calcHist
(
&
image
,
1
,
0
,
cv
::
Mat
(),
hist
,
1
,
&
histSize
,
&
histRange
);
//计算背景像素
int
maxIdx
[
2
]
=
{
255
,
255
};
cv
::
minMaxIdx
(
hist
,
NULL
,
NULL
,
NULL
,
maxIdx
);
//背景阈值
int
backThresh
=
15
*
(
maxIdx
[
0
]
-
2
);
//去掉背景
cv
::
parallel_for_
(
cv
::
Range
(
0
,
Y
),
[
&
](
const
cv
::
Range
range
)
->
void
{
for
(
int
y
=
range
.
start
;
y
<
range
.
end
;
y
++
)
{
for
(
int
x
=
0
;
x
<
X
;
x
++
)
{
if
((
image
.
data
)[(
x
)
+
(
y
)
*
X
]
>=
backThresh
)
{
(
image
.
data
)[(
x
)
+
(
y
)
*
X
]
=
backThresh
;
}
}
}
});
//去掉干扰
cv
::
Mat
binary
,
srcPrev
;
cv
::
bitwise_not
(
image
,
srcPrev
);
return
FUNC_OK
;
#pragma region resize img
//const int minInputSize = 832;
...
...
@@ -7944,3 +8124,5 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
return
FUNC_OK
;
}
eyemLib/eyemMisc.h
查看文件 @
547390f
...
...
@@ -5,6 +5,7 @@
#ifndef __EYEM_MISC_H
#define __EYEM_MISC_H
#include <numeric>
#include "eyemLib.h"
#include <tbb\tbb.h>
...
...
eyemLib/stegers.cpp
0 → 100644
查看文件 @
547390f
#include "stegers.h"
contour
::
contour
()
{
clear
();
}
//constructor
contour
::
contour
(
int32_t
nnum
,
std
::
vector
<
float
>&
nrow
,
std
::
vector
<
float
>&
ncol
,
std
::
vector
<
float
>&
nangle
,
std
::
vector
<
float
>&
nresponse
,
contour_class
ncont_class
)
{
num
=
nnum
;
row
=
nrow
;
col
=
ncol
;
angle
=
nangle
;
response
=
nresponse
;
cont_class
=
ncont_class
;
}
void
contour
::
clear
()
{
num
=
0
;
row
.
resize
(
0
);
col
.
resize
(
0
);
angle
.
resize
(
0
);
response
.
resize
(
0
);
width_l
.
resize
(
0
);
width_r
.
resize
(
0
);
asymmetry
.
resize
(
0
);
contrast
.
resize
(
0
);
cont_class
=
contour_class
::
cont_no_junc
;
}
chord
::
chord
()
{
r
=
0
;
cb
=
0
;
ce
=
0
;
}
chord
::
chord
(
short
nr
,
short
ncb
,
short
nce
)
{
r
=
nr
;
cb
=
ncb
;
ce
=
nce
;
}
region
::
region
(
const
std
::
vector
<
int32_t
>&
image
,
uint32_t
min_val
,
int32_t
image_width
,
int32_t
image_m_height
)
{
rl
.
resize
(
0
);
long
grey
;
long
r
,
c
,
l
,
count
;
bool
inside
;
inside
=
false
;
count
=
0
;
rl
.
emplace_back
();
for
(
r
=
0
;
r
<
image_m_height
;
r
++
)
{
for
(
c
=
0
;
c
<
image_width
;
c
++
)
{
l
=
LCOR
(
r
,
c
,
image_width
);
grey
=
image
[
l
];
if
(
grey
>=
min_val
)
{
if
(
!
inside
)
{
inside
=
true
;
rl
[
count
].
r
=
(
int16_t
)
r
;
rl
[
count
].
cb
=
(
int16_t
)
c
;
}
}
else
{
if
(
inside
)
{
inside
=
false
;
rl
[
count
].
ce
=
(
int16_t
)(
c
-
1
);
count
++
;
rl
.
emplace_back
();
}
}
}
if
(
inside
)
{
inside
=
false
;
rl
[
count
].
ce
=
(
int16_t
)(
image_width
-
1
);
count
++
;
rl
.
emplace_back
();
}
}
this
->
num
=
count
;
}
//
//bool region::test() {
// const char* frame[] =
// {
// "00100100",
// "00110100",
// "00011000",
// "01000100",
// "01000000",
// 0 };
// const char* gold[] =
// {
// "00100100",
// "00110100",
// "00011000",
// "02000100",
// "02000000",
// 0 };
//
// cv::Mat pels(5, 8, CV_8U);
// DrawShape(pels, frame);
//
// std::vector<int32_t> lpels(5 * 8);
// for (auto row = 0; row < pels.rows; row++)
// for (auto col = 0; col < pels.cols; col++) {
// auto l = LCOR(row, col, pels.cols);
// lpels[l] = int32_t(pels.at<uint8_t>(row, col));
// }
//
// region rg(lpels, 1, pels.cols, pels.rows);
// bool check = rg.rl.size() == 9;
// if (!check) return check;
//
// std::vector<chord> golds;
// golds.emplace_back(0, 2, 2);
// golds.emplace_back(0, 5, 5);
// golds.emplace_back(1, 2, 3);
// golds.emplace_back(1, 5, 5);
// golds.emplace_back(2, 3, 4);
// golds.emplace_back(3, 1, 1);
// golds.emplace_back(3, 5, 5);
// golds.emplace_back(4, 1, 1);
// golds.emplace_back(0, 0, 0);
//
// for (int i = 0; i < 9; i++)
// assert(rg.rl[i] == golds[i]);
//
// return true;
//
}
\ No newline at end of file
eyemLib/stegers.h
0 → 100644
查看文件 @
547390f
#pragma once
#include <vector>
#include <ostream>
#ifndef LCOR
#define LCOR(row,col,width) (row)*(width) + (col)
#endif
enum
class
contour_class
{
/** no end point is a junction */
cont_no_junc
,
/** only the start point of the line is a junction */
cont_start_junc
,
/** only the end point of the line is a junction */
cont_end_junc
,
/** both end points of the line are junctions */
cont_both_junc
,
/** the contour is closed */
cont_closed
};
class
contour
{
/** number of points */
public
:
//default constructor
contour
();
//constructor
contour
(
int32_t
nnum
,
std
::
vector
<
float
>&
nrow
,
std
::
vector
<
float
>&
ncol
,
std
::
vector
<
float
>&
nangle
,
std
::
vector
<
float
>&
nresponse
,
contour_class
ncont_class
);
void
clear
();
float
compute_length
()
const
{
std
::
vector
<
float
>::
const_iterator
row_b
=
row
.
begin
()
+
1
;
std
::
vector
<
float
>::
const_iterator
col_b
=
col
.
begin
()
+
1
;
float
length
=
0
.
0
f
;
for
(;
row_b
<
row
.
end
()
&&
col_b
<
col
.
end
();
row_b
++
,
col_b
++
)
{
float
dr
=
*
(
row_b
)
-*
(
row_b
-
1
);
float
dc
=
*
(
col_b
)
-*
(
col_b
-
1
);
length
+=
std
::
sqrt
(
dr
*
dr
+
dc
*
dc
);
}
return
length
;
}
int32_t
num
=
0
;
std
::
vector
<
float
>
row
;
/** column coordinates of the line points (X coordinate in ImageJ) */
std
::
vector
<
float
>
col
;
/** angle of normal (measured from the row (Y) axis) */
std
::
vector
<
float
>
angle
;
/** response of line point (second derivative) */
std
::
vector
<
float
>
response
;
/** width to the left of the line */
std
::
vector
<
float
>
width_l
;
/** width to the right of the line */
std
::
vector
<
float
>
width_r
;
/** asymmetry of the line point */
std
::
vector
<
float
>
asymmetry
;
/** contrast of the line point */
std
::
vector
<
float
>
contrast
;
/** contour class (e.g., closed, no_junc) */
contour_class
cont_class
;
};
class
crossRef
{
public
:
/*
Storage the Crossref variables, it is the Correction.java code
This data structure facilitates the quick search for the next possible starting point of a line.An array of crossrefs will be accumulatedand
sorted according to its value.xand y are the coordinates of a point in the image.When this point has been processed it will be marked as done.
*/
crossRef
(
int32_t
x
=
0
,
int32_t
y
=
0
,
double
value
=
0
.
0
,
bool
done
=
false
)
:
m_x
(
x
),
m_y
(
y
),
m_val
(
value
),
m_done
(
done
)
{}
// Accessors
const
int32_t
&
x
()
const
{
return
m_x
;
}
const
int32_t
&
y
()
const
{
return
m_y
;
}
const
double
&
value
()
const
{
return
m_val
;
}
bool
done
()
const
{
return
m_done
;
}
void
setDone
()
const
{
m_done
=
true
;
}
void
setUnDone
()
const
{
m_done
=
false
;
}
int32_t
compareTo
(
crossRef
&
other
)
{
int32_t
rt
=
(
m_val
>
other
.
value
())
?
-
1
:
(
m_val
<
other
.
value
())
?
1
:
0
;
return
rt
;
}
bool
operator
==
(
const
crossRef
&
other
)
const
{
return
this
->
m_val
==
other
.
value
();
}
bool
operator
<
(
const
crossRef
&
other
)
const
{
return
this
->
m_val
<
other
.
value
();
}
bool
operator
>
(
const
crossRef
&
other
)
const
{
return
this
->
m_val
>
other
.
value
();
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
ous
,
const
crossRef
&
dis
)
{
// return + str(self.x) + + str(self.y) + + str(self.value) + + str(self.done)
ous
<<
"x: "
<<
dis
.
x
()
<<
"
\t
y: "
<<
dis
.
y
()
<<
"
\t
value: "
<<
dis
.
value
()
<<
"
\t
done: "
<<
std
::
boolalpha
<<
dis
.
done
();
return
ous
;
}
private
:
int32_t
m_x
,
m_y
;
double
m_val
;
mutable
bool
m_done
;
};
/** Data structure to store three doubles: x,y and t (distance along line) */
class
doublepoint
{
public
:
double
cx
=
0
;
double
cy
=
0
;
double
t
=
0
;
doublepoint
()
{}
doublepoint
(
double
ccx
,
double
ccy
,
double
ct
)
{
cx
=
ccx
;
cy
=
ccy
;
t
=
ct
;
}
doublepoint
(
double
ccx
,
double
ccy
)
{
cx
=
ccx
;
cy
=
ccy
;
t
=
0
;
}
};
/** Offsets to a specific location in the image. An array of this type is
returned by the modified Bresenham algorithm in width.c. It is also used
in link.c to hold an array of pixel locations to check for appropriate
neighbors. */
class
offset
{
public
:
int32_t
x
;
int32_t
y
;
offset
()
{
x
=
0
;
y
=
0
;
}
offset
(
int32_t
nx
,
int32_t
ny
)
{
x
=
nx
;
y
=
ny
;
}
};
/** This data structure is used to accumulate junction information. It is
needed to split lines at junction points. */
class
junction
{
/** Index of line that is already processed */
public
:
int32_t
cont1
=
0
;
/** Index of line that runs into cont1 */
int32_t
cont2
=
0
;
/** Index of the junction point in cont1 */
int32_t
pos
=
0
;
/** y-(row-)coordinate of the junction point (corrected for ImageJ)*/
float
x
=
0
;
/** x-(col-)coordinate of the junction point (corrected for ImageJ)*/
float
y
=
0
;
junction
()
{}
junction
(
int32_t
ncont1
,
int32_t
ncont2
,
int32_t
npos
,
float
nx
,
float
ny
)
{
cont1
=
ncont1
;
cont2
=
ncont2
;
pos
=
npos
;
x
=
nx
;
y
=
ny
;
}
bool
operator
==
(
const
junction
&
other
)
const
{
return
this
->
pos
==
other
.
pos
;
}
bool
operator
<
(
const
junction
&
other
)
const
{
return
this
->
pos
<
other
.
pos
;
}
bool
operator
>
(
const
junction
&
other
)
const
{
return
this
->
pos
>
other
.
pos
;
}
/** This function compares two junctions according to their first line indexes,
and, if needed, by the position of the junction within the line. It is
called by qsort. */
static
bool
compare
(
const
junction
&
thisJunction
,
const
junction
&
otherjunction
)
{
if
(
thisJunction
.
cont1
==
otherjunction
.
cont1
)
{
return
thisJunction
.
pos
>=
otherjunction
.
pos
;
}
else
{
return
thisJunction
.
cont1
>
otherjunction
.
cont1
;
}
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
ous
,
const
junction
&
dis
)
{
ous
<<
"cont1: "
<<
dis
.
cont1
<<
"
\t
cont2: "
<<
dis
.
cont2
<<
"
\t
pos: "
<<
dis
.
pos
<<
"
\t
xy: "
<<
dis
.
x
<<
","
<<
dis
.
y
;
return
ous
;
}
};
/** A chord in a run-length encoded region */
class
chord
{
/** row coordinate of the chord */
public
:
// default dtor, copy ctor ok
short
r
=
0
;
/** column coordinate of the start of the chord */
short
cb
=
0
;
/** column coordinate of the end of the chord */
short
ce
=
0
;
chord
();
chord
(
short
nr
,
short
ncb
,
short
nce
);
bool
operator
==
(
chord
&
other
)
const
{
return
this
->
r
==
other
.
r
&&
this
->
cb
==
other
.
cb
&&
this
->
ce
==
other
.
ce
;
}
};
/** Run-length encoded region of an image. This type is returned by the
threshold() function. It provides the means to efficiently link line points
into lines. */
class
region
{
public
:
region
(
const
std
::
vector
<
int32_t
>&
image
,
uint32_t
min_val
,
int32_t
image_width
,
int32_t
image_m_height
);
int32_t
num
=
0
;
// number of chords
std
::
vector
<
chord
>
rl
;
// array of chords
//static bool test();
};
\ No newline at end of file
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论