In this post we will introduce the most used object of the new OpenCV3 library, using C++.

The aim of the Mat object is to represent a matrix. It is composed by two parts: the header and the data.

  • The header contains information about the matrix itself (like the size of the matrix, the data type, number of channels etc…)
  • The data contains the pointer to the real matrix

Each Mat object has its header, while the data can be shared between multiple instances. The data will be deallocated only when there are no Mat objects pointing to it.

Mat is a very useful object: it is used in a lot of OpenCV functions and it also provides an automatic memory allocation and its release, so the programmers don’t need to do it manually.

Library

The Mat object and the functions we will see in this post are defined within the Core library.

We can include it with the following preprocessor directive:

#include <opencv2\core\core.hpp>

Everything within this package is contained belogns to the cv namespace.

You can choose to prepend the namespace cv:: to each object and function of the core library you are using as follows

cv::Mat
// or
cv::imread(...)

You can also avoid prepending the namespace with the using namespace directive, as follows:

using namespace cv;

We will choose the second way.

Creating the Mat object

Sharing the same data

When using the assignment operator or the copy constructor, we get Mat instances having their own header, but sharing the same data.

In the following example, objects A, B and C will point to the same data, so modifying one or more cells in matrix A, the same changes will result on matrices B and C.

Mat A = ...;
Mat B(A);
// or
Mat C = A;

Cloning the data

To obtain two distinct matrices, so that modifying a value on the first will not affect the same value of the second, we can use the clone() or copyTo() operators.

In this way the two matrices will have different headers and two distinct datas, which will have the same values at the moment of the clone operation.

Mat A = ...;
Mat B = A.clone();
// or
Mat C;
A.copyTo(C);

Reading an image

To initialize a Mat object filling its values directly from an image saved into the memory, you can use the imread function, whose signature is

imread(String & filename, int flags = IMREAD_COLOR)

which expects two parameters:

  • the name of the image file to load and file
  • the image mode (the default is IMREAD_COLOR), for example:
IMREAD_UNCHANGED  If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
IMREAD_GRAYSCALE  If set, always convert image to the single channel grayscale image.
IMREAD_COLOR      If set, always convert image to the 3 channel BGR color image.
IMREAD_ANYDEPTH   If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
IMREAD_ANYCOLOR   If set, the image is read in any possible color format.

The function loads the image from the specified file, allocates the memory and returns the Mat object.

If the image cannot be read, the function returns an empty matrix (Mat::data==NULL).

Creating a new Mat object

We can create a Mat object also specifying its size (the number of rows and columns), the number of channels per cell and its initial value.

Mat A(int rows, int cols, int type, Scalar & s);

the type parameter is constructed according to the following convention:

CV_[number of bits per value][value Type]C[number of channels]
eg:
CV_8UC1   -  8  bit per channel, Unsigned char, 1 channel per cell
CV_8UC2   -  8  bit per channel, Unsigned char, 2 channels per cell
CV_8UC3   -  8  bit per channel, Unsigned char, 3 channels per cell
CV_8UC(n) -  8  bit per channel, Unsigned char, n channels per cell
CV_64FC1  -  64 bits per channel, float , 1 channel per cell
CV_64FC4  -  64 bits per channel, float , 4 channels per cell
CV_64FC(n)-  64 bits per channel, float , n channels per cell

The Scalar type s is an optional 4-element short vector value to initialize each matrix element with.

The type Scalar is widely used in OpenCV to pass pixel values.

Let’s see some examples:

Mat M(2,2, CV_8UC3, Scalar(0,0,255)); // creates a 2x2 matrix, each value is an 8 bit unsigned short, 3 channels for each cell, initialized to 0, 0 and 255.

Mat B(2,2, CV_8UC(1), Scalar::all(0));// creates a 3x3 matrix, each value is an 8 bit unsigned short, only 1 channel for each cell, initializing all cell values  to 0 value.

Other ways to create the Mat object

Three methods similar to the constructor seen above are Mat::zeros , Mat::ones and Mat::eye.

You can use these 3 functions specifying the number of rows, of columns and the type of the cell.

Mat A = Mat::zeros(2, 2, CV_8UC1); // sets all elements to 0
Mat B = Mat::ones(3, 3, CV_8UC1); // sets all elements to 1
Mat C = Mat::eye(4, 4, CV_8UC1); // sets all elements to 0, except the main diagonal to 1

The last method to create (small) matrices is using the « operator:

