2. OpenCV with C++

2.1. OpenCV Basics

2.1.1. Introduction

In this section, the procedure to run the C++ code using OpenCV library is shown. Here, “Hello OpenCV” is printed on the screen. Aim is to validate the OpenCV installation and usage therefore the opencv.hpp is included in the code but not used in this example.

  • First create the “Hello OpenCV” code as below,
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// HelloOpenCV.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>


int main(){
    printf("Hello OpenCV\n");
    return 0;
}
  • Now, run the code as below,
$ g++ HelloOpenCV.cpp -o HelloOpenCV `pkg-config --libs opencv`
$ ./HelloOpenCV

2.1.1.1. CMakeLists.txt

ALso, we can crate a CMakeLists.txt file to run the code as below,

  • Next, we need to create one CMakeLists.txt file which will included the “OpenCV” library to the path and generate the executable file for the above code,
# CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project( HelloOpenCVExample )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( HelloOpenCV HelloOpenCV.cpp )
target_link_libraries( HelloOpenCV ${OpenCV_LIBS} )
  • Now, generate the executable as below,
$ cmake .
$ make
$ ./HelloOpenCV
Hello OpenCV

2.1.2. Load image

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
//  DisplayImage.cpp

// g++ DisplayImage.cpp -o DisplayImage `pkg-config --libs opencv`

// Display the image

#include <stdio.h>
#include <opencv2/opencv.hpp>

int main(int argc, char** argv )
{

    cv::Mat image;  // variable image of datatype Matrix
    image = cv::imread("./OpenCV.png");

    cv::imshow("Display Image", image);
    cv::waitKey(0);
    return 0;
}
../_images/Screenshot_1.jpg

Fig. 2.1 Shapes

2.1.3. Load Video

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// DisplayVideo.cpp


#include <stdio.h>
#include <opencv2/opencv.hpp>

int main(int argc, char** argv )
{

    cv::Mat frame;  // variable frame of datatype Matrix
    cv::VideoCapture capture;
    capture.open("versal.mp4");

    for(;;){
        capture>>frame;
        if(frame.empty())
            break;
        cv::imshow("Window", frame);

        if(cv::waitKey(30)>=0)
                break;
    }
    return 0;
}
$  g++ DisplayVideo.cpp -o DisplayVideo `pkg-config --libs opencv`
$ ./DisplayVideo

2.1.4. Basic operations on images

2.1.4.1. Accessing and modifying pixel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// access_modify_pixel.py


#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv )
{

    cv::Mat img;  // variable image of datatype Matrix
    img = cv::imread("images/shapes.jpg");

    // For color image i.e. 3 channel
    Vec3b intensity = img.at<Vec3b>(10, 10);
    cout << "BGR " << intensity << "\n";

    // print individual component [B G R]
    int blue = intensity.val[0];
    cout << "blue " << blue << "\n";
    int green = intensity.val[1];
    cout << "green " << green << "\n";
    int red = intensity.val[2];
    cout << "red " << red << "\n";


    // modify pixel
    img.at<Vec3b>(10, 10) = (0, 0, 255);
    // For color image i.e. 3 channel
    intensity = img.at<Vec3b>(10, 10);
    cout << "BGR after modification " << intensity << "\n";

    cv::imshow("Display Image", img);
    cv::waitKey(0);

    return 0;
}
g++ access_modify_pixel.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_2.jpg

Fig. 2.2 Red dot at (10 10)

2.1.4.2. Split and Merge

  • In this section, the color image is split and plotted into R, G and B color. Also, these R, G and B are merged together to get the original image.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// split_merge.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv )
{

    cv::Mat img, sum_rgb;  // variable image of datatype Matrix
    img = cv::imread("images/shapes.jpg");
    cv::imshow("Display Image", img);

    // three channel to store b, g, r
    cv::Mat rgbchannel[3];

    // split image
    cv::split(img, rgbchannel);

    // plot individual component
    cv::namedWindow("Blue",CV_WINDOW_AUTOSIZE);
    cv::imshow("Red", rgbchannel[0]);

    cv::namedWindow("Green",CV_WINDOW_AUTOSIZE);
    cv::imshow("Green", rgbchannel[1]);

    cv::namedWindow("Red",CV_WINDOW_AUTOSIZE);
    cv::imshow("Blue", rgbchannel[2]);

    // merge : (input, num_of_channel, output)
    cv::merge(rgbchannel, 3, sum_rgb);
    cv::imshow("Merged", sum_rgb);

    cv::waitKey(0);

    return 0;
}
g++ split_merge.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_3.jpg

