-1

I'm using OpenCV (v 2.4.9.1, Ubuntu 16.04) to do a resize and crop on an image, the original image is a JPEG file with dimensions 640x480.

cv::Mat _aspect_preserving_resize(const cv::Mat& image, int target_width)
{
    cv::Mat output;
    int min_dim = ( image.cols >= image.rows ) ? image.rows : image.cols;
    float scale = ( ( float ) target_width ) / min_dim;
    cv::resize( image, output, cv::Size(int(image.cols*scale), int(image.rows*scale)));
    return output;
}

cv::Mat _center_crop(cv::Mat& image, cv::Size& input_size) 
{
    cv::Rect myROI(int(image.cols/2-input_size.width/2), int(image.rows/2-input_size.height/2), input_size.width, input_size.height);
    cv::Mat croppedImage = image(myROI);
    return croppedImage;
}

int min_input_size = int(input_size.height * 1.14);
cv::Mat image = cv::imread("power-dril/47105738371_72f83eeb37_z.jpg");
cv::Mat output = _aspect_preserving_resize(image, min_input_size);
cv::Mat result = _center_crop(output, input_size);

After this I display the images, and it looks perfect - as I would expect it to be:

enter image description here

The problem comes when I stream this image, where I notice that the size (in elements) of the cropped image is only a third of what I would expect. It looks as if there is only one cannel on the resultant crop. It should have had 224*224*3=150528, but I'm getting only 50176 when I'm doing

std::cout << cropped_image.total() << " " << cropped_image.type() << endl;
>>> 50176 16

Any idea what's wrong here? The type of the resulting cv::Mat looks okay, and also visually it looks ok, so how there is only one channel?

Thanks in advance.

stateMachine
  • 5,227
  • 4
  • 13
  • 29
Nadav
  • 563
  • 3
  • 17

2 Answers2

0

Basic Structures — OpenCV 2.4.13.7 documentation says:

Mat::total

Returns the total number of array elements.

C++: size_t Mat::total() const

The method returns the number of array elements (a number of pixels if the array represents an image).

Therefore, the return value is the number of pixels 224*224=50176 and your expected value is wrong.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • Thanks @MikeCAT, when I print the the ```total()``` before cropping I do get the value that I expect. Is there a way to save\keep\retain the data cahnnel-wise? EDIT: When I call ```channels()``` I do get ```3```. – Nadav Jun 28 '20 at 09:10
0

My terminology was wrong, as pointed by @MikeCAT, and it seems that the issue should be solved in the serialization logic. I went with a solution along the lines of this one: Convert Mat to Array/Vector in OpenCV

My original code didn't check the channels() function.

if (curr_img.isContinuous()) {
    int totalsz = curr_img.dataend-curr_img.datastart;
    array.assign(curr_img.datastart, curr_img.datastart + totalsz);
} else {
    int rowsz = CV_ELEM_SIZE(curr_img.type()) * curr_img.cols;
    for (int i = 0; i < curr_img.rows; ++i) {
        array.insert(array.end(), curr_img.ptr<uint8_t>(i), curr_img.ptr<uint8_t>(i) + rowsz);
    }
}
Nadav
  • 563
  • 3
  • 17