Ask Your Question
1

Convert std::vector<double> to Mat and show the image

asked 2016-01-02 17:58:34 -0500

updated 2016-01-03 07:58:49 -0500

I have a std::vector<double> which contains pixel values calculated from somewhere else. Now I want to convert this to a Mat type and show it. But I faced some problems...only some part of the resulted image looks find and the rest seems to be corrupted. Can you please tell me what am I doing wrong?

image description

Here is my code:

void convertMeanVectorToImageAndShow(cv::Size size, int type
                                     , PedRec::mean_vector *vector
                                     , QString windowName) {

    cv::Mat mat;
    mat.create(size.height, size.width, type);

    int rows = mat.rows;
    int cols = mat.cols;

    if (mat.isContinuous()) {
        cols = rows*cols;
        rows = 1;
    } 

    for (int r = 0; r < rows; ++r)
    {
        uchar *pOutput = mat.ptr<uchar>(r);

        for (int c = 0; c < cols; ++c)
        {
            *pOutput = (uchar)vector->at(c);
            ++pOutput;
        }
    }

    cv::imshow(windowName.toStdString(), mat);
}

UPDATE Thanks to @theodore , now I at least get a non-corrupted image.

uchar pv[vector->size()];
for(unsigned int i = 0; i < vector->size(); i++) {
    pv[i] = (uchar) vector->at(i);
}

cv::Mat out(size, CV_8UC1);
memcpy(out.data, &pv, vector->size());

cv::imshow(windowName.toStdString(), out);

But it is different than what I expect. In fact what I am doing is getting the mean value of 6000 pedestrian images and the resulted image should at least in theory look like a pedestrian. But this is what I get:

image description

If you compare this with what I had in the begging of my question, this does not look like a pedestrain. the top of the my first image looks like a head and body of a pedestrian. I guess there is something wrong with the type CV_8UC1 ? because my original images are pmg GrayScale. for example:

Type of these images are (int) 16

image description

edit retag flag offensive close merge delete

Comments

1

is it a vector<double> as you state in the title or vector<uchar> as you state in the post?

theodore gravatar imagetheodore ( 2016-01-02 19:31:46 -0500 )edit

@theodore yes infact it is double but the cast to uchar wouldn't make any difference at the end, right?

Sean87 gravatar imageSean87 ( 2016-01-03 07:02:57 -0500 )edit

well it depends on the values that you have as double.

theodore gravatar imagetheodore ( 2016-01-03 07:20:44 -0500 )edit

@theodore Thanks, using your code I get a better looking image. I am pretty sure my double values are between [0, 255]. Can you check my updated question please?

Sean87 gravatar imageSean87 ( 2016-01-03 07:38:27 -0500 )edit

@Sean87 change the line memcpy(out.data, &pv, vector->size()); to memcpy(out.data, &pv, vector->size()*sizeof(uchar));

theodore gravatar imagetheodore ( 2016-01-03 09:27:10 -0500 )edit

2 answers

Sort by ยป oldest newest most voted
4

answered 2016-01-02 19:40:30 -0500

theodore gravatar image

updated 2016-01-02 19:42:01 -0500

In any case you can try the following:

//create Mat from vector
vector<uchar> vec; // vector with your data
int rows = 3;
int cols = 4;

if(vec.size() == rows*cols) // check that the rows and cols match the size of your vector
{
    Mat m = Mat(rows, cols, CV_8UC1); // initialize matrix of uchar of 1-channel where you will store vec data
    //copy vector to mat
    memcpy(m.data, vec.data(), vec.size()*sizeof(uchar)); // change uchar to any type of data values that you want to use instead
}

the above code should do the trick.

edit flag offensive delete link more

Comments

Thanks, your answer took care of my problem with converting the array. guess my own code was ok, the problem was type of the image. the original image type is 16 and I think I read the original image data not correctly. please see my update if you have any comments. I will make a new question anyway.

Sean87 gravatar imageSean87 ( 2016-01-03 08:40:27 -0500 )edit
1

try to read the image with the options CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR in the imread() to correctly read the images

theodore gravatar imagetheodore ( 2016-01-03 11:00:25 -0500 )edit

@theodore thanks thanks thanks! that did the trick!!!

Sean87 gravatar imageSean87 ( 2016-01-03 12:45:32 -0500 )edit

This solution only works for c++11....

jaquense gravatar imagejaquense ( 2017-02-12 15:16:07 -0500 )edit

This is a clear and concise solution using the built-in cvMat constructor. Thx!

Overmind735 gravatar imageOvermind735 ( 2019-03-06 12:32:10 -0500 )edit
3

answered 2016-01-03 08:50:45 -0500

try this code. i think it shows you a simpler way.

#include "highgui.hpp"

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    vector<double> testVector;

    for( int i = 0; i < 65536; i++)
    {
        testVector.push_back( i % 256 );
    }

    Mat testMat = Mat( testVector ).reshape( 0, 256 );

    testMat.convertTo( testMat, CV_8UC1 );

    imshow("testMat",testMat);
    waitKey();
}
edit flag offensive delete link more

Comments

nice approach ;-)

theodore gravatar imagetheodore ( 2016-01-03 14:03:07 -0500 )edit

yep...very interesting!

Sean87 gravatar imageSean87 ( 2016-01-03 14:43:31 -0500 )edit

But how would this understand the size of image I want to make??

Sean87 gravatar imageSean87 ( 2016-01-03 15:01:24 -0500 )edit
2

@Sean87 if you notice the second parameter of .reshape() is number of rows, and that's the only info that you need since internally .reshape() will figure out the number of cols according to the number of rows that you have given. Plus you need the number of channels(first parameter) if you want a multichannel Mat.

theodore gravatar imagetheodore ( 2016-01-03 15:08:22 -0500 )edit
1
sturkmen gravatar imagesturkmen ( 2016-01-03 15:17:27 -0500 )edit
Login/Signup to Answer

Question Tools

2 followers

Stats

Asked: 2016-01-02 17:58:34 -0500

Seen: 21,828 times

Last updated: Jan 03 '16