Mat A = (Mat_<int>(3,3) << 0, 1, 2, -1, 0, 1, 2, -1, -2);

Output

The Mat object can be inserted into the « operators to print the matrix to a stream.

Mat A = (Mat_<int>(2,2) << 0, 1, -1, -2);
std::cout << A << std::endl;

Save the matrix in an image file on the disk

To save a Mat object, creating an image file on the disk, use the imwrite function. Parametes are:

  • const String & filename - the file name (including the path) where to save the image
  • InputArray img - the object containing the matrix to save

Let’s check an example:

Mat A = (Mat_<int>(2,2) << 0, 1, -1, -2);
imwrite( "../../images/myIImage.jpg", A );

Accessing pixel values

To access to the intensity value of a pixel of the matrix, first you have to know the number of channels per pixel. In a simple grayscale image, there will be only 1 channel, while in a RGB color image there will be 3 channels per pixel.

On a single channel, for example a Mat object of type 8UC1, you can access the pixel value (0-255) in the following way:

Scalar intensity = matrix.at<uchar>(y, x);
Note: to maintain the usual math order (first the row, then the column number), you have to specify the y parameter before the x parameter

It can be very tricky, so you can use the Point object to prevent sneaky errors:

Scalar intensity = matrix.at<uchar>(Point(x, y));

You can also use this notation to change the value of a pixel:

matrix.at<uchar>(Point(x, y)) = 0;  // setting the pixel (x,y) to 0

On a 3-channel image, the way to access to each pixel and to the 3 values of each pixel (one per channel) is the following:

Vec3b intensity = matrix.at<Vec3b>(Point(x, y));
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];
Note: the RedGreenBlue order is the inverse of what you can expect

Of course, if the matrix type is not equals to 8UC1 you have to change the type of the variables representing each channel. For example, with data type CV_64FC1, the variables’ type will be:

Vec3f intensity = img.at<Vec3f>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

Splitting the RGB image

OpenCV provides the split() function to split the 3-channels RGB image into 3 Mat objects, one per channel. The parameters are the Mat object containing the source image and the vector of Mat objects, representing each RGB channel in reverse order, where the first is Blue, then Green and Red.

vector<Mat> bgr_channels;
split( image , bgr_channels );

Visualizing an image

To visualize an image on the screen, especially to check the results of your algorithm, OpenCV includes some very useful method for creating (namedWindow) and visualizing (imshow) a 8UC image.

Both methods will require, as the first parameter, a String containing the name of the window. Each window will be referenced by its name.

Let’s look at an example:

Mat matrix = imread("../data/image.jpg");
namedWindow("windowName", WINDOW_AUTOSIZE);
imshow("windowName", matrix);
waitKey(0);

waitKey(timeout) is a function waiting until a timeout for a key stroke. When pressing the key, the focus must be in the “windowName” window, otherwise it’s discarded.

Note 1: setting the timeout to 0, the function will wait undefinitively until the key stroke
Note 2: putting the waitKey function inside a loop, it will create a transition where the speed depends on the timeout time (lower timeout, higher speed)

In this first post about computer vision, and in particular about the usage of OpenCV library, we will use the Windows 7 operating system and the Visual Studio 2012 IDE. I’m assuming that you’ve got this IDE already installed.

Download and install OpenCV

First of all, we need to download and install the OpenCV library. You can find the already compiled packages here.

Once you have downloaded it, run the executable file. Select the directory where the library install. Note: to avoid the pain of the hell, DO NOT USE PATH WITH SPACES!!

Environment configurations

Now we have to set the environment variables. In particular, we add the OPENCV variable with value:

c:\opencv

If we decide to use static libraries into our C++ software, our environment variables configuration is already done.

If we want to use dynamic libraries (windows’ DLL), we have to specify to the operating system the location where to find them. We do it by adding to the PATH variable the OpenCV bin path:

%OPENCV%\build\x64\vc11\bin

Note: the vc11 compiler type is specific for Visual Studio 2012, vc10 for VS2010 and vc12 for later versions.

Visual Studio 2012 configurations

After setting all environment variables, we are ready to launch VisualStudio. First of all, we create a new Win32 Application project.

Once the project is created, we need to set the include path and the additional libraries path. Unfortunately we have to set these properties for each project. Visual Studio helps us to do quickly those things by creating a properties file the first time, save it and then load it for each project.

To do this, we need to switch from the Solution explorer window to Property manager. As we can see, there are two main directories: Debug and Release.

