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.
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
C:\Users\yourID\source\repos\DLIP\Props
Basic Image Processing
Example 1. Read / Write / Display
You can use the OpenCV C++ library to read, write, and display images/videos. Here is a related example.
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ /* open the video camera no.0 */ VideoCapture cap(0);if (!cap.isOpened()) // if not success, exit the programm { cout <<"Cannot open the video cam\n";return-1; }namedWindow("MyVideo", WINDOW_AUTOSIZE);while (1) { Mat frame; /* read a new frame from video */bool bSuccess =cap.read(frame);if (!bSuccess) // if not success, break loop { cout <<"Cannot find a frame from video stream\n";break; }imshow("MyVideo", frame);if (waitKey(30) ==27) // wait for 'ESC' press for 30ms. If 'ESC' is pressed, break loop { cout <<"ESC key is pressed by user\n";break; } }}
Basic Image Container: Mat Class
Mat Class
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 2. Matrix Operation: Create / Copy
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ /* Create or Construct Mat */ Mat A(10,10, CV_8UC3, Scalar::all(155)); Mat B(A.size(), CV_8UC1); Mat C = Mat::zeros(A.size(), CV_8UC1); Mat D = Mat::ones(A.size(), CV_32FC1); cout <<"MAT A: "<< A << endl << endl; cout <<"MAT B: "<< B << endl << endl; cout <<"MAT C: "<< C << endl << endl; cout <<"MAT D: "<< D << endl << endl; /* Get size of A (rows, cols) */ cout <<"Size of A: "<<A.size() << endl; cout <<"# of Rows of A: "<<A.rows << endl; cout <<"# of Cols of A: "<<A.cols << endl; cout <<"# of Channel of A: "<<A.channels() << endl; /* Copy/Clone Mat A to E/F */ Mat E, F;A.copyTo(E); F =A.clone(); /* Convert channel */ Mat img =imread("../../../Image/HGU_logo.jpg"); // CV8UC3 Image Mat img_gray;cvtColor(img, img_gray, COLOR_BGR2GRAY); /* Chnage image type (8UC1 or 32FC1) */ Mat img_32F;img_gray.convertTo(img_32F, CV_32FC1,1.0/255.0);imshow("img_32F", img_32F); //cout << "img_32F: " << img_32F.channels() << endl << endl;waitKey(0);}
Basic Image Operation: Crop, Rotate, Resize, Color Convert
The methods for performing tasks such as image crop, rotate, resize, and color conversion (such as converting to grayscale) are as follows. If you want to learn more about the functions below, refer to the OpenCV documentation.
Example 3. Basic Image Operation
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ /* read image */ Mat img =imread("../../../Image/HGU_logo.jpg");imshow("img", img); /* Crop(Region of Interest) */ Rect r(10,10,150,150); // (x, y, width, height) Mat roiImg =img(r);imshow("roiImg", roiImg); /* Rotate */ Mat rotImg;rotate(img, rotImg, ROTATE_90_CLOCKWISE);imshow("rotImg", rotImg); /* Resize */ Mat resizedImg;resize(img, resizedImg,Size(1000,100));imshow("resizedImg", resizedImg);waitKey(0);}
Exercise 1
Flip horizontally of the original image
Here's the code to flip the original HGU_logo image horizontally using the OpenCV flip function. Please refer to the documentation below to find more details about cv::flip()
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ /* read src */ // Add code here /* Flip src image // Add code here /* Show source(src) and destination(dst) */ // Add code herewaitKey(0);}
+Extra Exercise 1
The flip function is useful when working with videos. Implement a program that flips the webcam feed horizontally when the h key is pressed using waitKey() function. Hint: flag vs delay time of waitKey
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ // Open video camera with index 0 VideoCapture cap(0); // Check if the video camera is opened successfullyif (!cap.isOpened()) { cout <<"Cannot open the video camera\n";return-1; } // Create a window to display the video feednamedWindow("MyVideo", WINDOW_AUTOSIZE);bool flipHorizontal =false;while (true) { Mat frame; // Read a new frame from the video feedbool readSuccess =cap.read(frame); // Check if reading the frame was successfulif (!readSuccess) { cout <<"Cannot find a frame from the video stream\n";break; } // Add code here // Display the frame in the "MyVideo" windowimshow("MyVideo", frame); // Wait for 30ms and check if the 'ESC' key is pressedif (waitKey(30) ==27) { cout <<"ESC key is pressed by the user\n";break; } }return0;}
Shallow Copy vs Deep Copy
Shallow Copy
Shallow Copy means copying only the memory addresses in the memory. Since it copies pointers pointing to the same object or data, the original and the copy end up sharing the same data. This can lead to issues, as modifications to one object or array will affect the other as well.
Deep Copy
Deep Copy means creating a copy of an object or data in a new memory space. The original and the copy are independent, having separate memory spaces, so modifications made to one side do not affect the other.
Example 4. Shallow_Deep_Copy
Compile and run the code below and see what happens
Before you execute this code, try to understand what it does
An image is composed of small units called pixels. Each pixel can be considered as the smallest unit of an image. Pixel intensity represents the brightness of a pixel. For grayscale images, pixel intensity ranges from 0 (black) to 255 (white). In color images, each channel (e.g., Red, Green, Blue) has its intensity value.
Rows and columns define an image's structure. Rows represent the vertical direction of the image, and columns represent the horizontal direction. The position of a pixel is denoted as (row, column) or (v, u), where v represents the row index and u represents the column index.
OpenCV provides different methods to access the intensity values of pixels in an image. Two common methods are using at<type>(v, u) and using pointers for faster operations.
Method 1. Accessing using at<type>(v,u) (Recommended)
Mat image=imread(filename);image.at<uchar>(v,u)=255;image.at<float>(v,u)=0.9;Â // For an RGB Image// (option1) Vec3b: 8-bit 3-D image (RGB)image.at<cv::Vec3b>(v,u)[0]=255;image.at<cv::Vec3b>(v,u)[1]=255;image.at<cv::Vec3b>(v,u)[2]=255;/* Method 1. Accessing using "at<type>(v, u)" */// For single channel image(Gray-scale)printf("%d",img_gray.at<uchar>(0,0));// For RGB imageprintf("%d",img.at<Vec3b>(0,0)[0]);printf("%d",img.at<Vec3b>(0,0)[1]);printf("%d",img.at<Vec3b>(0,0)[2]);
Method 2. Using Pointer for faster operation
/* Method 2. Accessing Using Pointer */// Gray Imageint pixel_temp;for (int v =0; v <img_gray.rows; v++){ uchar* img_data =img_gray.ptr<uchar>(v);for (int u =0; u <img_gray.cols; u++) pixel_temp =img_data[u];}//RGB Imageint pixel_temp_r, pixel_temp_g, pixel_temp_b;int cnt =0;for (int v =0; v <img.rows; v++){ uchar* img_data =img.ptr<uchar>(v);for (int u =0; u <img.cols *img.channels(); u = u+3) { pixel_temp_r =img_data[u]; pixel_temp_g =img_data[u+1]; pixel_temp_b =img_data[u+2]; }}
Example 5. Access pixel intensity of Gray-Scale Image(1D image)
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ Mat src; // read image src =imread("../../../Image/HGU_logo.jpg",0);int v =src.rows; //행(가로)int u =src.cols; //열(세로)for (int i =0; i < v; ++i)for (int j =0; j < u; ++j)printf("%d\n",src.at<uchar>(i, j));return0;}
Exercise 2
Calculate the average intensity value using at<type>(v,u)
Calculate the summation of the pixel intensity and calculate the average intensity value. Use cv::Mat::rows, cv::Mat::cols.
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ // Load the image in gray-scale Mat src =imread("../../../Image/HGU_logo.jpg",0);if (src.empty()) { cout <<"Error: Couldn't open the image."<< endl;return-1; } // Calculate the sum of pixel intensities using 'at' functiondouble sumIntensity =0.0;for (int i =0; i <src.rows; i++) { // Add code here } // Calculate the total number of pixels in the imageint pixelCount = // Add code here // Calculate the average intensity of the imagedouble avgIntensity = // Add code here // Print the results cout <<"Sum of intensity: "<< sumIntensity << endl; cout <<"Number of pixels: "<< pixelCount << endl; cout <<"Average intensity: "<< avgIntensity << endl; // Display the gray-scale imageimshow("src", src);waitKey(0);return0;}
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ // Load the image Mat src =imread("../../../Image/HGU_logo.jpg",0);if (src.empty()) { cout <<"Error: Couldn't open the image."<< endl;return-1; } // Calculate the sum of pixel intensities using 'at' functiondouble sumIntensity =0.0;for (int i =0; i <src.rows; ++i) {for (int j =0; j <src.cols; ++j) { // Access each pixel in the gray-scale image and add its intensity to the sum sumIntensity +=src.at<uchar>(i, j); } } // Calculate the total number of pixels in the imageint pixelCount =src.rows *src.cols; // Calculate the average intensity of the imagedouble avgIntensity = sumIntensity / pixelCount; // Print the results cout <<"Sum of intensity: "<< sumIntensity << endl; cout <<"Number of pixels: "<< pixelCount << endl; cout <<"Average intensity: "<< avgIntensity << endl; // Display the gray-scale imageimshow("src", src);waitKey(0);return0;}
Exercise 3
Intensity Inversion in Grayscale Images
Write a code to invert the colors of this Grayscale image. The resulting image should look like the following. For example, a pixel with an intensity of 100 should become a value of 255 - 100, which is 155 after the color inversion. Use Mat::zeros, .at<type>(v,u)
#include<iostream>#include<opencv2/opencv.hpp>usingnamespace std;usingnamespace cv;intmain(){ // Load the image Mat src =imread("../../../Image/HGU_logo.jpg",0);if (src.empty()) { cout <<"Error: Couldn't open the image."<< endl;return-1; } // Initialize dst with the same size as srcGray Mat dst = Mat::zeros(src.size(),src.type()); // Invert the colors by accessing each pixel // Add code here // Display the original and inverted imagesimshow("src", src);imshow("dst", dst);waitKey(0);return0;}