Fig. 2.3 Split and merge

2.1.4.3. Crop image

In this section, we will crop the image in 4 equal part and change the color of 2 parts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// crop_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv )
{

    cv::Mat img;  // variable image of datatype Matrix
    cv::Mat top_left, top_right, bottom_left, bottom_right;
    int w, h, cX, cY;

    img = cv::imread("images/shapes.jpg");

    cout << "(width, height)"<< img.size() << endl;
    cout << "Width : " << img.cols << endl;
    cout << "Height: " << img.rows << endl;

    w = img.size().width;
    h = img.size().height;

    cX = (int)w/2;
    cY = (int)h/2;
    cout << "(cX, cY) = (" << cX << ", " << cY << ")" << endl;


    // (start_x, start_y, len_x, len_y)
    cv::Rect top_left_roi(0, 0, cX, cY);
    top_left = img(top_left_roi);
    cv::imshow("Top left", top_left);

    cv::Rect top_right_roi(cX, 0, cX, cY);
    top_right = img(top_right_roi);
    cv::imshow("Top right", top_right);

    cv::Rect bottom_left_roi(0, cY, cX, cY);
    bottom_left = img(bottom_left_roi);
    cv::imshow("Bottom left", bottom_left);

    cv::Rect bottom_right_roi(cX, cY, cX, cY);
    bottom_right = img(bottom_right_roi);
    cv::imshow("Bottom right", bottom_right);

    // or use above or below, both have same results
    // // (start_x, start_y, len_x, len_y)
    // cv::Rect top_left_roi(0, 0, cX, cY);
    // top_left = img(top_left_roi);
    // cv::imshow("Top left", top_left);

    // cv::Rect top_right_roi(cX, 0, w - cX, cY);
    // top_right = img(top_right_roi);
    // cv::imshow("Top right", top_right);

    // cv::Rect bottom_left_roi(0, cY, cX, h - cY);
    // bottom_left = img(bottom_left_roi);
    // cv::imshow("Bottom left", bottom_left);

    // cv::Rect bottom_right_roi(cX, cY, w - cX, h - cY);
    // bottom_right = img(bottom_right_roi);
    // cv::imshow("Bottom right", bottom_right);


    cv::waitKey(0);

    return(0);
}
g++ crop_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_4.jpg

Fig. 2.4 Crop image

2.1.4.4. Image arithmetic

  • OpenCV sets the maximum and minimum as 255 and 0 respectively.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// image_arith.cpp


#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;
// using namespace cv;

int main(int argc, char** argv )
{


    // ############# Various method to define Matrix #################

    // intialize matrix with contant value 80
    cv::Mat matB(3, 3, CV_8UC1, cv::Scalar(80));
    cout << "matB = " << endl << " " << matB << endl << endl;

    // zero matrix
    cv::Mat matZeros = cv::Mat::zeros(3,3, CV_8UC1);
    cout << "matZeros = " << endl << " " << matZeros << endl << endl;

    // eye matrix
    cv::Mat matEye = cv::Mat::eye(3, 3, CV_64F);
    cout << "matEye = " << endl << " " << matEye << endl << endl;

    // ones matrix
    cv::Mat matOnes = cv::Mat::ones(3, 3, CV_32F);
    cout << "matOnes = " << endl << " " << matOnes << endl << endl;

    float data[10] = { 221, 23, 9, 104, 51, 65, 76, 48, 210 };
    cv::Mat A = cv::Mat(3, 3, CV_32F, data);
    cout << "A = " << endl << " " << A << endl << endl;

    cv::Mat B(3, 3, CV_8UC1, cv::Scalar(80));
    cout << "B = " << endl << " " << B << endl << endl;

    // convert format
    cv::Mat A_convert = cv::Mat(3, 3, CV_8UC1);
    A.convertTo(A_convert, CV_8UC1);
    cout << "A_convert = " << endl << " " << A_convert << endl << endl;


    // define 3x3 matrix
    cv::Mat matOut = cv::Mat(3, 3, CV_8UC1);

    // ######################## Add/subtract ####################################

    // cv::add(A_convert, B, matOut) is not possible due to different data type
    cv::add(A_convert, B, matOut);
    cout << "A_convert + B = \n" << matOut << endl << endl;

    // subtract
    cv::subtract(A_convert, B, matOut);
    cout << "A_convert - B = \n" << matOut << endl << endl;


    // ############ Image addtion

    cv::Mat img, add_img, sub_img;  // variable image of datatype Matrix

    // read image
    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    // define new mat with same size as img
    cv::Mat new_pixel = 90 * cv::Mat::ones(img.size(), img.type());

    // add and show
    cv::add(img, new_pixel, add_img);
    cv::imshow("Add image", add_img);

    // subtract and show
    cv::subtract(img, new_pixel, sub_img);
    cv::imshow("Subtract image", sub_img);


    cv::waitKey(0);

    return(0);
}
g++ image_arith.cpp -o out `pkg-config --libs opencv` && ./out
  • Output will be as below,
