Tutorial: C++ basics for OpenCV
Tutorial: C++ basics
Deep Learning Image Processing. Updated. 2024.2
I. Introduction
The OpenCV Library has >2500 algorithms, extensive documentation, and sample code for real-time computer vision. You can see basic information about OpenCV at the following sites,
In this tutorial, you will learn fundamental concepts of the C++ language to use the OpenCV API. You will learn namespace, class, C++ syntax to use image reading, writing and displaying.
OpenCV Example Code Image File Read / Write / Display
Copy #include <iostream>
#include <opencv.hpp>
using namespace std;
using namespace cv;
int main ()
{
/* read image */
String filename1 = "image.jpg" ; // class
Mat img = imread (filename1); //Mat class
Mat img_gray = imread ( "image.jpg" , 0 ); // read in grayscale
/* write image */
String filename2 = "writeTest.jpg" ; // C++ class/syntax (String, cout, cin)
imwrite (filename2 , img);
Â
/* display image */
namedWindow ( "image" , WINDOW_AUTOSIZE);
imshow ( "image" , img);
namedWindow ( "image_gray" , WINDOW_AUTOSIZE);
imshow ( "image_gray" , img_gray);
waitKey ( 0 );
}
C++ for OpenCV
OpenCV is provided in C++, Python, Java. We will learn how to use OpenCV in
C++ (general image processing)
Python (for Deep learning processing)
For C++, we need to learn
Overloading, namespace, template
C++
C++ is a general-purpose programming language created by Bjarne Stroustrup as an extension of the C programming language . C++ is portable and can be used to develop applications that can be adapted to multiple platforms. You can see basic C++ tutorials in following site,
Project Workspace Setting
Create the lecture workspace as C:\Users\yourID\source\repos
e.g. C:\Users\ykkim\source\repos
Then, create sub-directories such as :
C:\Users\yourID\source\repos\DLIP
C:\Users\yourID\source\repos\DLIP\Tutorial
C:\Users\yourID\source\repos\DLIP\Include
C:\Users\yourID\source\repos\DLIP\Assignment
C:\Users\yourID\source\repos\DLIP\LAB
C:\Users\yourID\source\repos\DLIP\Image
Define and Declare Functions in Header Files
We will learn how to declare and define functions in the header file
Exercise 1
Create a new C++ project in Visual Studio Community
Project Name: DLIP_Tutorial_C++_Ex1
Project Folder: C:\Users\yourID\source\repos\DLIP\Tutorial\
Create a new C+ source file
File Name: DLIP_Tutorial_C++_Ex1.cpp
Create new header files
File Names: TU_DLIP.h
, TU_DLIP.cpp
Lib Folder: C:\Users\yourID\source\repos\DLIP\Include\
Declare the sum function in the header file(TU_DLIP.h
) as
Copy int sum ( int val1 , int val2);
Define the sum function in the header source file(TU_DLIP.cpp
) as
Copy int sum ( int val1 , int val2){...}
Include the header file in the main source code of DLIP_Tutorial_C++_Ex1.cpp
.
Modify the source main code to print the sum value of any two numbers
DLIP_Tutorial_C++_Ex1.cpp TU_DLIP.h TU_DLIP.cpp
Copy //#include "TU_DLIP.h"
#include "../../../Include/TU_DLIP.h"
#include <iostream>
int main ()
{
// =============================
// Exercise 1 :: Define Function
// =============================
int val1 = 11 ;
int val2 = 22 ;
// Add code here
std :: cout << out << std :: endl;
}
Copy #ifndef _TU_DLIP_H // same as "#if !define _TU_DLIP_H" (or #pragma once)
#define _TU_DLIP_H
#include <iostream>
// =============================
// Exercise 1 :: Define Function
// =============================
// Add code here
#endif // !_TU_DLIP_H
Copy #include "TU_DLIP.h"
#include <iostream>
// =============================
// Exercise 1 :: Define Function
// =============================
int sum ( int val1 , int val2)
{
// Add code here
}
C++ Class
Class is similar to C structure:
Structure: Cannot inclue functions. Only variables
Class: Can include variables, functions definition/declaration, other classes
Structure (C) Class (C++)
Copy #include <stdio.h>
#include <stdlib.h>
typedef struct {
char number[ 20 ];
char password[ 20 ];
char name[ 20 ];
int balance;
}Account;
Copy #inclue < iostream >
using namespace std;
/* Class Definition */
class Account {
public :
char number [ 20 ];
char password [ 20 ];
char name [ 20 ];
int balance;
void deposit ( int money); // Can include functions
void withdraw ( int money); // Can include functions
};
/* Class Function Definition */
void Account :: deposit ( int money){
balance += money;
}
void Account :: withdraw ( int money){
balance -= money;
}
Class Constructor
Constructor is special method automatically called when an object of a class is created.
Use the same name as the class, followed by parentheses ()
It does not have any return values.
Copy class MyNum {
public :
MyNum (); // Constructor 1
MyNum ( int x); // Constructor 2
int num;
};
// Class Constructor 1
MyNum :: MyNum (){}
// Class Constructor 2
MyNum :: MyNum ( int x)
{
num = x;
}
int main (){
// Creating object by constructor 1
MyNum mynum;
mynum . num = 10 ;
// Creating object by constructor 2
MyNum mynum2 ( 10 );
}
Mat Class in OpenCV
The image data are in forms of 1D, 2D, 3D arrays with values 0~255 or 0~1
OpenCV provides the Mat class for operating multi dimensional images
Example Printing out informations about the source image using OpenCV
Copy #include "opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main ( int argc , char* argv[])
{
cv :: Mat src , gray , dst;
src = cv :: imread ( "testImage.jpg" );
if ( src . empty ())
std :: cout << "src is empty!!" << std :: endl;
// Print result
std :: cout << "is empty? \t: " << src . empty () << std :: endl;
std :: cout << "channels \t: " << src . channels () << std :: endl;
std :: cout << "row of src \t: " << src . rows << std :: endl;
std :: cout << "col of src \t: " << src . cols << std :: endl;
std :: cout << "type of src \t: " << src . type () << std :: endl;
cv :: namedWindow ( "src" );
cv :: imshow ( "src" , src);
cv :: waitKey ( 0 );
}
Results
Exercise 2
Create a new C++ project in Visual Studio Community
Project Name: DLIP_Tutorial_C++_Ex2
Project Folder: C:\Users\yourID\source\repos\DLIP\Tutorial\
Create a new C+ source file
File Name: DLIP_Tutorial_C++_Ex2.cpp
Create a Class 'MyNum'
Modify the header file TU_DLIP.h
and TU_DLIP.cpp
to declare a class member named as MyNum .
Member variables: val1, val2 // integer type
Member functions: int sum() // returns the sum of val1 and val2
Member functions: void print() // prints values of val1, val2, and sum
Then, compile and run the program.
DLIP_Tutorial_C++_Ex2.cpp TU_DLIP.h TU_DLIP.cpp
Copy //#include "TU_DLIP.h"
#include "../../../Include/TU_DLIP.h"
int main ()
{
// =============================
// Exercise 1: Define Function
// =============================
int val1 = 11 ;
int val2 = 22 ;
int out = sum (val1 , val2);
std :: cout << out << std :: endl;
// ====================================
// Exercise 2: Create a Class 'MyNum'
// ====================================
MyNum mynum ( 10 , 20 );
mynum . print ();
}
Copy #ifndef _TU_DLIP_H // same as "#if !define _TU_DLIP_H" (or #pragma once)
#define _TU_DLIP_H
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2)
{
return val1 + val2;
}
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
// Declare Constructor, function(sum, print), variable(val1, val2)
class MyNum
{
// Add code here
};
#endif // !_TU_DLIP_H
Copy #include "TU_DLIP.h"
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2)
{
return val1 + val2;
}
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
// Constructor: x1 -> val1, x2 -> val2
MyNum :: MyNum ( int x1 , int x2)
{
// Add code here
}
int MyNum :: sum ( void )
{
// Add code here
}
void MyNum :: print ( void )
{
// Add code here
}
Solution
TU_DLIP_solution.h TU_DLIP_solution.cpp
Copy #ifndef _TU_DLIP_H // same as "#if !define _TU_DLIP_H" (or #pragma once)
#define _TU_DLIP_H
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2);
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
class MyNum
{
public :
MyNum ( int x1 , int x2);
int val1;
int val2;
int sum ( void );
void print ( void );
};
#endif // !_TU_DLIP_H
Copy #include "TU_DLIP.h"
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2)
{
int out = val1 + val2;
return out;
}
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
// Constructor: x1 -> val1, x2 -> val2
MyNum :: MyNum ( int x1 , int x2)
{
val1 = x1;
val2 = x2;
}
int MyNum :: sum ( void )
{
return val1 + val2;
}
void MyNum :: print ( void )
{
std :: cout << "MyNum.val1: " << val1 << std :: endl;
std :: cout << "MyNum.val2: " << val2 << std :: endl;
std :: cout << "Sum : " << sum () << std :: endl;
}
Namespace
A namespace provides a scope to the identifiers (the names of types, functions, variables, etc) inside it.
Uses :: as scope resolution operator
Use namespace in order to avoid collision using functions with the same name e.g. KimHandong --> Student::KimHandong, TA::KimHandong
Copy // Method 1. Calling specific function(recommended)
int main ( void ){
project_A :: add_value ( 3 , 7 );
project_A :: subtract_value ( 10 , 2 );
return 0 ;
}
// Method 2. Calling all functions in the namespace
using namespace project_A;
int main ( void ){
add_value ( 3 , 7 );
subtract_value ( 10 , 2 );
return 0 ;
}
std::cout, std::cin, std::endl are also defined in iostream
Copy // Method 1
std :: cout << "print this" << std :: endl;
// Method 2
using namespace std
cout<<"print this"<<endl;
Exercise 3
Create another Class 'MyNum'
In this exercise, you create the MyNum
class, previously implemented in Exercise 2 , with the same class name in different namespaces, proj\_A
, and proj\_B
.
Create a new C++ project in Visual Studio Community
Project Name: DLIP_Tutorial_C++_Ex3
Project Folder: C:\Users\yourID\source\repos\DLIP\Tutorial\
Create a new C+ source file
File Name: DLIP_Tutorial_C++_Ex3.cpp
Modify the header file TU_DLIP.h
and TU_DLIP.cpp
to declare two class members named as MyNum in proj\_A
and proj\_B
.
Use namespace to identify two classes clearly
First MyNum class: namespace name proj_A
Second MyNum class: namespace name proj_B
Also, declare class member variables for each MyNum class: Constructor / val1 / val2 / val3 / sum / print
Constructor MyNum(int in1, int in2, int in3)
: A constructor for specifying values val1
, val2
, val3
val1
, val2
, val3
: member variable of integer type
sum(void)
: member function that returns the sum of val1, val2, and val3
`print(void): member function that prints val1, val2, val3, and sum
DLIP_Tutorial_C++_Ex3.cpp TU_DLIP.h TU_DLIP.cpp
Copy #include "../../../Include/TU_DLIP.h"
#include "TU_DLIP.h"
void main ()
{
proj_A :: MyNum mynum1 ( 1 , 2 , 3 );
proj_B :: MyNum mynum2 ( 4 , 5 , 6 );
mynum1 . print ();
mynum2 . print ();
system ( "pause" );
}
Copy #ifndef _TU_DLIP_H // same as "#if !define _TU_DLIP_H" (or #pragma once)
#define _TU_DLIP_H
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2);
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
class MyNum
{
public :
MyNum ( int x1 , int x2);
int val1;
int val2;
int sum ( void );
void print ( void );
};
// ======================================================
// Exercise 3: Create two Class "MyNum" in proj_A, proj_B
// ======================================================
namespace proj_A
{
// Add code here
}
namespace proj_B
{
// Add code here
}
#endif // !_TU_DLIP_H
Copy #include "TU_DLIP.h"
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2)
{
return val1 + val2;
}
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
MyNum :: MyNum ( int x1 , int x2)
{
val1 = x1;
val2 = x2;
}
int MyNum :: sum ( void )
{
return val1 + val2;
}
void MyNum :: print ( void )
{
std :: cout << "MyNum.val1 : " << val1 << std :: endl;
std :: cout << "MyNum.val2 : " << val2 << std :: endl;
std :: cout << "Sum : " << sum () << std :: endl;
}
// ======================================================
// Exercise 3: Create two Class "MyNum" in proj_A, proj_B
// ======================================================
proj_A :: MyNum :: MyNum ( int x1 , int x2 , int x3)
{
// Add code here
}
int proj_A :: MyNum :: sum ( void )
{
// Add code here
}
void proj_A :: MyNum :: print ( void )
{
// Add code here
}
proj_B :: MyNum :: MyNum ( int x1 , int x2 , int x3)
{
// Add code here
}
int proj_B :: MyNum :: sum ( void )
{
// Add code here
}
void proj_B :: MyNum :: print ( void )
{
// Add code here
}
TU_DLIP_Solution.h TU_DLIP_solution.cpp
Copy #ifndef _TU_DLIP_H // same as "#if !define _TU_DLIP_H" (or #pragma once)
#define _TU_DLIP_H
#include <iostream>
// =============================
// Exercise 1: Define Function
// =============================
int sum ( int val1 , int val2);
// ====================================
// Exercise 2: Create a Class "MyNum"
// ====================================
class MyNum
{
public :
MyNum ( int x1 , int x2);
int val1;
int val2;
int sum ( void );
void print ( void );
};
// ======================================================
// Exercise 3: Create two Class "MyNum" in proj_A, proj_B
// ======================================================
namespace proj_A
{
class MyNum
{
public :
MyNum ( int x1 , int x2 , int x3);
int val1;
int val2;
int val3;
int sum ( void );
void print ( void );
};
}
namespace proj_B
{
class MyNum
{
public :
MyNum ( int x1 , int x2 , int x3);
int val1;
int val2;
int val3;
int sum ( void );
void print ( void );
};
}
#endif // !_TU_DLIP_H
Copy #include "TU_DLIP.h"
#include <iostream>
// =============================
// Exercise 1 :: Define Function
// =============================
int sum ( int val1 , int val2)
{
return val1 + val2;
}
// ====================================
// Exercise 2 :: Create a Class "MyNum"
// ====================================
MyNum :: MyNum ( int x1 , int x2)
{
val1 = x1;
val2 = x2;
}
int MyNum :: sum ( void )
{
return val1 + val2;
}
void MyNum :: print ( void )
{
std :: cout << "MyNum.val1 : " << val1 << std :: endl;
std :: cout << "MyNum.val2 : " << val2 << std :: endl;
std :: cout << "Sum : " << sum () << std :: endl;
}
// ======================================================
// Exercise 3: Create two Class "MyNum" in proj_A, proj_B
// ======================================================
proj_A :: MyNum :: MyNum ( int x1 , int x2 , int x3)
{
val1 = x1;
val2 = x2;
val3 = x3;
}
int proj_A :: MyNum :: sum ( void )
{
return val1 + val2 + val3;
}
void proj_A :: MyNum :: print ( void )
{
std :: cout << "MyNum.val1 : " << val1 << std :: endl;
std :: cout << "MyNum.val2 : " << val2 << std :: endl;
std :: cout << "MyNum.val3 : " << val3 << std :: endl;
std :: cout << "Sum : " << sum () << std :: endl;
}
proj_B :: MyNum :: MyNum ( int x1 , int x2 , int x3)
{
val1 = x1;
val2 = x2;
val3 = x3;
}
int proj_B :: MyNum :: sum ( void )
{
return val1 + val2 + val3;
}
void proj_B :: MyNum :: print ( void )
{
std :: cout << "MyNum.val1 : " << val1 << std :: endl;
std :: cout << "MyNum.val2 : " << val2 << std :: endl;
std :: cout << "MyNum.val3 : " << val3 << std :: endl;
std :: cout << "Sum : " << sum () << std :: endl;
}
Template
A template can make a variable type(int, float, char..) as a variable. How can you use the same function but with a different number type as the input argument? : add(float A, float B), add(int A, int B) &rarr
add(T A, T B) where T=int or T=float
Function Overloading
Functions with the same name (but with different types or number of parameters) can be defined.
Different return type (with everything else the same) is not a function overloading.
Example
cv::Mat
can be created in many different ways. Use the up or down the keyboard to see what the options are.
Function Overloading Reference
Copy #include <opencv2/opencv.hpp>
#include <iostream>
cv :: Mat cvtGray ( const cv :: Mat color);
void cvtGray (cv :: Mat color , cv :: Mat & gray);
void main () {
cv :: Mat src , gray , dst;
src = cv :: imread ( "image.jpg" );
if ( src . empty ())
std :: cout << "src is empty!!" << std :: endl;
cvtGray (src , gray);
cv :: namedWindow ( "src" );
cv :: imshow ( "src" , src);
cv :: namedWindow ( "gray" );
cv :: imshow ( "gray" , gray);
cv :: waitKey ( 0 );
}
cv :: Mat cvtGray (cv :: Mat color)
{
cv :: Mat gray;
color = cv :: Mat :: zeros ( color . size () , CV_8UC3);
cv :: cvtColor (color , gray , CV_RGB2GRAY);
return gray;
}
void cvtGray (cv :: Mat color , cv :: Mat gray)
{
cv :: cvtColor (color , gray , CV_RGB2GRAY);
cv :: namedWindow ( "inside_function" );
cv :: imshow ( "inside_function" , gray);
}
Default Parameter
Default parameter in OpenCV
Pointer
A pointer is a variable whose value is the address of another variable.
What are Pointers?
A pointer is a variable whose value is the address of another variable. i.e. direct address of the memory locations Pointers are the basis for data structures.
Define a pointer variable int *ptr;
Assign the address of a variable to a pointer ptr = &var
Access the value at the address available in the pointer variable int value = *ptr
Example
Copy #include <iostream>
void swap ( int * a , int * b);
int main () {
int val1 = 10 ;
int val2 = 20 ;
printf ( "Before SWAP operation \n" );
printf ( "val1: %d \n" , val1);
printf ( "val2: %d \n" , val2);
swap ( & val1 , & val2);
printf ( "After SWAP operation \n" );
printf ( "val1: %d \n" , val1);
printf ( "val2: %d \n" , val2);
system ( "pause" );
return 0 ;
}
void swap ( int * a , int * b) {
int temp = * a;
* a = * b;
* b = temp;
}
Reference
Reference can replace the use of pointer *
The disadvantage of reference is "We do not know if a function is call-by-value or call-by-reference"
Copy // C/C++ syntax (Pointer)
#include <iostream>
void swap ( int * a , int * b){
int temp = * a;
* a = * b;
* b = temp;
}
int main ( void ){
int value1 = 10 ;
int value2 = 20 ;
std :: cout << "value1 :" << value1 << " " ;
std :: cout << "value2 :" << value2 << std :: endl;
swap ( & value1 , & value2);
std :: cout << "value1 :" << value1 << " " ;
std :: cout << "value2 :" << value2 << std :: endl;
return 0 ;
}
// C++ only (Reference)
#include <iostream>
void swap ( int & a , int & b){
int temp = a;
a = b;
b = temp;
}
int main ( void ){
int value1 = 10 ;
int value2 = 20 ;
std :: cout << "value1 :" << value1 << " " ;
std :: cout << "value2 :" << value2 << std :: endl;
swap (value1 , value2);
std :: cout << "value1 :" << value1 << " " ;
std :: cout << "value2 :" << value2 << std :: endl;
return 0 ;
}