Reading/writing images
Following the introduction to matrices, we are going to start with the OpenCV code basics. The first thing that we have to learn is how to read and write images:
#include <iostream> #include <string> #include <sstream> using namespace std; // OpenCV includes #include "opencv2/core.hpp" #include "opencv2/highgui.hpp" using namespace cv; int main(int argc, const char** argv) { // Read images Mat color= imread("../lena.jpg"); Mat gray= imread("../lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);
if(! color.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
} // Write images imwrite("lenaGray.jpg", gray); // Get same pixel with opencv function int myRow=color.cols-1; int myCol=color.rows-1; Vec3b pixel= color.at<Vec3b>(myRow, myCol); cout << "Pixel value (B,G,R): (" << (int)pixel[0] << "," << (int)pixel[1] << "," << (int)pixel[2] << ")" << endl; // show images imshow("Lena BGR", color); imshow("Lena Gray", gray); // wait for any key press waitKey(0); return 0; }
Let's now move on to understanding the code:
// OpenCV includes #include "opencv2/core.hpp" #include "opencv2/highgui.hpp" using namespace cv;
First, we have to include the declarations of the functions that we need in our sample. These functions come from core (basic image data handling) and highgui (cross-platform I/O functions provided by OpenCV are core and highui;; the first includes the basic classes, such as matrices, while the second includes the functions to read, write, and show images with graphical interfaces). Now it is time to read images:
// Read images
Mat color= imread("../lena.jpg");
Mat gray= imread("../lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);
imread is the main function for reading images. This function opens an image and stores it in a matrix format. imread accepts two parameters. The first parameter is a string containing the image's path, while the second is optional and, by default, loads the image as a color image. The second parameter allows the following options:
- cv::IMREAD_UNCHANGED: If set, this returns a 16-bit/32-bit image when the input has the corresponding depth, otherwise it converts it to 8-bit
- cv::IMREAD_COLOR: If set, this always converts an image to a color one (BGR, 8-bit unsigned)
- cv::IMREAD_GRAYSCALE: If set, this always converts an image to a grayscale one (8-bit unsigned)
To save images, we can use the imwrite function, which stores a matrix image in our computer:
// Write images imwrite("lenaGray.jpg", gray);
The first parameter is the path where we want to save the image with the extension format that we desire. The second parameter is the matrix image that we want to save. In our code sample, we create and store a gray version of the image and then save it as a .jpg file. The gray image that we loaded will be stored in the gray variable:
// Get same pixel with opencv function int myRow=color.cols-1; int myCol=color.rows-1;
Using the .cols and .rows attributes of a matrix, we can get access to the number of columns and rows in an image, or, in other words, the width and height:
Vec3b pixel= color.at<Vec3b>(myRow, myCol); cout << "Pixel value (B,G,R): (" << (int)pixel[0] << "," << (int)pixel[1] << "," << (int)pixel[2] << ")" << endl;
To access one pixel of the image, we use the template function cv::Mat::at<typename t>(row,col) from the Mat OpenCV class. The template parameter is the desired return type. A type name in an 8-bit color image is a Vec3b class that stores three unsigned char data (Vec = vector, 3 = number of components, and b = 1 byte). In the case of the gray image, we can directly use the unsigned character, or any other number format used in the image, such as uchar pixel= color.at<uchar>(myRow, myCol). Finally, in order to show the images, we can use the imshow function, which creates a window with a title as a first parameter and the image matrix as a second parameter:
// show images imshow("Lena BGR", color); imshow("Lena Gray", gray); // wait for any key press waitKey(0);
The result of the preceding code is demonstrated in the following image. The left-hand image is a color image, and the right-hand image is a grayscale image:
Finally, by way of an example for the following samples, we are going to create the CMakeLists.txt file and see how to compile the code using the file.
The following code describes the CMakeLists.txt file:
cmake_minimum_required (VERSION 3.0) cmake_policy(SET CMP0012 NEW) PROJECT(project) # Requires OpenCV FIND_PACKAGE( OpenCV 4.0.0 REQUIRED ) MESSAGE("OpenCV version : ${OpenCV_VERSION}") include_directories(${OpenCV_INCLUDE_DIRS}) link_directories(${OpenCV_LIB_DIR}) ADD_EXECUTABLE(sample main.cpp) TARGET_LINK_LIBRARIES(sample ${OpenCV_LIBS})
To compile our code using this CMakeLists.txt file, we have to carry out the following steps:
- Create a build folder.
- Inside the build folder, execute CMake or open CMake GUI app in Windows, choose the source and build folders, and press the Configure and Generate buttons.
- If you are on Linux or macOS, generate a Makefile as usual, and then compile the project using the make command. If you are on Windows, open the project using the editor selected in step 2 and then compile.
Finally, after compiling our application, we will have an executable called app in the build folder that we can execute.