OpenCV 250 + 10:  [[255]]
Numpy 250 + 10:  [4]
Initial pixel at [50, 50]   :  [  1 255   0]
Add/subtract 90
OpenCV addition pixel at [50, 50]   :  [ 91 255  90]
OpenCV subtract pixel at [50, 50]   :  [  0 165   0]
Numpy addition pixel at [50, 50]    :  [  0 165   0]
Numpy subtract pixel at [50, 50]    :  [  0 165   0]
../_images/Screenshot_5.jpg

Fig. 2.5 Image arithmetic

2.1.4.5. Threshold

For every pixel, the same threshold value is applied. If the pixel value is smaller than the threshold, it is set to 0, otherwise it is set to a maximum value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// threshold_img.cpp


#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv )
{

    cv::Mat img, thresh_img;  // variable image of datatype Matrix

    img = cv::imread("images/rose.jpg");
    cv::imshow("Rose", img);

    cv::threshold(img, thresh_img, 100, 255, cv::THRESH_BINARY);
    cv::imshow("Threshold Binary", thresh_img);

    cv::threshold(img, thresh_img, 100, 255, cv::THRESH_BINARY_INV);
    cv::imshow("Threshold Binary Inverse", thresh_img);

    cv::waitKey(0);
    return 0;
}
../_images/Screenshot_6.jpg

Fig. 2.6 Threshold

2.1.5. Geometric Transformations

2.1.5.1. Scaling

Scaling is just resizing of the image. OpenCV comes with a function cv2.resize() for this purpose.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// scale_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv )
{

    cv::Mat img, resize_img;  // variable image of datatype Matrix
    int w, h;

    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    w = img.size().width;
    h = img.size().height;

    cv::resize(img, resize_img, cv::Size((int)w/2, (int)h/2), cv::INTER_CUBIC);
    cv::imshow("Resize Shapes", resize_img);

    cv::waitKey(0);
    return 0;
}
g++ scale_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_7.jpg

Fig. 2.7 Resize or scaling

2.1.5.2. Flip

Three types of flips are possible,

  • 0 : Horizontal flip
  • 1 : Vertical flip
  • -1 : Both horizontal and vertical flip
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// flip_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv )
{

    cv::Mat img, flip_horizontal, flip_vertical, flip_both;  // variable image of datatype Matrix

    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    // flip horizontal
    cv::flip(img, flip_horizontal, 0);
    cv::imshow("Horizontal Flip", flip_horizontal); // display image

    // flip vertical
    cv::flip(img, flip_vertical, 1);
    cv::imshow("Vertical Flip", flip_vertical); // display image

    // flip vertical and horizontal both
    cv::flip(img, flip_both, -1);
    cv::imshow("Horizontal and Vertical Flip", flip_both); // display image

    cv::waitKey(0);
    return 0;
}
g++ flip_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_8.jpg

Fig. 2.8 Flip

2.1.5.3. Translation

