diff --git a/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown b/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown index 5716410d39..454f745177 100644 --- a/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown +++ b/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown @@ -1,12 +1,15 @@ Making your own linear filters! {#tutorial_filter_2d} =============================== +@prev_tutorial{tutorial_threshold_inRange} +@next_tutorial{tutorial_copyMakeBorder} + Goal ---- In this tutorial you will learn how to: -- Use the OpenCV function @ref cv::filter2D to create your own linear filters. +- Use the OpenCV function **filter2D()** to create your own linear filters. Theory ------ @@ -40,61 +43,127 @@ Expressing the procedure above in the form of an equation we would have: \f[H(x,y) = \sum_{i=0}^{M_{i} - 1} \sum_{j=0}^{M_{j}-1} I(x+i - a_{i}, y + j - a_{j})K(i,j)\f] -Fortunately, OpenCV provides you with the function @ref cv::filter2D so you do not have to code all +Fortunately, OpenCV provides you with the function **filter2D()** so you do not have to code all these operations. +### What does this program do? +- Loads an image +- Performs a *normalized box filter*. For instance, for a kernel of size \f$size = 3\f$, the + kernel would be: + +\f[K = \dfrac{1}{3 \cdot 3} \begin{bmatrix} +1 & 1 & 1 \\ + 1 & 1 & 1 \\ + 1 & 1 & 1 +\end{bmatrix}\f] + +The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11. + +- The filter output (with each kernel) will be shown during 500 milliseconds + Code ---- --# **What does this program do?** - - Loads an image - - Performs a *normalized box filter*. For instance, for a kernel of size \f$size = 3\f$, the - kernel would be: +The tutorial code's is shown in the lines below. - \f[K = \dfrac{1}{3 \cdot 3} \begin{bmatrix} - 1 & 1 & 1 \\ - 1 & 1 & 1 \\ - 1 & 1 & 1 - \end{bmatrix}\f] +@add_toggle_cpp +You can also download it from +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp) +@include cpp/tutorial_code/ImgTrans/filter2D_demo.cpp +@end_toggle - The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11. +@add_toggle_java +You can also download it from +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java) +@include java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java +@end_toggle - - The filter output (with each kernel) will be shown during 500 milliseconds - --# 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/filter2D_demo.cpp) - @include cpp/tutorial_code/ImgTrans/filter2D_demo.cpp +@add_toggle_python +You can also download it from +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/Filter2D/filter2D.py) +@include python/tutorial_code/ImgTrans/Filter2D/filter2D.py +@end_toggle Explanation ----------- --# Load an image - @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp load --# Initialize the arguments for the linear filter - @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp init_arguments --# Perform an infinite loop updating the kernel size and applying our linear filter to the input - image. Let's analyze that more in detail: --# First we define the kernel our filter is going to use. Here it is: - @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp update_kernel - The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$. The second - line actually builds the kernel by setting its value to a matrix filled with \f$1's\f$ and - normalizing it by dividing it between the number of elements. +#### Load an image --# After setting the kernel, we can generate the filter by using the function @ref cv::filter2D : - @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp apply_filter - The arguments denote: +@add_toggle_cpp +@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp load +@end_toggle - -# *src*: Source image - -# *dst*: Destination image - -# *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is +@add_toggle_java +@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java load +@end_toggle + +@add_toggle_python +@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py load +@end_toggle + +#### Initialize the arguments + +@add_toggle_cpp +@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp init_arguments +@end_toggle + +@add_toggle_java +@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java init_arguments +@end_toggle + +@add_toggle_python +@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py init_arguments +@end_toggle + +##### Loop + +Perform an infinite loop updating the kernel size and applying our linear filter to the input +image. Let's analyze that more in detail: + +- First we define the kernel our filter is going to use. Here it is: + +@add_toggle_cpp +@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp update_kernel +@end_toggle + +@add_toggle_java +@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java update_kernel +@end_toggle + +@add_toggle_python +@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py update_kernel +@end_toggle + +The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$. +The second line actually builds the kernel by setting its value to a matrix filled with +\f$1's\f$ and normalizing it by dividing it between the number of elements. + +- After setting the kernel, we can generate the filter by using the function **filter2D()** : + +@add_toggle_cpp +@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp apply_filter +@end_toggle + +@add_toggle_java +@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java apply_filter +@end_toggle + +@add_toggle_python +@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py apply_filter +@end_toggle + +- The arguments denote: + - *src*: Source image + - *dst*: Destination image + - *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is the same as the source. - -# *kernel*: The kernel to be scanned through the image - -# *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)* - indicates the center by default. - -# *delta*: A value to be added to each pixel during the correlation. By default it is \f$0\f$ - -# *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial) + - *kernel*: The kernel to be scanned through the image + - *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)* + indicates the center by default. + - *delta*: A value to be added to each pixel during the correlation. By default it is \f$0\f$ + - *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial) --# Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be +- Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be updated in the range indicated. Results @@ -104,4 +173,4 @@ Results result should be a window that shows an image blurred by a normalized filter. Each 0.5 seconds the kernel size should change, as can be seen in the series of snapshots below: - ![](images/filter_2d_tutorial_result.jpg) +![](images/filter_2d_tutorial_result.jpg) diff --git a/doc/tutorials/imgproc/table_of_content_imgproc.markdown b/doc/tutorials/imgproc/table_of_content_imgproc.markdown index d25502369a..5dd3d57c02 100644 --- a/doc/tutorials/imgproc/table_of_content_imgproc.markdown +++ b/doc/tutorials/imgproc/table_of_content_imgproc.markdown @@ -77,6 +77,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_filter_2d + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán diff --git a/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp b/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp index 24aef46b97..3b7f3a96b5 100644 --- a/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp @@ -15,56 +15,60 @@ using namespace cv; */ int main ( int argc, char** argv ) { - /// Declare variables - Mat src, dst; + // Declare variables + Mat src, dst; - Mat kernel; - Point anchor; - double delta; - int ddepth; - int kernel_size; - const char* window_name = "filter2D Demo"; + Mat kernel; + Point anchor; + double delta; + int ddepth; + int kernel_size; + const char* window_name = "filter2D Demo"; - //![load] - String imageName("../data/lena.jpg"); // by default - if (argc > 1) - { - imageName = argv[1]; - } - src = imread( imageName, IMREAD_COLOR ); // Load an image + //![load] + const char* imageName = argc >=2 ? argv[1] : "../data/lena.jpg"; - if( src.empty() ) - { return -1; } - //![load] + // Loads an image + src = imread( imageName, IMREAD_COLOR ); // Load an image - //![init_arguments] - /// Initialize arguments for the filter - anchor = Point( -1, -1 ); - delta = 0; - ddepth = -1; - //![init_arguments] + if( src.empty() ) + { + printf(" Error opening image\n"); + printf(" Program Arguments: [image_name -- default ../data/lena.jpg] \n"); + return -1; + } + //![load] - /// Loop - Will filter the image with different kernel sizes each 0.5 seconds - int ind = 0; - for(;;) - { - char c = (char)waitKey(500); - /// Press 'ESC' to exit the program - if( c == 27 ) - { break; } + //![init_arguments] + // Initialize arguments for the filter + anchor = Point( -1, -1 ); + delta = 0; + ddepth = -1; + //![init_arguments] - //![update_kernel] - /// Update kernel size for a normalized box filter - kernel_size = 3 + 2*( ind%5 ); - kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size); - //![update_kernel] + // Loop - Will filter the image with different kernel sizes each 0.5 seconds + int ind = 0; + for(;;) + { + //![update_kernel] + // Update kernel size for a normalized box filter + kernel_size = 3 + 2*( ind%5 ); + kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size); + //![update_kernel] - //![apply_filter] - filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT ); - //![apply_filter] - imshow( window_name, dst ); - ind++; - } + //![apply_filter] + // Apply filter + filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT ); + //![apply_filter] + imshow( window_name, dst ); - return 0; + char c = (char)waitKey(500); + // Press 'ESC' to exit the program + if( c == 27 ) + { break; } + + ind++; + } + + return 0; } diff --git a/samples/java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java b/samples/java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java new file mode 100644 index 0000000000..aa685d9afe --- /dev/null +++ b/samples/java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java @@ -0,0 +1,81 @@ +/** + * @file Filter2D_demo.java + * @brief Sample code that shows how to implement your own linear filters by using filter2D function + */ + +import org.opencv.core.*; +import org.opencv.core.Point; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class Filter2D_DemoRun { + + public void run(String[] args) { + // Declare variables + Mat src, dst = new Mat(); + + Mat kernel = new Mat(); + Point anchor; + double delta; + int ddepth; + int kernel_size; + String window_name = "filter2D Demo"; + + //! [load] + String imageName = ((args.length > 0) ? args[0] : "../data/lena.jpg"); + + // Load an image + src = Imgcodecs.imread(imageName, Imgcodecs.IMREAD_COLOR); + + // Check if image is loaded fine + if( src.empty() ) { + System.out.println("Error opening image!"); + System.out.println("Program Arguments: [image_name -- default ../data/lena.jpg] \n"); + System.exit(-1); + } + //! [load] + + //! [init_arguments] + // Initialize arguments for the filter + anchor = new Point( -1, -1); + delta = 0.0; + ddepth = -1; + //! [init_arguments] + + // Loop - Will filter the image with different kernel sizes each 0.5 seconds + int ind = 0; + while( true ) + { + //! [update_kernel] + // Update kernel size for a normalized box filter + kernel_size = 3 + 2*( ind%5 ); + Mat ones = Mat.ones( kernel_size, kernel_size, CvType.CV_32F ); + Core.multiply(ones, new Scalar(1/(double)(kernel_size*kernel_size)), kernel); + //! [update_kernel] + + //! [apply_filter] + // Apply filter + Imgproc.filter2D(src, dst, ddepth , kernel, anchor, delta, Core.BORDER_DEFAULT ); + //! [apply_filter] + HighGui.imshow( window_name, dst ); + + int c = HighGui.waitKey(500); + // Press 'ESC' to exit the program + if( c == 27 ) + { break; } + + ind++; + } + + System.exit(0); + } +} + +public class Filter2D_Demo { + public static void main(String[] args) { + // Load the native library. + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + new Filter2D_DemoRun().run(args); + } +} diff --git a/samples/python/tutorial_code/ImgTrans/Filter2D/filter2D.py b/samples/python/tutorial_code/ImgTrans/Filter2D/filter2D.py new file mode 100644 index 0000000000..e4d1afe590 --- /dev/null +++ b/samples/python/tutorial_code/ImgTrans/Filter2D/filter2D.py @@ -0,0 +1,54 @@ +""" +@file filter2D.py +@brief Sample code that shows how to implement your own linear filters by using filter2D function +""" +import sys +import cv2 +import numpy as np + + +def main(argv): + window_name = 'filter2D Demo' + + ## [load] + imageName = argv[0] if len(argv) > 0 else "../data/lena.jpg" + + # Loads an image + src = cv2.imread(imageName, cv2.IMREAD_COLOR) + + # Check if image is loaded fine + if src is None: + print ('Error opening image!') + print ('Usage: filter2D.py [image_name -- default ../data/lena.jpg] \n') + return -1 + ## [load] + ## [init_arguments] + # Initialize ddepth argument for the filter + ddepth = -1 + ## [init_arguments] + # Loop - Will filter the image with different kernel sizes each 0.5 seconds + ind = 0 + while True: + ## [update_kernel] + # Update kernel size for a normalized box filter + kernel_size = 3 + 2 * (ind % 5) + kernel = np.ones((kernel_size, kernel_size), dtype=np.float32) + kernel /= (kernel_size * kernel_size) + ## [update_kernel] + ## [apply_filter] + # Apply filter + dst = cv2.filter2D(src, ddepth, kernel) + ## [apply_filter] + cv2.imshow(window_name, dst) + + c = cv2.waitKey(500) + if c == 27: + break + + ind += 1 + + return 0 + + +if __name__ == "__main__": + main(sys.argv[1:])