Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
张士柳
/
eyemLib
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
图表
网络
创建新的问题
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 61eb66e4
由
张士柳
编写于
2021-07-29 17:33:34 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
无
1 个父辈
0361ce5a
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
255 行增加
和
203 行删除
eyemLib-Sharp/EyemLib.cs
eyemLib/eyemEdge1d.cpp
eyemLib/eyemFit.cpp
eyemLib/eyemLib.h
eyemLib/eyemLib.vcxproj
eyemLib-Sharp/EyemLib.cs
查看文件 @
61eb66e
...
...
@@ -853,9 +853,21 @@ namespace eyemLib_Sharp
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
//边缘查找
private
static
extern
int
eyemEdge1dGenPosRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
out
MeasureHandle
hObject
);
//findLine
/// <summary>
/// 寻找边缘
/// </summary>
/// <param name="tpImage">图像</param>
/// <param name="tpLineSt">卡尺起点</param>
/// <param name="tpLineEd">卡尺终点</param>
/// <param name="iWhRoi">卡尺宽度</param>
/// <param name="nCalipers">卡尺数量</param>
/// <param name="iSearchDirec">搜索方向(起点到终点方向的垂直方向)</param>
/// <param name="dAmpThreshold">最小边缘幅度</param>
/// <param name="ccTransition">灰度值过渡的类型以确定边缘'first','all', 'negative', 'positive'</param>
/// <param name="hObject">结果</param>
/// <returns></returns>
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
i
Transition
,
out
MeasureHandle
hObject
);
private
static
extern
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
nCalipers
,
int
iSearchDirec
,
double
dAmpThreshold
,
string
cc
Transition
,
out
MeasureHandle
hObject
);
[
DllImport
(
"eyemLib.dll"
,
CharSet
=
CharSet
.
None
,
CallingConvention
=
CallingConvention
.
Cdecl
)]
private
static
extern
int
eyemSkeleton
(
EyemImage
tpImage
);
//边缘
...
...
@@ -1284,18 +1296,22 @@ namespace eyemLib_Sharp
#
endregion
#
region
Test
1D
Edge
//EyemOcsDXY tpLineSt = new EyemOcsDXY();
//tpLineSt.dX = 947;
//tpLineSt.dY = 1;
//EyemOcsDXY tpLineEd = new EyemOcsDXY();
//tpLineEd.dX = 149;
//tpLineEd.dY = 548;
//MeasureHandle hObject;
//eyemEdge1dGenMeasureRect(ucpImage, tpLineSt, tpLineEd, 10, "all", 0, 0.9, 30, out hObject);
//eyemEdge1dGenPosRect(ucpImage, tpLineSt, tpLineEd, 50, 0, 0.9, 30, out hObject);
//eyemEdge1dFindLine(ucpImage, tpLineSt, tpLineEd, 15, 0, out hObject);
///hObject.Dispose();
EyemOcsDXY
tpLineSt
=
new
EyemOcsDXY
();
tpLineSt
.
dX
=
671
;
tpLineSt
.
dY
=
718
;
EyemOcsDXY
tpLineEd
=
new
EyemOcsDXY
();
tpLineEd
.
dX
=
858
;
tpLineEd
.
dY
=
716
;
MeasureHandle
hObject
;
//eyemEdge1dGenMeasureRect(image, tpLineSt, tpLineEd, 10, "all", 0, 0.9, 30, out hObject);
//eyemEdge1dGenPosRect(image, tpLineSt, tpLineEd, 50, 0, 0.9, 30, out hObject);
sw
.
Restart
();
eyemEdge1dFindLine
(
image
,
tpLineSt
,
tpLineEd
,
25
,
35
,
-
1
,
15
,
"negative"
,
out
hObject
);
sw
.
Stop
();
Console
.
WriteLine
(
"时间:"
+
sw
.
ElapsedMilliseconds
.
ToString
());
return
;
//hObject.Dispose();
#
endregion
#
region
Test
Matrix
...
...
@@ -1341,29 +1357,29 @@ namespace eyemLib_Sharp
#
region
Test
RobustFitLine
EyemOcsDXY
taPoint
=
new
EyemOcsDXY
();
List
<
EyemOcsDXY
>
taPoints
=
new
List
<
EyemOcsDXY
>();
//
EyemOcsDXY taPoint = new EyemOcsDXY();
//
List<EyemOcsDXY> taPoints = new List<EyemOcsDXY>();
//x^2/4+y^2/9=1
for
(
double
i
=
-
2.0
;
i
<=
2.0
;
i
+=
0.1
)
{
taPoint
.
dX
=
i
;
taPoint
.
dY
=
3
*
Math
.
Sqrt
(
1
-
Math
.
Pow
(
i
,
2
)
/
4
);
taPoints
.
Add
(
taPoint
);
//
for (double i = -2.0; i <= 2.0; i += 0.1)
//
{
//
taPoint.dX = i;
//
taPoint.dY = 3 * Math.Sqrt(1 - Math.Pow(i, 2) / 4);
//
taPoints.Add(taPoint);
taPoint
.
dX
=
i
;
taPoint
.
dY
=
-
3
*
Math
.
Sqrt
(
1
-
Math
.
Pow
(
i
,
2
)
/
4
);
taPoints
.
Add
(
taPoint
);
}
//
taPoint.dX = i;
//
taPoint.dY = -3 * Math.Sqrt(1 - Math.Pow(i, 2) / 4);
//
taPoints.Add(taPoint);
//
}
taPoint
.
dX
=
0
;
taPoint
.
dY
=
2
;
taPoints
.
Add
(
taPoint
);
//
taPoint.dX = 0;
//
taPoint.dY = 2;
//
taPoints.Add(taPoint);
taPoint
.
dX
=
2
;
taPoint
.
dY
=
1
;
taPoints
.
Add
(
taPoint
);
//
taPoint.dX = 2;
//
taPoint.dY = 1;
//
taPoints.Add(taPoint);
//taPoint.dX = 1;
//taPoint.dY = -1;
...
...
@@ -1418,12 +1434,12 @@ namespace eyemLib_Sharp
//EyemOcsDABCD tpPlane = new EyemOcsDABCD();
IntPtr
tpPoint
=
eyemStructArray2IntPtr
(
taPoints
.
ToArray
());
//eyemRobustFitPlane(taPoints.Count, tpPoint, 6, 0, ref tpPlane);
EyemOcsDXYLSQ
tpEllipse
=
new
EyemOcsDXYLSQ
();
eyemRobustFitEllipse
(
taPoints
.
Count
,
tpPoint
,
6
,
0
,
ref
tpEllipse
);
//
IntPtr tpPoint = eyemStructArray2IntPtr(taPoints.ToArray());
//
//
eyemRobustFitPlane(taPoints.Count, tpPoint, 6, 0, ref tpPlane);
//
EyemOcsDXYLSQ tpEllipse = new EyemOcsDXYLSQ();
//
eyemRobustFitEllipse(taPoints.Count, tpPoint, 6, 0, ref tpEllipse);
return
;
//
return;
//eyemFitLine(taPoints.Count, tpPoint, 10, ref tpLine);
//eyemRobustFitLine(taPoints.Count, tpPoint, 2, 0, ref tpLine);
//eyemFitLineRANSAC(taPoints.Count, tpPoint, 5, ref tpLine);
...
...
eyemLib/eyemEdge1d.cpp
查看文件 @
61eb66e
...
...
@@ -43,7 +43,7 @@ static cv::Mat projectMap(const cv::Mat map, int threshold)
std
::
vector
<
cv
::
Point
>
rejectPoint
;
for
(
int
i
=
0
;
i
<
temp
.
cols
;
i
++
)
{
rejectPoint
.
push_back
(
cv
::
Point
(
i
,
(
int
)(
height
-
temp
.
at
<
double
>
(
cv
::
Point
(
i
,
0
)))));
rejectPoint
.
push_back
(
cv
::
Point
(
i
,
(
int
)(
height
-
temp
.
at
<
float
>
(
cv
::
Point
(
i
,
0
)))));
}
cv
::
polylines
(
image
,
rejectPoint
,
false
,
cv
::
Scalar
(
0
,
255
,
0
),
1
,
8
,
0
);
...
...
@@ -53,11 +53,6 @@ static cv::Mat projectMap(const cv::Mat map, int threshold)
return
image
;
}
static
void
interp2
(
cv
::
Mat
&
src
,
cv
::
Mat
&
dst
,
cv
::
Mat
&
map1
,
cv
::
Mat
&
map2
)
{
}
int
eyemEdge1dGenMeasureRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
const
char
*
ccSubType
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
IntPtr
*
hObject
)
{
cv
::
Mat
image
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
CV_8UC1
,
tpImage
.
vpImage
);
...
...
@@ -385,60 +380,210 @@ int eyemEdge1dGenPosRect(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLi
int
eyemEdge1dFitLine
(
IntPtr
hObject
,
EyemOcsDABC
*
tpLine
)
{
// cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
// if (image.empty()) {
// return FUNC_IMAGE_NOT_EXIST;
// }
// const int X = image.cols, Y = image.rows;
// //显示用
// cv::Mat cc;
// cv::cvtColor(image, cc, cv::COLOR_GRAY2BGR);
//
// //判断越界
// if (tpLineSt.dX < 0 || tpLineSt.dY < 0 || tpLineSt.dX>X || tpLineSt.dY>Y || tpLineEd.dX<0 || tpLineEd.dY<0 || tpLineEd.dX>X || tpLineEd.dY>Y) {
// return FUNC_ILLEGAL_ARGUMENT;
// }
// //主轴倾角,这个角度是带有方向的(-180°~180°)
// double t;
// t = atan2(tpLineEd.dY - tpLineSt.dY, tpLineEd.dX - tpLineSt.dX);
// //直线上的坐标
// float capLenth = (float)cv::norm(cv::Point2d(tpLineSt.dX, tpLineSt.dY) - cv::Point2d(tpLineEd.dX, tpLineEd.dY));
// //卡尺个数(后期可以根据需求更改)
// nCalipers = nCalipers >= cvFloor(capLenth) ? cvFloor(capLenth) : nCalipers;
// //步长
// float plusStep = capLenth / (float)nCalipers;
// //分配内存
// const int _Size = (nCalipers + 1)*(2 * iWhRoi + 1) * sizeof(uint8_t);
// uint8_t *pMap = (uint8_t *)malloc(_Size);
// if (NULL == pMap)
// return FUNC_NOT_ENOUGH_MEM;
// memset(pMap, 0, _Size);
// //线采样
// std::vector<cv::Mat> vmSamples;
// cv::Mat nSamples(nCalipers + 1, 2 * iWhRoi + 1, CV_8UC1, pMap);
// for (int n = 0; n <= nCalipers; n++) {
// //中轴线路径上的点
// float plusX, plusY;
// plusX = n*plusStep*(float)cos(t);
// plusY = n*plusStep*(float)sin(t);
//
// cv::Point2f pt((float)tpLineSt.dX + plusX, (float)tpLineSt.dY + plusY);
// std::vector<cv::Point2f> mpts;
// for (int m = -iWhRoi; m <= iWhRoi; m++) {
// //待插值坐标
// float _plusX, _plusY;
// _plusX = (float)m*(float)cos(t + iTransition*PI_BY_2) + pt.x;
// _plusY = (float)m*(float)sin(t + iTransition*PI_BY_2) + pt.y;
// //防止越界
// if (_plusX < 0 || _plusX >= X - 1 || _plusY < 0 || _plusY >= Y - 1) {
// continue;
// }
// mpts.push_back(cv::Point2f(_plusX, _plusY));
// //插值计算灰度值
// int x = (int)floor(_plusX), y = (int)floor(_plusY);
// float u = _plusX - floor(_plusX);
// float v = _plusY - floor(_plusY);
// float gv = (1.0f - u)*(1.0f - v)*(float)image.ptr<uint8_t>(y)[x] + (1.0f - u)*v*(float)image.ptr<uint8_t>(y + 1)[x] +
// u*(1.0f - v)*(float)image.ptr<uint8_t>(y)[x + 1] + u*v*(float)image.ptr<uint8_t>(y + 1)[x + 1];
// //填入灰度值
// //pMap[(iWhRoi - m) + n*nSamples.cols] = cvRound(gv);//正常图像
// //pMap[(iWhRoi + m) + n*nSamples.cols] = cvRound(gv);//沿着采样方向的不正常图像
// }
//#ifdef _DEBUG
// cv::arrowedLine(cc, mpts[0], mpts[mpts.size() - 1], cv::Scalar(0, 255, 0), 1);
//#endif
// }
// //TODO:后续考虑边界填充
//
// //释放内存(Tips:当存在越界时候在用free释放时会报错)
// free((void *)pMap);
//根据导数符号确定由暗到明和由明到暗方向,执行圆拟合与直线拟合
//std::vector<EyemOcsDXY> *tpEdges = reinterpret_cast<std::vector<EyemOcsDXY>*>(hObject);
return
FUNC_OK
;
}
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
i
Transition
,
IntPtr
*
hObject
)
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
nCalipers
,
int
iSearchDirec
,
double
dAmpThreshold
,
const
char
*
cc
Transition
,
IntPtr
*
hObject
)
{
cv
::
Mat
image
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
CV_8UC1
,
tpImage
.
vpImage
);
cv
::
Mat
image
=
cv
::
Mat
(
tpImage
.
iHeight
,
tpImage
.
iWidth
,
MAKETYPE
(
tpImage
.
iDepth
,
tpImage
.
iChannels
),
tpImage
.
vpImage
).
clone
();
if
(
image
.
empty
())
{
return
FUNC_IMAGE_NOT_EXIST
;
}
const
int
X
=
image
.
cols
,
Y
=
image
.
rows
;
//显示用
cv
::
Mat
cc
;
cv
::
cvtColor
(
image
,
cc
,
cv
::
COLOR_GRAY2BGR
);
if
(
tpLineSt
.
dX
<
0
||
tpLineSt
.
dY
<
0
||
tpLineSt
.
dX
>
tpImage
.
iWidth
||
tpLineSt
.
dY
>
tpImage
.
iHeight
\
||
tpLineEd
.
dX
<
0
||
tpLineEd
.
dY
<
0
||
tpLineEd
.
dX
>
tpImage
.
iWidth
||
tpLineEd
.
dY
>
tpImage
.
iHeight
)
//判断越界
if
(
tpLineSt
.
dX
<
0
||
tpLineSt
.
dY
<
0
||
tpLineSt
.
dX
>
X
||
tpLineSt
.
dY
>
Y
||
tpLineEd
.
dX
<
0
||
tpLineEd
.
dY
<
0
||
tpLineEd
.
dX
>
X
||
tpLineEd
.
dY
>
Y
)
{
return
FUNC_ILLEGAL_ARGUMENT
;
//主轴倾斜角
double
t
=
.0
,
a
=
.0
,
b
=
.0
,
c
=
.0
;
t
=
atan2
(
-
tpLineEd
.
dX
+
tpLineSt
.
dX
,
tpLineEd
.
dY
-
tpLineSt
.
dY
)
/** 180. / PI*/
;
//主轴直线方程ax+by+c=0
a
=
-
(
tpLineSt
.
dY
-
tpLineEd
.
dY
);
b
=
(
tpLineSt
.
dX
-
tpLineEd
.
dX
);
c
=
tpLineEd
.
dX
*
tpLineSt
.
dY
-
tpLineSt
.
dX
*
tpLineEd
.
dY
;
double
x
=
(
tpLineSt
.
dX
+
tpLineEd
.
dX
)
/
2
;
double
y
=
-
(
a
*
x
+
c
)
/
b
;
double
*
dpWhalf
=
new
double
[
2
*
iWhRoi
+
1
];
for
(
int
i
=
-
iWhRoi
,
j
=
0
;
i
<=
iWhRoi
,
j
<
2
*
iWhRoi
+
1
;
i
++
,
j
++
)
}
//主轴倾角,这个角度是带有方向的(-180°~180°)
double
t
;
t
=
atan2
(
tpLineEd
.
dY
-
tpLineSt
.
dY
,
tpLineEd
.
dX
-
tpLineSt
.
dX
);
//直线上的坐标
float
capLenth
=
(
float
)
cv
::
norm
(
cv
::
Point2d
(
tpLineSt
.
dX
,
tpLineSt
.
dY
)
-
cv
::
Point2d
(
tpLineEd
.
dX
,
tpLineEd
.
dY
));
//卡尺个数
nCalipers
=
nCalipers
>=
cvFloor
(
capLenth
)
?
cvFloor
(
capLenth
)
:
nCalipers
;
//步长
float
plusStep
=
capLenth
/
(
float
)
nCalipers
;
//判断灰度值过滤类型
int
np
=
1
;
if
(
strcmp
(
"positive"
,
ccTransition
)
==
0
)
{
np
=
1
;
}
else
if
(
strcmp
(
"negative"
,
ccTransition
)
==
0
)
{
np
=
-
1
;
}
else
if
(
strcmp
(
"first"
,
ccTransition
))
{
}
//分配内存
const
int
_Size
=
(
nCalipers
+
1
)
*
(
2
*
iWhRoi
+
1
)
*
sizeof
(
uint8_t
);
uint8_t
*
pMap
=
(
uint8_t
*
)
malloc
(
_Size
);
if
(
NULL
==
pMap
)
return
FUNC_NOT_ENOUGH_MEM
;
memset
(
pMap
,
0
,
_Size
);
//线采样
cv
::
Size
szMap
(
2
*
iWhRoi
+
1
,
nCalipers
+
1
);
cv
::
Mat
nSamples
(
szMap
,
CV_8UC1
,
pMap
);
for
(
int
n
=
0
;
n
<=
nCalipers
;
n
++
)
{
dpWhalf
[
j
]
=
i
;
//中轴线路径上的点
float
plusX
,
plusY
;
plusX
=
(
float
)
n
*
plusStep
*
(
float
)
cos
(
t
);
plusY
=
(
float
)
n
*
plusStep
*
(
float
)
sin
(
t
);
cv
::
Point2f
pLine
((
float
)
tpLineSt
.
dX
+
plusX
,
(
float
)
tpLineSt
.
dY
+
plusY
);
cv
::
Mat
vmSample
(
1
,
szMap
.
width
,
CV_32FC1
);
for
(
int
m
=
-
iWhRoi
;
m
<=
iWhRoi
;
m
++
)
{
//待插值坐标
float
_plusX
,
_plusY
;
_plusX
=
(
float
)
m
*
(
float
)
cos
(
t
+
iSearchDirec
*
PI_BY_2
)
+
pLine
.
x
;
_plusY
=
(
float
)
m
*
(
float
)
sin
(
t
+
iSearchDirec
*
PI_BY_2
)
+
pLine
.
y
;
//防止越界
if
(
_plusX
<
0
||
_plusX
>=
X
-
1
||
_plusY
<
0
||
_plusY
>=
Y
-
1
)
{
continue
;
}
//插值计算灰度值
int
x
=
(
int
)
floor
(
_plusX
),
y
=
(
int
)
floor
(
_plusY
);
float
u
=
_plusX
-
floor
(
_plusX
);
float
v
=
_plusY
-
floor
(
_plusY
);
float
gv
=
(
1.0
f
-
u
)
*
(
1.0
f
-
v
)
*
(
float
)
image
.
ptr
<
uint8_t
>
(
y
)[
x
]
+
(
1.0
f
-
u
)
*
v
*
(
float
)
image
.
ptr
<
uint8_t
>
(
y
+
1
)[
x
]
+
u
*
(
1.0
f
-
v
)
*
(
float
)
image
.
ptr
<
uint8_t
>
(
y
)[
x
+
1
]
+
u
*
v
*
(
float
)
image
.
ptr
<
uint8_t
>
(
y
+
1
)[
x
+
1
];
//填入灰度值
vmSample
.
ptr
<
float_t
>
(
0
)[
iWhRoi
+
m
]
=
gv
;
//pMap[(iWhRoi - m) + n*nSamples.cols] = cvRound(gv);//正常图像
//pMap[(iWhRoi + m) + n*nSamples.cols] = cvRound(gv);//沿着采样方向的不正常图像
}
//定位,默认过滤一半像素
const
cv
::
Mat
whalf
=
(
cv
::
Mat_
<
float
>
(
1
,
5
)
<<
np
,
np
,
0
,
-
np
,
-
np
);
cv
::
Mat
map1
=
projectMap
(
vmSample
,
dAmpThreshold
);
float
*
pMag
=
new
float
[
szMap
.
width
];
cv
::
Mat
mag
(
cv
::
Size
(
szMap
.
width
,
1
),
CV_32FC1
,
pMag
);
cv
::
sepFilter2D
(
vmSample
,
mag
,
CV_32F
,
whalf
,
cv
::
Mat
::
ones
(
1
,
1
,
CV_32F
));
cv
::
Mat
map2
=
projectMap
(
mag
,
dAmpThreshold
);
//计算幅度最大值
float
maxVal
=
*
std
::
max_element
(
pMag
,
pMag
+
szMap
.
width
);
float
dist
=
(
float
)
std
::
distance
(
pMag
,
std
::
max_element
(
pMag
,
pMag
+
szMap
.
width
));
//遍历幅度值
for
(
int
i
=
0
;
i
<
szMap
.
width
;
i
++
)
{
}
//最终坐标
cv
::
Point2f
pSt
,
pEd
;
pSt
=
cv
::
Point2f
(
-
iWhRoi
*
(
float
)
cos
(
t
+
iSearchDirec
*
PI_BY_2
)
+
pLine
.
x
,
-
iWhRoi
*
(
float
)
sin
(
t
+
iSearchDirec
*
PI_BY_2
)
+
pLine
.
y
);
pEd
=
cv
::
Point2f
(
iWhRoi
*
(
float
)
cos
(
t
+
iSearchDirec
*
PI_BY_2
)
+
pLine
.
x
,
iWhRoi
*
(
float
)
sin
(
t
+
iSearchDirec
*
PI_BY_2
)
+
pLine
.
y
);
//阈值限定,计算亚像素坐标
if
(
maxVal
>
dAmpThreshold
)
{
int
l
,
m
,
r
;
float
a
,
b
,
c
,
u
;
m
=
(
int
)
dist
;
l
=
m
-
1
<
0
?
m
:
m
-
1
;
r
=
m
+
1
>=
szMap
.
width
?
m
:
m
+
1
;
a
=
pMag
[
l
];
b
=
pMag
[
m
];
c
=
pMag
[
r
];
//存在异常,无法计算亚像素坐标
float
dstX
,
dstY
;
if
(
abs
(
a
-
b
-
b
+
c
)
>
EPS
)
{
u
=
0.5
f
*
(
a
-
c
)
/
(
a
-
b
-
b
+
c
);
dstX
=
pSt
.
x
+
(
dist
+
0.5
f
+
u
)
*
(
float
)
cos
(
t
+
iSearchDirec
*
PI_BY_2
);
dstY
=
pSt
.
y
+
(
dist
+
0.5
f
+
u
)
*
(
float
)
sin
(
t
+
iSearchDirec
*
PI_BY_2
);
}
else
{
dstX
=
pSt
.
x
+
(
dist
+
0.5
f
)
*
(
float
)
cos
(
t
+
iSearchDirec
*
PI_BY_2
);
dstY
=
pSt
.
y
+
(
dist
+
0.5
f
)
*
(
float
)
sin
(
t
+
iSearchDirec
*
PI_BY_2
);
}
cc
.
ptr
<
cv
::
Vec3b
>
(
cvRound
(
dstY
))[
cvRound
(
dstX
)]
=
cv
::
Vec3b
(
0
,
255
,
255
);
}
cv
::
Mat
whalf
(
1
,
2
*
iWhRoi
+
1
,
CV_64F
,
dpWhalf
);
cv
::
Mat
map1
,
map2
;
//沿法线方向采样
map1
=
whalf
*
cos
(
t
);
map2
=
whalf
*
sin
(
t
);
map1
+=
cv
::
Mat
::
ones
(
1
,
31
,
CV_64F
)
*
x
;
map2
+=
cv
::
Mat
::
ones
(
1
,
31
,
CV_64F
)
*
y
;
cv
::
Mat
dst
;
interp2
(
image
,
dst
,
map1
,
map2
);
cv
::
Mat
cc
;
cv
::
cvtColor
(
image
,
cc
,
cv
::
COLOR_GRAY2BGR
);
for
(
int
i
=
0
;
i
<
31
;
i
++
)
{
cc
.
at
<
cv
::
Vec3b
>
(
cv
::
Point
(
cvRound
(
map1
.
at
<
double
>
(
0
,
i
)),
cvRound
(
map2
.
at
<
double
>
(
0
,
i
))))
=
cv
::
Vec3b
(
0
,
255
,
0
);
#ifdef _DEBUG
//cv::arrowedLine(cc, pSt, pEd, cv::Scalar(0, 255, 0), 1);
#endif
}
//TODO:后续考虑边界填充
//释放内存(Tips:当存在越界时候在用free释放时会报错)
free
((
void
*
)
pMap
);
return
FUNC_OK
;
}
...
...
eyemLib/eyemFit.cpp
查看文件 @
61eb66e
...
...
@@ -744,147 +744,37 @@ int eyemRobustFitPlane(int iPtnNum, EyemOcsDXYZ *taPoint, int iCalcMode, double
static
void
fitEllipse_wods
(
int
iPtnNum
,
const
EyemOcsDXY
*
taPoints
,
float
*
weights
,
float
*
linebuf
)
{
//计算系数
double
sa
[
25
],
sb
[
5
],
sx
[
5
];
cv
::
Mat
a
=
cv
::
Mat
(
5
,
5
,
CV_64F
,
sa
),
b
=
cv
::
Mat
(
5
,
1
,
CV_64F
,
sb
);
//系数矩阵A*X=B;
cv
::
Mat
x
=
cv
::
Mat
(
5
,
1
,
CV_64F
,
sx
);
memset
(
sa
,
0
,
sizeof
(
sa
));
memset
(
sb
,
0
,
sizeof
(
sb
));
memset
(
sx
,
0
,
sizeof
(
sx
));
for
(
int
i
=
0
;
i
<
iPtnNum
;
i
++
)
{
sa
[
0
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
;
sa
[
1
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
2
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
3
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
;
sa
[
4
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
5
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
6
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
7
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
8
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
9
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
10
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
11
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
12
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
13
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
14
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
15
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
;
sa
[
16
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
17
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
18
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
;
sa
[
19
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
20
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
21
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
22
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sa
[
23
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
;
sa
[
24
]
+=
(
double
)
weights
[
i
]
*
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
;
sb
[
0
]
+=
(
double
)
weights
[
i
]
*
(
-
taPoints
[
i
].
dX
*
taPoints
[
i
].
dX
);
sb
[
1
]
+=
(
double
)
weights
[
i
]
*
(
-
taPoints
[
i
].
dX
*
taPoints
[
i
].
dY
);
sb
[
2
]
+=
(
double
)
weights
[
i
]
*
(
-
taPoints
[
i
].
dY
*
taPoints
[
i
].
dY
);
sb
[
3
]
+=
(
double
)
weights
[
i
]
*
(
-
taPoints
[
i
].
dY
);
sb
[
3
]
+=
(
double
)
weights
[
i
]
*
(
-
taPoints
[
i
].
dX
);
//6%左右的点不要
std
::
vector
<
cv
::
Point2f
>
taPoint
;
for
(
int
i
=
0
;
i
<
iPtnNum
;
i
++
)
{
if
(
weights
[
i
])
{
taPoint
.
push_back
(
cv
::
Point2f
((
float
)
taPoints
[
i
].
dX
,
(
float
)
taPoints
[
i
].
dY
));
}
cv
::
solve
(
a
,
b
,
x
,
cv
::
DECOMP_SVD
);
//计算椭圆参数Ax^2+Bxy+Cy^2+Dx+Ey+F=0 F=1
float
s
,
l
,
t
,
x0
,
y0
,
A
,
B
,
C
,
D
,
E
,
F
;
//对应的
A
=
(
float
)
sx
[
0
],
B
=
(
float
)
sx
[
1
],
C
=
(
float
)
sx
[
2
],
D
=
(
float
)
sx
[
3
],
E
=
(
float
)
sx
[
4
],
F
=
1.0
f
;
//中心x
x0
=
(
B
*
E
-
2.0
f
*
C
*
D
)
/
(
4.0
f
*
A
*
C
-
B
*
B
);
//中心y
y0
=
(
B
*
D
-
2.0
f
*
A
*
E
)
/
(
4.0
f
*
A
*
C
-
B
*
B
);
//倾角
if
(
abs
(
B
/
A
)
<=
0.0001
f
&&
1.0
f
<
C
/
A
)
t
=
0.0
f
;
else
if
(
abs
(
B
/
A
)
<=
0.0001
f
&&
1.0
f
>
C
/
A
)
t
=
(
float
)
PI_BY_2
;
else
if
(
1.0
f
<
C
/
A
)
t
=
0.5
f
*
atan
((
B
/
A
)
/
(
1.0
f
-
C
/
A
));
else
t
=
(
float
)
PI_BY_2
+
0.5
f
*
atan
((
B
/
A
)
/
(
1.0
f
-
C
/
A
));
//长轴半径
l
=
sqrt
(
2.0
f
*
(
A
*
x0
*
x0
+
C
*
y0
*
y0
*
B
*
x0
*
y0
-
1.0
f
)
/
(
A
+
C
-
sqrt
((
A
-
C
)
*
(
A
-
C
)
+
B
*
B
)));
//短轴半径
s
=
sqrt
(
2.0
f
*
(
A
*
x0
*
x0
+
C
*
y0
*
y0
*
B
*
x0
*
y0
-
1.0
f
)
/
(
A
+
C
+
sqrt
((
A
-
C
)
*
(
A
-
C
)
+
B
*
B
)));
}
//拟合椭圆
auto
rbox
=
cv
::
fitEllipse
(
taPoint
);
//结果
linebuf
[
0
]
=
x0
;
linebuf
[
1
]
=
y0
;
linebuf
[
2
]
=
cv
::
max
(
l
,
s
);
linebuf
[
3
]
=
cv
::
min
(
l
,
s
);
linebuf
[
4
]
=
t
;
linebuf
[
0
]
=
rbox
.
center
.
x
;
linebuf
[
1
]
=
rbox
.
center
.
y
;
linebuf
[
2
]
=
cv
::
max
(
rbox
.
size
.
width
/
2.0
f
,
rbox
.
size
.
height
/
2.0
f
);
linebuf
[
3
]
=
cv
::
min
(
rbox
.
size
.
width
/
2.0
f
,
rbox
.
size
.
height
/
2.0
f
);
linebuf
[
4
]
=
rbox
.
angle
*
(
float
)
PI
/
180.0
f
;
}
int
eyemRobustFitEllipse
(
int
iPtnNum
,
EyemOcsDXY
*
taPoint
,
int
iCalcMode
,
double
dRobustCoef
,
EyemOcsDXYLSQ
&
tpEllipse
)
{
double
min_err
=
DBL_MAX
,
err
=
0
;
void
(
*
calc_weights_param
)
(
float
*
,
int
,
float
*
,
float
)
=
0
;
float
linebuf
[
5
]
=
{
.0
f
};
memset
(
linebuf
,
0
,
5
*
sizeof
(
float
));
std
::
vector
<
float
>
weights
(
iPtnNum
,
1.0
);
switch
(
iCalcMode
)
{
case
EYEM_DIST_L1
:
calc_weights_param
=
weightL1
;
break
;
case
EYEM_DIST_L12
:
calc_weights_param
=
weightL12
;
break
;
case
EYEM_DIST_FAIR
:
calc_weights_param
=
weightFair
;
break
;
case
EYEM_DIST_WELSCH
:
calc_weights_param
=
weightWelsch
;
break
;
case
EYEM_DIST_HUBER
:
calc_weights_param
=
weightHuber
;
break
;
case
EYEM_DIST_TUKEY
:
calc_weights_param
=
weightTukey
;
break
;
case
EYEM_DIST_CAUCHY
:
calc_weights_param
=
weightCauchy
;
break
;
case
EYEM_DIST_LOGISTIC
:
calc_weights_param
=
weightLogistic
;
break
;
case
EYEM_DIST_ANDREWS
:
calc_weights_param
=
weightAndrews
;
break
;
case
EYEM_DIST_ATLWORTH
:
calc_weights_param
=
weightTalworth
;
break
;
case
EYEM_DIST_USER
:
calc_weights_param
=
weightUser
;
break
;
default:
break
;
}
//迭代计算
for
(
int
n
=
0
;
n
<
100
;
n
++
)
{
float
sum_dist
=
.0
,
sum_w
=
.0
;
fitEllipse_wods
(
iPtnNum
,
taPoint
,
&
weights
[
0
],
linebuf
);
//椭圆参数
float
x0
=
linebuf
[
0
],
y0
=
linebuf
[
1
],
l
=
linebuf
[
2
],
s
=
linebuf
[
3
],
t
=
linebuf
[
4
],
c
=
sqrt
(
abs
(
l
*
l
-
s
*
s
));
//焦点
cv
::
Point2f
f1
(
x0
-
c
*
cos
(
t
),
y0
-
c
*
sin
(
t
)),
f
2
(
x0
+
c
*
cos
(
t
),
y0
+
c
*
sin
(
t
));
cv
::
AutoBuffe
r
<
float
>
dist
(
iPtnNum
);
cv
::
Point2f
F1
(
x0
-
c
*
cos
(
t
),
y0
-
c
*
sin
(
t
)),
F
2
(
x0
+
c
*
cos
(
t
),
y0
+
c
*
sin
(
t
));
std
::
vecto
r
<
float
>
dist
(
iPtnNum
);
for
(
int
k
=
0
;
k
<
iPtnNum
;
k
++
)
{
dist
[
k
]
=
fabs
(((
float
)
cv
::
norm
(
cv
::
Point2f
((
float
)
taPoint
[
k
].
dX
,
(
float
)
taPoint
[
k
].
dY
)
-
f1
)
+
(
float
)
cv
::
norm
(
cv
::
Point2f
((
float
)
taPoint
[
k
].
dX
,
(
float
)
taPoint
[
k
].
dY
)
-
f
2
))
-
2.0
f
*
l
);
dist
[
k
]
=
fabs
(((
float
)
cv
::
norm
(
cv
::
Point2f
((
float
)
taPoint
[
k
].
dX
,
(
float
)
taPoint
[
k
].
dY
)
-
F1
)
+
(
float
)
cv
::
norm
(
cv
::
Point2f
((
float
)
taPoint
[
k
].
dX
,
(
float
)
taPoint
[
k
].
dY
)
-
F
2
))
-
2.0
f
*
l
);
sum_dist
+=
dist
[
k
];
}
err
=
sum_dist
;
if
(
sum_dist
<
FLT_EPSILON
)
break
;
/*calculate weight*/
calc_weights_param
(
dist
,
iPtnNum
,
&
weights
[
0
],
(
float
)
dRobustCoef
);
if
(
std
::
abs
(
err
-
min_err
)
<
FLT_EPSILON
)
break
;
min_err
=
err
;
}
tpEllipse
.
dL
=
linebuf
[
2
],
tpEllipse
.
dS
=
linebuf
[
3
],
tpEllipse
.
dQ
=
linebuf
[
4
],
tpEllipse
.
dXo
=
linebuf
[
0
],
tpEllipse
.
dYo
=
linebuf
[
1
];
return
FUNC_OK
;
}
...
...
eyemLib/eyemLib.h
查看文件 @
61eb66e
...
...
@@ -645,7 +645,7 @@ extern "C" {
EXPORTS
int
eyemEdge1dGenPosRect
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
iTransition
,
double
dSigma
,
double
dAmpThresh
,
IntPtr
*
hObject
);
EXPORTS
int
eyemEdge1dFitLine
(
IntPtr
hObject
,
int
iClippingEndPoints
,
int
iMaxIterations
,
double
dRobustCoef
,
EyemOcsDABC
*
tpLine
);
EXPORTS
int
eyemEdge1dFitCircle
(
IntPtr
hObject
,
int
iClippingEndPoints
,
int
iMaxIterations
,
double
dRobustCoef
,
EyemOcsDXYR
*
tpCircle
);
EXPORTS
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
i
Transition
,
IntPtr
*
hObject
);
EXPORTS
int
eyemEdge1dFindLine
(
EyemImage
tpImage
,
EyemOcsDXY
tpLineSt
,
EyemOcsDXY
tpLineEd
,
int
iWhRoi
,
int
nCalipers
,
int
iSearchDirec
,
double
dAmpThreshold
,
const
char
*
cc
Transition
,
IntPtr
*
hObject
);
EXPORTS
bool
eyemEdge1dGenMeasureFree
(
IntPtr
hObject
);
#ifdef __cplusplus
...
...
eyemLib/eyemLib.vcxproj
查看文件 @
61eb66e
...
...
@@ -85,6 +85,7 @@
<LinkIncremental>false</LinkIncremental>
<IncludePath>D:\opencv420\build\include;D:\opencv420\build\include\opencv2;D:\tbb2017_20170604oss\include;D:\zxing-cpp-master\core\src;D:\zxing-cpp-master\opencv\src;$(IncludePath)</IncludePath>
<LibraryPath>D:\opencv420\build\x64\vc14\lib;D:\tbb2017_20170604oss\lib\intel64\vc14;D:\zxing-cpp-master\build\Release;$(LibraryPath)</LibraryPath>
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论