Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
eaf5a163
Commit
eaf5a163
authored
Sep 09, 2014
by
Alexander Karsakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added HoughLinesP OCL implementation
parent
39b27a19
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
295 additions
and
10 deletions
+295
-10
hough.cpp
modules/imgproc/src/hough.cpp
+52
-4
hough_lines.cl
modules/imgproc/src/opencl/hough_lines.cl
+166
-0
test_houghlines.cpp
modules/imgproc/test/ocl/test_houghlines.cpp
+77
-6
No files found.
modules/imgproc/src/hough.cpp
View file @
eaf5a163
...
...
@@ -652,6 +652,9 @@ HoughLinesProbabilistic( Mat& image,
}
}
}
#ifdef HAVE_OPENCL
static
bool
ocl_makePointsList
(
InputArray
_src
,
OutputArray
_pointsList
,
InputOutputArray
_counters
)
{
UMat
src
=
_src
.
getUMat
();
...
...
@@ -660,8 +663,8 @@ static bool ocl_makePointsList(InputArray _src, OutputArray _pointsList, InputOu
UMat
counters
=
_counters
.
getUMat
();
ocl
::
Device
dev
=
ocl
::
Device
::
getDefault
();
const
int
pix
els
PerWI
=
16
;
int
workgroup_size
=
min
((
int
)
dev
.
maxWorkGroupSize
(),
(
src
.
cols
+
pix
elsPerWI
-
1
)
/
pixels
PerWI
);
const
int
pixPerWI
=
16
;
int
workgroup_size
=
min
((
int
)
dev
.
maxWorkGroupSize
(),
(
src
.
cols
+
pix
PerWI
-
1
)
/
pix
PerWI
);
ocl
::
Kernel
pointListKernel
(
"make_point_list"
,
ocl
::
imgproc
::
hough_lines_oclsrc
,
format
(
"-D MAKE_POINTS_LIST -D GROUP_SIZE=%d -D LOCAL_SIZE=%d"
,
workgroup_size
,
src
.
cols
));
if
(
pointListKernel
.
empty
())
...
...
@@ -690,7 +693,7 @@ static bool ocl_fillAccum(InputArray _pointsList, OutputArray _accum, int total_
size_t
localThreads
[
2
];
size_t
globalThreads
[
2
];
in
t
local_memory_needed
=
(
numrho
+
2
)
*
sizeof
(
int
);
size_
t
local_memory_needed
=
(
numrho
+
2
)
*
sizeof
(
int
);
if
(
local_memory_needed
>
dev
.
localMemSize
())
{
accum
.
setTo
(
Scalar
::
all
(
0
));
...
...
@@ -781,10 +784,54 @@ static bool ocl_HoughLinesP(InputArray _src, OutputArray _lines, double rho, dou
CV_Assert
(
_src
.
type
()
==
CV_8UC1
);
UMat
src
=
_src
.
getUMat
();
int
numangle
=
cvRound
(
CV_PI
/
theta
);
int
numrho
=
cvRound
(((
src
.
cols
+
src
.
rows
)
*
2
+
1
)
/
rho
);
UMat
pointsList
;
UMat
counters
(
1
,
2
,
CV_32SC1
,
Scalar
::
all
(
0
));
if
(
!
ocl_makePointsList
(
src
,
pointsList
,
counters
))
return
false
;
int
total_points
=
counters
.
getMat
(
ACCESS_READ
).
at
<
int
>
(
0
,
0
);
if
(
total_points
<=
0
)
{
_lines
.
assign
(
UMat
(
0
,
0
,
CV_32SC4
));
return
true
;
}
UMat
accum
;
if
(
!
ocl_fillAccum
(
pointsList
,
accum
,
total_points
,
rho
,
theta
,
numrho
,
numangle
))
return
false
;
ocl
::
Kernel
getLinesKernel
(
"get_lines"
,
ocl
::
imgproc
::
hough_lines_oclsrc
,
format
(
"-D GET_LINES_PROBABOLISTIC"
));
if
(
getLinesKernel
.
empty
())
return
false
;
// TODO: investigate other strategies to choose linesMax
int
linesMax
=
min
(
total_points
*
numangle
/
threshold
,
4096
);
UMat
lines
(
linesMax
,
1
,
CV_32SC4
);
getLinesKernel
.
args
(
ocl
::
KernelArg
::
ReadOnly
(
accum
),
ocl
::
KernelArg
::
ReadOnly
(
src
),
ocl
::
KernelArg
::
WriteOnlyNoSize
(
lines
),
ocl
::
KernelArg
::
PtrWriteOnly
(
counters
),
linesMax
,
threshold
,
(
int
)
minLineLength
,
(
int
)
maxGap
,
(
float
)
rho
,
(
float
)
theta
);
size_t
globalThreads
[
2
]
=
{
numrho
,
numangle
};
if
(
!
getLinesKernel
.
run
(
2
,
globalThreads
,
NULL
,
false
))
return
false
;
int
total_lines
=
min
(
counters
.
getMat
(
ACCESS_READ
).
at
<
int
>
(
0
,
1
),
linesMax
);
if
(
total_lines
>
0
)
_lines
.
assign
(
lines
.
rowRange
(
Range
(
0
,
total_lines
)));
else
_lines
.
assign
(
UMat
(
0
,
0
,
CV_32SC4
));
return
true
;
}
#endif
/* HAVE_OPENCL */
}
void
cv
::
HoughLines
(
InputArray
_image
,
OutputArray
_lines
,
...
...
@@ -810,7 +857,8 @@ void cv::HoughLinesP(InputArray _image, OutputArray _lines,
double
rho
,
double
theta
,
int
threshold
,
double
minLineLength
,
double
maxGap
)
{
CV_OCL_RUN
(
_image
.
isUMat
()
&&
_lines
.
isUMat
(),
ocl_HoughLinesP
(
_image
,
_lines
,
rho
,
theta
,
threshold
,
minLineLength
,
maxGap
));
CV_OCL_RUN
(
_image
.
isUMat
()
&&
_lines
.
isUMat
(),
ocl_HoughLinesP
(
_image
,
_lines
,
rho
,
theta
,
threshold
,
minLineLength
,
maxGap
));
Mat
image
=
_image
.
getMat
();
std
::
vector
<
Vec4i
>
lines
;
...
...
modules/imgproc/src/opencl/hough_lines.cl
View file @
eaf5a163
...
...
@@ -172,4 +172,169 @@ __kernel void get_lines(__global uchar * accum_ptr, int accum_step, int accum_of
}
}
#elif GET_LINES_PROBABOLISTIC
#define ACCUM(ptr) *((__global int*)(ptr))
__kernel void get_lines(__global const uchar * accum_ptr, int accum_step, int accum_offset, int accum_rows, int accum_cols,
__global const uchar * src_ptr, int src_step, int src_offset, int src_rows, int src_cols,
__global uchar * lines_ptr, int lines_step, int lines_offset, __global int* lines_index_ptr,
int linesMax, int threshold, int lineLength, int lineGap, float rho, float theta)
{
int x = get_global_id(0);
int y = get_global_id(1);
__global uchar* accum = accum_ptr + mad24(y+1, accum_step, mad24(x+1, (int) sizeof(int), accum_offset));
__global int4* lines = (__global int4*)(lines_ptr + lines_offset);
__global int* lines_index = lines_index_ptr + 1;
int curVote = ACCUM(accum);
if (curVote >= threshold &&
curVote > ACCUM(accum - accum_step - sizeof(int)) &&
curVote > ACCUM(accum - accum_step) &&
curVote > ACCUM(accum - accum_step + sizeof(int)) &&
curVote > ACCUM(accum - sizeof(int)) &&
curVote > ACCUM(accum + sizeof(int)) &&
curVote > ACCUM(accum + accum_step - sizeof(int)) &&
curVote > ACCUM(accum + accum_step) &&
curVote > ACCUM(accum + accum_step + sizeof(int)))
{
const float radius = (x - (accum_cols - 2 - 1) * 0.5f) * rho;
const float angle = y * theta;
float cosa;
float sina = sincos(angle, &cosa);
float2 p0 = (float2)(cosa * radius, sina * radius);
float2 dir = (float2)(-sina, cosa);
float2 pb[4] = { (float2)(-1, -1), (float2)(-1, -1), (float2)(-1, -1), (float2)(-1, -1) };
float a;
if (dir.x != 0)
{
a = -p0.x / dir.x;
pb[0].x = 0;
pb[0].y = p0.y + a * dir.y;
a = (src_cols - 1 - p0.x) / dir.x;
pb[1].x = src_cols - 1;
pb[1].y = p0.y + a * dir.y;
}
if (dir.y != 0)
{
a = -p0.y / dir.y;
pb[2].x = p0.x + a * dir.x;
pb[2].y = 0;
a = (src_rows - 1 - p0.y) / dir.y;
pb[3].x = p0.x + a * dir.x;
pb[3].y = src_rows - 1;
}
if (pb[0].x == 0 && (pb[0].y >= 0 && pb[0].y < src_rows))
{
p0 = pb[0];
if (dir.x < 0)
dir = -dir;
}
else if (pb[1].x == src_cols - 1 && (pb[0].y >= 0 && pb[0].y < src_rows))
{
p0 = pb[1];
if (dir.x > 0)
dir = -dir;
}
else if (pb[2].y == 0 && (pb[2].x >= 0 && pb[2].x < src_cols))
{
p0 = pb[2];
if (dir.y < 0)
dir = -dir;
}
else if (pb[3].y == src_rows - 1 && (pb[3].x >= 0 && pb[3].x < src_cols))
{
p0 = pb[3];
if (dir.y > 0)
dir = -dir;
}
float2 d;
if (fabs(dir.x) > fabs(dir.y))
{
d.x = dir.x > 0 ? 1 : -1;
d.y = dir.y / fabs(dir.x);
}
else
{
d.x = dir.x / fabs(dir.y);
d.y = dir.y > 0 ? 1 : -1;
}
float2 line_end[2];
int gap;
bool inLine = false;
float2 p1 = p0;
if (p1.x < 0 || p1.x >= src_cols || p1.y < 0 || p1.y >= src_rows)
return;
for (;;)
{
if (*(src_ptr + mad24(p1.y, src_step, p1.x + src_offset)))
{
gap = 0;
if (!inLine)
{
line_end[0] = p1;
line_end[1] = p1;
inLine = true;
}
else
{
line_end[1] = p1;
}
}
else if (inLine)
{
if (++gap > lineGap)
{
bool good_line = fabs(line_end[1].x - line_end[0].x) >= lineLength ||
fabs(line_end[1].y - line_end[0].y) >= lineLength;
if (good_line)
{
int index = atomic_inc(lines_index);
if (index < linesMax)
lines[index] = (int4)(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y);
}
gap = 0;
inLine = false;
}
}
p1 = p1 + d;
if (p1.x < 0 || p1.x >= src_cols || p1.y < 0 || p1.y >= src_rows)
{
if (inLine)
{
bool good_line = fabs(line_end[1].x - line_end[0].x) >= lineLength |
|
fabs
(
line_end[1].y
-
line_end[0].y
)
>=
lineLength
;
if
(
good_line
)
{
int
index
=
atomic_inc
(
lines_index
)
;
if
(
index
<
linesMax
)
lines[index]
=
(
int4
)(
line_end[0].x,
line_end[0].y,
line_end[1].x,
line_end[1].y
)
;
}
}
break
;
}
}
}
}
#
endif
\ No newline at end of file
modules/imgproc/test/ocl/test_houghlines.cpp
View file @
eaf5a163
...
...
@@ -15,17 +15,18 @@ namespace ocl {
struct
Vec2fComparator
{
bool
operator
()(
const
cv
::
Vec2f
&
a
,
const
cv
::
Vec2f
b
)
const
bool
operator
()(
const
Vec2f
&
a
,
const
Vec2f
b
)
const
{
if
(
a
[
0
]
!=
b
[
0
])
return
a
[
0
]
<
b
[
0
];
else
return
a
[
1
]
<
b
[
1
];
}
};
PARAM_TEST_CASE
(
HoughLinesTestBase
,
double
,
double
,
int
)
/////////////////////////////// HoughLines ////////////////////////////////////
PARAM_TEST_CASE
(
HoughLines
,
double
,
double
,
int
)
{
double
rhoStep
;
double
thetaStep
;
double
rhoStep
,
thetaStep
;
int
threshold
;
Size
src_size
;
...
...
@@ -80,8 +81,6 @@ PARAM_TEST_CASE(HoughLinesTestBase, double, double, int)
}
};
typedef
HoughLinesTestBase
HoughLines
;
OCL_TEST_P
(
HoughLines
,
RealImage
)
{
readRealTestData
();
...
...
@@ -105,10 +104,81 @@ OCL_TEST_P(HoughLines, GeneratedImage)
}
}
/////////////////////////////// HoughLinesP ///////////////////////////////////
PARAM_TEST_CASE
(
HoughLinesP
,
int
,
double
,
double
)
{
double
rhoStep
,
thetaStep
,
minLineLength
,
maxGap
;
int
threshold
;
Size
src_size
;
Mat
src
,
dst
;
UMat
usrc
,
udst
;
virtual
void
SetUp
()
{
rhoStep
=
1.0
;
thetaStep
=
CV_PI
/
180
;
threshold
=
GET_PARAM
(
0
);
minLineLength
=
GET_PARAM
(
1
);
maxGap
=
GET_PARAM
(
2
);
}
virtual
void
readRealTestData
()
{
Mat
img
=
readImage
(
"shared/pic5.png"
,
IMREAD_GRAYSCALE
);
Canny
(
img
,
src
,
50
,
200
,
3
);
src
.
copyTo
(
usrc
);
}
virtual
void
Near
(
double
eps
=
0.
)
{
Mat
lines_gpu
=
udst
.
getMat
(
ACCESS_READ
);
if
(
dst
.
total
()
>
0
&&
lines_gpu
.
total
()
>
0
)
{
Mat
result_cpu
(
src
.
size
(),
CV_8UC1
,
Scalar
::
all
(
0
));
Mat
result_gpu
(
src
.
size
(),
CV_8UC1
,
Scalar
::
all
(
0
));
MatConstIterator_
<
Vec4i
>
it
=
dst
.
begin
<
Vec4i
>
(),
end
=
dst
.
end
<
Vec4i
>
();
for
(
;
it
!=
end
;
it
++
)
{
Vec4i
p
=
*
it
;
line
(
result_cpu
,
Point
(
p
[
0
],
p
[
1
]),
Point
(
p
[
2
],
p
[
3
]),
Scalar
(
255
));
}
it
=
lines_gpu
.
begin
<
Vec4i
>
(),
end
=
lines_gpu
.
end
<
Vec4i
>
();
for
(
;
it
!=
end
;
it
++
)
{
Vec4i
p
=
*
it
;
line
(
result_gpu
,
Point
(
p
[
0
],
p
[
1
]),
Point
(
p
[
2
],
p
[
3
]),
Scalar
(
255
));
}
EXPECT_MAT_SIMILAR
(
result_cpu
,
result_gpu
,
eps
);
}
}
};
OCL_TEST_P
(
HoughLinesP
,
RealImage
)
{
readRealTestData
();
OCL_OFF
(
cv
::
HoughLinesP
(
src
,
dst
,
rhoStep
,
thetaStep
,
threshold
,
minLineLength
,
maxGap
));
OCL_ON
(
cv
::
HoughLinesP
(
usrc
,
udst
,
rhoStep
,
thetaStep
,
threshold
,
minLineLength
,
maxGap
));
Near
(
0.2
);
}
OCL_INSTANTIATE_TEST_CASE_P
(
Imgproc
,
HoughLines
,
Combine
(
Values
(
1
,
0.5
),
// rhoStep
Values
(
CV_PI
/
180.0
,
CV_PI
/
360.0
),
// thetaStep
Values
(
80
,
150
)));
// threshold
OCL_INSTANTIATE_TEST_CASE_P
(
Imgproc
,
HoughLinesP
,
Combine
(
Values
(
100
,
150
),
// threshold
Values
(
50
,
100
),
// minLineLength
Values
(
5
,
10
)));
// maxLineGap
}
}
// namespace cvtest::ocl
#endif // HAVE_OPENCL
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment