OpenCV: Basic Image Processing Functions Reference: http...

23
OpenCV: Basic Image Processing Functions Reference: http://www.opencv.org By: Dr. Rajeev Srivastava, IIT(BHU), Varanasi Highlights: 1. Functions for Reading, Writing, and Displaying Images in OpenCV 2. Functions for Discrete Fourier Transform for Images in OpenCV 3. Functions for Image Enhancement in OpenCV 4. Restoration of images: Filtering Theory 5. Edge Detection: Canny Edge detector

Transcript of OpenCV: Basic Image Processing Functions Reference: http...

Page 1: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

OpenCV: Basic Image Processing Functions

Reference: http://www.opencv.org

By: Dr. Rajeev Srivastava, IIT(BHU), Varanasi

Highlights:

1. Functions for Reading, Writing, and Displaying Images in OpenCV

2. Functions for Discrete Fourier Transform for Images in OpenCV

3. Functions for Image Enhancement in OpenCV

4. Restoration of images: Filtering Theory

5. Edge Detection: Canny Edge detector

Page 2: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Experiment 1: To write and execute program for Load, Modify and Save an image

1. Reading an image from a file:

IplImage* img=0;

img=cvLoadImage(fileName);

if(!img) printf("Could not load image file: %s\n",fileName);

Supported image formats: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM,SR,

RAS, TIFF, TIF

By default, the loaded image is forced to be a 3-channel color image. This default can be

modified by using:

img=cvLoadImage(fileName,flag);

flag: >0 the loaded image is forced to be a 3-channel color image

=0 the loaded image is forced to be a 1 channel grayscale image

<0 the loaded image is loaded as is (with number of channels in the file).

2. Writing an image to a file:

if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n",outFileName);

The output file format is determined based on the file name extension.

Sample Code:

#include <cv.h>

#include <highgui.h>

using namespace cv;

int main( int argc, char** argv )

{

char* imageName = argv[1];

Mat image;

image = imread( imageName, 1 );

if( argc != 2 || !image.data )

{

Page 3: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

printf( " No image data \n " );

return -1;

}

Mat gray_image;

cvtColor( image, gray_image, CV_BGR2GRAY );

imwrite( "../../images/Gray_Image.jpg", gray_image );

namedWindow( imageName, CV_WINDOW_AUTOSIZE );

namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );

imshow( imageName, image );

imshow( "Gray image", gray_image );

waitKey(0);

return 0;

}

Output:

Fig 1: Display and Write Image

Page 4: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Experiment 2: To write and execute program for Discrete Fourier Transform of image

i. Expand the image to an optimal size

Mat padded; //expand input image to optimal size

int m = getOptimalDFTSize( I.rows );

int n = getOptimalDFTSize( I.cols ); // on the border add zero pixels

copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT,

Scalar::all(0));

ii. Make place for both the complex and the real values.

Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};

Mat complexI;

merge(planes, 2, complexI); // Add to the expanded another plane with zeros

iii. Make the Discrete Fourier Transform.

dft(complexI, complexI);

iv. Transform the real and complex values to magnitude.

split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))

magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude

Mat magI = planes[0];

v. Switch to a logarithmic scale.

magI += Scalar::all(1); // switch to logarithmic scale

log(magI, magI);

vi. Crop and rearrange.

magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

int cx = magI.cols/2;

int cy = magI.rows/2;

Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant

Page 5: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Mat q1(magI, Rect(cx, 0, cx, cy)); // Top-Right

Mat q2(magI, Rect(0, cy, cx, cy)); // Bottom-Left

Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right

Mat tmp;

q0.copyTo(tmp);

q3.copyTo(q0);

tmp.copyTo(q3);

q1.copyTo(tmp);

q2.copyTo(q1);

tmp.copyTo(q2);

vii. Normalize.

normalize(magI, magI, 0, 1, CV_MINMAX);

Sample Code:

#include "opencv2/core/core.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/highgui/highgui.hpp"

#include <iostream>

int main(int argc, char ** argv)

{

const char* filename = argc >=2 ? argv[1] : "atom.jpg";

Mat I = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);

if( I.empty())

return -1;

Mat padded; //expand input image to optimal size

int m = getOptimalDFTSize( I.rows );

int n = getOptimalDFTSize( I.cols ); // on the border add zero values

copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

Page 6: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};

Mat complexI;

merge(planes, 2, complexI); // Add to the expanded another plane with zeros

dft(complexI, complexI); // this way the result may fit in the source matrix

// compute the magnitude and switch to logarithmic scale

// => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))

split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))

magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude

Mat magI = planes[0];

magI += Scalar::all(1); // switch to logarithmic scale

log(magI, magI);

// crop the spectrum, if it has an odd number of rows or columns

magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

// rearrange the quadrants of Fourier image so that the origin is at the image center

int cx = magI.cols/2;

int cy = magI.rows/2;

Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant

Mat q1(magI, Rect(cx, 0, cx, cy)); // Top-Right

Mat q2(magI, Rect(0, cy, cx, cy)); // Bottom-Left

Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right

Mat tmp; // swap quadrants (Top-Left with Bottom-Right)

q0.copyTo(tmp);

q3.copyTo(q0);

tmp.copyTo(q3);

q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left)

q2.copyTo(q1);

tmp.copyTo(q2);

normalize(magI, magI, 0, 1, CV_MINMAX);

imshow("Input Image" , I ); // Show the result

Page 7: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

imshow("spectrum magnitude", magI);

waitKey();

return 0;

}

Output:

Figure 2: Discrete Fourier Transform

Page 8: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Experiment 3: To write and execute program for Changing the contrast and brightness of

an image

i. We begin by creating parameters to save \alpha and \beta to be entered by the

user:

double alpha;

int beta;

ii. We load an image using imread and save it in a Mat object:

Mat image = imread( argv[1] );

iii. Now, since we will make some transformations to this image, we need a new Mat

object to store it. Also, we want this to have the following features:

Initial pixel values equal to zero

Same size and type as the original image

Mat new_image = Mat::zeros( image.size(), image.type() );

We observe that Mat::zeros returns a Matlab-style zero initializer based on image.size() and

image.type()

iv. Now, to perform the operation g(i,j) = \alpha \cdot f(i,j) + \beta we will access to

each pixel in image. Since we are operating with RGB images, we will have three

values per pixel (R, G and B), so we will also access them separately. Here is the

piece of code:

for( int y = 0; y < image.rows; y++ )

{ for( int x = 0; x < image.cols; x++ )

{ for( int c = 0; c < 3; c++ )

{ new_image.at<Vec3b>(y,x)[c] =

saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta ); }

}

}

Page 9: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

v. Finally, we create windows and show the images, the usual way.

namedWindow("Original Image", 1);

namedWindow("New Image", 1);

imshow("Original Image", image);

imshow("New Image", new_image);

waitKey(0);

Sample Code:

#include <cv.h>

#include <highgui.h>

#include <iostream>

using namespace cv;

double alpha; /**< Simple contrast control */

int beta; /**< Simple brightness control */

int main( int argc, char** argv )

{

/// Read image given by user

Mat image = imread( argv[1] );

Mat new_image = Mat::zeros( image.size(), image.type() );

/// Initialize values

std::cout<<" Basic Linear Transforms "<<std::endl;

std::cout<<"-------------------------"<<std::endl;

std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;

std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta;

/// Do the operation new_image(i,j) = alpha*image(i,j) + beta

for( int y = 0; y < image.rows; y++ )

{ for( int x = 0; x < image.cols; x++ )

{ for( int c = 0; c < 3; c++ )

{

new_image.at<Vec3b>(y,x)[c] =

saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );

}

}

}

/// Create Windows

namedWindow("Original Image", 1);

namedWindow("New Image", 1);

/// Show stuff

imshow("Original Image", image);

Page 10: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

imshow("New Image", new_image);

/// Wait until user press some key

waitKey();

return 0;

}

Output:

Running our code and using and

Figure 3: Changing the contrast and brightness of an image

Page 11: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Experiment 4: To write and execute program for Filtering images using following method

Eroding

Dilating

Smoothing

Inverting

Adjusting Brightness

Adjusting Contrast

Eroding

cvErode(img, img, 0, 2)

The 1st parameter is the source image.

The 2nd parameter is the destination image which is to be the eroded image.

Here the 3rd parameter is the structuring element used for erosion. If it is 0, a 3×3 rectangular

structuring element is used.

The 4th parameter is the number of times, erosion is applied.

Sample Program:

#include "stdafx.h"

#include <cv.h>

#include <highgui.h>

int main()

{

//display the original image

IplImage* img = cvLoadImage("C:/MyPic.jpg");

cvNamedWindow("MyWindow");

cvShowImage("MyWindow", img);

//erode and display the eroded image

cvErode(img, img, 0, 2);

cvNamedWindow("Eroded");

cvShowImage("Eroded", img);

cvWaitKey(0);

//cleaning up

cvDestroyWindow("MyWindow");

cvDestroyWindow("Eroded");

cvReleaseImage(&img);

return 0;

}

Page 12: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Output:

Figure 4: Original image (left), Image after applying erosion (right)

Dilating

cvDilate(img, img, 0, 2)

The 1st parameter is the source image.

The 2nd parameter is the destination image which is to be the dilated image.

Here the 3rd parameter is the structuring element used for dilation. If it is 0, a 3×3 rectangular structuring

