Suppose I have a Mat variable small_image with dimensions 98x158x32 (type float). Now I want to zero pad this image (ie. add a border of zeros to the image). I want to add 7 zeros above and below the image, and 12 zeros left and right of the image. The first idea was to use the cv copyMakeBorder (see copyMakeBorder doc), which seems perfect for this:
int old_size[3];
old_size[0] = 98;
old_size[1] = 158;
old_size[2] = 32;
int pad_size[3];
pad_size[0] = old_size[0] + 2 * 7;
pad_size[1] = old_size[1] + 2 * 12;
pad_size[2] = old_size[2];
cv::Mat image_padded(3, pad_size, CV_32FC1, cv::Scalar(0)); //Initialize the larger Mat to 0
copyMakeBorder(small_image,image_padded,7,7,12,12,BORDER_CONSTANT,Scalar(0));
However, this code gives a memcopy error. Does anyone see the problem here?
The alternative as described in this post does not work either:
cv::Rect roi( cv::Point( 12, 7 ), small_image.size() );
small_image.copyTo( image_padded( roi ) );
It claims that "Assertion failed (m.dims <= 2)", while both Mat variables are 3D matrices.
Any help to achieve the zero padding would be greatly appreciated!
Neither of the methods you described work since they are meant to be used for 2D matrices. You have a 3D Mat which requires that you specify ranges in all three dimensions. You can use the ()
operator which works with an array of ranges combined with copyTo
as in the example below.
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
int main()
{
int old_size[3];
old_size[0] = 5;
old_size[1] = 5;
old_size[2] = 2;
int pad_size[3];
pad_size[0] = old_size[0] + 2 * 1;
pad_size[1] = old_size[1] + 2 * 2;
pad_size[2] = old_size[2];
cv::Mat small_image(3, old_size, CV_32FC1, cv::Scalar(1));
cv::Mat image_padded(3, pad_size, CV_32FC1, cv::Scalar(0));
cv::Range ranges[3];
ranges[0] = cv::Range(1, old_size[0]+1);
ranges[1] = cv::Range(2, old_size[1]+2);
ranges[2] = cv::Range(0, old_size[2]);
small_image.copyTo(image_padded(ranges));
for (int i = 0; i < pad_size[0]; i++)
for (int j = 0; j < pad_size[1]; j++)
for (int k = 0; k < pad_size[2]; k++)
std::cout << image_padded.at<float>(i, j, k) << ", ";
}
which will give:
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With