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
f7d85bfe
Commit
f7d85bfe
authored
Aug 22, 2017
by
tribta
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Tutorial Sobel Derivatives
parent
3250f11f
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
243 additions
and
29 deletions
+243
-29
sobel_derivatives.markdown
...roc/imgtrans/sobel_derivatives/sobel_derivatives.markdown
+65
-28
table_of_content_imgproc.markdown
doc/tutorials/imgproc/table_of_content_imgproc.markdown
+2
-0
Sobel_Demo.cpp
samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
+8
-1
SobelDemo.java
samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java
+94
-0
sobel_demo.py
...les/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py
+74
-0
No files found.
doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown
View file @
f7d85bfe
Sobel Derivatives {#tutorial_sobel_derivatives}
Sobel Derivatives {#tutorial_sobel_derivatives}
=================
=================
@prev_tutorial{tutorial_copyMakeBorder}
@next_tutorial{tutorial_laplace_operator}
Goal
Goal
----
----
In this tutorial you will learn how to:
In this tutorial you will learn how to:
-
Use the OpenCV function
@ref cv::Sobel
to calculate the derivatives from an image.
-
Use the OpenCV function
**Sobel()**
to calculate the derivatives from an image.
-
Use the OpenCV function
@ref cv::Scharr
to calculate a more accurate derivative for a kernel of
-
Use the OpenCV function
**Scharr()**
to calculate a more accurate derivative for a kernel of
size
\f
$3
\c
dot 3
\f
$
size
\f
$3
\c
dot 3
\f
$
Theory
Theory
...
@@ -83,7 +86,7 @@ Assuming that the image to be operated is \f$I\f$:
...
@@ -83,7 +86,7 @@ Assuming that the image to be operated is \f$I\f$:
@note
@note
When the size of the kernel is
`3`
, the Sobel kernel shown above may produce noticeable
When the size of the kernel is
`3`
, the Sobel kernel shown above may produce noticeable
inaccuracies (after all, Sobel is only an approximation of the derivative). OpenCV addresses
inaccuracies (after all, Sobel is only an approximation of the derivative). OpenCV addresses
this inaccuracy for kernels of size 3 by using the
@ref cv::Scharr
function. This is as fast
this inaccuracy for kernels of size 3 by using the
**Scharr()**
function. This is as fast
but more accurate than the standar Sobel function. It implements the following kernels:
but more accurate than the standar Sobel function. It implements the following kernels:
\f
[
G_{x} =
\b
egin{bmatrix}
\f
[
G_{x} =
\b
egin{bmatrix}
-3 & 0 & +3
\\
-3 & 0 & +3
\\
...
@@ -95,9 +98,9 @@ Assuming that the image to be operated is \f$I\f$:
...
@@ -95,9 +98,9 @@ Assuming that the image to be operated is \f$I\f$:
+3 & +10 & +3
+3 & +10 & +3
\e
nd{bmatrix}
\f
]
\e
nd{bmatrix}
\f
]
@note
@note
You can check out more information of this function in the OpenCV reference
(@ref cv::Scharr )
.
You can check out more information of this function in the OpenCV reference
-
**Scharr()**
.
Also, in the sample code below, you will notice that above the code for
@ref cv::Sobel
function
Also, in the sample code below, you will notice that above the code for
**Sobel()**
function
there is also code for the
@ref cv::Scharr
function commented. Uncommenting it (and obviously
there is also code for the
**Scharr()**
function commented. Uncommenting it (and obviously
commenting the Sobel stuff) should give you an idea of how this function works.
commenting the Sobel stuff) should give you an idea of how this function works.
Code
Code
...
@@ -107,28 +110,55 @@ Code
...
@@ -107,28 +110,55 @@ Code
-
Applies the
*Sobel Operator*
and generates as output an image with the detected
*edges*
-
Applies the
*Sobel Operator*
and generates as output an image with the detected
*edges*
bright on a darker background.
bright on a darker background.
-# The tutorial code's is shown lines below. You can also download it from
-# The tutorial code's is shown lines below.
[
here
](
https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
)
@include samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
@add_toggle_cpp
You can also download it from
[
here
](
https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
)
@include samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
@end_toggle
@add_toggle_java
You can also download it from
[
here
](
https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java
)
@include samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java
@end_toggle
@add_toggle_python
You can also download it from
[
here
](
https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py
)
@include samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py
@end_toggle
Explanation
Explanation
-----------
-----------
-# First we declare the variables we are going to use:
#### Declare variables
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp variables
-# As usual we load our source image
*src*
:
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp variables
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp load
-# First, we apply a @ref cv::GaussianBlur to our image to reduce the noise ( kernel size = 3 )
#### Load source image
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp reduce_noise
-# Now we convert our filtered image to grayscale:
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp load
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert_to_gray
-# Second, we calculate the "
*derivatives*
" in
*x*
and
*y*
directions. For this, we use the
#### Reduce noise
function @ref cv::Sobel as shown below:
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp sobel
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp reduce_noise
#### Grayscale
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert_to_gray
#### Sobel Operator
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp sobel
-
We calculate the "derivatives" in
*x*
and
*y*
directions. For this, we use the
function
**Sobel()**
as shown below:
The function takes the following arguments:
The function takes the following arguments:
- *src_gray*: In our example, the input image. Here it is *CV_8U*
- *src_gray*: In our example, the input image. Here it is *CV_8U*
- *grad_x*
/*grad_y*
: The output image.
- *grad_x*
/ *grad_y*
: The output image.
- *ddepth*: The depth of the output image. We set it to *CV_16S* to avoid overflow.
- *ddepth*: The depth of the output image. We set it to *CV_16S* to avoid overflow.
- *x_order*: The order of the derivative in **x** direction.
- *x_order*: The order of the derivative in **x** direction.
- *y_order*: The order of the derivative in **y** direction.
- *y_order*: The order of the derivative in **y** direction.
...
@@ -137,13 +167,20 @@ Explanation
...
@@ -137,13 +167,20 @@ Explanation
Notice that to calculate the gradient in *x* direction we use: \f$x_{order}= 1\f$ and
Notice that to calculate the gradient in *x* direction we use: \f$x_{order}= 1\f$ and
\f$y_{order} = 0\f$. We do analogously for the *y* direction.
\f$y_{order} = 0\f$. We do analogously for the *y* direction.
-# We convert our partial results back to
*CV_8U*
:
#### Convert output to a CV_8U image
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert
-# Finally, we try to approximate the
*gradient*
by adding both directional gradients (note that
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert
this is not an exact calculation at all! but it is good for our purposes).
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp blend
#### Gradient
-# Finally, we show our result:
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp display
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp blend
We try to approximate the
*gradient*
by adding both directional gradients (note that
this is not an exact calculation at all! but it is good for our purposes).
#### Show results
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp display
Results
Results
-------
-------
...
...
doc/tutorials/imgproc/table_of_content_imgproc.markdown
View file @
f7d85bfe
...
@@ -91,6 +91,8 @@ In this section you will learn about the image processing (manipulation) functio
...
@@ -91,6 +91,8 @@ In this section you will learn about the image processing (manipulation) functio
-
@subpage tutorial_sobel_derivatives
-
@subpage tutorial_sobel_derivatives
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán
*Author:* Ana Huamán
...
...
samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
View file @
f7d85bfe
...
@@ -30,6 +30,7 @@ int main( int argc, char** argv )
...
@@ -30,6 +30,7 @@ int main( int argc, char** argv )
cout
<<
"
\n
Press 'ESC' to exit program.
\n
Press 'R' to reset values ( ksize will be -1 equal to Scharr function )"
;
cout
<<
"
\n
Press 'ESC' to exit program.
\n
Press 'R' to reset values ( ksize will be -1 equal to Scharr function )"
;
//![variables]
//![variables]
// First we declare the variables we are going to use
Mat
image
,
src
,
src_gray
;
Mat
image
,
src
,
src_gray
;
Mat
grad
;
Mat
grad
;
const
String
window_name
=
"Sobel Demo - Simple Edge Detector"
;
const
String
window_name
=
"Sobel Demo - Simple Edge Detector"
;
...
@@ -40,11 +41,14 @@ int main( int argc, char** argv )
...
@@ -40,11 +41,14 @@ int main( int argc, char** argv )
//![variables]
//![variables]
//![load]
//![load]
String
imageName
=
parser
.
get
<
String
>
(
"@input"
);
// by default
String
imageName
=
parser
.
get
<
String
>
(
"@input"
);
// As usual we load our source image (src)
image
=
imread
(
imageName
,
IMREAD_COLOR
);
// Load an image
image
=
imread
(
imageName
,
IMREAD_COLOR
);
// Load an image
// Check if image is loaded fine
if
(
image
.
empty
()
)
if
(
image
.
empty
()
)
{
{
printf
(
"Error opening image: %s
\n
"
,
imageName
.
c_str
());
return
1
;
return
1
;
}
}
//![load]
//![load]
...
@@ -52,10 +56,12 @@ int main( int argc, char** argv )
...
@@ -52,10 +56,12 @@ int main( int argc, char** argv )
for
(;;)
for
(;;)
{
{
//![reduce_noise]
//![reduce_noise]
// Remove noise by blurring with a Gaussian filter ( kernel size = 3 )
GaussianBlur
(
image
,
src
,
Size
(
3
,
3
),
0
,
0
,
BORDER_DEFAULT
);
GaussianBlur
(
image
,
src
,
Size
(
3
,
3
),
0
,
0
,
BORDER_DEFAULT
);
//![reduce_noise]
//![reduce_noise]
//![convert_to_gray]
//![convert_to_gray]
// Convert the image to grayscale
cvtColor
(
src
,
src_gray
,
COLOR_BGR2GRAY
);
cvtColor
(
src
,
src_gray
,
COLOR_BGR2GRAY
);
//![convert_to_gray]
//![convert_to_gray]
...
@@ -72,6 +78,7 @@ int main( int argc, char** argv )
...
@@ -72,6 +78,7 @@ int main( int argc, char** argv )
//![sobel]
//![sobel]
//![convert]
//![convert]
// converting back to CV_8U
convertScaleAbs
(
grad_x
,
abs_grad_x
);
convertScaleAbs
(
grad_x
,
abs_grad_x
);
convertScaleAbs
(
grad_y
,
abs_grad_y
);
convertScaleAbs
(
grad_y
,
abs_grad_y
);
//![convert]
//![convert]
...
...
samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java
0 → 100644
View file @
f7d85bfe
/**
* @file SobelDemo.java
* @brief Sample code using Sobel and/or Scharr OpenCV functions to make a simple Edge Detector
*/
import
org.opencv.core.*
;
import
org.opencv.highgui.HighGui
;
import
org.opencv.imgcodecs.Imgcodecs
;
import
org.opencv.imgproc.Imgproc
;
class
SobelDemoRun
{
public
void
run
(
String
[]
args
)
{
//! [declare_variables]
// First we declare the variables we are going to use
Mat
src
,
src_gray
=
new
Mat
();
Mat
grad
=
new
Mat
();
String
window_name
=
"Sobel Demo - Simple Edge Detector"
;
int
scale
=
1
;
int
delta
=
0
;
int
ddepth
=
CvType
.
CV_16S
;
//! [declare_variables]
//! [load]
// As usual we load our source image (src)
// Check number of arguments
if
(
args
.
length
==
0
){
System
.
out
.
println
(
"Not enough parameters!"
);
System
.
out
.
println
(
"Program Arguments: [image_path]"
);
System
.
exit
(-
1
);
}
// Load the image
src
=
Imgcodecs
.
imread
(
args
[
0
]);
// Check if image is loaded fine
if
(
src
.
empty
()
)
{
System
.
out
.
println
(
"Error opening image: "
+
args
[
0
]);
System
.
exit
(-
1
);
}
//! [load]
//! [reduce_noise]
// Remove noise by blurring with a Gaussian filter ( kernel size = 3 )
Imgproc
.
GaussianBlur
(
src
,
src
,
new
Size
(
3
,
3
),
0
,
0
,
Core
.
BORDER_DEFAULT
);
//! [reduce_noise]
//! [convert_to_gray]
// Convert the image to grayscale
Imgproc
.
cvtColor
(
src
,
src_gray
,
Imgproc
.
COLOR_RGB2GRAY
);
//! [convert_to_gray]
//! [sobel]
/// Generate grad_x and grad_y
Mat
grad_x
=
new
Mat
(),
grad_y
=
new
Mat
();
Mat
abs_grad_x
=
new
Mat
(),
abs_grad_y
=
new
Mat
();
/// Gradient X
//Imgproc.Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, Core.BORDER_DEFAULT );
Imgproc
.
Sobel
(
src_gray
,
grad_x
,
ddepth
,
1
,
0
,
3
,
scale
,
delta
,
Core
.
BORDER_DEFAULT
);
/// Gradient Y
//Imgproc.Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, Core.BORDER_DEFAULT );
Imgproc
.
Sobel
(
src_gray
,
grad_y
,
ddepth
,
0
,
1
,
3
,
scale
,
delta
,
Core
.
BORDER_DEFAULT
);
//! [sobel]
//![convert]
// converting back to CV_8U
Core
.
convertScaleAbs
(
grad_x
,
abs_grad_x
);
Core
.
convertScaleAbs
(
grad_y
,
abs_grad_y
);
//![convert]
//! [add_weighted]
/// Total Gradient (approximate)
Core
.
addWeighted
(
abs_grad_x
,
0.5
,
abs_grad_y
,
0.5
,
0
,
grad
);
//! [add_weighted]
//! [display]
HighGui
.
imshow
(
window_name
,
grad
);
HighGui
.
waitKey
(
0
);
//! [display]
System
.
exit
(
0
);
}
}
public
class
SobelDemo
{
public
static
void
main
(
String
[]
args
)
{
// Load the native library.
System
.
loadLibrary
(
Core
.
NATIVE_LIBRARY_NAME
);
new
SobelDemoRun
().
run
(
args
);
}
}
samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py
0 → 100644
View file @
f7d85bfe
"""
@file sobel_demo.py
@brief Sample code using Sobel and/or Scharr OpenCV functions to make a simple Edge Detector
"""
import
sys
import
cv2
def
main
(
argv
):
## [variables]
# First we declare the variables we are going to use
window_name
=
(
'Sobel Demo - Simple Edge Detector'
)
scale
=
1
delta
=
0
ddepth
=
cv2
.
CV_16S
## [variables]
## [load]
# As usual we load our source image (src)
# Check number of arguments
if
len
(
argv
)
<
1
:
print
(
'Not enough parameters'
)
print
(
'Usage:
\n
morph_lines_detection.py < path_to_image >'
)
return
-
1
# Load the image
src
=
cv2
.
imread
(
argv
[
0
],
cv2
.
IMREAD_COLOR
)
# Check if image is loaded fine
if
src
is
None
:
print
(
'Error opening image: '
+
argv
[
0
])
return
-
1
## [load]
## [reduce_noise]
# Remove noise by blurring with a Gaussian filter ( kernel size = 3 )
src
=
cv2
.
GaussianBlur
(
src
,
(
3
,
3
),
0
)
## [reduce_noise]
## [convert_to_gray]
# Convert the image to grayscale
gray
=
cv2
.
cvtColor
(
src
,
cv2
.
COLOR_BGR2GRAY
)
## [convert_to_gray]
## [sobel]
# Gradient-X
# grad_x = cv2.Scharr(gray,ddepth,1,0)
grad_x
=
cv2
.
Sobel
(
gray
,
ddepth
,
1
,
0
,
ksize
=
3
,
scale
=
scale
,
delta
=
delta
,
borderType
=
cv2
.
BORDER_DEFAULT
)
# Gradient-Y
# grad_y = cv2.Scharr(gray,ddepth,0,1)
grad_y
=
cv2
.
Sobel
(
gray
,
ddepth
,
0
,
1
,
ksize
=
3
,
scale
=
scale
,
delta
=
delta
,
borderType
=
cv2
.
BORDER_DEFAULT
)
## [sobel]
## [convert]
# converting back to uint8
abs_grad_x
=
cv2
.
convertScaleAbs
(
grad_x
)
abs_grad_y
=
cv2
.
convertScaleAbs
(
grad_y
)
## [convert]
## [blend]
## Total Gradient (approximate)
grad
=
cv2
.
addWeighted
(
abs_grad_x
,
0.5
,
abs_grad_y
,
0.5
,
0
)
## [blend]
## [display]
cv2
.
imshow
(
window_name
,
grad
)
cv2
.
waitKey
(
0
)
## [display]
return
0
if
__name__
==
"__main__"
:
main
(
sys
.
argv
[
1
:])
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