0

I have to process a .PNG file. The processing takes an std::vector as input and I would like to show the images as grayscale. So what I did:

Mat img = imread("Image.PNG");
cvtColor(img, img, COLOR_RGB2GRAY);
imshow(windowName,img); 

This image looks fine and cout<<img<<endl; spits out realistic values between 0 and 255. Then I want to convert this cv::Mat to an std::vector

std::vector<double> imgvec;
imgvec.assign(img.begin<double>(), img.end<double>());

The values are now all really small (around 1e-180). Why does this happen and how can I solve it?

UPDATE:

I tried the following as suggested by @Swift-Friday Pie:

std::vector<double> imgvec;
if (img.isContinuous()){
    imgvec.assign((double*)img.datastart, (double*)img.dataend);
}else{
    for (int i = 0; i < img.rows; i++){
        imgvec.insert(imgvec.end(), img.ptr<double>(i) + img.cols);
    }
}

However, this given me the following error:

no matching function for call to 'std::vector<double>::insert(std::vector<double>::iterator, double*)'
user7845839
  • 23
  • 1
  • 2
  • 9
  • Why are you using `double` if you need `unsigned char`? – zindarod May 23 '18 at 11:16
  • @zindarod Because the processing part is an external library that takes `std::vector` as input – user7845839 May 23 '18 at 11:18
  • The first `if` branch in your update is definitely incorrect. `img` does not store data in double format, so reading the data bytes as if they were doubles will produce garbage. I suspect that this is the same problem with `img.begin()` but I don't know the OpenCV iterators enough to say for sure. The same mistake happens in the second branch, except you're trying to write the pointer to the data into the vector (instead of the data that it points to). – Max Langhof May 23 '18 at 11:38

2 Answers2

1

You haven't pass the right parameters to insert function it takes three parameters. So the updated code will be,

 std::vector<double> imgvec;
if (palette.isContinuous()) {
    imgvec.assign(palette.datastart, palette.dataend);  // No need to typecast to double * 
}
else {
    for (int i = 0; i < palette.rows; i++) {
        imgvec.insert(imgvec.end(), palette.ptr<double>(i),palette.ptr<double>(i) + palette.cols);
    }
}

The error in your code is about the typecasting to double*

Lakshraj
  • 291
  • 2
  • 18
  • 1
    There are, in fact, [four overloads](http://en.cppreference.com/w/cpp/container/vector/insert) of `std::vector::insert` taking two parameters (and none taking four parameters) – hlt May 23 '18 at 11:24
  • Oh Sorry three parameters – Lakshraj May 23 '18 at 11:26
1

I would do it like that, could you give it a try?

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


template <typename T, typename ... Ts>
void insert_all(std::vector<T> &vec, Ts ... ts)
{
   (vec.push_back(ts), ...);
}

int main ()
{
 cv::Mat img = cv::imread("Image.PNG");
 cv::cvtColor(img, img, cv::COLOR_RGB2GRAY);
 std::vector<cv::Mat> imgvec;
 imgvec.reserve(1);
 insert_all(imgvec, img);
} 

g++ -std=c++17 test.cpp -o test `pkg-config --cflags --libs opencv`
Ja_cpp
  • 2,426
  • 7
  • 27
  • 49
  • When I implement the code as you wrote it, I get the following errors: `MainConfMap.cpp: In function ‘void insert_all(std::vector<_Tp>&, Ts ...)’: MainConfMap.cpp:19:22: error: expected primary-expression before ‘...’ token MainConfMap.cpp:19:22: error: expected ‘)’ before ‘...’ token MainConfMap.cpp:19:26: error: parameter packs not expanded with ‘...’: MainConfMap.cpp:19:26: note: ‘ts’ ` – user7845839 May 23 '18 at 12:50
  • I used fold-expressions which is only available in c++17. So make sure you're compiling with std=c++17 – Ja_cpp May 23 '18 at 13:09