-1

i'm learning c++ api of opencv, and for a simple approach i've started with try to downsample image (ok i know that there is pyrDown with gaussian resampling but it's for learning how to access element in Mat class)

this is my code:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

#define original_window "original"
#define manual_window "manual"

using namespace cv;
using namespace std;

Mat img, manual;

void downsample(Mat src, Mat &dst, const Size& s) {
    float factor = src.rows/(float)s.width;
    Mat_<Vec3f> _dst = Mat(s, src.type());
    Mat_<Vec3f> _src = src;
    for(int i=0; i<src.cols; i+=factor) {
        int _i = i/factor;
        for(int j=0; j<src.rows; j+=factor) {
            int _j = j/factor;
            _dst (_j, _i) = _src(j,i);
        }
    }
    cout << "downsample image size: " << _dst.rows << " " << _dst.cols << endl;
    dst = Mat(_dst);
}


int main(int /*argc*/, char** /*argv*/) {

    img = imread("lena.jpg"); 
    cout << "original image size: " << img.rows << " " << img.cols << endl;

    downsample(img, manual, Size(img.cols/2, img.rows/2));

    namedWindow(original_window, CV_WINDOW_AUTOSIZE);
    namedWindow(manual_window, CV_WINDOW_AUTOSIZE);

    while( true )
    {
        char c = (char)waitKey(10);
        
        if( c == 27 )
          { break; }
        
        imshow( original_window, img );
        imshow( manual_window, manual );
    }
        
    return 0;
}

now, i'm doing a downsampling in a fool way: i'm just deleting elements. and i'm try to use c++ api with Mat_.

in manual window i get a white window, and i don't understand why. event if i try to cout manual i'seeing different values.. what's wrong with this piece of code?

EDIT 1

i've found a solution:

dst.convertTo(dst, src.type()); // in this particular case: src.type() == CV_8UC3 

at the end of downsample()

now my question is: why that? i declare Mat(s, src.type()); why it is modified?

EDIT 2

if i use @go4sri answer with this line

_dst (_j, _i) = src.at<Vec3f>(j, i);

i get this output: enter image description here

i really does not understand why..

Community
  • 1
  • 1
nkint
  • 11,513
  • 31
  • 103
  • 174

1 Answers1

1

The way to access an element in OpenCV's Mat is as follows:

for a single channel matrix(tmp)

Matrix_Name.at<dataType>(row, col)

For a three channel matrix( as is the case for a color image), you will need to use the Vec3b/Vec3f type depending upon if yours is a unsigned char/float matrix.

As yours is a unsigned char 3Dimensional matrix: you will have to access it as src.at<Vec3b>(i, j)

Your downsample should have been:

void downsample(const Mat& src, Mat &dst, const Size& s) {
    float factor = src.rows/(float)s.height;
    Mat _dst = Mat(s, src.type());

    for(int i=0; i < src.cols; i += factor) {
        int _i = i/factor;
        for(int j=0; j<src.rows; j+=factor) {
            int _j = j/factor;
            _dst.at<Vec3b> (_j, _i) = src.at<Vec3b>(j, i);
        }
    }
    cout << "downsample image size: " << _dst.rows << " " << _dst.cols << endl;
    dst = Mat(_dst);
}
go4sri
  • 1,490
  • 2
  • 15
  • 29
  • sorry but with your `src.at(i, j)` i get strange result, see the edit – nkint Jul 13 '12 at 11:00
  • That is because, I did not look at your main function earlier. your data type is unsigned char and not float. Moreover, _rows_ correspond to _height_ - not the width of the image!! See the edited answer. – go4sri Jul 13 '12 at 12:37
  • have you tried the code you post me? i'm using lena.jpg of opencv official examples, same result – nkint Jul 13 '12 at 13:13
  • Yes, I did try it and it did resize to the dimensions. – go4sri Jul 13 '12 at 13:14