Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Opencv
提交
73e1d64a
O
Opencv
项目概览
Greenplum
/
Opencv
11 个月 前同步成功
通知
7
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Opencv
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
73e1d64a
编写于
9月 27, 2016
作者:
A
Alexander Alekhin
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #6956 from mshabunin:fix-chessboard-bug
上级
f4b84dd4
b8bce552
变更
5
展开全部
隐藏空白更改
内联
并排
Showing
5 changed file
with
515 addition
and
656 deletion
+515
-656
modules/calib3d/src/calibinit.cpp
modules/calib3d/src/calibinit.cpp
+389
-460
modules/calib3d/src/checkchessboard.cpp
modules/calib3d/src/checkchessboard.cpp
+100
-178
modules/calib3d/src/precomp.hpp
modules/calib3d/src/precomp.hpp
+3
-0
modules/calib3d/test/test_chesscorners.cpp
modules/calib3d/test/test_chesscorners.cpp
+21
-16
modules/python/test/test_calibration.py
modules/python/test/test_calibration.py
+2
-2
未找到文件。
modules/calib3d/src/calibinit.cpp
浏览文件 @
73e1d64a
此差异已折叠。
点击以展开。
modules/calib3d/src/checkchessboard.cpp
浏览文件 @
73e1d64a
...
...
@@ -46,28 +46,26 @@
#include <vector>
#include <algorithm>
//#define DEBUG_WINDOWS
using
namespace
cv
;
using
namespace
std
;
#if defined(DEBUG_WINDOWS)
# include "opencv2/opencv_modules.hpp"
# ifdef HAVE_OPENCV_HIGHGUI
# include "opencv2/highgui.hpp"
# else
# undef DEBUG_WINDOWS
# endif
#endif
int
cvCheckChessboardBinary
(
IplImage
*
src
,
CvSize
size
);
static
void
icvGetQuadrangleHypotheses
(
CvSeq
*
contours
,
std
::
vector
<
std
::
pair
<
float
,
int
>
>&
quads
,
int
class_id
)
static
void
icvGetQuadrangleHypotheses
(
const
std
::
vector
<
std
::
vector
<
cv
::
Point
>
>
&
contours
,
const
std
::
vector
<
cv
::
Vec4i
>
&
hierarchy
,
std
::
vector
<
std
::
pair
<
float
,
int
>
>&
quads
,
int
class_id
)
{
const
float
min_aspect_ratio
=
0.3
f
;
const
float
max_aspect_ratio
=
3.0
f
;
const
float
min_box_size
=
10.0
f
;
for
(
CvSeq
*
seq
=
contours
;
seq
!=
NULL
;
seq
=
seq
->
h_next
)
typedef
std
::
vector
<
std
::
vector
<
cv
::
Point
>
>::
const_iterator
iter_t
;
iter_t
i
;
for
(
i
=
contours
.
begin
();
i
!=
contours
.
end
();
++
i
)
{
CvBox2D
box
=
cvMinAreaRect2
(
seq
);
const
iter_t
::
difference_type
idx
=
i
-
contours
.
begin
();
if
(
hierarchy
.
at
(
idx
)[
3
]
!=
-
1
)
continue
;
// skip holes
const
std
::
vector
<
cv
::
Point
>
&
c
=
*
i
;
cv
::
RotatedRect
box
=
cv
::
minAreaRect
(
c
);
float
box_size
=
MAX
(
box
.
size
.
width
,
box
.
size
.
height
);
if
(
box_size
<
min_box_size
)
{
...
...
@@ -98,113 +96,98 @@ inline bool less_pred(const std::pair<float, int>& p1, const std::pair<float, in
return
p1
.
first
<
p2
.
first
;
}
// does a fast check if a chessboard is in the input image. This is a workaround to
// a problem of cvFindChessboardCorners being slow on images with no chessboard
// - src: input image
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int
cvCheckChessboard
(
IplImage
*
src
,
CvSize
size
)
static
void
fillQuads
(
Mat
&
white
,
Mat
&
black
,
double
white_thresh
,
double
black_thresh
,
vector
<
pair
<
float
,
int
>
>
&
quads
)
{
if
(
src
->
nChannels
>
1
)
Mat
thresh
;
{
cvError
(
CV_BadNumChannels
,
"cvCheckChessboard"
,
"supports single-channel images only"
,
__FILE__
,
__LINE__
);
vector
<
vector
<
Point
>
>
contours
;
vector
<
Vec4i
>
hierarchy
;
threshold
(
white
,
thresh
,
white_thresh
,
255
,
THRESH_BINARY
);
findContours
(
thresh
,
contours
,
hierarchy
,
RETR_CCOMP
,
CHAIN_APPROX_SIMPLE
);
icvGetQuadrangleHypotheses
(
contours
,
hierarchy
,
quads
,
1
);
}
if
(
src
->
depth
!=
8
)
{
cvError
(
CV_BadDepth
,
"cvCheckChessboard"
,
"supports depth=8 images only"
,
__FILE__
,
__LINE__
);
vector
<
vector
<
Point
>
>
contours
;
vector
<
Vec4i
>
hierarchy
;
threshold
(
black
,
thresh
,
black_thresh
,
255
,
THRESH_BINARY_INV
);
findContours
(
thresh
,
contours
,
hierarchy
,
RETR_CCOMP
,
CHAIN_APPROX_SIMPLE
);
icvGetQuadrangleHypotheses
(
contours
,
hierarchy
,
quads
,
0
);
}
}
const
int
erosion_count
=
1
;
const
float
black_level
=
20.
f
;
const
float
white_level
=
130.
f
;
const
float
black_white_gap
=
70.
f
;
#if defined(DEBUG_WINDOWS)
cvNamedWindow
(
"1"
,
1
);
cvShowImage
(
"1"
,
src
);
cvWaitKey
(
0
);
#endif //DEBUG_WINDOWS
CvMemStorage
*
storage
=
cvCreateMemStorage
();
IplImage
*
white
=
cvCloneImage
(
src
);
IplImage
*
black
=
cvCloneImage
(
src
);
static
bool
checkQuads
(
vector
<
pair
<
float
,
int
>
>
&
quads
,
const
cv
::
Size
&
size
)
{
const
size_t
min_quads_count
=
size
.
width
*
size
.
height
/
2
;
std
::
sort
(
quads
.
begin
(),
quads
.
end
(),
less_pred
);
cvErode
(
white
,
white
,
NULL
,
erosion_count
);
cvDilate
(
black
,
black
,
NULL
,
erosion_count
);
IplImage
*
thresh
=
cvCreateImage
(
cvGetSize
(
src
),
IPL_DEPTH_8U
,
1
)
;
// now check if there are many hypotheses with similar sizes
// do this by floodfill-style algorithm
const
float
size_rel_dev
=
0.4
f
;
int
result
=
0
;
for
(
float
thresh_level
=
black_level
;
thresh_level
<
white_level
&&
!
result
;
thresh_level
+=
20.0
f
)
for
(
size_t
i
=
0
;
i
<
quads
.
size
();
i
++
)
{
cvThreshold
(
white
,
thresh
,
thresh_level
+
black_white_gap
,
255
,
CV_THRESH_BINARY
);
#if defined(DEBUG_WINDOWS)
cvShowImage
(
"1"
,
thresh
);
cvWaitKey
(
0
);
#endif //DEBUG_WINDOWS
CvSeq
*
first
=
0
;
std
::
vector
<
std
::
pair
<
float
,
int
>
>
quads
;
cvFindContours
(
thresh
,
storage
,
&
first
,
sizeof
(
CvContour
),
CV_RETR_CCOMP
);
icvGetQuadrangleHypotheses
(
first
,
quads
,
1
);
cvThreshold
(
black
,
thresh
,
thresh_level
,
255
,
CV_THRESH_BINARY_INV
);
#if defined(DEBUG_WINDOWS)
cvShowImage
(
"1"
,
thresh
);
cvWaitKey
(
0
);
#endif //DEBUG_WINDOWS
cvFindContours
(
thresh
,
storage
,
&
first
,
sizeof
(
CvContour
),
CV_RETR_CCOMP
);
icvGetQuadrangleHypotheses
(
first
,
quads
,
0
);
const
size_t
min_quads_count
=
size
.
width
*
size
.
height
/
2
;
std
::
sort
(
quads
.
begin
(),
quads
.
end
(),
less_pred
);
// now check if there are many hypotheses with similar sizes
// do this by floodfill-style algorithm
const
float
size_rel_dev
=
0.4
f
;
for
(
size_t
i
=
0
;
i
<
quads
.
size
();
i
++
)
size_t
j
=
i
+
1
;
for
(;
j
<
quads
.
size
();
j
++
)
{
size_t
j
=
i
+
1
;
for
(;
j
<
quads
.
size
();
j
++
)
if
(
quads
[
j
].
first
/
quads
[
i
].
first
>
1.0
f
+
size_rel_dev
)
{
if
(
quads
[
j
].
first
/
quads
[
i
].
first
>
1.0
f
+
size_rel_dev
)
{
break
;
}
break
;
}
}
if
(
j
+
1
>
min_quads_count
+
i
)
if
(
j
+
1
>
min_quads_count
+
i
)
{
// check the number of black and white squares
std
::
vector
<
int
>
counts
;
countClasses
(
quads
,
i
,
j
,
counts
);
const
int
black_count
=
cvRound
(
ceil
(
size
.
width
/
2.0
)
*
ceil
(
size
.
height
/
2.0
));
const
int
white_count
=
cvRound
(
floor
(
size
.
width
/
2.0
)
*
floor
(
size
.
height
/
2.0
));
if
(
counts
[
0
]
<
black_count
*
0.75
||
counts
[
1
]
<
white_count
*
0.75
)
{
// check the number of black and white squares
std
::
vector
<
int
>
counts
;
countClasses
(
quads
,
i
,
j
,
counts
);
const
int
black_count
=
cvRound
(
ceil
(
size
.
width
/
2.0
)
*
ceil
(
size
.
height
/
2.0
));
const
int
white_count
=
cvRound
(
floor
(
size
.
width
/
2.0
)
*
floor
(
size
.
height
/
2.0
));
if
(
counts
[
0
]
<
black_count
*
0.75
||
counts
[
1
]
<
white_count
*
0.75
)
{
continue
;
}
result
=
1
;
break
;
continue
;
}
return
true
;
}
}
return
false
;
}
// does a fast check if a chessboard is in the input image. This is a workaround to
// a problem of cvFindChessboardCorners being slow on images with no chessboard
// - src: input image
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int
cvCheckChessboard
(
IplImage
*
src
,
CvSize
size
)
{
cv
::
Mat
img
=
cv
::
cvarrToMat
(
src
);
return
checkChessboard
(
img
,
size
);
}
cvReleaseImage
(
&
thresh
);
cvReleaseImage
(
&
white
);
cvReleaseImage
(
&
black
);
cvReleaseMemStorage
(
&
storage
);
int
checkChessboard
(
const
cv
::
Mat
&
img
,
const
cv
::
Size
&
size
)
{
CV_Assert
(
img
.
channels
()
==
1
&&
img
.
depth
()
==
CV_8U
);
const
int
erosion_count
=
1
;
const
float
black_level
=
20.
f
;
const
float
white_level
=
130.
f
;
const
float
black_white_gap
=
70.
f
;
Mat
white
;
Mat
black
;
erode
(
img
,
white
,
Mat
(),
Point
(
-
1
,
-
1
),
erosion_count
);
dilate
(
img
,
black
,
Mat
(),
Point
(
-
1
,
-
1
),
erosion_count
);
int
result
=
0
;
for
(
float
thresh_level
=
black_level
;
thresh_level
<
white_level
&&
!
result
;
thresh_level
+=
20.0
f
)
{
vector
<
pair
<
float
,
int
>
>
quads
;
fillQuads
(
white
,
black
,
thresh_level
+
black_white_gap
,
thresh_level
,
quads
);
if
(
checkQuads
(
quads
,
size
))
result
=
1
;
}
return
result
;
}
...
...
@@ -214,90 +197,29 @@ int cvCheckChessboard(IplImage* src, CvSize size)
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int
c
vCheckChessboardBinary
(
IplImage
*
src
,
CvSize
size
)
int
c
heckChessboardBinary
(
const
cv
::
Mat
&
img
,
const
cv
::
Size
&
size
)
{
if
(
src
->
nChannels
>
1
)
{
cvError
(
CV_BadNumChannels
,
"cvCheckChessboard"
,
"supports single-channel images only"
,
__FILE__
,
__LINE__
);
}
if
(
src
->
depth
!=
8
)
{
cvError
(
CV_BadDepth
,
"cvCheckChessboard"
,
"supports depth=8 images only"
,
__FILE__
,
__LINE__
);
}
CvMemStorage
*
storage
=
cvCreateMemStorage
();
CV_Assert
(
img
.
channels
()
==
1
&&
img
.
depth
()
==
CV_8U
);
IplImage
*
white
=
cvCloneImage
(
src
);
IplImage
*
black
=
cvCloneImage
(
src
);
IplImage
*
thresh
=
cvCreateImage
(
cvGetSize
(
src
),
IPL_DEPTH_8U
,
1
);
Mat
white
=
img
.
clone
();
Mat
black
=
img
.
clone
();
int
result
=
0
;
for
(
int
erosion_count
=
0
;
erosion_count
<=
3
;
erosion_count
++
)
{
if
(
1
==
result
)
break
;
if
(
0
!=
erosion_count
)
// first iteration keeps original images
{
cvErode
(
white
,
white
,
NULL
,
1
);
cvDilate
(
black
,
black
,
NULL
,
1
);
}
cvThreshold
(
white
,
thresh
,
128
,
255
,
CV_THRESH_BINARY
);
CvSeq
*
first
=
0
;
std
::
vector
<
std
::
pair
<
float
,
int
>
>
quads
;
cvFindContours
(
thresh
,
storage
,
&
first
,
sizeof
(
CvContour
),
CV_RETR_CCOMP
);
icvGetQuadrangleHypotheses
(
first
,
quads
,
1
);
if
(
1
==
result
)
break
;
cvThreshold
(
black
,
thresh
,
128
,
255
,
CV_THRESH_BINARY_INV
);
cvFindContours
(
thresh
,
storage
,
&
first
,
sizeof
(
CvContour
),
CV_RETR_CCOMP
);
icvGetQuadrangleHypotheses
(
first
,
quads
,
0
);
const
size_t
min_quads_count
=
size
.
width
*
size
.
height
/
2
;
std
::
sort
(
quads
.
begin
(),
quads
.
end
(),
less_pred
);
// now check if there are many hypotheses with similar sizes
// do this by floodfill-style algorithm
const
float
size_rel_dev
=
0.4
f
;
for
(
size_t
i
=
0
;
i
<
quads
.
size
();
i
++
)
{
size_t
j
=
i
+
1
;
for
(;
j
<
quads
.
size
();
j
++
)
{
if
(
quads
[
j
].
first
/
quads
[
i
].
first
>
1.0
f
+
size_rel_dev
)
{
break
;
}
}
if
(
0
!=
erosion_count
)
// first iteration keeps original images
{
erode
(
white
,
white
,
Mat
(),
Point
(
-
1
,
-
1
),
1
);
dilate
(
black
,
black
,
Mat
(),
Point
(
-
1
,
-
1
),
1
);
}
if
(
j
+
1
>
min_quads_count
+
i
)
{
// check the number of black and white squares
std
::
vector
<
int
>
counts
;
countClasses
(
quads
,
i
,
j
,
counts
);
const
int
black_count
=
cvRound
(
ceil
(
size
.
width
/
2.0
)
*
ceil
(
size
.
height
/
2.0
));
const
int
white_count
=
cvRound
(
floor
(
size
.
width
/
2.0
)
*
floor
(
size
.
height
/
2.0
));
if
(
counts
[
0
]
<
black_count
*
0.75
||
counts
[
1
]
<
white_count
*
0.75
)
{
continue
;
}
result
=
1
;
break
;
}
}
vector
<
pair
<
float
,
int
>
>
quads
;
fillQuads
(
white
,
black
,
128
,
128
,
quads
);
if
(
checkQuads
(
quads
,
size
))
result
=
1
;
}
cvReleaseImage
(
&
thresh
);
cvReleaseImage
(
&
white
);
cvReleaseImage
(
&
black
);
cvReleaseMemStorage
(
&
storage
);
return
result
;
}
\ No newline at end of file
}
modules/calib3d/src/precomp.hpp
浏览文件 @
73e1d64a
...
...
@@ -117,4 +117,7 @@ template<typename T> inline int compressElems( T* ptr, const uchar* mask, int ms
}
int
checkChessboard
(
const
cv
::
Mat
&
img
,
const
cv
::
Size
&
size
);
int
checkChessboardBinary
(
const
cv
::
Mat
&
img
,
const
cv
::
Size
&
size
);
#endif
modules/calib3d/test/test_chesscorners.cpp
浏览文件 @
73e1d64a
...
...
@@ -51,29 +51,31 @@ using namespace cv;
#define _L2_ERR
void
show_points
(
const
Mat
&
gray
,
const
Mat
&
u
,
const
vector
<
Point2f
>&
v
,
Size
pattern_size
,
bool
was_found
)
//#define DEBUG_CHESSBOARD
#ifdef DEBUG_CHESSBOARD
#include "opencv2/highgui.hpp"
void
show_points
(
const
Mat
&
gray
,
const
Mat
&
expected
,
const
vector
<
Point2f
>&
actual
,
bool
was_found
)
{
Mat
rgb
(
gray
.
size
(),
CV_8U
);
merge
(
vector
<
Mat
>
(
3
,
gray
),
rgb
);
for
(
size_t
i
=
0
;
i
<
v
.
size
();
i
++
)
circle
(
rgb
,
v
[
i
],
3
,
Scalar
(
255
,
0
,
0
),
FILLED
);
for
(
size_t
i
=
0
;
i
<
actual
.
size
();
i
++
)
circle
(
rgb
,
actual
[
i
],
5
,
Scalar
(
0
,
0
,
200
),
1
,
LINE_AA
);
if
(
!
u
.
empty
()
)
if
(
!
expected
.
empty
()
)
{
const
Point2f
*
u_data
=
u
.
ptr
<
Point2f
>
();
size_t
count
=
u
.
cols
*
u
.
rows
;
const
Point2f
*
u_data
=
expected
.
ptr
<
Point2f
>
();
size_t
count
=
expected
.
cols
*
expected
.
rows
;
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
circle
(
rgb
,
u_data
[
i
],
3
,
Scalar
(
0
,
255
,
0
),
FILLED
);
}
if
(
!
v
.
empty
())
{
Mat
corners
((
int
)
v
.
size
(),
1
,
CV_32FC2
,
(
void
*
)
&
v
[
0
]);
drawChessboardCorners
(
rgb
,
pattern_size
,
corners
,
was_found
);
circle
(
rgb
,
u_data
[
i
],
4
,
Scalar
(
0
,
240
,
0
),
1
,
LINE_AA
);
}
//namedWindow( "test", 0 ); imshow( "test", rgb ); waitKey(0);
putText
(
rgb
,
was_found
?
"FOUND !!!"
:
"NOT FOUND"
,
Point
(
5
,
20
),
FONT_HERSHEY_PLAIN
,
1
,
Scalar
(
0
,
240
,
0
));
imshow
(
"test"
,
rgb
);
while
((
uchar
)
waitKey
(
0
)
!=
'q'
)
{};
}
#else
#define show_points(...)
#endif
enum
Pattern
{
CHESSBOARD
,
CIRCLES_GRID
,
ASYMMETRIC_CIRCLES_GRID
};
...
...
@@ -253,7 +255,6 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename )
result
=
findCirclesGrid
(
gray
,
pattern_size
,
v
,
CALIB_CB_ASYMMETRIC_GRID
|
algorithmFlags
);
break
;
}
show_points
(
gray
,
Mat
(),
v
,
pattern_size
,
result
);
if
(
result
^
doesContatinChessboard
||
v
.
size
()
!=
count_exp
)
{
...
...
@@ -280,7 +281,7 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename )
if
(
pattern
==
CHESSBOARD
)
cornerSubPix
(
gray
,
v
,
Size
(
5
,
5
),
Size
(
-
1
,
-
1
),
TermCriteria
(
TermCriteria
::
EPS
|
TermCriteria
::
MAX_ITER
,
30
,
0.1
));
//find4QuadCornerSubpix(gray, v, Size(5, 5));
show_points
(
gray
,
expected
,
v
,
pattern_size
,
result
);
show_points
(
gray
,
expected
,
v
,
result
);
#ifndef WRITE_POINTS
// printf("called find4QuadCornerSubpix\n");
err
=
calcError
(
v
,
expected
);
...
...
@@ -298,6 +299,10 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename )
max_precise_error
=
MAX
(
max_precise_error
,
err
);
#endif
}
else
{
show_points
(
gray
,
Mat
(),
v
,
result
);
}
#ifdef WRITE_POINTS
Mat
mat_v
(
pattern_size
,
CV_32FC2
,
(
void
*
)
&
v
[
0
]);
...
...
modules/python/test/test_calibration.py
浏览文件 @
73e1d64a
...
...
@@ -57,7 +57,7 @@ class calibration_test(NewOpenCVTests):
eps
=
0.01
normCamEps
=
10.0
normDistEps
=
0.0
01
normDistEps
=
0.0
5
cameraMatrixTest
=
[[
532.80992189
,
0.
,
342.4952186
],
[
0.
,
532.93346422
,
233.8879292
],
...
...
@@ -68,4 +68,4 @@ class calibration_test(NewOpenCVTests):
self
.
assertLess
(
abs
(
rms
-
0.196334638034
),
eps
)
self
.
assertLess
(
cv2
.
norm
(
camera_matrix
-
cameraMatrixTest
,
cv2
.
NORM_L1
),
normCamEps
)
self
.
assertLess
(
cv2
.
norm
(
dist_coefs
-
distCoeffsTest
,
cv2
.
NORM_L1
),
normDistEps
)
\ No newline at end of file
self
.
assertLess
(
cv2
.
norm
(
dist_coefs
-
distCoeffsTest
,
cv2
.
NORM_L1
),
normDistEps
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录