Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Opencv
提交
c67d4fc6
O
Opencv
项目概览
Greenplum
/
Opencv
9 个月 前同步成功
通知
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,体验更适合开发者的 AI 搜索 >>
提交
c67d4fc6
编写于
1月 28, 2023
作者:
A
Alexander Alekhin
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #23076 from inayd:22012-bugfixFillPoly
上级
bd9d60c4
54449b61
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
277 addition
and
15 deletion
+277
-15
modules/imgproc/src/drawing.cpp
modules/imgproc/src/drawing.cpp
+44
-15
modules/imgproc/test/test_drawing.cpp
modules/imgproc/test/test_drawing.cpp
+233
-0
未找到文件。
modules/imgproc/src/drawing.cpp
浏览文件 @
c67d4fc6
...
...
@@ -63,7 +63,7 @@ CollectPolyEdges( Mat& img, const Point2l* v, int npts,
int
shift
,
Point
offset
=
Point
()
);
static
void
FillEdgeCollection
(
Mat
&
img
,
std
::
vector
<
PolyEdge
>&
edges
,
const
void
*
color
);
FillEdgeCollection
(
Mat
&
img
,
std
::
vector
<
PolyEdge
>&
edges
,
const
void
*
color
,
int
line_type
);
static
void
PolyLine
(
Mat
&
img
,
const
Point2l
*
v
,
int
npts
,
bool
closed
,
...
...
@@ -1031,7 +1031,7 @@ EllipseEx( Mat& img, Point2l center, Size2l axes,
v
.
push_back
(
center
);
std
::
vector
<
PolyEdge
>
edges
;
CollectPolyEdges
(
img
,
&
v
[
0
],
(
int
)
v
.
size
(),
edges
,
color
,
line_type
,
XY_SHIFT
);
FillEdgeCollection
(
img
,
edges
,
color
);
FillEdgeCollection
(
img
,
edges
,
color
,
line_type
);
}
}
...
...
@@ -1259,37 +1259,60 @@ CollectPolyEdges( Mat& img, const Point2l* v, int count, std::vector<PolyEdge>&
pt1
.
x
=
(
pt1
.
x
+
offset
.
x
)
<<
(
XY_SHIFT
-
shift
);
pt1
.
y
=
(
pt1
.
y
+
delta
)
>>
shift
;
if
(
line_type
<
CV_AA
)
Point2l
pt0c
(
pt0
),
pt1c
(
pt1
);
if
(
line_type
<
CV_AA
)
{
t0
.
y
=
pt0
.
y
;
t1
.
y
=
pt1
.
y
;
t0
.
x
=
(
pt0
.
x
+
(
XY_ONE
>>
1
))
>>
XY_SHIFT
;
t1
.
x
=
(
pt1
.
x
+
(
XY_ONE
>>
1
))
>>
XY_SHIFT
;
Line
(
img
,
t0
,
t1
,
color
,
line_type
);
Line
(
img
,
t0
,
t1
,
color
,
line_type
);
// use clipped endpoints to create a more accurate PolyEdge
if
((
unsigned
)
t0
.
x
>=
(
unsigned
)(
img
.
cols
)
||
(
unsigned
)
t1
.
x
>=
(
unsigned
)(
img
.
cols
)
||
(
unsigned
)
t0
.
y
>=
(
unsigned
)(
img
.
rows
)
||
(
unsigned
)
t1
.
y
>=
(
unsigned
)(
img
.
rows
))
{
clipLine
(
img
.
size
(),
t0
,
t1
);
if
(
t0
.
y
!=
t1
.
y
)
{
pt0c
.
y
=
t0
.
y
;
pt1c
.
y
=
t1
.
y
;
pt0c
.
x
=
(
int64
)(
t0
.
x
)
<<
XY_SHIFT
;
pt1c
.
x
=
(
int64
)(
t1
.
x
)
<<
XY_SHIFT
;
}
}
else
{
pt0c
.
x
+=
XY_ONE
>>
1
;
pt1c
.
x
+=
XY_ONE
>>
1
;
}
}
else
{
t0
.
x
=
pt0
.
x
;
t1
.
x
=
pt1
.
x
;
t0
.
y
=
pt0
.
y
<<
XY_SHIFT
;
t1
.
y
=
pt1
.
y
<<
XY_SHIFT
;
LineAA
(
img
,
t0
,
t1
,
color
);
LineAA
(
img
,
t0
,
t1
,
color
);
}
if
(
pt0
.
y
==
pt1
.
y
)
if
(
pt0
.
y
==
pt1
.
y
)
continue
;
if
(
pt0
.
y
<
pt1
.
y
)
edge
.
dx
=
(
pt1c
.
x
-
pt0c
.
x
)
/
(
pt1c
.
y
-
pt0c
.
y
);
if
(
pt0
.
y
<
pt1
.
y
)
{
edge
.
y0
=
(
int
)(
pt0
.
y
);
edge
.
y1
=
(
int
)(
pt1
.
y
);
edge
.
x
=
pt0
.
x
;
edge
.
x
=
pt0
c
.
x
+
(
pt0
.
y
-
pt0c
.
y
)
*
edge
.
dx
;
// correct starting point for clipped lines
}
else
{
edge
.
y0
=
(
int
)(
pt1
.
y
);
edge
.
y1
=
(
int
)(
pt0
.
y
);
edge
.
x
=
pt1
.
x
;
edge
.
x
=
pt1
c
.
x
+
(
pt1
.
y
-
pt1c
.
y
)
*
edge
.
dx
;
// correct starting point for clipped lines
}
edge
.
dx
=
(
pt1
.
x
-
pt0
.
x
)
/
(
pt1
.
y
-
pt0
.
y
);
edges
.
push_back
(
edge
);
}
}
...
...
@@ -1306,7 +1329,7 @@ struct CmpEdges
/**************** helper macros and functions for sequence/contour processing ***********/
static
void
FillEdgeCollection
(
Mat
&
img
,
std
::
vector
<
PolyEdge
>&
edges
,
const
void
*
color
)
FillEdgeCollection
(
Mat
&
img
,
std
::
vector
<
PolyEdge
>&
edges
,
const
void
*
color
,
int
line_type
)
{
PolyEdge
tmp
;
int
i
,
y
,
total
=
(
int
)
edges
.
size
();
...
...
@@ -1315,6 +1338,12 @@ FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color )
int
y_max
=
INT_MIN
,
y_min
=
INT_MAX
;
int64
x_max
=
0xFFFFFFFFFFFFFFFF
,
x_min
=
0x7FFFFFFFFFFFFFFF
;
int
pix_size
=
(
int
)
img
.
elemSize
();
int
delta
;
if
(
line_type
<
CV_AA
)
delta
=
0
;
else
delta
=
XY_ONE
-
1
;
if
(
total
<
2
)
return
;
...
...
@@ -1394,12 +1423,12 @@ FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color )
if
(
keep_prelast
->
x
>
prelast
->
x
)
{
x1
=
(
int
)((
prelast
->
x
+
XY_ONE
-
1
)
>>
XY_SHIFT
);
x1
=
(
int
)((
prelast
->
x
+
delta
)
>>
XY_SHIFT
);
x2
=
(
int
)(
keep_prelast
->
x
>>
XY_SHIFT
);
}
else
{
x1
=
(
int
)((
keep_prelast
->
x
+
XY_ONE
-
1
)
>>
XY_SHIFT
);
x1
=
(
int
)((
keep_prelast
->
x
+
delta
)
>>
XY_SHIFT
);
x2
=
(
int
)(
prelast
->
x
>>
XY_SHIFT
);
}
...
...
@@ -1995,7 +2024,7 @@ void fillPoly( Mat& img, const Point** pts, const int* npts, int ncontours,
CollectPolyEdges
(
img
,
_pts
.
data
(),
npts
[
i
],
edges
,
buf
,
line_type
,
shift
,
offset
);
}
FillEdgeCollection
(
img
,
edges
,
buf
);
FillEdgeCollection
(
img
,
edges
,
buf
,
line_type
);
}
...
...
@@ -2654,7 +2683,7 @@ cvDrawContours( void* _img, CvSeq* contour,
}
if
(
thickness
<
0
)
cv
::
FillEdgeCollection
(
img
,
edges
,
ext_buf
);
cv
::
FillEdgeCollection
(
img
,
edges
,
ext_buf
,
line_type
);
if
(
h_next
&&
contour0
)
contour0
->
h_next
=
h_next
;
...
...
modules/imgproc/test/test_drawing.cpp
浏览文件 @
c67d4fc6
...
...
@@ -632,4 +632,237 @@ TEST(Drawing, fillpoly_circle)
EXPECT_LT
(
diff_fp3
,
1.
);
}
TEST
(
Drawing
,
fillpoly_fully
)
{
unsigned
imageWidth
=
256
;
unsigned
imageHeight
=
256
;
int
type
=
CV_8UC1
;
int
shift
=
0
;
Point
offset
(
0
,
0
);
cv
::
LineTypes
lineType
=
LINE_4
;
int
imageSizeOffset
=
15
;
cv
::
Mat
img
(
imageHeight
,
imageWidth
,
type
);
img
=
0
;
std
::
vector
<
cv
::
Point
>
polygonPoints
;
polygonPoints
.
push_back
(
cv
::
Point
(
100
,
-
50
));
polygonPoints
.
push_back
(
cv
::
Point
(
imageSizeOffset
,
imageHeight
-
imageSizeOffset
));
polygonPoints
.
push_back
(
cv
::
Point
(
imageSizeOffset
,
imageSizeOffset
));
// convert data
std
::
vector
<
const
cv
::
Point
*>
polygonPointPointers
(
polygonPoints
.
size
());
for
(
size_t
i
=
0
;
i
<
polygonPoints
.
size
();
i
++
)
{
polygonPointPointers
[
i
]
=
&
polygonPoints
[
i
];
}
const
cv
::
Point
**
data
=
&
polygonPointPointers
.
front
();
int
size
=
(
int
)
polygonPoints
.
size
();
const
int
*
npts
=
&
size
;
int
ncontours
=
1
;
// generate image
cv
::
fillPoly
(
img
,
data
,
npts
,
ncontours
,
255
,
lineType
,
shift
,
offset
);
// check for artifacts
{
cv
::
Mat
binary
=
img
<
128
;
cv
::
Mat
labelImage
(
binary
.
size
(),
CV_32S
);
cv
::
Mat
labelCentroids
;
int
labels
=
cv
::
connectedComponents
(
binary
,
labelImage
,
4
);
EXPECT_EQ
(
2
,
labels
)
<<
"artifacts occured"
;
}
// check if filling went over border
{
int
xy_shift
=
16
,
delta
=
offset
.
y
+
((
1
<<
shift
)
>>
1
);
int
xy_one
=
1
<<
xy_shift
;
Point
pt0
(
polygonPoints
[
polygonPoints
.
size
()
-
1
]),
pt1
;
for
(
size_t
i
=
0
;
i
<
polygonPoints
.
size
();
i
++
,
pt0
=
pt1
)
{
pt1
=
polygonPoints
[
i
];
// offset/shift treated like in fillPoly
Point
t0
(
pt0
),
t1
(
pt1
);
t0
.
x
=
(
t0
.
x
+
offset
.
x
)
<<
(
xy_shift
-
shift
);
t0
.
y
=
(
t0
.
y
+
delta
)
>>
shift
;
t1
.
x
=
(
t1
.
x
+
offset
.
x
)
<<
(
xy_shift
-
shift
);
t1
.
y
=
(
t1
.
y
+
delta
)
>>
shift
;
if
(
lineType
<
CV_AA
)
{
t0
.
x
=
(
t0
.
x
+
(
xy_one
>>
1
))
>>
xy_shift
;
t1
.
x
=
(
t1
.
x
+
(
xy_one
>>
1
))
>>
xy_shift
;
// LINE_4 to use the same type of line which is used in fillPoly
line
(
img
,
t0
,
t1
,
0
,
1
,
LINE_4
,
0
);
}
else
{
t0
.
x
>>=
(
xy_shift
);
t1
.
x
>>=
(
xy_shift
);
line
(
img
,
t0
,
t1
,
0
,
1
,
lineType
,
0
);
}
}
cv
::
Mat
binary
=
img
<
254
;
cv
::
Mat
labelImage
(
binary
.
size
(),
CV_32S
);
int
labels
=
cv
::
connectedComponents
(
binary
,
labelImage
,
4
);
EXPECT_EQ
(
2
,
labels
)
<<
"filling went over the border"
;
}
}
PARAM_TEST_CASE
(
FillPolyFully
,
unsigned
,
unsigned
,
int
,
int
,
Point
,
cv
::
LineTypes
)
{
unsigned
imageWidth
;
unsigned
imageHeight
;
int
type
;
int
shift
;
Point
offset
;
cv
::
LineTypes
lineType
;
virtual
void
SetUp
()
{
imageWidth
=
GET_PARAM
(
0
);
imageHeight
=
GET_PARAM
(
1
);
type
=
GET_PARAM
(
2
);
shift
=
GET_PARAM
(
3
);
offset
=
GET_PARAM
(
4
);
lineType
=
GET_PARAM
(
5
);
}
void
draw_polygon
(
cv
::
Mat
&
img
,
const
std
::
vector
<
cv
::
Point
>&
polygonPoints
)
{
// convert data
std
::
vector
<
const
cv
::
Point
*>
polygonPointPointers
(
polygonPoints
.
size
());
for
(
size_t
i
=
0
;
i
<
polygonPoints
.
size
();
i
++
)
{
polygonPointPointers
[
i
]
=
&
polygonPoints
[
i
];
}
const
cv
::
Point
**
data
=
&
polygonPointPointers
.
front
();
int
size
=
(
int
)
polygonPoints
.
size
();
const
int
*
npts
=
&
size
;
int
ncontours
=
1
;
// generate image
cv
::
fillPoly
(
img
,
data
,
npts
,
ncontours
,
255
,
lineType
,
shift
,
offset
);
}
void
check_artifacts
(
cv
::
Mat
&
img
)
{
// check for artifacts
cv
::
Mat
binary
=
img
<
128
;
cv
::
Mat
labelImage
(
binary
.
size
(),
CV_32S
);
cv
::
Mat
labelCentroids
;
int
labels
=
cv
::
connectedComponents
(
binary
,
labelImage
,
4
);
EXPECT_EQ
(
2
,
labels
)
<<
"artifacts occured"
;
}
void
check_filling_over_border
(
cv
::
Mat
&
img
,
const
std
::
vector
<
cv
::
Point
>&
polygonPoints
)
{
int
xy_shift
=
16
,
delta
=
offset
.
y
+
((
1
<<
shift
)
>>
1
);
int
xy_one
=
1
<<
xy_shift
;
Point
pt0
(
polygonPoints
[
polygonPoints
.
size
()
-
1
]),
pt1
;
for
(
size_t
i
=
0
;
i
<
polygonPoints
.
size
();
i
++
,
pt0
=
pt1
)
{
pt1
=
polygonPoints
[
i
];
// offset/shift treated like in fillPoly
Point
t0
(
pt0
),
t1
(
pt1
);
t0
.
x
=
(
t0
.
x
+
offset
.
x
)
<<
(
xy_shift
-
shift
);
t0
.
y
=
(
t0
.
y
+
delta
)
>>
shift
;
t1
.
x
=
(
t1
.
x
+
offset
.
x
)
<<
(
xy_shift
-
shift
);
t1
.
y
=
(
t1
.
y
+
delta
)
>>
shift
;
if
(
lineType
<
CV_AA
)
{
t0
.
x
=
(
t0
.
x
+
(
xy_one
>>
1
))
>>
xy_shift
;
t1
.
x
=
(
t1
.
x
+
(
xy_one
>>
1
))
>>
xy_shift
;
// LINE_4 to use the same type of line which is used in fillPoly
line
(
img
,
t0
,
t1
,
0
,
1
,
LINE_4
,
0
);
}
else
{
t0
.
x
>>=
(
xy_shift
);
t1
.
x
>>=
(
xy_shift
);
line
(
img
,
t0
,
t1
,
0
,
1
,
lineType
,
0
);
}
}
cv
::
Mat
binary
=
img
<
254
;
cv
::
Mat
labelImage
(
binary
.
size
(),
CV_32S
);
int
labels
=
cv
::
connectedComponents
(
binary
,
labelImage
,
4
);
EXPECT_EQ
(
2
,
labels
)
<<
"filling went over the border"
;
}
void
run_test
(
const
std
::
vector
<
cv
::
Point
>&
polygonPoints
)
{
cv
::
Mat
img
(
imageHeight
,
imageWidth
,
type
);
img
=
0
;
draw_polygon
(
img
,
polygonPoints
);
check_artifacts
(
img
);
check_filling_over_border
(
img
,
polygonPoints
);
}
};
TEST_P
(
FillPolyFully
,
DISABLED_fillpoly_fully
)
{
int
imageSizeOffset
=
15
;
// testing for polygon with straight edge at left/right side
int
positions1
[
2
]
=
{
imageSizeOffset
,
(
int
)
imageWidth
-
imageSizeOffset
};
for
(
size_t
i
=
0
;
i
<
2
;
i
++
)
{
for
(
int
y
=
imageHeight
+
50
;
y
>
-
50
;
y
-=
1
)
{
// define polygon
std
::
vector
<
cv
::
Point
>
polygonPoints
;
polygonPoints
.
push_back
(
cv
::
Point
(
100
,
imageHeight
-
y
));
polygonPoints
.
push_back
(
cv
::
Point
(
positions1
[
i
],
positions1
[
1
]));
polygonPoints
.
push_back
(
cv
::
Point
(
positions1
[
i
],
positions1
[
0
]));
run_test
(
polygonPoints
);
}
}
// testing for polygon with straight edge at top/bottom side
int
positions2
[
2
]
=
{
imageSizeOffset
,
(
int
)
imageHeight
-
imageSizeOffset
};
for
(
size_t
i
=
0
;
i
<
2
;
i
++
)
{
for
(
int
x
=
imageWidth
+
50
;
x
>
-
50
;
x
-=
1
)
{
// define polygon
std
::
vector
<
cv
::
Point
>
polygonPoints
;
polygonPoints
.
push_back
(
cv
::
Point
(
imageWidth
-
x
,
100
));
polygonPoints
.
push_back
(
cv
::
Point
(
positions2
[
1
],
positions2
[
i
]));
polygonPoints
.
push_back
(
cv
::
Point
(
positions2
[
0
],
positions2
[
i
]));
run_test
(
polygonPoints
);
}
}
}
INSTANTIATE_TEST_CASE_P
(
FillPolyTest
,
FillPolyFully
,
testing
::
Combine
(
testing
::
Values
(
256
),
testing
::
Values
(
256
),
testing
::
Values
(
CV_8UC1
),
testing
::
Values
(
0
,
1
,
2
),
testing
::
Values
(
cv
::
Point
(
0
,
0
),
cv
::
Point
(
10
,
10
)),
testing
::
Values
(
LINE_4
,
LINE_8
,
LINE_AA
)
)
);
}}
// namespace
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录