Translation is the shifting of object’s location.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// translate_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv )
{

    cv::Mat img, shift_img;  // variable image of datatype Matrix

    // create shift matrix
    float data[6] = { 1, 0, 30, 0, 1, 50 };
    cv::Mat shift_matrix_float = cv::Mat(2, 3, CV_32F, data);
    cout << shift_matrix_float;

    // convert to CV_64F format
    cv::Mat shift_matrix = cv::Mat(2, 3, CV_64F);
    shift_matrix_float.convertTo(shift_matrix, CV_64F);

    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    // flip horizontal
    cv::warpAffine(img, shift_img, shift_matrix, img.size());
    cv::imshow("Translate Flip", shift_img); // display image


    cv::waitKey(0);
    return 0;
}
g++ translate_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_9.jpg

Fig. 2.9 Translation

2.1.5.4. Rotation

  • We need to define the rotation angle along with a point for rotation.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// rotate_img.cpp


#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv ){

    cv::Mat img, rotate_matrix, rotated;
    int w, h; // width, height

    // read image
    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    // width and height of image
    w = img.size().width;
    h = img.size().height;

    // rotation points
    cv::Point2f rotation_center(w/2, h/2);

    rotate_matrix = cv::getRotationMatrix2D(rotation_center, 45, 1.0);

    cv::warpAffine(img, rotated, rotate_matrix, img.size());
    cv::imshow("Rotated by 45 Degrees", rotated);

    cv::waitKey(0);
    return 0;
}
g++ rotate_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_10.jpg

Fig. 2.10 Rotation

2.1.6. Drawing

  • In this section, lines, rectangle, circle and ellipse are drawn using OpenCV.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// drawing_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv ){

    cv::Mat img, rotate_matrix, rotated;
    int w, h; // width, height

    // read image
    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    // width and height of image
    w = img.size().width;
    h = img.size().height;

    // draw horizontal line
    cv::line( img, cv::Point( 0, (int)h/2 ), cv::Point( w, (int)h/2), cv::Scalar( 255, 0, 0 ), 3);
    // draw vertical line
    cv::line( img, cv::Point( (int)w/2, 0 ), cv::Point( (int)w/2, h), cv::Scalar( 255, 0, 0 ), 3);

    // draw rectangle
    cv::rectangle( img, cv::Point(5, 10), cv::Point(200, 170), cv::Scalar( 0, 0, 255 ), 3);

    // draw circle
    // center coordinates (w//2, h//2) and radius (50) are
    // required to to draw circle. 10 is the line width
    cv::circle(img, cv::Point((int)w/2, (int)h/2), 50, cv::Scalar(0, 0, 0), 10); // black
    cv::circle(img, cv::Point((int)w/2, (int)h/2), 30, cv::Scalar(0, 0, 255), -1); // -1 : filled circle

    cv::imshow("Shapes", img);

    cv::waitKey(0);
    return 0;
}
g++ drawing_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_11.jpg

Fig. 2.11 Drawing

2.1.7. Bitwise operation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// bitwise_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv ){

    cv::Mat and_img;

    // create and display frame of size 300 for rectangle and circle
    cv::Mat rectangle(300, 300, CV_8UC1, cv::Scalar(0)); // rectangle
    cv::Mat circle(300, 300, CV_8UC1, cv::Scalar(0)); // circle


    // draw and show rectangle
    cv::rectangle( rectangle, cv::Point(20, 20), cv::Point(280, 280), cv::Scalar( 255 ), -1);
    cv::imshow("Rectangle", rectangle);

    // draw and show circle
    cv::circle(circle, cv::Point(150, 150), 150, cv::Scalar(255), -1); // black
    cv::imshow("Circle", circle);

    // bitwise and operation
    cv::bitwise_and(circle, rectangle, and_img);
    cv::imshow("And", and_img);



    // another example
    cv::Mat rect1 = cv::Mat::zeros( cv::Size(400,200), CV_8UC1);
    cv::Mat rect2 = cv::Mat::zeros( cv::Size(400,200), CV_8UC1);


    rect1( cv::Range(0, 200), cv::Range(0, 200) ) = 255;
    cv::imshow("rect1", rect1);

    rect2( cv::Range(100, 150), cv::Range(150, 250) ) = 255;
    cv::imshow("rect2", rect2);

    cv::Mat result;

    bitwise_and(rect1, rect2, result);
    cv::imshow("AND", result);

    bitwise_or(rect1, rect2, result);
    cv::imshow("OR", result);

    bitwise_xor(rect1, rect2, result);
    cv::imshow("XOR", result);

    bitwise_not(rect2, result);
    cv::imshow("rect2 NOT", result);


    cv::waitKey(0);
    return 0;
}
g++ bitwise_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_12.jpg