element is used.

The 4th parameter is the number of times, dilation is applied.

Sample Code:

#include "stdafx.h"

#include <cv.h>

#include <highgui.h>

int main()

{

//display the original image

IplImage* img = cvLoadImage("C:/MyPic.jpg");

cvNamedWindow("MyWindow");

cvShowImage("MyWindow", img);

//dilate and display the dilated image

Page 13: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

cvDilate(img, img, 0, 2);

cvNamedWindow("Dilated");

cvShowImage("Dilated", img);

cvWaitKey(0);

//cleaning up

cvDestroyWindow("MyWindow");

cvDestroyWindow("Dilated");

cvReleaseImage(&img);

return 0;

}

Output:

Figure 5: Original image (left), Image after applying dilation (right)

Smoothing

cvSmooth(img, img, CV_GAUSSIAN,3,3)

The 1st parameter is the source image.

The 2nd parameter is the destination image.

The 3rd parameter is the method, used for smoothing the image. There are several methods that you can

use for this parameter.

Page 14: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

CV_BLUR_NO_SCALE

CV_BLUR

CV_GAUSSIAN

V_MEDIAN

CV_BILATERAL

Every of these methods has some features and restrictions listed below.

CV_BLUR_NO_SCALE supports for single channel images only.

CV_BLUR and CV_GAUSSIAN support for 1 or 3 channel, 8 and 32 bit floating point images. These

two methods can process images in place.

CV_MEDIAN and CV_BILATERAL support for 1 or 3 channel, 8 bit images and cannot process

images in place.

The 4th parameter is the aperture width. (It is a technical term. It defines how much you are going to

smooth the image). You have to use positive odd number (1,3,5,7,...)

The 5th parameter is the aperture height. (It is a technical term. It defines how much you are going to

smooth the image).

Sample Program:

#include "stdafx.h"

#include <cv.h>

#include <highgui.h>

int main()

{

//display the original image

IplImage* img = cvLoadImage("C:/MyPic.jpg");

cvNamedWindow("MyWindow");

cvShowImage("MyWindow", img);

//erode and display the smoothed image

cvSmooth(img, img, CV_GAUSSIAN,3,3);

cvNamedWindow("Smoothed");

cvShowImage("Smoothed", img);

cvWaitKey(0);

//cleaning up

cvDestroyWindow("MyWindow");

cvDestroyWindow("Smoothed");

cvReleaseImage(&img);

return 0;

}

Page 15: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Output:

Figure 6: Original image (left), Image after applying smmothing (right)

Inverting

cvNot(img, img)

This function inverts every bit in every element of the image in the 1st parameter and places the result in

the image in the 2nd parameter.

This function can process images in place. That means same variable can be used for the 1st and 2nd

parameters.

Sample Code:

#include "stdafx.h"

#include <cv.h>

#include <highgui.h>

int main()

{

//display the original image

IplImage* img = cvLoadImage("C:/MyPic.jpg");

cvNamedWindow("MyWindow");

cvShowImage("MyWindow", img);

//invert and display the inverted image

cvNot(img, img);

cvNamedWindow("Inverted");

Page 16: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

cvShowImage("Inverted", img);

cvWaitKey(0);

//cleaning up

cvDestroyWindow("MyWindow");

cvDestroyWindow("Inverted");

cvReleaseImage(&img);

return 0;

}

Output:

Figure 7: Original image (left), Image after applying inversion (right)

Page 17: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Adjusting Brightness

cvAddS(img, cvScalar(70,70,70), img)

1st parameter is the source image.

3rd parameter is the destination image.

2nd parameter is the value; we are going to add to each and every pixel value of the source image. Here

I have usedcvScalar(70,70,70) because the source image consists of 3 channels. (Color images always

consist of 3 channels to represent red, green and blue). If the source image is a gray scale image which

consists of 1 channel, you may usecvScalar(70) as the 2nd parameter. If you want to decrease the

brightness, you may use cvScalar(-50,-50,-50) as the 2nd parameter.

This function can process images in place. That means same variable can be used for the 1st and 2nd

parameters.

Sample Program

#include "stdafx.h"

#include <cv.h>

#include <highgui.h>

int main()

{

//display the original image

IplImage* img = cvLoadImage("C:/MyPic.jpg");

cvNamedWindow("MyWindow");

cvShowImage("MyWindow", img);

//increase the brightness and display the brightened image

cvAddS(img, cvScalar(70,70,70), img);

cvNamedWindow("Brightened");

cvShowImage("Brightened", img);

cvWaitKey(0);

//cleaning up

cvDestroyWindow("MyWindow");

cvDestroyWindow("Brightened");

cvReleaseImage(&img);

return 0;

}