Right click on the former, Add new project Property sheet. Now go to C/C++ -> Additional Include Directories and add

$(OPENCV)\build\include

Then Linker -> General -> Additional Include Directories and add

$(OPENCV)\build\x64\vc11\lib

Finally, Linker -> Input -> Additional Dependencies and add:

opencv_world300d.lib

We can confirm the modifications and press the save icon.

We need to do the same thing for the Release directory too, with the only difference that consists in omitting the d letter at the end of each Additional Dependencies library (d is only for debug). The Additional Dependencies will be:

opencv_world300.lib

Doing these operations, we have created two properties files. We can load those files into every new project without specifying all the properties every time.

x64 configuration

Only if your system is 64 bit, you need to do the last configuration.

In the Properties windows, click the Configuration Manager… button. In the window that appears, click in the combobox under the Platform column, select the ****. In the **New platform** combobox, select **x64**. Confirm everything and your project is configurated to work into a 64 bit system.

*Note: this setting is to do for every project, since it’s not possible to save it into the Property Sheet.

Note: sometimes Visual Studio fails to compile although everything appears to be well configurated. Try to close and re-open the IDE: it will probably work again.

Here are the links to download the debug and release property sheets for Visual Studio 2012.

Python has a lot of powerful libraries. In this post we’ll use openpyxl, which allows you to work easily with Excel spreadsheets.

We will refer to the Python2 version of the library. It is also available for Python3 and should also be compatible with this one.

The full project documentation is available here.

The Excel formats currently supported by this module are:

  • .xlsx
  • .xlsm
  • .xltx
  • .xltm

Installing the library

First of all, we need to install the openpyxl module, so make sure you have installed a Python package management system.

In this post we will use pip. It comes already installed if your’re using Python 2 >= 2.7.9 or Python 3 >= 3.4. If it’s not installed yet, you can do it in your Linux system running:

sudo apt-get install pip

to install pip for Python2, or

sudo apt-get install pip3

for Python3.

After that, install the openpyxl library using pip:

pip install openpyxl

If you want to be able to include images into the Excel file, you have to install also the pillow module:

pip install pillow

Using the library

Shebang & importing

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from openpyxl import load_workbook

The second line is used to declare the UTF-8 encoding of the Python source file.

Opening the file

wb = load_workbook("excelFileName.xlsx" [, data_only=True])

Setting the data_only attribute to True, you will access to the values of the cells, otherwise you will access to the formula of the cell.

Selecting a sheet

To select the current sheet, use

sheet = wb.active

If you wnat to access to a specific sheet knowing its name, do

sheet = wb["D1_densa_WGS84_quota"]

Reading & writing a cell value

To read a cell value:

val = sheet["D2"].value

ws['D2'] = val

Saving the file

After the modifications apported to the file, remember to save the file:

wb.save('aFileName.xlsm')

Note that the file name used in save() function can be different to the file name used in open() function. In that case, it will create a new file, otherwise if the name is the same it will overwrite the old file.

Threating column letters as numbers

Working with letters to index a column can be difficult, expecially when you have to do with a lot of column. A simply solution is to call two functions which gives you the column index of a given letter or the column letter by a given index.

To use these functions, first you have to import them, and then you can invoke.

from openpyxl.cell import get_column_letter, column_index_from_string

colDIndex = column_index_from_string('D')
colLetter = get_column_letter(colIndex)

Getting the max col and row used

It’s useful sometimes to know the last row or column used in the current sheet.

To know these informations, you can use the functions:

maxRow= sheet.max_row
maxCol= sheet.max_column

Full example

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from openpyxl import load_workbook
from openpyxl.cell import get_column_letter, column_index_from_string

wb = load_workbook("name.xlsx")    #, data_only=True)

sheet = wb.active
# or sheet = wb["Sheet1"]

excelNorthCol = "A"
excelEastCol = "B"
rowIndex = 1
valueToWrite = 10


north = sheet["{0}{1}".format(excelNorthCol, str(rowIndex))].value # (sheet["A1"].value)
east = sheet["{0}{1}".format(excelEastCol, str(rowIndex))].value # (sheet["B1"].value)


maxCol = sheet.max_column
cell = get_column_letter(maxCol+1) + str(rowIndex)

# or, eventually:
# columnIndexToWrite = 3
# cell = get_column_letter(columnIndexToWrite) + str(rowIndex)

sheet[cell] = valueToWrite

wb.save("name.xlsx")