Tutorial Sobel Derivatives
authortribta <joaocartuchoo@gmail.com>
Tue, 22 Aug 2017 11:28:23 +0000 (12:28 +0100)
committertribta <joaocartuchoo@gmail.com>
Thu, 5 Oct 2017 11:17:36 +0000 (14:17 +0300)
doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown
doc/tutorials/imgproc/table_of_content_imgproc.markdown
samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java [new file with mode: 0644]
samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py [new file with mode: 0644]

index 3112b08..f6010fc 100644 (file)
@@ -1,13 +1,16 @@
 Sobel Derivatives {#tutorial_sobel_derivatives}
 =================
 
+@prev_tutorial{tutorial_copyMakeBorder}
+@next_tutorial{tutorial_laplace_operator}
+
 Goal
 ----
 
 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 @ref cv::Scharr to calculate a more accurate derivative for a kernel of
+-   Use the OpenCV function **Sobel()** to calculate the derivatives from an image.
+-   Use the OpenCV function **Scharr()** to calculate a more accurate derivative for a kernel of
     size \f$3 \cdot 3\f$
 
 Theory
@@ -83,7 +86,7 @@ Assuming that the image to be operated is \f$I\f$:
 @note
     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
-    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:
     \f[G_{x} = \begin{bmatrix}
     -3 & 0 & +3  \\
@@ -95,9 +98,9 @@ Assuming that the image to be operated is \f$I\f$:
     +3 & +10 & +3
     \end{bmatrix}\f]
 @note
-    You can check out more information of this function in the OpenCV reference (@ref cv::Scharr ).
-    Also, in the sample code below, you will notice that above the code for @ref cv::Sobel function
-    there is also code for the @ref cv::Scharr function commented. Uncommenting it (and obviously
+    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 **Sobel()** function
+    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.
 
 Code
@@ -107,28 +110,55 @@ Code
     -   Applies the *Sobel Operator* and generates as output an image with the detected *edges*
         bright on a darker background.
 
--#  The tutorial code's is shown lines below. You can also download it from
-    [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
+-#  The tutorial code's is shown lines below.
+
+@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
 -----------
 
--#  First we declare the variables we are going to use:
-    @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 load
--#  First, we apply a @ref cv::GaussianBlur to our image to reduce the noise ( kernel size = 3 )
-    @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 convert_to_gray
--#  Second, we calculate the "*derivatives*" in *x* and *y* directions. For this, we use the
-    function @ref cv::Sobel as shown below:
-    @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp sobel
+#### Declare variables
+
+@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp variables
+
+#### Load source image
+
+@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp load
+
+#### Reduce noise
+
+@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:
 
     -   *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.
     -   *x_order*: The order of the derivative in **x** direction.
     -   *y_order*: The order of the derivative in **y** direction.
@@ -137,13 +167,20 @@ Explanation
     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.
 
--#  We convert our partial results back to *CV_8U*:
-    @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert
--#  Finally, 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).
-    @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp blend
--#  Finally, we show our result:
-    @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp display
+#### Convert output to a CV_8U image
+
+@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert
+
+#### Gradient
+
+@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
 -------
index 5ee75f3..f4c57cd 100644 (file)
@@ -91,6 +91,8 @@ In this section you will learn about the image processing (manipulation) functio
 
 -   @subpage tutorial_sobel_derivatives
 
+    *Languages:* C++, Java, Python
+
     *Compatibility:* \> OpenCV 2.0
 
     *Author:* Ana Huamán
index 5209380..16661d8 100644 (file)
@@ -30,6 +30,7 @@ int main( int argc, char** argv )
   cout << "\nPress 'ESC' to exit program.\nPress 'R' to reset values ( ksize will be -1 equal to Scharr function )";
 
   //![variables]
+  // First we declare the variables we are going to use
   Mat image,src, src_gray;
   Mat grad;
   const String window_name = "Sobel Demo - Simple Edge Detector";
@@ -40,11 +41,14 @@ int main( int argc, char** argv )
   //![variables]
 
   //![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
 
+  // Check if image is loaded fine
   if( image.empty() )
   {
+    printf("Error opening image: %s\n", imageName.c_str());
     return 1;
   }
   //![load]
@@ -52,10 +56,12 @@ int main( int argc, char** argv )
   for (;;)
   {
     //![reduce_noise]
+    // Remove noise by blurring with a Gaussian filter ( kernel size = 3 )
     GaussianBlur(image, src, Size(3, 3), 0, 0, BORDER_DEFAULT);
     //![reduce_noise]
 
     //![convert_to_gray]
+    // Convert the image to grayscale
     cvtColor(src, src_gray, COLOR_BGR2GRAY);
     //![convert_to_gray]
 
@@ -72,6 +78,7 @@ int main( int argc, char** argv )
     //![sobel]
 
     //![convert]
+    // converting back to CV_8U
     convertScaleAbs(grad_x, abs_grad_x);
     convertScaleAbs(grad_y, abs_grad_y);
     //![convert]
diff --git a/samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java b/samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java
new file mode 100644 (file)
index 0000000..815c16b
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * @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);
+    }
+}
diff --git a/samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py b/samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py
new file mode 100644 (file)
index 0000000..4afe3af
--- /dev/null
@@ -0,0 +1,74 @@
+"""
+@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:\nmorph_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:])