Basic OpenCV operations: dealing with regions

3 minute read

Hey there! In another post I already started talking about OpenCV usefulness and described an example of pixels manipulation. Let’s move forward: this time we will manipulate entire areas of an image. This must answer the second question.

It asks to swap the areas of the input picture. Consider an image cutted in four parts:

A B
C D

what we are going to do is swap the positions of the areas A, B, C and D diagonally. This we will lead to:

D C
B A

Let’s do the magic!

Code

We start including dependencies. Let’s use iostream and opencv to, respectively, inform the user about any issue that may appear (the image was not opened correctly) and manipulate the picture.

Let’s set up namespaces also. They prevent name conflicts and save lazy coders from typing too much.

#include <iostream>
#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;

Now that everything is fine we need to allocate memory to the original image. Images are matrices, so we are going to use OpenCV Mat class to do that.

int main(int argc, char** argv){
  Mat image;

Let’s get the image. It will be passed to our code during its call, and to know how to do that please read here. It’s important to break the process if image opening goes wrong, in order to avoid greater troubles, so return 0.

  // checking image reading
  image= imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);
  if(!image.data){
    cout << "image could not be opened" << endl;
    return 0;
  }

We love to see pictures. Let’s visualize what we’re working on! Notice namedWindow and imshow does basically the same, but I believe there must be a difference between them. The waitKey is pretty straight forward, and its inner working is well-documented.

  namedWindow("Original Image",WINDOW_AUTOSIZE);
  imshow("Original Image", image);
  waitKey();

We will create our collage using Regions of Interest (ROI). I chose this way of doing this due to some references, but there may be other ways of doing so. Anyway… this way requires we define rectangles (our collage is basically swapt rectangles, see?), and these rectangles need height and width information to be created. So… to get this data, we just need to divide the image rows and cols by two.

  int dim_x = image.rows/2;
  int dim_y = image.cols/2;

  cout<<"dim_x = "<<dim_x<<"; dim_y = "<< dim_y<<endl; 

Ok, now we must allocate memory to the processed image. The object processed_image receives a copy of image as its initialization.

  //creating clone image which will become the processed image
  Mat processed_image = image.clone();

Below I define the rectangular areas that captures the Regions of Interest. The Rect Class has four constructor parameters: the top left corner coordinates, the width and the height. If we consider the origin of the system at top left corner, the X axis points towards right and the Y axis points downwards.

  Rect A_area(0, 0, dim_x, dim_y);  
  Rect B_area(dim_x,0 ,dim_x, dim_y);
  Rect C_area(0 , dim_y, dim_x, dim_y);
  Rect D_area(dim_x , dim_y, dim_x, dim_y);

Now we define our four parts A, B, C and D using the rectangular areas. It means A, B, C and D are images, as well!

  Mat A = image(A_area);
  Mat B = image(B_area);
  Mat C = image(C_area);
  Mat D = image(D_area);

The final product is the original rectangle with the four little images copied.

  A.copyTo(processed_image(D_area));
  B.copyTo(processed_image(C_area));
  C.copyTo(processed_image(B_area));
  D.copyTo(processed_image(A_area));

The process is done! We just need to show the processed picture.

  namedWindow("Processed Image",WINDOW_AUTOSIZE);
  imshow("Processed Image", processed_image);

  waitKey();


  return 0;
}

Example

One example of code run can be seen below.

And here we can see, at the left, the original image, and at the right, the processed one.

Original and Processed images.

Conclusion

The code explained in this post can be found here. There may be some trash I didn’t removed. Anyway… thanks for reading!