Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
张士柳
/
eyemLib
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
图表
网络
创建新的问题
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit cde6cc7d
由
张士柳
编写于
2021-09-13 09:06:54 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
无
1 个父辈
7dd24868
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
354 行增加
和
2090 行删除
eyemLib-Sharp/EyemLib.cs
eyemLib-Sharp/EyemLibDemo.cs
eyemLib/eyemBin.cpp
eyemLib/eyemCodeDetector.cpp
eyemLib/eyemEdge1d.cpp
eyemLib/eyemEdge1d.h
eyemLib/eyemLib.h
eyemLib/eyemLib.vcxproj
eyemLib/eyemLib.vcxproj.filters
eyemLib/eyemMatchShapes.h
eyemLib/eyemMisc.cpp
eyemLib/stegers.cpp
eyemLib/stegers.h
eyemLib-Sharp/EyemLib.cs
查看文件 @
cde6cc7
...
@@ -405,9 +405,9 @@ namespace eyemLib_Sharp
...
@@ -405,9 +405,9 @@ namespace eyemLib_Sharp
public
IntPtr
lpszName
;
// 名称
public
IntPtr
lpszName
;
// 名称
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemRigidMatrix
public
struct
EyemRigidMatrix
{
{
public
double
a00
;
// a00
public
double
a00
;
// a00
public
double
a01
;
// a01
public
double
a01
;
// a01
public
double
b00
;
// b00
public
double
b00
;
// b00
...
@@ -415,6 +415,17 @@ namespace eyemLib_Sharp
...
@@ -415,6 +415,17 @@ namespace eyemLib_Sharp
public
double
a11
;
// a11
public
double
a11
;
// a11
public
double
b10
;
// b10
public
double
b10
;
// b10
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemHSVModel
{
[
MarshalAs
(
UnmanagedType
.
ByValArray
,
SizeConst
=
3
)]
public
double
[]
dpRangeL
,
dpRangeU
;
// 提取下限,提取上限[H S V]
[
MarshalAs
(
UnmanagedType
.
ByValArray
,
SizeConst
=
3
)]
public
double
[]
dpRangeLExt
,
dpRangeUExt
;
// 额外提取下限,额外提取上限(针对处于跨模型颜色,比如红色)[H S V]
}
// 用于HSV颜色模型分割(H(0-180)、S(0-255)、V(0-255))
#
endregion
#
endregion
#
region
通用
#
region
通用
...
@@ -537,7 +548,7 @@ namespace eyemLib_Sharp
...
@@ -537,7 +548,7 @@ namespace eyemLib_Sharp
/// <param name="tpDstImg">结果</param>
/// <param name="tpDstImg">结果</param>
/// <returns></returns>
/// <returns></returns>
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemBinThresholdC
(
EyemImage
tpImage
,
[
MarshalAs
(
UnmanagedType
.
LPArray
)]
int
[]
ipRangeL
,
[
MarshalAs
(
UnmanagedType
.
LPArray
)]
int
[]
ipRangeU
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemBinThresholdC
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
out
EyemImage
tpDstImg
);
/// <summary>
/// <summary>
/// 局部自适应二值化
/// 局部自适应二值化
...
@@ -1031,7 +1042,7 @@ namespace eyemLib_Sharp
...
@@ -1031,7 +1042,7 @@ namespace eyemLib_Sharp
private
static
extern
int
setSkipProcessID
(
int
pid
);
private
static
extern
int
setSkipProcessID
(
int
pid
);
//圆形mark点定位
//圆形mark点定位
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemMarkerTracing
(
EyemImage
tpImage
,
double
dThreshold
,
ref
EyemOcsFXYR
tpCircle
,
out
EyemImage
tpDstImg
,
bool
bHighAccuracy
=
false
);
private
static
extern
int
eyemMarkerTracing
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
ref
EyemOcsFXYR
tpCircle
,
out
EyemImage
tpDstImg
,
bool
bHighAccuracy
=
false
);
//多功能工具
//多功能工具
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemMulFuncTool
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
funcName
,
double
dThreshold
,
int
iNumToIgnore
,
ref
EyemOcsFXYR
tpCircle
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemMulFuncTool
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
string
funcName
,
double
dThreshold
,
int
iNumToIgnore
,
ref
EyemOcsFXYR
tpCircle
,
out
EyemImage
tpDstImg
);
...
@@ -1040,7 +1051,7 @@ namespace eyemLib_Sharp
...
@@ -1040,7 +1051,7 @@ namespace eyemLib_Sharp
#
region
测试专用接口
#
region
测试专用接口
//测试接口
//测试接口
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemLibImpl
(
EyemImage
tpImage
,
out
EyemImage
tpDstImg
);
private
static
extern
int
eyemLibImpl
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
out
EyemImage
tpDstImg
);
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemEdge1dRidgeDetection
(
EyemImage
tpImage
);
private
static
extern
int
eyemEdge1dRidgeDetection
(
EyemImage
tpImage
);
...
@@ -1108,7 +1119,7 @@ namespace eyemLib_Sharp
...
@@ -1108,7 +1119,7 @@ namespace eyemLib_Sharp
string
file
=
fileName
.
Split
(
new
string
[]
{
"\\"
},
StringSplitOptions
.
RemoveEmptyEntries
)[
2
];
string
file
=
fileName
.
Split
(
new
string
[]
{
"\\"
},
StringSplitOptions
.
RemoveEmptyEntries
)[
2
];
flag
=
eyemInitNNDataCodeModel
(
".\\darknet\\detect-tiny.cfg"
,
".\\darknet\\detect-tiny.weights"
,
""
,
""
)
&
eyemInitNNDetector
(
".\\darknet\\detect-tiny-label.cfg"
,
".\\darknet\\detect-tiny-label.weights"
);
//
flag = eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", "", "") & eyemInitNNDetector(".\\darknet\\detect-tiny-label.cfg", ".\\darknet\\detect-tiny-label.weights");
//EyemImage image1 = new EyemImage(); EyemImage image2 = new EyemImage();
//EyemImage image1 = new EyemImage(); EyemImage image2 = new EyemImage();
//flag = eyemMatMalloc(512, 512, 1, "uint8_t", out image1);
//flag = eyemMatMalloc(512, 512, 1, "uint8_t", out image1);
...
@@ -1126,23 +1137,39 @@ namespace eyemLib_Sharp
...
@@ -1126,23 +1137,39 @@ namespace eyemLib_Sharp
//flag = eyemCvtColor(tpDstImg, ColorConversionCodes.COLOR_GRAY2BGR, ref tpDstImg);
//flag = eyemCvtColor(tpDstImg, ColorConversionCodes.COLOR_GRAY2BGR, ref tpDstImg);
flag
=
eyemLibImpl
(
image
,
out
tpDstImg
);
////红色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 0, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 10, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 156, 43, 46 }; tpHsvModel.dpRangeUExt = new double[] { 180, 255, 255 };
////绿色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 35, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 77, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
////蓝色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 100, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 124, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
//flag = eyemLibImpl(image, tpHsvModel, out tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//if (bitmap != null)
//{
//{
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//}
//}
return
;
//
return;
//flag = eyemNormalize(ref image);
//flag = eyemNormalize(ref image);
//EyemImage image1 = new EyemImage(); EyemImage image2 = new EyemImage(); EyemImage image3 = new EyemImage();
//EyemImage image1 = new EyemImage(); EyemImage image2 = new EyemImage(); EyemImage image3 = new EyemImage();
//eyemDecompose(image, out image1, out image2, out image3);
//eyemDecompose(image, out image1, out image2, out image3);
//flag = eyemBinThresholdC(image,
new int[] { 55, 0, 0 }, new int[] { 135, 225, 225 }
, out tpDstImg);
//flag = eyemBinThresholdC(image,
tpHsvModel
, out tpDstImg);
//sw.Restart();
//sw.Restart();
//EyemOcsFXYR tpCircle = new EyemOcsFXYR();
//flag = eyemMarkerTracing(image,
120
, ref tpCircle, out tpDstImg, false);
//flag = eyemMarkerTracing(image,
tpHsvModel
, ref tpCircle, out tpDstImg, false);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//if (bitmap != null)
...
@@ -1152,10 +1179,9 @@ namespace eyemLib_Sharp
...
@@ -1152,10 +1179,9 @@ namespace eyemLib_Sharp
//eyemImageFree(ref tpDstImg);
//eyemImageFree(ref tpDstImg);
//sw.Stop();
//sw.Stop();
//Console.WriteLine("时间:" + sw.ElapsedMilliseconds.ToString());
//Console.WriteLine("时间:" + sw.ElapsedMilliseconds.ToString());
//
return;
return
;
//flag = eyemEdge1dRidgeDetection(image);
//flag = eyemEdge1dRidgeDetection(image);
//return;
#
region
Test
Blob
#
region
Test
Blob
//sw.Restart();
//sw.Restart();
...
@@ -1312,9 +1338,9 @@ namespace eyemLib_Sharp
...
@@ -1312,9 +1338,9 @@ namespace eyemLib_Sharp
#
endregion
#
endregion
EyemRect
tpRoi
=
new
EyemRect
();
EyemRect
tpRoi
=
new
EyemRect
();
tpRoi
.
iXs
=
200
;
tpRoi
.
iYs
=
20
0
;
tpRoi
.
iXs
=
50
;
tpRoi
.
iYs
=
5
0
;
tpRoi
.
iWidth
=
image
.
iWidth
-
4
00
;
tpRoi
.
iWidth
=
image
.
iWidth
-
1
00
;
tpRoi
.
iHeight
=
image
.
iHeight
-
4
00
;
tpRoi
.
iHeight
=
image
.
iHeight
-
1
00
;
//flag = eyemMulFuncTool(image, tpRoi, "__func1", 65, 75, ref tpCircle, out tpDstImg);
//flag = eyemMulFuncTool(image, tpRoi, "__func1", 65, 75, ref tpCircle, out tpDstImg);
...
@@ -1390,7 +1416,7 @@ namespace eyemLib_Sharp
...
@@ -1390,7 +1416,7 @@ namespace eyemLib_Sharp
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS","IP_LOWCONTRAST_PARTS"
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS","IP_LOWCONTRAST_PARTS"
//eyemCountObject(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObject(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_
LONG
_PARTS", ipReelNum, out tpDstImg);
//eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_
SQUARE
_PARTS", ipReelNum, out tpDstImg);
//eyemCountObjectE(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObjectE(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "20210825095751-1", hModelID, ipReelNum, 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);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "D:\\模板文件\\" + "20210825095751-1.tpl", hModelID, ipReelNum, out tpDstImg);
...
...
eyemLib-Sharp/EyemLibDemo.cs
查看文件 @
cde6cc7
...
@@ -33,10 +33,10 @@ namespace eyemLib_Sharp
...
@@ -33,10 +33,10 @@ namespace eyemLib_Sharp
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemRect2
public
struct
EyemRect2
{
{
int
iXs
;
// 起始点(左上角) x 坐标
public
int
iXs
;
// 起始点(左上角) x 坐标
int
iYs
;
// 起始点(左上角) y 坐标
public
int
iYs
;
// 起始点(左上角) y 坐标
int
iXe
;
// 端点(右下) x 坐标
public
int
iXe
;
// 端点(右下) x 坐标
int
iYe
;
// 端点(右下) y 坐标
public
int
iYe
;
// 端点(右下) y 坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
...
@@ -49,6 +49,14 @@ namespace eyemLib_Sharp
...
@@ -49,6 +49,14 @@ namespace eyemLib_Sharp
public
double
dVar
;
// 某种可能会使用的值
public
double
dVar
;
// 某种可能会使用的值
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
BboxContainer
{
//最多支持100个目标
[
MarshalAs
(
UnmanagedType
.
ByValArray
,
SizeConst
=
100
)]
public
EyemRect
[]
bboxes
;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Orthogonal Coordinate System
// Orthogonal Coordinate System
...
@@ -58,56 +66,56 @@ namespace eyemLib_Sharp
...
@@ -58,56 +66,56 @@ namespace eyemLib_Sharp
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIXY
public
struct
EyemOcsIXY
{
{
int
iX
;
// X坐标
public
int
iX
;
// X坐标
int
iY
;
// Y坐标
public
int
iY
;
// Y坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIXYZ
public
struct
EyemOcsIXYZ
{
{
int
iX
;
// X坐标
public
int
iX
;
// X坐标
int
iY
;
// Y坐标
public
int
iY
;
// Y坐标
int
iZ
;
// Z坐标
public
int
iZ
;
// Z坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIXYQ
public
struct
EyemOcsIXYQ
{
{
int
iX
;
// X坐标
public
int
iX
;
// X坐标
int
iY
;
// Y坐标
public
int
iY
;
// Y坐标
int
iQ
;
// θ
public
int
iQ
;
// θ
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIXYR
// 用于表示圆
public
struct
EyemOcsIXYR
// 用于表示圆
{
{
int
iX
;
// X坐标
public
int
iX
;
// X坐标
int
iY
;
// Y坐标
public
int
iY
;
// Y坐标
int
iR
;
// 半径
public
int
iR
;
// 半径
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIABC
// 用于表示直线(一般形式)
public
struct
EyemOcsIABC
// 用于表示直线(一般形式)
{
{
int
iA
;
// a
public
int
iA
;
// a
int
iB
;
// b
public
int
iB
;
// b
int
iC
;
// c
public
int
iC
;
// c
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIRQ
// 用于表示直线(黑森标准形式)或矢量
public
struct
EyemOcsIRQ
// 用于表示直线(黑森标准形式)或矢量
{
{
int
iR
;
// ρ
public
int
iR
;
// ρ
int
iQ
;
// θ
public
int
iQ
;
// θ
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsIXYQS
public
struct
EyemOcsIXYQS
{
{
int
iX
;
// X坐标(单位:像素)
public
int
iX
;
// X坐标(单位:像素)
int
iY
;
// Y坐标(单位:像素)
public
int
iY
;
// Y坐标(单位:像素)
int
iQ
;
// 斜率(単位:rad)
public
int
iQ
;
// 斜率(単位:rad)
int
iS
;
// 刻度
public
int
iS
;
// 刻度
}
}
...
@@ -117,56 +125,56 @@ namespace eyemLib_Sharp
...
@@ -117,56 +125,56 @@ namespace eyemLib_Sharp
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFXY
public
struct
EyemOcsFXY
{
{
float
fX
;
// X坐标
public
float
fX
;
// X坐标
float
fY
;
// Y坐标
public
float
fY
;
// Y坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFXYZ
public
struct
EyemOcsFXYZ
{
{
float
fX
;
// X坐标
public
float
fX
;
// X坐标
float
fY
;
// Y坐标
public
float
fY
;
// Y坐标
float
fZ
;
// Z坐标
public
float
fZ
;
// Z坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFXYQ
public
struct
EyemOcsFXYQ
{
{
float
fX
;
// X坐标
public
float
fX
;
// X坐标
float
fY
;
// Y坐标
public
float
fY
;
// Y坐标
float
fQ
;
// θ
public
float
fQ
;
// θ
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFXYR
// 用于表示圆
public
struct
EyemOcsFXYR
// 用于表示圆
{
{
float
fX
;
// X坐标
public
float
fX
;
// X坐标
float
fY
;
// Y坐标
public
float
fY
;
// Y坐标
float
fR
;
// 半径
public
float
fR
;
// 半径
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFABC
// 用于表示直线(一般形式)
public
struct
EyemOcsFABC
// 用于表示直线(一般形式)
{
{
float
fA
;
// a
public
float
fA
;
// a
float
fB
;
// b
public
float
fB
;
// b
float
fC
;
// c
public
float
fC
;
// c
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFRQ
// 用于表示直线(黑森标准形式)或矢量
public
struct
EyemOcsFRQ
// 用于表示直线(黑森标准形式)或矢量
{
{
float
fR
;
// ρ
public
float
fR
;
// ρ
float
fQ
;
// θ
public
float
fQ
;
// θ
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsFXYQS
public
struct
EyemOcsFXYQS
{
{
float
fX
;
// X坐标(単位:像素)
public
float
fX
;
// X坐标(単位:像素)
float
fY
;
// Y坐标(単位:像素)
public
float
fY
;
// Y坐标(単位:像素)
float
fQ
;
// 斜率(単位:rad)
public
float
fQ
;
// 斜率(単位:rad)
float
fS
;
// 刻度
public
float
fS
;
// 刻度
}
}
...
@@ -176,93 +184,93 @@ namespace eyemLib_Sharp
...
@@ -176,93 +184,93 @@ namespace eyemLib_Sharp
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDXY
public
struct
EyemOcsDXY
{
{
public
double
dX
;
// X坐标
public
double
dX
;
// X坐标
public
double
dY
;
// Y坐标
public
double
dY
;
// Y坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDXYZ
public
struct
EyemOcsDXYZ
{
{
double
dX
;
// X坐标
public
double
dX
;
// X坐标
double
dY
;
// Y坐标
public
double
dY
;
// Y坐标
double
dZ
;
// Z坐标
public
double
dZ
;
// Z坐标
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDXYQ
public
struct
EyemOcsDXYQ
{
{
double
dX
;
// X坐标
public
double
dX
;
// X坐标
double
dY
;
// Y坐标
public
double
dY
;
// Y坐标
double
dQ
;
// θ
public
double
dQ
;
// θ
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDXYR
// 用于表示圆
public
struct
EyemOcsDXYR
// 用于表示圆
{
{
double
dX
;
// 中心的X坐标
public
double
dX
;
// 中心的X坐标
double
dY
;
// 中心的Y坐标
public
double
dY
;
// 中心的Y坐标
double
dR
;
// 半径
public
double
dR
;
// 半径
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDABC
// 直线(一般形)的表现形式
public
struct
EyemOcsDABC
// 直线(一般形)的表现形式
{
{
double
dA
;
// a
public
double
dA
;
// a
double
dB
;
// b
public
double
dB
;
// b
double
dC
;
// c
public
double
dC
;
// c
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDRQ
// 直線(ヘッセの標準形)やベクトルの表現に使用
public
struct
EyemOcsDRQ
// 用于表示直线(黑森标准形状)和矢量
{
{
double
dR
;
// ρ
public
double
dR
;
// ρ
double
dQ
;
// θ
public
double
dQ
;
// θ
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDXYQS
public
struct
EyemOcsDXYQS
{
{
double
dX
;
// X座標
public
double
dX
;
// X坐标
double
dY
;
// Y座標
public
double
dY
;
// Y坐标
double
dQ
;
// 回転角
(単位:rad)
public
double
dQ
;
// 旋转角度
(単位:rad)
double
dS
;
// スケール
public
double
dS
;
// 规模
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDABCD
// 平面(一般形)の表現に使用
public
struct
EyemOcsDABCD
// 用于表示平面(一般形式)
{
{
double
dA
;
// a
public
double
dA
;
// a
double
dB
;
// b
public
double
dB
;
// b
double
dC
;
// c
public
double
dC
;
// c
double
dD
;
// d
public
double
dD
;
// d
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDXYLSQ
// 楕円の表現に使用
public
struct
EyemOcsDXYLSQ
// 用于表示椭圆
{
{
double
dXo
;
// 中心のX座標
public
double
dXo
;
// 中心X坐标
double
dYo
;
// 中心のY座標
public
double
dYo
;
// 中心Y坐标
double
dL
;
// 長軸
半径
public
double
dL
;
// 长轴
半径
double
dS
;
// 短軸
半径
public
double
dS
;
// 短轴
半径
double
dQ
;
// 長軸の傾き
(単位:rad)
public
double
dQ
;
// 长轴倾斜角
(単位:rad)
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDPV
// 3次元空間内の直線の表現に使用
public
struct
EyemOcsDPV
// 用于表示三维空间中的直线
{
{
EyemOcsDXYZ
tP
;
// 直線上の1点の座標
public
EyemOcsDXYZ
tP
;
// 直线上一点的坐标
EyemOcsDXYZ
tV
;
// 直線の方向ベクトル
public
EyemOcsDXYZ
tV
;
// 直线方向矢量
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemOcsDCRUVW
// 楕円体の表現に使用
public
struct
EyemOcsDCRUVW
// 用于表示椭圆体
{
{
EyemOcsDXYZ
tC
;
// 楕円体の
中心
public
EyemOcsDXYZ
tC
;
// 椭圆体
中心
EyemOcsDXYZ
tR
;
// 軸の半径(dX:長軸, dY:中軸, dZ:短軸)
public
EyemOcsDXYZ
tR
;
// 轴半径(dX:长轴、dY:中轴、dZ:短轴)
double
dU
;
// 長軸のXY平面への射影がX軸となす角(単位:rad)
public
double
dU
;
// 长轴投影到 XY 平面与 X 轴的角(单位:rad)
double
dV
;
// 長軸のXY平面とのなす角(単位:rad)
public
double
dV
;
// 长轴与XY平面之角(单位:rad)
double
dW
;
// 長軸まわりの回転角(単位:rad)
public
double
dW
;
// 绕长轴旋转角度(单位:rad)
}
}
// Blob 分析结果
// Blob 分析结果
...
@@ -281,10 +289,10 @@ namespace eyemLib_Sharp
...
@@ -281,10 +289,10 @@ namespace eyemLib_Sharp
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemChainCode
public
struct
EyemChainCode
{
{
int
iLabel
;
// 标签
public
int
iLabel
;
// 标签
double
dX
;
// x坐标
public
double
dX
;
// x坐标
double
dY
;
// y坐标
public
double
dY
;
// y坐标
double
dVx
,
dVy
;
// 向量
public
double
dVx
,
dVy
;
// 向量
}
}
// 条码 解码结果
// 条码 解码结果
...
@@ -297,20 +305,54 @@ namespace eyemLib_Sharp
...
@@ -297,20 +305,54 @@ namespace eyemLib_Sharp
public
IntPtr
hType
;
// 码类型
public
IntPtr
hType
;
// 码类型
public
IntPtr
hText
;
// 码内容
public
IntPtr
hText
;
// 码内容
}
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemModelID
{
public
IntPtr
vpImage
;
// 地址
public
int
iXs
;
// 图像X坐标
public
int
iYs
;
// 图像Y坐标
public
int
iWidth
;
// 图像内存X方向大小
public
int
iHeight
;
// 图像内存Y方向大小
public
double
dMatchDeg
;
// 匹配度
public
IntPtr
lpszName
;
// 名称
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemRigidMatrix
{
public
double
a00
;
// a00
public
double
a01
;
// a01
public
double
b00
;
// b00
public
double
a10
;
// a10
public
double
a11
;
// a11
public
double
b10
;
// b10
}
[
StructLayout
(
LayoutKind
.
Sequential
)]
public
struct
EyemHSVModel
{
[
MarshalAs
(
UnmanagedType
.
ByValArray
,
SizeConst
=
3
)]
public
double
[]
dpRangeL
,
dpRangeU
;
// 提取下限,提取上限[H S V]
[
MarshalAs
(
UnmanagedType
.
ByValArray
,
SizeConst
=
3
)]
public
double
[]
dpRangeLExt
,
dpRangeUExt
;
// 额外提取下限,额外提取上限(针对处于跨模型颜色的补充,比如红色)[H S V]
}
// 用于HSV颜色模型分割(H(0-180)、S(0-255)、V(0-255))
#
endregion
#
endregion
#
region
项目
#
region
项目
/// <summary>
/// <summary>
/// 圆形
/矩形(红色)m
ark点定位
/// 圆形
M
ark点定位
/// </summary>
/// </summary>
/// <param name="tpImage">
输入
图像</param>
/// <param name="tpImage">图像</param>
/// <param name="
dThreshold">二值化
阈值</param>
/// <param name="
tpHSVModel">HSV
阈值</param>
/// <param name="tpCircle">结果</param>
/// <param name="tpCircle">结果</param>
/// <param name="
bHighAccuracy">是否是高精度定位
</param>
/// <param name="
tpDstImg">结果图
</param>
/// <
returns></returns
>
/// <
param name="bHighAccuracy">是否使用高精度</param
>
//
圆形mark点定位
//
/ <returns>0=FUNC_OK</returns>
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemMarkerTracing
(
EyemImage
tpImage
,
double
dThreshold
,
ref
EyemOcsFXYR
tpCircle
,
out
EyemImage
tpDstImg
,
bool
bHighAccuracy
=
false
);
private
static
extern
int
eyemMarkerTracing
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
ref
EyemOcsFXYR
tpCircle
,
out
EyemImage
tpDstImg
,
bool
bHighAccuracy
=
false
);
#
endregion
#
endregion
#
region
通用
#
region
通用
...
@@ -360,16 +402,31 @@ namespace eyemLib_Sharp
...
@@ -360,16 +402,31 @@ namespace eyemLib_Sharp
public
static
void
eyeyTestTemplateModelMethod
(
string
fileName
)
public
static
void
eyeyTestTemplateModelMethod
(
string
fileName
)
{
{
#
region
//从本地读图
#
region
//从本地读图
//EyemImage image, tpDstImg;
EyemImage
image
,
tpDstImg
;
//int flag = eyemImageRead(fileName, -1, out image);
int
flag
=
eyemImageRead
(
fileName
,
-
1
,
out
image
);
//if (flag != 0)
if
(
flag
!=
0
)
//{
{
// Console.WriteLine("读图失败!");
Console
.
WriteLine
(
"读图失败!"
);
// return;
return
;
//}
}
////红色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 0, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 10, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 156, 43, 46 }; tpHsvModel.dpRangeUExt = new double[] { 180, 255, 255 };
////绿色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 35, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 77, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
////蓝色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 100, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 124, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
//EyemOcsFXYR tpCircle = new EyemOcsFXYR();
//EyemOcsFXYR tpCircle = new EyemOcsFXYR();
//flag = eyemMarkerTracing(image,
120
, ref tpCircle, out tpDstImg);
//flag = eyemMarkerTracing(image,
tpHsvModel
, ref tpCircle, out tpDstImg);
////free image
////free image
//eyemImageFree(ref image);
//eyemImageFree(ref image);
...
@@ -380,7 +437,7 @@ namespace eyemLib_Sharp
...
@@ -380,7 +437,7 @@ namespace eyemLib_Sharp
//image = eyemCvtToEyemImage(/*Bitmap*/);
//image = eyemCvtToEyemImage(/*Bitmap*/);
//flag = eyemMarkerTracing(image,
120
, ref tpCircle, out tpDstImg);
//flag = eyemMarkerTracing(image,
tpHsvModel
, ref tpCircle, out tpDstImg);
////free image
////free image
//Marshal.FreeHGlobal(image.vpImage);
//Marshal.FreeHGlobal(image.vpImage);
...
...
eyemLib/eyemBin.cpp
查看文件 @
cde6cc7
...
@@ -1243,13 +1243,15 @@ int eyemBinAutoThreshold(EyemImage tpImage, double dSigma, int iLightDark, int b
...
@@ -1243,13 +1243,15 @@ int eyemBinAutoThreshold(EyemImage tpImage, double dSigma, int iLightDark, int b
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemBinThresholdC
(
EyemImage
tpImage
,
int
ipRangeL
[
3
],
int
ipRangeU
[
3
]
,
EyemImage
*
tpDstImg
)
int
eyemBinThresholdC
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
EyemImage
*
tpDstImg
)
{
{
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
image
.
empty
())
if
(
image
.
empty
())
return
FUNC_IMAGE_NOT_EXIST
;
return
FUNC_IMAGE_NOT_EXIST
;
//图像尺寸
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
//非彩色图像处理
int
incn
=
image
.
channels
();
int
incn
=
image
.
channels
();
if
(
incn
>
3
)
{
if
(
incn
>
3
)
{
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGRA2BGR
);
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGRA2BGR
);
...
@@ -1261,9 +1263,19 @@ int eyemBinThresholdC(EyemImage tpImage, int ipRangeL[3], int ipRangeU[3], EyemI
...
@@ -1261,9 +1263,19 @@ int eyemBinThresholdC(EyemImage tpImage, int ipRangeL[3], int ipRangeU[3], EyemI
cv
::
Mat
imghsv
;
cv
::
Mat
imghsv
;
cv
::
cvtColor
(
image
,
imghsv
,
cv
::
COLOR_BGR2HSV
);
cv
::
cvtColor
(
image
,
imghsv
,
cv
::
COLOR_BGR2HSV
);
//分割
//红色比较特殊,分两个区间
cv
::
Mat
mask
;
cv
::
Mat
mask1
,
mask2
(
cv
::
Size
(
X
,
Y
),
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
inRange
(
imghsv
,
cv
::
Scalar
(
ipRangeL
[
0
],
ipRangeL
[
1
],
ipRangeL
[
2
]),
cv
::
Scalar
(
ipRangeU
[
0
],
ipRangeU
[
1
],
ipRangeU
[
2
]),
mask
);
cv
::
inRange
(
imghsv
,
cv
::
Scalar
(
tpHSVModel
.
dpRangeL
[
0
],
tpHSVModel
.
dpRangeL
[
1
],
tpHSVModel
.
dpRangeL
[
2
]),
cv
::
Scalar
(
tpHSVModel
.
dpRangeU
[
0
],
tpHSVModel
.
dpRangeU
[
1
],
tpHSVModel
.
dpRangeU
[
2
]),
mask1
);
//多个分割阈值
if
((
tpHSVModel
.
dpRangeLExt
[
0
]
+
tpHSVModel
.
dpRangeLExt
[
1
]
+
tpHSVModel
.
dpRangeLExt
[
2
])
!=
0
||
(
tpHSVModel
.
dpRangeUExt
[
0
]
+
tpHSVModel
.
dpRangeUExt
[
1
]
+
tpHSVModel
.
dpRangeUExt
[
2
])
!=
0
)
{
cv
::
inRange
(
imghsv
,
cv
::
Scalar
(
tpHSVModel
.
dpRangeLExt
[
0
],
tpHSVModel
.
dpRangeLExt
[
1
],
tpHSVModel
.
dpRangeLExt
[
2
]),
cv
::
Scalar
(
tpHSVModel
.
dpRangeUExt
[
0
],
tpHSVModel
.
dpRangeUExt
[
1
],
tpHSVModel
.
dpRangeUExt
[
2
]),
mask2
);
}
//合并
cv
::
Mat
maskj
;
cv
::
bitwise_or
(
mask1
,
mask2
,
maskj
);
//输出结果图像
//输出结果图像
if
(
NULL
!=
tpDstImg
->
vpImage
)
{
if
(
NULL
!=
tpDstImg
->
vpImage
)
{
...
@@ -1273,7 +1285,7 @@ int eyemBinThresholdC(EyemImage tpImage, int ipRangeL[3], int ipRangeU[3], EyemI
...
@@ -1273,7 +1285,7 @@ int eyemBinThresholdC(EyemImage tpImage, int ipRangeL[3], int ipRangeU[3], EyemI
tpDstImg
->
vpImage
=
NULL
;
tpDstImg
->
vpImage
=
NULL
;
}
}
tpDstImg
->
iWidth
=
mask
.
cols
;
tpDstImg
->
iHeight
=
mask
.
rows
;
tpDstImg
->
iDepth
=
mask
.
depth
();
tpDstImg
->
iChannels
=
mask
.
channels
();
tpDstImg
->
iWidth
=
mask
j
.
cols
;
tpDstImg
->
iHeight
=
maskj
.
rows
;
tpDstImg
->
iDepth
=
maskj
.
depth
();
tpDstImg
->
iChannels
=
maskj
.
channels
();
//内存尺寸
//内存尺寸
int
_Size
=
tpDstImg
->
iWidth
*
tpDstImg
->
iHeight
*
tpDstImg
->
iChannels
*
sizeof
(
uint8_t
);
int
_Size
=
tpDstImg
->
iWidth
*
tpDstImg
->
iHeight
*
tpDstImg
->
iChannels
*
sizeof
(
uint8_t
);
...
@@ -1285,7 +1297,7 @@ int eyemBinThresholdC(EyemImage tpImage, int ipRangeL[3], int ipRangeU[3], EyemI
...
@@ -1285,7 +1297,7 @@ int eyemBinThresholdC(EyemImage tpImage, int ipRangeL[3], int ipRangeU[3], EyemI
memset
(
tpDstImg
->
vpImage
,
0
,
_Size
);
memset
(
tpDstImg
->
vpImage
,
0
,
_Size
);
//拷贝数据
//拷贝数据
memcpy
(
tpDstImg
->
vpImage
,
mask
.
data
,
_Size
);
memcpy
(
tpDstImg
->
vpImage
,
mask
j
.
data
,
_Size
);
return
FUNC_OK
;
return
FUNC_OK
;
}
}
...
...
eyemLib/eyemCodeDetector.cpp
查看文件 @
cde6cc7
...
@@ -95,7 +95,7 @@ std::vector<std::string> CodeDetector::Impl::decode(const cv::Mat& img, std::vec
...
@@ -95,7 +95,7 @@ std::vector<std::string> CodeDetector::Impl::decode(const cv::Mat& img, std::vec
continue
;
continue
;
}
}
float
padding_w
=
0.1
f
,
padding_h
=
0.1
f
;
float
padding_w
=
0.1
f
,
padding_h
=
0.1
f
;
auto
min_padding
=
3
5
;
auto
min_padding
=
1
5
;
int
padx
=
(
int
)
cv
::
max
(
padding_w
*
bbox
.
width
,
static_cast
<
float
>
(
min_padding
));
int
padx
=
(
int
)
cv
::
max
(
padding_w
*
bbox
.
width
,
static_cast
<
float
>
(
min_padding
));
int
pady
=
(
int
)
cv
::
max
(
padding_h
*
bbox
.
height
,
static_cast
<
float
>
(
min_padding
));
int
pady
=
(
int
)
cv
::
max
(
padding_h
*
bbox
.
height
,
static_cast
<
float
>
(
min_padding
));
...
@@ -115,7 +115,7 @@ std::vector<std::string> CodeDetector::Impl::decode(const cv::Mat& img, std::vec
...
@@ -115,7 +115,7 @@ std::vector<std::string> CodeDetector::Impl::decode(const cv::Mat& img, std::vec
auto
scale_list
=
getScaleList
(
cropped_img
.
cols
,
cropped_img
.
rows
);
auto
scale_list
=
getScaleList
(
cropped_img
.
cols
,
cropped_img
.
rows
);
for
(
auto
cur_scale
:
scale_list
)
{
for
(
auto
cur_scale
:
scale_list
)
{
//测试用
//测试用
cv
::
medianBlur
(
cropped_img
,
cropped_img
,
3
);
//
cv::medianBlur(cropped_img, cropped_img, 3);
//缩放图像
//缩放图像
cv
::
Mat
scaled_img
=
cv
::
Mat
scaled_img
=
processImageScale
(
cropped_img
,
cur_scale
);
processImageScale
(
cropped_img
,
cur_scale
);
...
...
eyemLib/eyemEdge1d.cpp
查看文件 @
cde6cc7
...
@@ -504,7 +504,7 @@ int eyemEdge1dGenArc(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLineEd
...
@@ -504,7 +504,7 @@ int eyemEdge1dGenArc(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLineEd
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyem
Edge1dRidgeDetection
(
EyemImage
tpImage
)
int
eyem
PolarTrans
(
EyemImage
tpImage
,
EyemOcsDXY
tpCenter
,
int
iRadius
,
int
iSapWidth
)
{
{
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
image
.
empty
())
{
if
(
image
.
empty
())
{
...
@@ -519,71 +519,65 @@ int eyemEdge1dRidgeDetection(EyemImage tpImage)
...
@@ -519,71 +519,65 @@ int eyemEdge1dRidgeDetection(EyemImage tpImage)
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGR2GRAY
);
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGR2GRAY
);
}
}
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
//判断越界
auto
polarity
=
line_polarity
::
dark
;
if
(
tpCenter
.
dX
<
0
||
tpCenter
.
dY
<
0
||
tpCenter
.
dX
>
X
||
tpCenter
.
dY
>
Y
)
{
float
sigma
=
1.832
,
low_thr
=
0.0
,
high_thr
=
0.05
;
return
0
;
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
());
float
C
=
2.0
f
*
(
float
)
CV_PI
*
(
float
)(
iRadius
+
iSapWidth
);
std
::
string
output
=
"AvgLength: "
+
std
::
to_string
(
avg_node_count
);
//步长(角度)
std
::
string
output2
=
"Count: "
+
std
::
to_string
(
results
.
size
());
float
plusStep
=
2.0
f
*
asinf
((
1.0
f
+
(
C
-
(
float
)
cvRound
(
C
))
/
(
float
)
cvRound
(
C
))
/
(
2.0
f
*
(
float
)(
iRadius
+
+
iSapWidth
)));
//长度
cv
::
Mat
display
;
int
iSapLength
=
cvRound
(
2.0
f
*
CV_PI
/
plusStep
);
cv
::
cvtColor
(
image
,
display
,
cv
::
COLOR_GRAY2BGR
);
//结果图像
cv
::
Mat
polarMat
(
cv
::
Size
(
iSapLength
,
2
*
iSapWidth
),
CV_8UC1
,
cv
::
Scalar
(
0
));
if
(
true
)
{
for
(
int
n
=
iSapWidth
;
n
>
-
iSapWidth
;
n
--
)
int
factor
=
8
;
{
for
(
auto
cc
=
0
;
cc
<
results
.
size
();
cc
++
)
{
//周长
const
contour
&
ct
=
results
[
cc
];
C
=
2.0
f
*
(
float
)
CV_PI
*
(
float
)(
iRadius
+
n
);
std
::
vector
<
cv
::
Point
>
pts
;
//步长(角度)
std
::
vector
<
float
>::
const_iterator
rowItr
=
ct
.
row
.
begin
();
plusStep
=
2.0
f
*
asinf
((
1.0
f
+
(
C
-
(
float
)
cvRound
(
C
))
/
(
float
)
cvRound
(
C
))
/
(
2.0
f
*
(
float
)(
iRadius
+
n
)));
std
::
vector
<
float
>::
const_iterator
colItr
=
ct
.
col
.
begin
();
//长度
for
(
auto
pp
=
0
;
pp
<
ct
.
row
.
size
();
pp
++
,
rowItr
++
,
colItr
++
)
{
iSapLength
=
cvRound
(
2.0
f
*
CV_PI
/
plusStep
);
pts
.
emplace_back
(
static_cast
<
int
>
(
*
colItr
*
factor
),
static_cast
<
int
>
(
*
rowItr
*
factor
));
//线采样
cv
::
Size
szMap
(
iSapLength
,
1
);
//采样图像
int
m
=
0
;
float
*
pPolarBuf
=
new
float
[
szMap
.
width
*
szMap
.
height
*
sizeof
(
float_t
)];
for
(
float
t
=
-
CV_PI
;
t
<
CV_PI
;
t
+=
plusStep
,
m
++
)
{
//路径上的点
float
_plusX
=
float
(
tpCenter
.
dX
+
(
float
)(
iRadius
+
n
)
*
cos
(
t
));
float
_plusY
=
float
(
tpCenter
.
dY
+
(
float
)(
iRadius
+
n
)
*
sin
(
t
));
//防止越界
if
(
_plusX
<
1
||
_plusX
>=
X
-
2
||
_plusY
<
1
||
_plusY
>=
Y
-
2
)
{
continue
;
}
}
polylines
(
display
,
pts
,
false
,
cv
::
Scalar
(
0
,
0
,
255
),
1
,
cv
::
LINE_AA
,
int
(
std
::
log2
(
factor
)));
//整数部分
}
int
x
=
cvRound
(
_plusX
),
y
=
cvRound
(
_plusY
);
//小数部分
int
start
=
100
;
float
u
=
abs
(
_plusX
-
((
float
)
x
+
0.5
f
))
;
auto
it
=
lm
.
begin
(
);
float
v
=
abs
(
_plusY
-
((
float
)
y
-
1.0
f
+
0.5
f
)
);
while
(
it
!=
lm
.
end
())
{
//插值计算灰度值
std
::
string
hout
=
"histogram ["
+
std
::
to_string
(
it
->
first
)
+
"] = "
+
std
::
to_string
(
it
->
second
);
float
gv
=
(
1.0
f
-
v
)
*
(
image
.
ptr
<
uint8_t
>
(
y
-
1
)[
x
]
*
(
1.0
f
-
u
)
+
image
.
ptr
<
uint8_t
>
(
y
-
1
)[
x
-
1
]
*
u
)
cv
::
putText
(
display
,
hout
.
c_str
(),
cv
::
Point
(
500
,
start
),
cv
::
FONT_HERSHEY_SIMPLEX
,
1.0
,
cv
::
Scalar
(
255
,
0
,
0
),
2
);
+
v
*
(
image
.
ptr
<
uint8_t
>
(
y
)[
x
]
*
(
1.0
f
-
u
)
+
image
.
ptr
<
uint8_t
>
(
y
)[
x
-
1
]
*
u
);
start
+=
30
;
//填入灰度值
it
++
;
pPolarBuf
[
m
]
=
gv
;
}
}
//仅支持8U类型
cv
::
Mat
polarMat1
(
szMap
,
CV_32FC1
,
pPolarBuf
);
polarMat1
.
convertTo
(
polarMat1
,
CV_8UC1
);
//插值,默认双线性插值
cv
::
Mat
polarMat2
;
cv
::
resize
(
polarMat1
,
polarMat2
,
cv
::
Size
(
polarMat
.
cols
,
1
));
//保存到大图
polarMat2
.
copyTo
(
polarMat
(
cv
::
Rect
(
0
,
iSapWidth
-
n
,
polarMat
.
cols
,
1
)));
//释放资源
delete
[]
pPolarBuf
;
pPolarBuf
=
NULL
;
}
}
//绘制profileLine
//drawCircle("", tpCenter, iRadius - iSapWidth, cv::Scalar(255, 153, 0), 2);
//drawCircle("", tpCenter, iRadius + iSapWidth, cv::Scalar(255, 153, 0), 2);
return
FUNC_OK
;
return
FUNC_OK
;
}
}
...
...
eyemLib/eyemEdge1d.h
查看文件 @
cde6cc7
...
@@ -5,1443 +5,7 @@
...
@@ -5,1443 +5,7 @@
#ifndef __EYEM_EDGE1D_H
#ifndef __EYEM_EDGE1D_H
#define __EYEM_EDGE1D_H
#define __EYEM_EDGE1D_H
#include <ostream>
#include "eyemLib.h"
#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 */
#endif
/* __EYEM_EDGE1D_H */
\ No newline at end of file
\ No newline at end of file
eyemLib/eyemLib.h
查看文件 @
cde6cc7
...
@@ -365,6 +365,12 @@ typedef struct {
...
@@ -365,6 +365,12 @@ typedef struct {
}
EyemOcsDCRUVW
;
// 用于表示椭圆体
}
EyemOcsDCRUVW
;
// 用于表示椭圆体
typedef
struct
{
double
dpRangeL
[
3
],
dpRangeU
[
3
];
// 提取下限,提取上限
double
dpRangeLExt
[
3
],
dpRangeUExt
[
3
];
// 额外提取下限,额外提取上限(针对处于跨模型颜色,比如红色)
}
EyemHSVModel
;
// 用于HSV颜色模型分割(H(0-180)、S(0-255)、V(0-255))
/********************************************************************************************/
/********************************************************************************************/
/* 每个特定于源的标头 */
/* 每个特定于源的标头 */
/********************************************************************************************/
/********************************************************************************************/
...
@@ -639,7 +645,7 @@ extern "C" {
...
@@ -639,7 +645,7 @@ extern "C" {
// 函数接口
// 函数接口
EXPORTS
int
eyemBinThreshold
(
EyemImage
tpSrcImg
,
int
iLightDark
,
double
dThresh
,
double
dMaxVal
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinThreshold
(
EyemImage
tpSrcImg
,
int
iLightDark
,
double
dThresh
,
double
dMaxVal
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinThresholdC
(
EyemImage
tpImage
,
int
ipRangeL
[
3
],
int
ipRangeU
[
3
]
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinThresholdC
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinAutoThreshold
(
EyemImage
tpSrcImg
,
double
dSigma
,
int
iLightDark
,
int
binMethod
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinAutoThreshold
(
EyemImage
tpSrcImg
,
double
dSigma
,
int
iLightDark
,
int
binMethod
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinNiBlack
(
EyemImage
tpSrcImg
,
int
iType
,
int
iWinSize
,
double
dK
,
int
binarizationMethod
,
double
dR
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinNiBlack
(
EyemImage
tpSrcImg
,
int
iType
,
int
iWinSize
,
double
dK
,
int
binarizationMethod
,
double
dR
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinDynThreshold
(
EyemImage
tpSrcImg
,
EyemImage
tpPreImg
,
double
dOffset
,
int
iType
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemBinDynThreshold
(
EyemImage
tpSrcImg
,
EyemImage
tpPreImg
,
double
dOffset
,
int
iType
,
EyemImage
*
tpDstImg
);
...
@@ -669,7 +675,7 @@ extern "C" {
...
@@ -669,7 +675,7 @@ extern "C" {
EXPORTS
int
eyemEdge1dGenPosRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
IntPtr
*
hObject
);
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
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
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
eyem
Edge1dRidgeDetection
(
EyemImage
tpImage
);
EXPORTS
int
eyem
PolarTrans
(
EyemImage
tpImage
,
EyemOcsDXY
tpCenter
,
int
iRadius
,
int
iSapWidth
);
EXPORTS
bool
eyemEdge1dGenMeasureFree
(
IntPtr
hObject
);
EXPORTS
bool
eyemEdge1dGenMeasureFree
(
IntPtr
hObject
);
#ifdef __cplusplus
#ifdef __cplusplus
...
@@ -884,9 +890,9 @@ extern "C" {
...
@@ -884,9 +890,9 @@ extern "C" {
EXPORTS
int
eyemReleaseModel
(
IntPtr
&
hModelID
);
EXPORTS
int
eyemReleaseModel
(
IntPtr
&
hModelID
);
EXPORTS
int
eyemTrackFeature
(
EyemImage
tpPrevImg
,
EyemImage
tpNextImg
,
EyemRect3
*
tpRois
,
int
iRoiNum
,
int
*
ipResults
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemTrackFeature
(
EyemImage
tpPrevImg
,
EyemImage
tpNextImg
,
EyemRect3
*
tpRois
,
int
iRoiNum
,
int
*
ipResults
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemAOIForTSAV
(
EyemImage
tpRefImg
,
EyemImage
tpNextImg
,
EyemRect3
*
tpRois
,
int
iRoiNum
);
EXPORTS
int
eyemAOIForTSAV
(
EyemImage
tpRefImg
,
EyemImage
tpNextImg
,
EyemRect3
*
tpRois
,
int
iRoiNum
);
EXPORTS
int
eyemMarkerTracing
(
EyemImage
tpImage
,
double
dThreshold
,
EyemOcsFXYR
*
tpCircle
,
EyemImage
*
tpDstImg
,
bool
bHighAccuracy
=
false
);
EXPORTS
int
eyemMarkerTracing
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
EyemOcsFXYR
*
tpCircle
,
EyemImage
*
tpDstImg
,
bool
bHighAccuracy
=
false
);
EXPORTS
int
eyemMulFuncTool
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
funcName
,
double
dThreshold
,
int
iNumToIgnore
,
EyemOcsFXYR
*
tpCircle
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemMulFuncTool
(
EyemImage
tpImage
,
EyemRect
tpRoi
,
const
char
*
funcName
,
double
dThreshold
,
int
iNumToIgnore
,
EyemOcsFXYR
*
tpCircle
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemLibImpl
(
EyemImage
tpImage
,
EyemImage
*
tpDstImg
);
EXPORTS
int
eyemLibImpl
(
EyemImage
tpImage
,
Eyem
HSVModel
tpHSVModel
,
Eyem
Image
*
tpDstImg
);
EXPORTS
int
eyemDrawLine
(
EyemImage
tpImage
,
EyemOcsDABC
tpLine
);
EXPORTS
int
eyemDrawLine
(
EyemImage
tpImage
,
EyemOcsDABC
tpLine
);
EXPORTS
int
eyemDrawCircle
(
EyemImage
tpImage
,
EyemOcsDXYR
tpCircle
);
EXPORTS
int
eyemDrawCircle
(
EyemImage
tpImage
,
EyemOcsDXYR
tpCircle
);
EXPORTS
int
eyemDrawRectangle
(
EyemImage
tpImag
,
EyemRect
tpRect
);
EXPORTS
int
eyemDrawRectangle
(
EyemImage
tpImag
,
EyemRect
tpRect
);
...
@@ -895,7 +901,7 @@ extern "C" {
...
@@ -895,7 +901,7 @@ extern "C" {
}
}
#endif
#endif
//跳过某接口执行
//
跳过某接口执行
extern
"C"
__declspec
(
dllexport
)
void
setSkipProcessID
(
int
pid
);
extern
"C"
__declspec
(
dllexport
)
void
setSkipProcessID
(
int
pid
);
// 日志回调定义
// 日志回调定义
...
...
eyemLib/eyemLib.vcxproj
查看文件 @
cde6cc7
...
@@ -183,7 +183,6 @@
...
@@ -183,7 +183,6 @@
<ClInclude Include="eyemSmooth.h" />
<ClInclude Include="eyemSmooth.h" />
<ClInclude Include="eyemCodeDetector.h" />
<ClInclude Include="eyemCodeDetector.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stegers.h" />
<ClInclude Include="yoloWrapper.h" />
<ClInclude Include="yoloWrapper.h" />
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
...
@@ -208,7 +207,6 @@
...
@@ -208,7 +207,6 @@
<ClCompile Include="eyemSmooth.cpp" />
<ClCompile Include="eyemSmooth.cpp" />
<ClCompile Include="eyemCodeDetector.cpp" />
<ClCompile Include="eyemCodeDetector.cpp" />
<ClCompile Include="libopencv.cpp" />
<ClCompile Include="libopencv.cpp" />
<ClCompile Include="stegers.cpp" />
<ClCompile Include="yoloWrapper.cpp" />
<ClCompile Include="yoloWrapper.cpp" />
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
...
...
eyemLib/eyemLib.vcxproj.filters
查看文件 @
cde6cc7
...
@@ -69,9 +69,6 @@
...
@@ -69,9 +69,6 @@
<ClInclude Include="eyemNNDetector.h">
<ClInclude Include="eyemNNDetector.h">
<Filter>源文件</Filter>
<Filter>源文件</Filter>
</ClInclude>
</ClInclude>
<ClInclude Include="stegers.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="eyemMatchShapes.h">
<ClInclude Include="eyemMatchShapes.h">
<Filter>源文件</Filter>
<Filter>源文件</Filter>
</ClInclude>
</ClInclude>
...
@@ -140,9 +137,6 @@
...
@@ -140,9 +137,6 @@
<ClCompile Include="eyemNNDetector.cpp">
<ClCompile Include="eyemNNDetector.cpp">
<Filter>源文件</Filter>
<Filter>源文件</Filter>
</ClCompile>
</ClCompile>
<ClCompile Include="stegers.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="eyemMatchShapes.cpp">
<ClCompile Include="eyemMatchShapes.cpp">
<Filter>源文件</Filter>
<Filter>源文件</Filter>
</ClCompile>
</ClCompile>
...
...
eyemLib/eyemMatchShapes.h
查看文件 @
cde6cc7
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
#define __EYEM_MATCHSHAPES_H
#define __EYEM_MATCHSHAPES_H
#include "eyemLib.h"
#include "eyemLib.h"
#include <algorithm>
class
shape_based_matching
class
shape_based_matching
{
{
...
@@ -38,5 +39,4 @@ private:
...
@@ -38,5 +39,4 @@ private:
void
release_double_matrix
(
double
**
&
matrix
,
int
size
);
void
release_double_matrix
(
double
**
&
matrix
,
int
size
);
};
};
#endif
/* __EYEM_MATCHSHAPES_H */
#endif
/* __EYEM_MATCHSHAPES_H */
\ No newline at end of file
\ No newline at end of file
eyemLib/eyemMisc.cpp
查看文件 @
cde6cc7
...
@@ -2494,6 +2494,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -2494,6 +2494,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if
(
coeff
>
1.0
f
)
{
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
}
}
//防止报错
if
(
_tplMat
.
cols
>
_traceMat
.
cols
||
_tplMat
.
rows
>
_traceMat
.
rows
)
{
if
(
_tplMat
.
cols
>
_traceMat
.
cols
||
_tplMat
.
rows
>
_traceMat
.
rows
)
{
return
FUNC_CANNOT_CALC
;
return
FUNC_CANNOT_CALC
;
}
}
...
@@ -2711,7 +2712,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -2711,7 +2712,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//更新元件间角度
//更新元件间角度
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
if
((
trackCenter
.
x
<
0
||
trackCenter
.
x
>
X
-
1
||
trackCenter
.
y
<
0
||
trackCenter
.
y
>
Y
-
1
)
||
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
found
=
false
;
}
}
else
{
else
{
...
@@ -2836,6 +2838,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -2836,6 +2838,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if
(
coeff
>
1.0
f
)
{
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
}
}
//防止报错
if
(
_tplMat
.
cols
>
_traceMat
.
cols
||
_tplMat
.
rows
>
_traceMat
.
rows
)
{
if
(
_tplMat
.
cols
>
_traceMat
.
cols
||
_tplMat
.
rows
>
_traceMat
.
rows
)
{
return
FUNC_CANNOT_CALC
;
return
FUNC_CANNOT_CALC
;
}
}
...
@@ -3046,7 +3049,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3046,7 +3049,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//更新元件间角度
//更新元件间角度
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
if
((
trackCenter
.
x
<
0
||
trackCenter
.
x
>
X
-
1
||
trackCenter
.
y
<
0
||
trackCenter
.
y
>
Y
-
1
)
||
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
found
=
false
;
}
}
else
{
else
{
...
@@ -3537,6 +3541,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3537,6 +3541,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if
(
coeff
>
1.0
f
)
{
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
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
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
...
@@ -3751,7 +3759,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3751,7 +3759,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//更新元件间角度
//更新元件间角度
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
if
((
trackCenter
.
x
<
0
||
trackCenter
.
x
>
X
-
1
||
trackCenter
.
y
<
0
||
trackCenter
.
y
>
Y
-
1
)
||
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
found
=
false
;
}
}
else
{
else
{
...
@@ -3876,6 +3885,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -3876,6 +3885,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if
(
coeff
>
1.0
f
)
{
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
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
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
...
@@ -4083,7 +4096,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4083,7 +4096,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//更新元件间角度
//更新元件间角度
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
if
((
trackCenter
.
x
<
0
||
trackCenter
.
x
>
X
-
1
||
trackCenter
.
y
<
0
||
trackCenter
.
y
>
Y
-
1
)
||
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
found
=
false
;
}
}
else
{
else
{
...
@@ -4147,7 +4161,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
...
@@ -4147,7 +4161,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
std
::
vector
<
uchar
>
colors0
(
nccomps
+
1
,
0
);
std
::
vector
<
uchar
>
colors0
(
nccomps
+
1
,
0
);
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
for
(
int
i
=
1
;
i
<
nccomps
;
i
++
)
{
colors0
[
i
]
=
255
;
colors0
[
i
]
=
255
;
if
((((
int
*
)
m2
.
data
)[(
cv
::
CC_STAT_AREA
)
+
(
i
)
*
m2
.
cols
]
<=
10
)
||
m2
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
]
*
m2
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]
>
400000
)
//经验值
if
((((
int
*
)
m2
.
data
)[(
cv
::
CC_STAT_AREA
)
+
(
i
)
*
m2
.
cols
]
<=
21
)
||
m2
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_WIDTH
]
*
m2
.
ptr
<
int
>
(
i
)[
cv
::
CC_STAT_HEIGHT
]
>
400000
)
//经验值
{
{
colors0
[
i
]
=
0
;
colors0
[
i
]
=
0
;
}
}
...
@@ -5278,6 +5292,10 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
...
@@ -5278,6 +5292,10 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
if
(
coeff
>
1.0
f
)
{
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
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
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
...
@@ -5491,7 +5509,8 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
...
@@ -5491,7 +5509,8 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
//更新元件间角度
//更新元件间角度
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
partDist
=
(
2
*
asin
(
dChordL
/
(
2
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
if
((
trackCenter
.
x
<
0
||
trackCenter
.
x
>
X
-
1
||
trackCenter
.
y
<
0
||
trackCenter
.
y
>
Y
-
1
)
||
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
found
=
false
;
}
}
else
{
else
{
...
@@ -5616,6 +5635,10 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
...
@@ -5616,6 +5635,10 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
if
(
coeff
>
1.0
f
)
{
if
(
coeff
>
1.0
f
)
{
cv
::
resize
(
_tplMat
,
_tplMat
,
cv
::
Size
(),
coeff
,
coeff
);
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
::
Mat
tplResult0
;
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
cv
::
matchTemplate
(
_traceMat
,
_tplMat
,
tplResult0
,
cv
::
TM_SQDIFF_NORMED
);
...
@@ -5824,7 +5847,8 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
...
@@ -5824,7 +5847,8 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
//更新元件间角度
//更新元件间角度
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
partDist
=
(
2.0
*
asin
(
dChordL
/
(
2.0
*
trackRadius
)))
*
180.0
/
PI
;
//追踪到了重复的元件
//追踪到了重复的元件
if
(
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
if
((
trackCenter
.
x
<
0
||
trackCenter
.
x
>
X
-
1
||
trackCenter
.
y
<
0
||
trackCenter
.
y
>
Y
-
1
)
||
trackMat
.
ptr
<
uint8_t
>
(
cvRound
(
trackCenter
.
y
))[
cvRound
(
trackCenter
.
x
)]
==
255
)
{
found
=
false
;
found
=
false
;
}
}
else
{
else
{
...
@@ -7568,7 +7592,7 @@ int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, i
...
@@ -7568,7 +7592,7 @@ int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, i
return
FUNC_OK
;
return
FUNC_OK
;
}
}
int
eyemMarkerTracing
(
EyemImage
tpImage
,
double
dThreshold
,
EyemOcsFXYR
*
tpCircle
,
EyemImage
*
tpDstImg
,
bool
bHighAccuracy
)
int
eyemMarkerTracing
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
EyemOcsFXYR
*
tpCircle
,
EyemImage
*
tpDstImg
,
bool
bHighAccuracy
)
{
{
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
...
@@ -7576,7 +7600,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
...
@@ -7576,7 +7600,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
return
FUNC_IMAGE_NOT_EXIST
;
return
FUNC_IMAGE_NOT_EXIST
;
const
int
X
=
image
.
cols
;
const
int
Y
=
image
.
rows
;
const
int
X
=
image
.
cols
;
const
int
Y
=
image
.
rows
;
int
incn
=
image
.
channels
();
int
incn
=
image
.
channels
();
if
(
incn
>
3
)
{
if
(
incn
>
3
)
{
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGRA2BGR
);
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_BGRA2BGR
);
...
@@ -7584,23 +7607,26 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
...
@@ -7584,23 +7607,26 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
else
if
(
incn
==
1
)
{
else
if
(
incn
==
1
)
{
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_GRAY2BGR
);
cv
::
cvtColor
(
image
,
image
,
cv
::
COLOR_GRAY2BGR
);
}
}
//滤波
//滤波
cv
::
blur
(
image
,
image
,
cv
::
Size
(
5
,
5
));
cv
::
blur
(
image
,
image
,
cv
::
Size
(
5
,
5
));
//用于显示
//用于显示
cv
::
Mat
cc
=
image
.
clone
();
cv
::
Mat
cc
=
image
.
clone
();
//转hsv空间
//转hsv空间
cv
::
Mat
imgGray
;
cv
::
Mat
imgGray
;
cv
::
cvtColor
(
image
,
imgGray
,
cv
::
COLOR_BGR2HSV
);
cv
::
cvtColor
(
image
,
imgGray
,
cv
::
COLOR_BGR2HSV
);
//红色比较特殊,分两个区间
//红色比较特殊,分两个区间
cv
::
Mat
mask1
,
mask2
;
cv
::
Mat
mask1
,
mask2
(
cv
::
Size
(
X
,
Y
),
CV_8UC1
,
cv
::
Scalar
(
0
));
cv
::
inRange
(
imgGray
,
cv
::
Scalar
(
0
,
43
,
46
),
cv
::
Scalar
(
10
,
255
,
255
),
mask1
);
cv
::
inRange
(
imgGray
,
cv
::
Scalar
(
tpHSVModel
.
dpRangeL
[
0
],
tpHSVModel
.
dpRangeL
[
1
],
tpHSVModel
.
dpRangeL
[
2
]),
cv
::
inRange
(
imgGray
,
cv
::
Scalar
(
156
,
43
,
46
),
cv
::
Scalar
(
180
,
255
,
255
),
mask2
);
cv
::
Scalar
(
tpHSVModel
.
dpRangeU
[
0
],
tpHSVModel
.
dpRangeU
[
1
],
tpHSVModel
.
dpRangeU
[
2
]),
mask1
);
//多个分割阈值
cv
::
Mat
maskj
,
imageR
;
if
((
tpHSVModel
.
dpRangeLExt
[
0
]
+
tpHSVModel
.
dpRangeLExt
[
1
]
+
tpHSVModel
.
dpRangeLExt
[
2
])
!=
0
||
(
tpHSVModel
.
dpRangeUExt
[
0
]
+
tpHSVModel
.
dpRangeUExt
[
1
]
+
tpHSVModel
.
dpRangeUExt
[
2
])
!=
0
)
{
cv
::
inRange
(
imgGray
,
cv
::
Scalar
(
tpHSVModel
.
dpRangeLExt
[
0
],
tpHSVModel
.
dpRangeLExt
[
1
],
tpHSVModel
.
dpRangeLExt
[
2
]),
cv
::
Scalar
(
tpHSVModel
.
dpRangeUExt
[
0
],
tpHSVModel
.
dpRangeUExt
[
1
],
tpHSVModel
.
dpRangeUExt
[
2
]),
mask2
);
}
//合并
cv
::
Mat
maskj
;
cv
::
bitwise_or
(
mask1
,
mask2
,
maskj
);
cv
::
bitwise_or
(
mask1
,
mask2
,
maskj
);
//去掉干扰
//去掉干扰
...
@@ -7642,20 +7668,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
...
@@ -7642,20 +7668,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
cv
::
Point2i
(
bbox
.
br
().
x
+
minSize
,
bbox
.
br
().
y
+
minSize
))
&
cv
::
Rect
(
0
,
0
,
X
,
Y
);
cv
::
Point2i
(
bbox
.
br
().
x
+
minSize
,
bbox
.
br
().
y
+
minSize
))
&
cv
::
Rect
(
0
,
0
,
X
,
Y
);
cv
::
Mat
limit
=
image
(
limRec
).
clone
();
cv
::
Mat
limit
=
image
(
limRec
).
clone
();
//转hsv空间
//cv::cvtColor(limit, limit, cv::COLOR_BGR2HSV);
/*cv::Mat mask1, mask2;
cv::inRange(limit, cv::Scalar(0, 43, 46), cv::Scalar(10, 255, 255), mask1);
cv::inRange(limit, cv::Scalar(156, 43, 46), cv::Scalar(180, 255, 255), mask2);
cv::Mat maskj, imageR;
cv::bitwise_or(mask1, mask2, maskj);
std::vector<std::vector<cv::Point>> _contours;
cv::findContours(maskj, _contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, limRec.tl());*/
//过滤
//过滤
std
::
vector
<
cv
::
Point
>
approx
;
std
::
vector
<
cv
::
Point
>
approx
;
float
arcL
=
(
float
)
cv
::
arcLength
(
cv
::
Mat
(
contour
),
true
);
float
arcL
=
(
float
)
cv
::
arcLength
(
cv
::
Mat
(
contour
),
true
);
...
@@ -7714,7 +7726,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
...
@@ -7714,7 +7726,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
if
(
AFAs
.
empty
())
{
if
(
AFAs
.
empty
())
{
return
FUNC_FAILED_DETECT
;
return
FUNC_FAILED_DETECT
;
}
}
//排序
//排序
std
::
sort
(
AFAs
.
begin
(),
AFAs
.
end
(),
std
::
less
<
AFA
>
());
std
::
sort
(
AFAs
.
begin
(),
AFAs
.
end
(),
std
::
less
<
AFA
>
());
//高精度定位
//高精度定位
...
@@ -7744,7 +7755,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
...
@@ -7744,7 +7755,6 @@ int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircl
tpCircle
->
fY
=
(
float
)
AFAs
[
0
].
tpCircle
.
dY
;
tpCircle
->
fY
=
(
float
)
AFAs
[
0
].
tpCircle
.
dY
;
tpCircle
->
fR
=
(
float
)
AFAs
[
0
].
tpCircle
.
dR
;
tpCircle
->
fR
=
(
float
)
AFAs
[
0
].
tpCircle
.
dR
;
}
}
//画图
//画图
cv
::
rectangle
(
cc
,
cv
::
Rect
(
cv
::
Point2f
(
tpCircle
->
fX
-
2.0
f
*
tpCircle
->
fR
,
tpCircle
->
fY
-
2.0
f
*
tpCircle
->
fR
),
cv
::
rectangle
(
cc
,
cv
::
Rect
(
cv
::
Point2f
(
tpCircle
->
fX
-
2.0
f
*
tpCircle
->
fR
,
tpCircle
->
fY
-
2.0
f
*
tpCircle
->
fR
),
cv
::
Point2f
(
tpCircle
->
fX
+
2.0
f
*
tpCircle
->
fR
,
tpCircle
->
fY
+
2.0
f
*
tpCircle
->
fR
)),
cv
::
Scalar
(
0
,
255
,
255
),
4
);
cv
::
Point2f
(
tpCircle
->
fX
+
2.0
f
*
tpCircle
->
fR
,
tpCircle
->
fY
+
2.0
f
*
tpCircle
->
fR
)),
cv
::
Scalar
(
0
,
255
,
255
),
4
);
...
@@ -7928,10 +7938,8 @@ int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, dou
...
@@ -7928,10 +7938,8 @@ int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, dou
return
FUNC_OK
;
return
FUNC_OK
;
}
}
#include "eyemMatchShapes.h"
#include "eyemMatchShapes.h"
int
eyemLibImpl
(
EyemImage
tpImage
,
EyemHSVModel
tpHSVModel
,
EyemImage
*
tpDstImg
)
int
eyemLibImpl
(
EyemImage
tpImage
,
EyemImage
*
tpDstImg
)
{
{
CV_Assert
(
NULL
!=
tpImage
.
vpImage
);
CV_Assert
(
NULL
!=
tpImage
.
vpImage
);
...
@@ -7940,10 +7948,17 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
...
@@ -7940,10 +7948,17 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
if
(
image
.
empty
())
if
(
image
.
empty
())
return
FUNC_IMAGE_NOT_EXIST
;
return
FUNC_IMAGE_NOT_EXIST
;
//多个分割阈值
if
((
tpHSVModel
.
dpRangeLExt
[
0
]
+
tpHSVModel
.
dpRangeLExt
[
1
]
+
tpHSVModel
.
dpRangeLExt
[
2
])
!=
0
||
(
tpHSVModel
.
dpRangeUExt
[
0
]
+
tpHSVModel
.
dpRangeUExt
[
1
]
+
tpHSVModel
.
dpRangeUExt
[
2
])
!=
0
)
{
std
::
cout
<<
"红色"
<<
std
::
endl
;
}
return
FUNC_OK
;
//shape_based_matching GM;
// object to implent geometric matching
//shape_based_matching GM; // object to implent geometric matching
//int lowThreshold = 10; //deafult value
//int lowThreshold = 10; //deafult value
//int highThreashold = 100; //deafult value
//int highThreashold = 100;
//deafult value
//double minScore = 0.25; //deafult value
//double minScore = 0.25; //deafult value
//double greediness = 0.8; //deafult value
//double greediness = 0.8; //deafult value
...
...
eyemLib/stegers.cpp
deleted
100644 → 0
查看文件 @
7dd2486
#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
\ No newline at end of file
eyemLib/stegers.h
deleted
100644 → 0
查看文件 @
7dd2486
#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
\ No newline at end of file
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论