# Tutorial: Element-Wise Matrix Operations in OpenCV

## Table of Contents

Element-wise matrix operations are mathematical functions and algorithms in computer vision that work on individual elements of a matrix or, in other words, pixels of an image. It's important to note that element-wise operations can be parallelized, which fundamentally means that the order in which the elements of a matrix are processed is not important.

## 1. Basic operations

OpenCV provides all the necessary functions and overloaded operators that you need to perform all four basic operations of addition, subtraction, multiplication, and division between two matrices or a matrix and a scalar.

### 1.1. The addition operation

The `add`

function and the `+`

operator can be used to add the
elements of two matrices, or a matrix and a scalar, as shown in the
following examples:

Mat image = imread("Test.png"); Mat overlay = imread("Overlay.png"); Mat result; add(image, overlay, result);

You can replace the last line in the preceding code with the following:

result = image + overlay;

The following image demonstrates the resulting image of an add operation of two images:

In case, you want to add a single scalar value to all elements of a
`Mat`

object, you can simply use something similar to the
following:

result = image + 80;

Once the above code is executed on a grayscale image, the result will be brighter than the source image. Note that if the image has three channels, you must use a three-item vector instead of a single value. For instance, to be able to make an RGB image brighter, you can use the following:

result = image + Vec3b(80, 80, 80);

Here's the image transformation when the above code is executed on it:

In the above example codes, simply increase the added value to get an even brighter image.

### 1.2. Weighted addition

Besides the simple addition of two images, you can also use the
weighted addition function to consider a weight for each of the two
images that are being added. Think of it as setting an opacity
level for each of the participants in an `add`

operation. To
perform a weighted addition, you can use the `addWeighted`

function:

double alpha = 1.0; // First image weight double beta = 0.30; // Second image weight double gamma = 0.0; // Added to the sum addWeighted(image, alpha, overlay, beta, gamma, result);

If executed on the sample pictures from the previous section with the add example, the result would be similar to the following:

Notice the transparent text that is similar to the watermark
usually applied by photo-editing applications. Notice the comments
in the code regarding the `alpha`

, `beta`

, and `gamma`

values?
Obviously, providing a `beta`

value of `1.0`

would have made this
example exactly the same as a regular `add`

function with no
transparency for the overlay text.

### 1.3. The subtraction operation

Similar to adding two `Mat`

objects to each other, you can also
`subtract`

all elements of one image from another using the
subtract function or the `-`

operator. Here's an example:

Mat image = imread("Test.png"); Mat overlay = imread("Overlay.png"); Mat result; subtract(image, overlay, result);

The last line in the preceding code can also be replaced with this:

result = image - overlay;

Here's the result of the subtraction operation:

Notice how the subtraction of higher pixel values (brighter pixels) from the source image results in the dark color of the overlay text. Also note that the subtraction operation depends on the order of its operands, unlike addition. Try swapping the operands and see what happens for yourself.

Just like addition, it's also possible to multiply a constant number with all of the pixels of an image. You can guess that the subtraction of a constant value from all pixels will result in a darker image (depending on the subtracted value) which is the opposite of the addition operation. Here's an example of making an image darker with a simple subtraction operation:

result = image - 80;

In case the source image is a three-channel RGB image, you need to use a vector as the second operand:

result = image - Vec3b(80, 80, 80);

### 1.4. The multiplication and division operations

Similar to addition and subtraction, you can also multiply all
elements of a `Mat`

object with all elements of another `Mat`

object. The same can be done with the division operation. Again,
both operations can be performed with a matrix and a
scalar. Multiplication can be done using OpenCV's `multiply`

function (similar to the `Mat::mul`

function), while division can
be performed using the `divide`

function.

Here are some examples:

double scale = 1.25; multiply(imageA, imageB, result1, scale); divide(imageA, imageB, result2, scale);

`scale`

in the above code is an additional parameter that can be
supplied to the `multiply`

and `divide`

functions to scale all of
the elements in the resulting `Mat`

object. You can also perform
multiplication or division with a scalar, as seen in the following
examples:

resultBrighter = image * 5; resultDarker = image / 5;

Obviously, the above code will produce two images, one that is five times brighter and one that is five times darker than the original image.

The important thing to note here is that, unlike addition and subtraction, the resulting image will not be homogeneously brighter or darker, and you'll notice that brighter areas become much brighter and vice versa.

