Tutorial Smoothing Images

This commit is contained in:
tribta 2017-08-20 17:14:12 +01:00
parent 5f6ce6f4b0
commit bc18fb481f
6 changed files with 411 additions and 139 deletions

View File

@ -1,16 +1,18 @@
Smoothing Images {#tutorial_gausian_median_blur_bilateral_filter}
================
@next_tutorial{tutorial_erosion_dilatation}
Goal
----
In this tutorial you will learn how to apply diverse linear filters to smooth images using OpenCV
functions such as:
- @ref cv::blur
- @ref cv::GaussianBlur
- @ref cv::medianBlur
- @ref cv::bilateralFilter
- **blur()**
- **GaussianBlur()**
- **medianBlur()**
- **bilateralFilter()**
Theory
------
@ -92,23 +94,41 @@ Code
- Loads an image
- Applies 4 different kinds of filters (explained in Theory) and show the filtered images
sequentially
@add_toggle_cpp
- **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/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/ImgProc/Smoothing.cpp
@include samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click
[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:**
@include samples/python/tutorial_code/imgProc/Smoothing/smoothing.py
@end_toggle
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.
-# **Normalized Block Filter:**
OpenCV offers the function @ref cv::blur to perform smoothing with this filter.
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp blur
#### Normalized Block Filter:
- OpenCV offers the function **blur()** to perform smoothing with this filter.
We specify 4 arguments (more details, check the Reference):
- *src*: Source image
- *dst*: Destination image
- *Size( w, h )*: Defines the size of the kernel to be used ( of width *w* pixels and height
@ -117,13 +137,22 @@ Explanation
respect to the neighborhood. If there is a negative value, then the center of the kernel is
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 :
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp gaussianblur
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java blur
@end_toggle
@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
- *dst*: Destination image
- *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
- \f$\sigma_{y}\f$: The standard deviation in y. Writing \f$0\f$ implies that \f$\sigma_{y}\f$ is
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:
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp medianblur
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java gaussianblur
@end_toggle
@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
- *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.
-# **Bilateral Filter**
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp medianblur
@end_toggle
Provided by OpenCV function @ref cv::bilateralFilter
@snippet cpp/tutorial_code/ImgProc/Smoothing.cpp bilateralfilter
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/Smoothing/Smoothing.java medianblur
@end_toggle
@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
- *dst*: Destination image
- *d*: The diameter of each pixel neighborhood.
- \f$\sigma_{Color}\f$: Standard deviation in the color space.
- \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
-------
- The code opens an image (in this case *lena.jpg*) and display it under the effects of the 4
filters explained.
- The code opens an image (in this case [lena.jpg](https://raw.githubusercontent.com/opencv/opencv/master/samples/data/lena.jpg))
and display it under the effects of the 4 filters explained.
- Here is a snapshot of the image smoothed using *medianBlur*:
![](images/Smoothing_Tutorial_Result_Median_Filter.jpg)

View File

@ -5,6 +5,8 @@ In this section you will learn about the image processing (manipulation) functio
- @subpage tutorial_gausian_median_blur_bilateral_filter
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán

View File

@ -1,112 +0,0 @@
/**
* file Smoothing.cpp
* brief Sample code for simple filters
* author OpenCV team
*/
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
/// Global Variables
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
/// Function headers
int display_caption( const char* caption );
int display_dst( int delay );
/**
* function main
*/
int main( void )
{
namedWindow( window_name, WINDOW_AUTOSIZE );
/// Load the source image
src = imread( "../data/lena.jpg", IMREAD_COLOR );
if( display_caption( "Original Image" ) != 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]
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; } }
//![blur]
/// Applying Gaussian blur
if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
//![gaussianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ GaussianBlur( src, dst, Size( i, i ), 0, 0 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![gaussianblur]
/// Applying Median blur
if( display_caption( "Median Blur" ) != 0 ) { return 0; }
//![medianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ medianBlur ( src, dst, i );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![medianblur]
/// Applying Bilateral Filter
if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
//![bilateralfilter]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ bilateralFilter ( src, dst, i, i*2, i/2 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![bilateralfilter]
/// Wait until user press a key
display_caption( "End: Press a key!" );
waitKey(0);
return 0;
}
/**
* @function display_caption
*/
int display_caption( const char* caption )
{
dst = Mat::zeros( src.size(), src.type() );
putText( dst, caption,
Point( src.cols/4, src.rows/2),
FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
imshow( window_name, dst );
int c = waitKey( DELAY_CAPTION );
if( c >= 0 ) { return -1; }
return 0;
}
/**
* @function display_dst
*/
int display_dst( int delay )
{
imshow( window_name, dst );
int c = waitKey ( delay );
if( c >= 0 ) { return -1; }
return 0;
}

View File

@ -0,0 +1,115 @@
/**
* file Smoothing.cpp
* brief Sample code for simple filters
* author OpenCV team
*/
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
/// Global Variables
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
/// Function headers
int display_caption( const char* caption );
int display_dst( int delay );
/**
* function main
*/
int main( int argc, char ** argv )
{
namedWindow( window_name, WINDOW_AUTOSIZE );
/// Load the source image
const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";
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;
}
if( display_caption( "Original Image" ) != 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]
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; } }
//![blur]
/// Applying Gaussian blur
if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
//![gaussianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ GaussianBlur( src, dst, Size( i, i ), 0, 0 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![gaussianblur]
/// Applying Median blur
if( display_caption( "Median Blur" ) != 0 ) { return 0; }
//![medianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ medianBlur ( src, dst, i );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![medianblur]
/// Applying Bilateral Filter
if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
//![bilateralfilter]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ bilateralFilter ( src, dst, i, i*2, i/2 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![bilateralfilter]
/// Done
display_caption( "Done!" );
return 0;
}
/**
* @function display_caption
*/
int display_caption( const char* caption )
{
dst = Mat::zeros( src.size(), src.type() );
putText( dst, caption,
Point( src.cols/4, src.rows/2),
FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
return display_dst(DELAY_CAPTION);
}
/**
* @function display_dst
*/
int display_dst( int delay )
{
imshow( window_name, dst );
int c = waitKey ( delay );
if( c >= 0 ) { return -1; }
return 0;
}

View File

@ -0,0 +1,101 @@
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);
}
}

View File

@ -0,0 +1,107 @@
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:])