Commit bc18fb48 authored by tribta's avatar tribta

Tutorial Smoothing Images

parent 5f6ce6f4
Smoothing Images {#tutorial_gausian_median_blur_bilateral_filter} Smoothing Images {#tutorial_gausian_median_blur_bilateral_filter}
================ ================
@next_tutorial{tutorial_erosion_dilatation}
Goal Goal
---- ----
In this tutorial you will learn how to apply diverse linear filters to smooth images using OpenCV In this tutorial you will learn how to apply diverse linear filters to smooth images using OpenCV
functions such as: functions such as:
- @ref cv::blur - **blur()**
- @ref cv::GaussianBlur - **GaussianBlur()**
- @ref cv::medianBlur - **medianBlur()**
- @ref cv::bilateralFilter - **bilateralFilter()**
Theory Theory
------ ------
...@@ -92,38 +94,65 @@ Code ...@@ -92,38 +94,65 @@ Code
- Loads an image - Loads an image
- Applies 4 different kinds of filters (explained in Theory) and show the filtered images - Applies 4 different kinds of filters (explained in Theory) and show the filtered images
sequentially sequentially
@add_toggle_cpp
- **Downloadable code**: Click
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click - **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp) [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java)
- **Code at glance:**
@include samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java
@end_toggle
@add_toggle_python
- **Downloadable code**: Click
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/imgProc/Smoothing/smoothing.py)
- **Code at glance:** - **Code at glance:**
@include samples/cpp/tutorial_code/ImgProc/Smoothing.cpp @include samples/python/tutorial_code/imgProc/Smoothing/smoothing.py
@end_toggle
Explanation Explanation
----------- -----------
-# Let's check the OpenCV functions that involve only the smoothing procedure, since the rest is Let's check the OpenCV functions that involve only the smoothing procedure, since the rest is
already known by now. already known by now.
-# **Normalized Block Filter:**
OpenCV offers the function @ref cv::blur to perform smoothing with this filter. #### Normalized Block Filter:
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp blur
- OpenCV offers the function **blur()** to perform smoothing with this filter.
We specify 4 arguments (more details, check the Reference): We specify 4 arguments (more details, check the Reference):
- *src*: Source image - *src*: Source image
- *dst*: Destination image - *dst*: Destination image
- *Size( w,h )*: Defines the size of the kernel to be used ( of width *w* pixels and height - *Size( w, h )*: Defines the size of the kernel to be used ( of width *w* pixels and height
*h* pixels) *h* pixels)
- *Point(-1, -1)*: Indicates where the anchor point (the pixel evaluated) is located with - *Point(-1, -1)*: Indicates where the anchor point (the pixel evaluated) is located with
respect to the neighborhood. If there is a negative value, then the center of the kernel is respect to the neighborhood. If there is a negative value, then the center of the kernel is
considered the anchor point. considered the anchor point.
-# **Gaussian Filter:** @add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp blur
@end_toggle
It is performed by the function @ref cv::GaussianBlur : @add_toggle_java
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp gaussianblur @snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java blur
@end_toggle
Here we use 4 arguments (more details, check the OpenCV reference): @add_toggle_python
@snippet samples/python/tutorial_code/imgProc/Smoothing/smoothing.py blur
@end_toggle
#### Gaussian Filter:
- It is performed by the function **GaussianBlur()** :
Here we use 4 arguments (more details, check the OpenCV reference):
- *src*: Source image - *src*: Source image
- *dst*: Destination image - *dst*: Destination image
- *Size(w, h)*: The size of the kernel to be used (the neighbors to be considered). \f$w\f$ and - *Size(w, h)*: The size of the kernel to be used (the neighbors to be considered). \f$w\f$ and
...@@ -134,35 +163,65 @@ Explanation ...@@ -134,35 +163,65 @@ Explanation
- \f$\sigma_{y}\f$: The standard deviation in y. Writing \f$0\f$ implies that \f$\sigma_{y}\f$ is - \f$\sigma_{y}\f$: The standard deviation in y. Writing \f$0\f$ implies that \f$\sigma_{y}\f$ is
calculated using kernel size. calculated using kernel size.
-# **Median Filter:** @add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp gaussianblur
@end_toggle
This filter is provided by the @ref cv::medianBlur function: @add_toggle_java
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp medianblur @snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java gaussianblur
@end_toggle
We use three arguments: @add_toggle_python
@snippet samples/python/tutorial_code/imgProc/Smoothing/smoothing.py gaussianblur
@end_toggle
#### Median Filter:
- This filter is provided by the **medianBlur()** function:
We use three arguments:
- *src*: Source image - *src*: Source image
- *dst*: Destination image, must be the same type as *src* - *dst*: Destination image, must be the same type as *src*
- *i*: Size of the kernel (only one because we use a square window). Must be odd. - *i*: Size of the kernel (only one because we use a square window). Must be odd.
-# **Bilateral Filter** @add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp medianblur
@end_toggle
Provided by OpenCV function @ref cv::bilateralFilter @add_toggle_java
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp bilateralfilter @snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java medianblur
@end_toggle
We use 5 arguments: @add_toggle_python
@snippet samples/python/tutorial_code/imgProc/Smoothing/smoothing.py medianblur
@end_toggle
#### Bilateral Filter
- Provided by OpenCV function **bilateralFilter()**
We use 5 arguments:
- *src*: Source image - *src*: Source image
- *dst*: Destination image - *dst*: Destination image
- *d*: The diameter of each pixel neighborhood. - *d*: The diameter of each pixel neighborhood.
- \f$\sigma_{Color}\f$: Standard deviation in the color space. - \f$\sigma_{Color}\f$: Standard deviation in the color space.
- \f$\sigma_{Space}\f$: Standard deviation in the coordinate space (in pixel terms) - \f$\sigma_{Space}\f$: Standard deviation in the coordinate space (in pixel terms)
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp bilateralfilter
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java bilateralfilter
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/Smoothing/smoothing.py bilateralfilter
@end_toggle
Results Results
------- -------
- The code opens an image (in this case *lena.jpg*) and display it under the effects of the 4 - The code opens an image (in this case [lena.jpg](https://raw.githubusercontent.com/opencv/opencv/master/samples/data/lena.jpg))
filters explained. and display it under the effects of the 4 filters explained.
- Here is a snapshot of the image smoothed using *medianBlur*: - Here is a snapshot of the image smoothed using *medianBlur*:
![](images/Smoothing_Tutorial_Result_Median_Filter.jpg) ![](images/Smoothing_Tutorial_Result_Median_Filter.jpg)
...@@ -5,6 +5,8 @@ In this section you will learn about the image processing (manipulation) functio ...@@ -5,6 +5,8 @@ In this section you will learn about the image processing (manipulation) functio
- @subpage tutorial_gausian_median_blur_bilateral_filter - @subpage tutorial_gausian_median_blur_bilateral_filter
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0 *Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán *Author:* Ana Huamán
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* author OpenCV team * author OpenCV team
*/ */
#include <iostream>
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp" #include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp" #include "opencv2/highgui.hpp"
...@@ -27,61 +28,66 @@ int display_dst( int delay ); ...@@ -27,61 +28,66 @@ int display_dst( int delay );
/** /**
* function main * function main
*/ */
int main( void ) int main( int argc, char ** argv )
{ {
namedWindow( window_name, WINDOW_AUTOSIZE ); namedWindow( window_name, WINDOW_AUTOSIZE );
/// Load the source image /// Load the source image
src = imread( "../data/lena.jpg", IMREAD_COLOR ); const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";
if( display_caption( "Original Image" ) != 0 ) { return 0; } src = imread( filename, IMREAD_COLOR );
if(src.empty()){
printf(" Error opening image\n");
printf(" Usage: ./Smoothing [image_name -- default ../data/lena.jpg] \n");
return -1;
}
dst = src.clone(); if( display_caption( "Original Image" ) != 0 ) { return 0; }
if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }
dst = src.clone();
if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }
/// Applying Homogeneous blur
if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }
//![blur] /// Applying Homogeneous blur
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }
{ blur( src, dst, Size( i, i ), Point(-1,-1) );
//![blur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ blur( src, dst, Size( i, i ), Point(-1,-1) );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![blur] //![blur]
/// Applying Gaussian blur /// Applying Gaussian blur
if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; } if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
//![gaussianblur] //![gaussianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ GaussianBlur( src, dst, Size( i, i ), 0, 0 ); { GaussianBlur( src, dst, Size( i, i ), 0, 0 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![gaussianblur] //![gaussianblur]
/// Applying Median blur /// Applying Median blur
if( display_caption( "Median Blur" ) != 0 ) { return 0; } if( display_caption( "Median Blur" ) != 0 ) { return 0; }
//![medianblur] //![medianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ medianBlur ( src, dst, i ); { medianBlur ( src, dst, i );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![medianblur] //![medianblur]
/// Applying Bilateral Filter /// Applying Bilateral Filter
if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; } if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
//![bilateralfilter] //![bilateralfilter]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ bilateralFilter ( src, dst, i, i*2, i/2 ); { bilateralFilter ( src, dst, i, i*2, i/2 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![bilateralfilter] //![bilateralfilter]
/// Wait until user press a key
display_caption( "End: Press a key!" );
waitKey(0); /// Done
display_caption( "Done!" );
return 0; return 0;
} }
/** /**
...@@ -89,15 +95,12 @@ int main( void ) ...@@ -89,15 +95,12 @@ int main( void )
*/ */
int display_caption( const char* caption ) int display_caption( const char* caption )
{ {
dst = Mat::zeros( src.size(), src.type() ); dst = Mat::zeros( src.size(), src.type() );
putText( dst, caption, putText( dst, caption,
Point( src.cols/4, src.rows/2), Point( src.cols/4, src.rows/2),
FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) ); FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
imshow( window_name, dst ); return display_dst(DELAY_CAPTION);
int c = waitKey( DELAY_CAPTION );
if( c >= 0 ) { return -1; }
return 0;
} }
/** /**
...@@ -105,8 +108,8 @@ int display_caption( const char* caption ) ...@@ -105,8 +108,8 @@ int display_caption( const char* caption )
*/ */
int display_dst( int delay ) int display_dst( int delay )
{ {
imshow( window_name, dst ); imshow( window_name, dst );
int c = waitKey ( delay ); int c = waitKey ( delay );
if( c >= 0 ) { return -1; } if( c >= 0 ) { return -1; }
return 0; return 0;
} }
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
class SmoothingRun {
/// Global Variables
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src = new Mat(), dst = new Mat();
String windowName = "Filter Demo 1";
public void run(String[] args) {
String filename = ((args.length > 0) ? args[0] : "../data/lena.jpg");
src = Imgcodecs.imread(filename, Imgcodecs.IMREAD_COLOR);
if( src.empty() ) {
System.out.println("Error opening image");
System.out.println("Usage: ./Smoothing [image_name -- default ../data/lena.jpg] \n");
System.exit(-1);
}
if( displayCaption( "Original Image" ) != 0 ) { System.exit(0); }
dst = src.clone();
if( displayDst( DELAY_CAPTION ) != 0 ) { System.exit(0); }
/// Applying Homogeneous blur
if( displayCaption( "Homogeneous Blur" ) != 0 ) { System.exit(0); }
//! [blur]
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
Imgproc.blur(src, dst, new Size(i, i), new Point(-1, -1));
displayDst(DELAY_BLUR);
}
//! [blur]
/// Applying Gaussian blur
if( displayCaption( "Gaussian Blur" ) != 0 ) { System.exit(0); }
//! [gaussianblur]
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
Imgproc.GaussianBlur(src, dst, new Size(i, i), 0, 0);
displayDst(DELAY_BLUR);
}
//! [gaussianblur]
/// Applying Median blur
if( displayCaption( "Median Blur" ) != 0 ) { System.exit(0); }
//! [medianblur]
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
Imgproc.medianBlur(src, dst, i);
displayDst(DELAY_BLUR);
}
//! [medianblur]
/// Applying Bilateral Filter
if( displayCaption( "Bilateral Blur" ) != 0 ) { System.exit(0); }
//![bilateralfilter]
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
Imgproc.bilateralFilter(src, dst, i, i * 2, i / 2);
displayDst(DELAY_BLUR);
}
//![bilateralfilter]
/// Done
displayCaption( "Done!" );
System.exit(0);
}
int displayCaption(String caption) {
dst = Mat.zeros(src.size(), src.type());
Imgproc.putText(dst, caption,
new Point(src.cols() / 4, src.rows() / 2),
Core.FONT_HERSHEY_COMPLEX, 1, new Scalar(255, 255, 255));
return displayDst(DELAY_CAPTION);
}
int displayDst(int delay) {
HighGui.imshow( windowName, dst );
int c = HighGui.waitKey( delay );
if (c >= 0) { return -1; }
return 0;
}
}
public class Smoothing {
public static void main(String[] args) {
// Load the native library.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new SmoothingRun().run(args);
}
}
import sys
import cv2
import numpy as np
# Global Variables
DELAY_CAPTION = 1500
DELAY_BLUR = 100
MAX_KERNEL_LENGTH = 31
src = None
dst = None
window_name = 'Smoothing Demo'
def main(argv):
cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
# Load the source image
imageName = argv[0] if len(argv) > 0 else "../data/lena.jpg"
global src
src = cv2.imread(imageName, 1)
if src is None:
print ('Error opening image')
print ('Usage: smoothing.py [image_name -- default ../data/lena.jpg] \n')
return -1
if display_caption('Original Image') != 0:
return 0
global dst
dst = np.copy(src)
if display_dst(DELAY_CAPTION) != 0:
return 0
# Applying Homogeneous blur
if display_caption('Homogeneous Blur') != 0:
return 0
## [blur]
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv2.blur(src, (i, i))
if display_dst(DELAY_BLUR) != 0:
return 0
## [blur]
# Applying Gaussian blur
if display_caption('Gaussian Blur') != 0:
return 0
## [gaussianblur]
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv2.GaussianBlur(src, (i, i), 0)
if display_dst(DELAY_BLUR) != 0:
return 0
## [gaussianblur]
# Applying Median blur
if display_caption('Median Blur') != 0:
return 0
## [medianblur]
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv2.medianBlur(src, i)
if display_dst(DELAY_BLUR) != 0:
return 0
## [medianblur]
# Applying Bilateral Filter
if display_caption('Bilateral Blur') != 0:
return 0
## [bilateralfilter]
# Remember, bilateral is a bit slow, so as value go higher, it takes long time
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv2.bilateralFilter(src, i, i * 2, i / 2)
if display_dst(DELAY_BLUR) != 0:
return 0
## [bilateralfilter]
# Done
display_caption('Done!')
return 0
def display_caption(caption):
global dst
dst = np.zeros(src.shape, src.dtype)
rows, cols, ch = src.shape
cv2.putText(dst, caption,
(int(cols / 4), int(rows / 2)),
cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255))
return display_dst(DELAY_CAPTION)
def display_dst(delay):
cv2.imshow(window_name, dst)
c = cv2.waitKey(delay)
if c >= 0 : return -1
return 0
if __name__ == "__main__":
main(sys.argv[1:])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment