Patrick.SE
Patrick.SE

Reputation: 4564

Tiling a small image into a bigger one with OpenCV

Let's say I have an image of 200x200 pixels. I'd like a 800x800 pixels version where I basically duplicate the 200x200 image and fill the 800x800 image with(Tile the smaller image into the bigger one).

How would you go to do that in openCV? It seems straight-forward, but I don't know how to either create another cv::Mat with the same type as the pattern, but with a bigger size(Canvas size) or if it's possible to take the original 200x200 pixels image and increase it's rows and cols then simply use a loop to paste the corner unto the rest of the image.

I'm using openCV 2.3 btw. I've done quite some processing on images with fixed dimensions, but I'm kind of clueless when it comes to increasing the dimensions of the matrix.

Upvotes: 4

Views: 6723

Answers (3)

Amir Forsati
Amir Forsati

Reputation: 5960

You can use tile function:

def tile_image(tile, height, width):      
  x_count = int(width / tile.shape[0]) + 1
  y_count = int(height / tile.shape[1]) + 1

  tiled = np.tile(tile, (y_count, x_count, 1))

  return tiled[0:height, 0:width]

Upvotes: 1

Hui Liu
Hui Liu

Reputation: 407

In C++, you can just do something like this:

cvx::Mat CreateLargeImage(const cvx::Mat& small, int new_rows, int new_cols) {
  // Create a Mat of the desired size, the mat may also be created by resizing of the smaller one.
  cvx::Mat result(new_rows, new_cols, 16);
  const int sm_rows = small.rows;
  const int sm_cols = small.cols;
  for (int r = 0; r < result.rows; ++r) {
    for (int c = 0; c < result.cols; ++c) {
        // use mod operation to effectively repeat the small Mat to the desired size.
        result.at<cvx::Vec3b>(r, c)[0] =
            small.at<cvx::Vec3b>(r % sm_rows, c % sm_cols)[0];
        result.at<cvx::Vec3b>(r, c)[1] =
            small.at<cvx::Vec3b>(r % sm_rows, c % sm_cols)[1];
        result.at<cvx::Vec3b>(r, c)[2] =
            small.at<cvx::Vec3b>(r % sm_rows, c % sm_cols)[2];
    }
  }
  return result;
}

Or you may use openCV's repeat function. e.g,

in Python

import cv2
...
duplicated = cv2.repeat(original, 4, 4)

in C++

 cv::Mat original= cv::imread("./benz.jpeg");
 cv::Mat duplicated;

 cv::repeat(original, 4, 4, duplicated);

Upvotes: 1

user650654
user650654

Reputation: 6128

FYI- The blog in @karlphillip's response, the basic idea is to use cvSetImageROI and cvResetImageROI. Both are C APIs.

In later versions, v2.4 and 3.x for example, one can define a Rect with the desired location and dimensions and refer to the desired section as img(rect).

Example in C API (functional style):

cvSetImageROI(new_img, cvRect(tlx, tly, width, height);
cvCopy(old_img, new_img);
cvResetImageROI(new_img);

In the C++ API using classes:

Mat roi(new_img, Rect(tlx, tly, width, height));
roi = old_img;    // or old_img.clone()

Another way in C++ (copies over the image):

old_img.copyTo(new_img(Rect(tlx, tly, width, height)))

Upvotes: 0

Related Questions