The reason for this is obviously the effect of multiplication and division operations, in which the value of brighter pixels grows or drops much faster than smaller values after the operation. It's interesting to note that this same technique is used in most photo-editing applications to brighten or darken the bright areas of an image.

## 2. Bitwise logical operations

Just like basic operations, you can also perform bitwise logical operations on all of the elements of two matrices or a matrix and a scalar. For this reason, you can use the following functions:

`bitwise_not`

`bitwise_and`

`bitwise_or`

`bitwise_xor`

It's immediately recognizable from their names that these functions
can perform `Not`

, `And`

, `Or`

, and `Exclusive OR`

operations.

First thing’s first, the `bitwise_not`

function is used to invert
all the bits of all the pixels in an image. This function has the
same effect as the inversion operation that can be found in most
photo editing applications. Here's how it's used:

bitwise_not(image, result);

The above code can be replaced with the following too, which uses an
overloaded bitwise `not`

operator (`~`

) in C++:

result = ~image;

If the image is a monochrome black and white image, the result will contain an image with all white pixels replaced with black and vice versa. In case the image is an RGB color image, the result will be inverted (in the sense of its binary pixel values), which is depicted in the following image:

The `bitwise_and`

function, or the `&`

operator, is used to perform
a bitwise `And`

operation on pixels from two images or on pixels
from an image and a scalar. Here is an example:

bitwise_and(image, mask, result);

You can simply use the `&`

operator and write the following instead:

result = image & mask;

The `bitwise_and`

function can be easily used to mask and extract
certain areas in images. For instance, the following image is a
demonstration of how `bitwise_and`

results in an image that passes
the white pixels and removes the black pixels:

Besides masking certain areas of an image, the bitwise `And`

operation can be used to filter out a channel altogether. To be able
to do this, you need to use the second form of the `&`

operator,
which takes a matrix and a scalar, and performs the `And`

operation
between all pixels and that value. Here is an example code that can
be used to mask (zero out) the green color channel in an RGB color
image:

result = image & Vec3b(0xFF, 0x00, 0xFF);

It’s time to move on to the next bitwise operation, the `Or`

operation. The `bitwise_or`

and `|`

operators can both be used to
perform a bitwise `Or`

operation on two images, or an image and a
scalar. Here is an example:

bitwise_or(image, mask, result);

You can use the `|`

operator in the `Or`

operation and simply write
the following instead of the above code:

result = image | mask;

If the `And`

operation was used to pass through the non-zero pixels
(or non-black pixels), then it can be said that the `Or`

operation
is used to pass through the pixel with the higher value (or
brighter) in any of its input images. Here's the result of
performing the bitwise `Or`

operation:

Similar to the bitwise `And`

operation, you can also use bitwise
`Or`

operation to update an individual channel or all the pixels of
an image. Here is an example that shows how you can update only the
green channel in an RGB image to have the maximum possible value
(which is 255, or hexadecimal `FF`

) in all of its pixels and leave
the other channels as they are:

result = image | Vec3b(0x00, 0xFF, 0x00);

Finally, you can use `bitwise_xor`

, or the `^`

operator to perform
an `Exclusive Or`

between the pixels of two images, or an image and
a scalar. Here is an example:

bitwise_xor(image, mask, result);

Or simply use the `^`

operator and write the following instead:

result = image ^ mask;

Here is the resulting image, if the `Exclusive Or`

operation is
performed on the example image from the preceding section:

Notice how this operation leads to the inversion of the pixels in
the masked area? Think about the reason behind this by writing down
the pixel values on a paper and trying to calculate the result by
yourself. `Exclusive Or`

, and all bitwise operations, can be used
for many other computer vision tasks if their behavior is clearly
understood.

## 3. Furthermore

If you found this article helpful and want to learn computer vision in more detail, you can explore Hands-On Algorithms for Computer Vision. I(KDr2) worked as the technical reviewer for this book. Packed with various hands-on computer vision examples, the book teaches you how to use the best and most popular computer vision algorithms using OpenCV. The author of the book, Amin Ahmadi Tazehkandi, is a computer vision expert, and this tutorial is also by him.

## 4. Discuss and Comment

Have few questions or feedback? Feel free to send me(killian.zhuo📧gmail.com) an email!