Fig. 2.12 Bitwise operation

2.1.8. Masking

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// mask_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv ){

    cv::Mat img, masked_img;
    int w, h; // width, height

    // read image
    img = cv::imread("images/shapes.jpg");
    cv::imshow("Shapes", img);

    // width and height of image
    w = img.size().width;
    h = img.size().height;


    cv::Mat circle = cv::Mat::zeros( cv::Size(w, h), CV_8UC3);
    cv::circle(circle, cv::Point(315, 265), 90, cv::Scalar(255, 255, 255), -1); // black
    cv::imshow("Circle", circle);

    cv::bitwise_and(img, circle, masked_img);
    cv::imshow("Masked image", masked_img);

    cv::waitKey(0);
    return 0;
}
g++ mask_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_13.jpg

Fig. 2.13 Masking

2.1.9. Edge detection

2.1.9.1. Sobel edge detection

// sobel_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv ){

    cv::Mat img, gray_img;
    int w, h; // width, height

    // read image
    img = cv::imread("images/lego.jpg");
    cv::imshow("Lego color", img);

    // width and height of image
    w = img.size().width;
    h = img.size().height;


    cv::cvtColor(img, gray_img, cv::COLOR_BGR2GRAY);
    cv::imshow("Lego ", gray_img);

    cv::Mat gX, gY;
    //  compute gradients along the X and Y axis, respectively
    cv::Sobel(gray_img, gX, CV_64F, 1, 0);
    cv::Sobel(gray_img, gY, CV_64F, 0, 1);
    // gX value after sobel conversion -52.0
    cout << "gX value after sobel conversion: " << (int)gX.at<double>(100, 200) << endl;


    // gX and gY are decimal number with +/- values
    // change these values to +ve integer format
    cv::convertScaleAbs(gX, gX);
    // gX value after Absolute scaling 52
    cv::convertScaleAbs(gY, gY);
    cout << "gX value after Absolute scaling: " << (int)gX.at<uchar>(100, 200) << endl;


    cv::Mat sobelCombined;
     cv::addWeighted(gX, 0.5, gY, 0.5, 0, sobelCombined);

    // show the output images
    cv::imshow("Sobel X", gX);
    cv::imshow("Sobel Y", gY);
    cv::imshow("Sobel Combined", sobelCombined);

    cv::waitKey(0);
    return 0;
}
g++ sobel_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_14.jpg

Fig. 2.14 Sobel edge detection

2.1.9.2. Canny edge detection

// canny_img.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int argc, char** argv ){

    cv::Mat img, gray_img;
    int w, h; // width, height

    // read image
    img = cv::imread("images/lego.jpg");
    cv::imshow("Lego color", img);

    // width and height of image
    w = img.size().width;
    h = img.size().height;


    cv::cvtColor(img, gray_img, cv::COLOR_BGR2GRAY);
    cv::imshow("Lego ", gray_img);

    cv::Mat canny_wide, canny_medium, canny_narrow;

    cv::Canny(gray_img, canny_wide, 10, 200);
    cv::Canny(gray_img, canny_medium, 50, 150);
    cv::Canny(gray_img, canny_narrow, 200, 250);

    // show the output images
    cv::imshow("Canny (10, 200)", canny_wide);
    cv::imshow("Canny (50, 150)", canny_medium);
    cv::imshow("Canny (200, 250)", canny_narrow);


    cv::waitKey(0);
    return 0;
}
g++ canny_img.cpp -o out `pkg-config --libs opencv` && ./out
../_images/Screenshot_15.jpg

Fig. 2.15 Canny edge detection