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
397870d7
Commit
397870d7
authored
Oct 09, 2014
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3279 from akarsakov:ocl_houghlines
parents
263fd81b
66a8acfd
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
382 additions
and
4 deletions
+382
-4
hough_segments.cu
modules/cudaimgproc/src/cuda/hough_segments.cu
+1
-1
generalized_hough.cpp
modules/cudaimgproc/src/generalized_hough.cpp
+3
-2
hough.cpp
modules/imgproc/src/hough.cpp
+193
-1
hough_lines.cl
modules/imgproc/src/opencl/hough_lines.cl
+0
-0
test_houghlines.cpp
modules/imgproc/test/ocl/test_houghlines.cpp
+185
-0
No files found.
modules/cudaimgproc/src/cuda/hough_segments.cu
View file @
397870d7
...
...
@@ -117,7 +117,7 @@ namespace cv { namespace cuda { namespace device
if (dir.x < 0)
dir = -dir;
}
else if (pb[1].x == cols - 1 && (pb[
0].y >= 0 && pb[0
].y < rows))
else if (pb[1].x == cols - 1 && (pb[
1].y >= 0 && pb[1
].y < rows))
{
p0 = pb[1];
if (dir.x > 0)
...
...
modules/cudaimgproc/src/generalized_hough.cpp
View file @
397870d7
...
...
@@ -239,8 +239,9 @@ namespace
void
GeneralizedHoughBase
::
detectImpl
(
InputArray
image
,
OutputArray
positions
,
OutputArray
votes
)
{
#ifndef HAVE_OPENCV_CUDAFILTERS
(
void
)
templ
;
(
void
)
templCenter
;
(
void
)
image
;
(
void
)
positions
;
(
void
)
votes
;
throw_no_cuda
();
#else
calcEdges
(
image
,
imageEdges_
,
imageDx_
,
imageDy_
);
...
...
modules/imgproc/src/hough.cpp
View file @
397870d7
...
...
@@ -42,6 +42,7 @@
//M*/
#include "precomp.hpp"
#include "opencl_kernels_imgproc.hpp"
namespace
cv
{
...
...
@@ -220,7 +221,7 @@ HoughLinesSDiv( const Mat& img,
std
::
vector
<
hough_index
>
lst
;
CV_Assert
(
img
.
type
()
==
CV_8UC1
);
CV_Assert
(
linesMax
>
0
&&
rho
>
0
&&
theta
>
0
);
CV_Assert
(
linesMax
>
0
);
threshold
=
MIN
(
threshold
,
255
);
...
...
@@ -652,13 +653,201 @@ HoughLinesProbabilistic( Mat& image,
}
}
#ifdef HAVE_OPENCL
#define OCL_MAX_LINES 4096
static
bool
ocl_makePointsList
(
InputArray
_src
,
OutputArray
_pointsList
,
InputOutputArray
_counters
)
{
UMat
src
=
_src
.
getUMat
();
_pointsList
.
create
(
1
,
(
int
)
src
.
total
(),
CV_32SC1
);
UMat
pointsList
=
_pointsList
.
getUMat
();
UMat
counters
=
_counters
.
getUMat
();
ocl
::
Device
dev
=
ocl
::
Device
::
getDefault
();
const
int
pixPerWI
=
16
;
int
workgroup_size
=
min
((
int
)
dev
.
maxWorkGroupSize
(),
(
src
.
cols
+
pixPerWI
-
1
)
/
pixPerWI
);
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
())
return
false
;
pointListKernel
.
args
(
ocl
::
KernelArg
::
ReadOnly
(
src
),
ocl
::
KernelArg
::
WriteOnlyNoSize
(
pointsList
),
ocl
::
KernelArg
::
PtrWriteOnly
(
counters
));
size_t
localThreads
[
2
]
=
{
workgroup_size
,
1
};
size_t
globalThreads
[
2
]
=
{
workgroup_size
,
src
.
rows
};
return
pointListKernel
.
run
(
2
,
globalThreads
,
localThreads
,
false
);
}
static
bool
ocl_fillAccum
(
InputArray
_pointsList
,
OutputArray
_accum
,
int
total_points
,
double
rho
,
double
theta
,
int
numrho
,
int
numangle
)
{
UMat
pointsList
=
_pointsList
.
getUMat
();
_accum
.
create
(
numangle
+
2
,
numrho
+
2
,
CV_32SC1
);
UMat
accum
=
_accum
.
getUMat
();
ocl
::
Device
dev
=
ocl
::
Device
::
getDefault
();
float
irho
=
(
float
)
(
1
/
rho
);
int
workgroup_size
=
min
((
int
)
dev
.
maxWorkGroupSize
(),
total_points
);
ocl
::
Kernel
fillAccumKernel
;
size_t
localThreads
[
2
];
size_t
globalThreads
[
2
];
size_t
local_memory_needed
=
(
numrho
+
2
)
*
sizeof
(
int
);
if
(
local_memory_needed
>
dev
.
localMemSize
())
{
accum
.
setTo
(
Scalar
::
all
(
0
));
fillAccumKernel
.
create
(
"fill_accum_global"
,
ocl
::
imgproc
::
hough_lines_oclsrc
,
format
(
"-D FILL_ACCUM_GLOBAL"
));
if
(
fillAccumKernel
.
empty
())
return
false
;
globalThreads
[
0
]
=
workgroup_size
;
globalThreads
[
1
]
=
numangle
;
fillAccumKernel
.
args
(
ocl
::
KernelArg
::
ReadOnlyNoSize
(
pointsList
),
ocl
::
KernelArg
::
WriteOnlyNoSize
(
accum
),
total_points
,
irho
,
(
float
)
theta
,
numrho
,
numangle
);
return
fillAccumKernel
.
run
(
2
,
globalThreads
,
NULL
,
false
);
}
else
{
fillAccumKernel
.
create
(
"fill_accum_local"
,
ocl
::
imgproc
::
hough_lines_oclsrc
,
format
(
"-D FILL_ACCUM_LOCAL -D LOCAL_SIZE=%d -D BUFFER_SIZE=%d"
,
workgroup_size
,
numrho
+
2
));
if
(
fillAccumKernel
.
empty
())
return
false
;
localThreads
[
0
]
=
workgroup_size
;
localThreads
[
1
]
=
1
;
globalThreads
[
0
]
=
workgroup_size
;
globalThreads
[
1
]
=
numangle
+
2
;
fillAccumKernel
.
args
(
ocl
::
KernelArg
::
ReadOnlyNoSize
(
pointsList
),
ocl
::
KernelArg
::
WriteOnlyNoSize
(
accum
),
total_points
,
irho
,
(
float
)
theta
,
numrho
,
numangle
);
return
fillAccumKernel
.
run
(
2
,
globalThreads
,
localThreads
,
false
);
}
}
static
bool
ocl_HoughLines
(
InputArray
_src
,
OutputArray
_lines
,
double
rho
,
double
theta
,
int
threshold
,
double
min_theta
,
double
max_theta
)
{
CV_Assert
(
_src
.
type
()
==
CV_8UC1
);
if
(
max_theta
<
0
||
max_theta
>
CV_PI
)
{
CV_Error
(
CV_StsBadArg
,
"max_theta must fall between 0 and pi"
);
}
if
(
min_theta
<
0
||
min_theta
>
max_theta
)
{
CV_Error
(
CV_StsBadArg
,
"min_theta must fall between 0 and max_theta"
);
}
if
(
!
(
rho
>
0
&&
theta
>
0
))
{
CV_Error
(
CV_StsBadArg
,
"rho and theta must be greater 0"
);
}
UMat
src
=
_src
.
getUMat
();
int
numangle
=
cvRound
((
max_theta
-
min_theta
)
/
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_32FC2
));
return
true
;
}
UMat
accum
;
if
(
!
ocl_fillAccum
(
pointsList
,
accum
,
total_points
,
rho
,
theta
,
numrho
,
numangle
))
return
false
;
const
int
pixPerWI
=
8
;
ocl
::
Kernel
getLinesKernel
(
"get_lines"
,
ocl
::
imgproc
::
hough_lines_oclsrc
,
format
(
"-D GET_LINES"
));
if
(
getLinesKernel
.
empty
())
return
false
;
int
linesMax
=
threshold
>
0
?
min
(
total_points
*
numangle
/
threshold
,
OCL_MAX_LINES
)
:
OCL_MAX_LINES
;
UMat
lines
(
linesMax
,
1
,
CV_32FC2
);
getLinesKernel
.
args
(
ocl
::
KernelArg
::
ReadOnly
(
accum
),
ocl
::
KernelArg
::
WriteOnlyNoSize
(
lines
),
ocl
::
KernelArg
::
PtrWriteOnly
(
counters
),
linesMax
,
threshold
,
(
float
)
rho
,
(
float
)
theta
);
size_t
globalThreads
[
2
]
=
{
(
numrho
+
pixPerWI
-
1
)
/
pixPerWI
,
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_32FC2
));
return
true
;
}
static
bool
ocl_HoughLinesP
(
InputArray
_src
,
OutputArray
_lines
,
double
rho
,
double
theta
,
int
threshold
,
double
minLineLength
,
double
maxGap
)
{
CV_Assert
(
_src
.
type
()
==
CV_8UC1
);
if
(
!
(
rho
>
0
&&
theta
>
0
))
{
CV_Error
(
CV_StsBadArg
,
"rho and theta must be greater 0"
);
}
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
;
int
linesMax
=
threshold
>
0
?
min
(
total_points
*
numangle
/
threshold
,
OCL_MAX_LINES
)
:
OCL_MAX_LINES
;
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
,
double
rho
,
double
theta
,
int
threshold
,
double
srn
,
double
stn
,
double
min_theta
,
double
max_theta
)
{
CV_OCL_RUN
(
srn
==
0
&&
stn
==
0
&&
_image
.
isUMat
()
&&
_lines
.
isUMat
(),
ocl_HoughLines
(
_image
,
_lines
,
rho
,
theta
,
threshold
,
min_theta
,
max_theta
));
Mat
image
=
_image
.
getMat
();
std
::
vector
<
Vec2f
>
lines
;
...
...
@@ -675,6 +864,9 @@ 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
));
Mat
image
=
_image
.
getMat
();
std
::
vector
<
Vec4i
>
lines
;
HoughLinesProbabilistic
(
image
,
(
float
)
rho
,
(
float
)
theta
,
threshold
,
cvRound
(
minLineLength
),
cvRound
(
maxGap
),
lines
,
INT_MAX
);
...
...
modules/imgproc/src/opencl/hough_lines.cl
0 → 100644
View file @
397870d7
This diff is collapsed.
Click to expand it.
modules/imgproc/test/ocl/test_houghlines.cpp
0 → 100644
View file @
397870d7
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright (C) 2014, Itseez, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../test_precomp.hpp"
#include "opencv2/ts/ocl_test.hpp"
#ifdef HAVE_OPENCL
namespace
cvtest
{
namespace
ocl
{
struct
Vec2fComparator
{
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
];
}
};
/////////////////////////////// HoughLines ////////////////////////////////////
PARAM_TEST_CASE
(
HoughLines
,
double
,
double
,
int
)
{
double
rhoStep
,
thetaStep
;
int
threshold
;
Size
src_size
;
Mat
src
,
dst
;
UMat
usrc
,
udst
;
virtual
void
SetUp
()
{
rhoStep
=
GET_PARAM
(
0
);
thetaStep
=
GET_PARAM
(
1
);
threshold
=
GET_PARAM
(
2
);
}
virtual
void
generateTestData
()
{
src_size
=
randomSize
(
500
,
1920
);
src
.
create
(
src_size
,
CV_8UC1
);
src
.
setTo
(
Scalar
::
all
(
0
));
line
(
src
,
Point
(
0
,
100
),
Point
(
100
,
100
),
Scalar
::
all
(
255
),
1
);
line
(
src
,
Point
(
0
,
200
),
Point
(
100
,
200
),
Scalar
::
all
(
255
),
1
);
line
(
src
,
Point
(
0
,
400
),
Point
(
100
,
400
),
Scalar
::
all
(
255
),
1
);
line
(
src
,
Point
(
100
,
0
),
Point
(
100
,
200
),
Scalar
::
all
(
255
),
1
);
line
(
src
,
Point
(
200
,
0
),
Point
(
200
,
200
),
Scalar
::
all
(
255
),
1
);
line
(
src
,
Point
(
400
,
0
),
Point
(
400
,
200
),
Scalar
::
all
(
255
),
1
);
src
.
copyTo
(
usrc
);
}
virtual
void
readRealTestData
()
{
Mat
img
=
readImage
(
"shared/pic5.png"
,
IMREAD_GRAYSCALE
);
Canny
(
img
,
src
,
100
,
150
,
3
);
src
.
copyTo
(
usrc
);
}
virtual
void
Near
(
double
eps
=
0.
)
{
EXPECT_EQ
(
dst
.
size
(),
udst
.
size
());
if
(
dst
.
total
()
>
0
)
{
Mat
lines_cpu
,
lines_gpu
;
dst
.
copyTo
(
lines_cpu
);
udst
.
copyTo
(
lines_gpu
);
std
::
sort
(
lines_cpu
.
begin
<
Vec2f
>
(),
lines_cpu
.
end
<
Vec2f
>
(),
Vec2fComparator
());
std
::
sort
(
lines_gpu
.
begin
<
Vec2f
>
(),
lines_gpu
.
end
<
Vec2f
>
(),
Vec2fComparator
());
EXPECT_LE
(
TestUtils
::
checkNorm2
(
lines_cpu
,
lines_gpu
),
eps
);
}
}
};
OCL_TEST_P
(
HoughLines
,
RealImage
)
{
readRealTestData
();
OCL_OFF
(
cv
::
HoughLines
(
src
,
dst
,
rhoStep
,
thetaStep
,
threshold
));
OCL_ON
(
cv
::
HoughLines
(
usrc
,
udst
,
rhoStep
,
thetaStep
,
threshold
));
Near
(
1e-5
);
}
OCL_TEST_P
(
HoughLines
,
GeneratedImage
)
{
for
(
int
j
=
0
;
j
<
test_loop_times
;
j
++
)
{
generateTestData
();
OCL_OFF
(
cv
::
HoughLines
(
src
,
dst
,
rhoStep
,
thetaStep
,
threshold
));
OCL_ON
(
cv
::
HoughLines
(
usrc
,
udst
,
rhoStep
,
thetaStep
,
threshold
));
Near
(
1e-5
);
}
}
/////////////////////////////// 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.25
);
}
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