Page 18: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Output:

Figure 8: Original image (left), Image after adjusting brightness (right)

Adjusting Contrast

cvScale(img, img, 2)

1st parameter is the source image.

2nd parameter is the destination image.

3rd parameter is the constant by which each and every pixel values are multiplied. If you use value 1,

there is no change. If you use a value more than 1, destination image will have a high contrast than the

source image. If you use a value less than 1, destination image will have a low contrast than the source

image.

Sample Code:

#include "stdafx.h"

#include <cv.h>

#include <highgui.h>

int main()

{

//display the original image

Page 19: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

IplImage* img = cvLoadImage("C:/MyPic.jpg");

cvNamedWindow("MyWindow");

cvShowImage("MyWindow", img);

//increase the contrast and display the image

cvScale(img, img, 2);

cvNamedWindow("Contrast");

cvShowImage("Contrast", img);

cvWaitKey(0);

//cleaning up

cvDestroyWindow("MyWindow");

cvDestroyWindow("Contrast");

cvReleaseImage(&img);

return 0;

}

Output:

Figure 9: Original image (left), Image after adjusting contrast (right)

Page 20: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

Experiment 5: To write and execute program for Canny edge detection of an image

i. Loads the source image:

/// Load an image

src = imread( argv[1] );

if( !src.data )

{ return -1; }

ii. Create a matrix of the same type and size of src (to be dst)

dst.create( src.size(), src.type() );

iii. Convert the image to grayscale (using the function cvtColor)

cvtColor( src, src_gray, CV_BGR2GRAY );

iv. Create a window to display the results

namedWindow( window_name, CV_WINDOW_AUTOSIZE );

v. Create a Trackbar for the user to enter the lower threshold for our Canny detector:

createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold,

CannyThreshold );

vi. Observe the following:

The variable to be controlled by the Trackbar is lowThreshold with a limit of max_lowThreshold

(which we set to 100 previously)

Each time the Trackbar registers an action, the callback function CannyThreshold will be

invoked.

vii. Now, check the CannyThreshold function, step by step:

a. First, we blur the image with a filter of kernel size 3:

blur( src_gray, detected_edges, Size(3,3) );

b. Second, we apply the OpenCV function Canny:

Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );

where the arguments are:

Page 21: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

detected_edges: Source image, grayscale

detected_edges: Output of the detector (can be the same as the input)

lowThreshold: The value entered by the user moving the Trackbar

highThreshold: Set in the program as three times the lower threshold (following Canny’s

recommendation)

kernel_size: We defined it to be 3 (the size of the Sobel kernel to be used internally)

viii. Fill a dst image with zeros (meaning the image is completely black).

dst = Scalar::all(0);

Finally, we will use the function copyTo to map only the areas of the image that are identified as

edges (on a black background).

src.copyTo( dst, detected_edges);

copyTo copy the src image onto dst. However, it will only copy the pixels in the locations where

they have non-zero values. Since the output of the Canny detector is the edge contours on a black

background, the resulting dst will be black in all the area but the detected edges.

ix. Display Result:

imshow( window_name, dst );

Sample Code:

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/highgui/highgui.hpp"

#include <stdlib.h>

#include <stdio.h>

using namespace cv;

/// Global variables

Mat src, src_gray;

Mat dst, detected_edges;

int edgeThresh = 1;

int lowThreshold;

int const max_lowThreshold = 100;

Page 22: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

int ratio = 3;

int kernel_size = 3;

char* window_name = "Edge Map";

void CannyThreshold(int, void*)

{

/// Reduce noise with a kernel 3x3

blur( src_gray, detected_edges, Size(3,3) );

/// Canny detector

Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );

/// Using Canny's output as a mask, we display our result

dst = Scalar::all(0);

src.copyTo( dst, detected_edges);

imshow( window_name, dst );

}

int main( int argc, char** argv )

{

/// Load an image

src = imread( argv[1] );

if( !src.data )

{ return -1; }

/// Create a matrix of the same type and size as src (for dst)

dst.create( src.size(), src.type() );

/// Convert the image to grayscale

cvtColor( src, src_gray, CV_BGR2GRAY );

/// Create a window

namedWindow( window_name, CV_WINDOW_AUTOSIZE );

Page 23: OpenCV: Basic Image Processing Functions Reference: http ...content.inflibnet.ac.in/.../50/ET/58-50-ET-V1-S1__opencvexperimentse… · CV_BLUR_NO_SCALE supports for single channel

/// Create a Trackbar for user to enter threshold

createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold,

CannyThreshold );

/// Show the image

CannyThreshold(0, 0);

/// Wait until user exit program by pressing a key

waitKey(0);

return 0;

}

Output:

Figure 10: Canny edge detection: Original image (left), Detected edges (right)