2

I am trying to read an RGB image and convert it to 1D array. When printing the values, I understand that the logic I have written for conversion is not correct. Can someone help me with this please? Also, when I am trying to define image_array, it is giving me an error.

Expression must have constant value.

I have posted the code below.

//reading the images
Mat img_rev = imread("C:/Users/20181217/Desktop/images/imgs/output_rev.png");
cvtColor(img_rev, img_rev, COLOR_BGR2RGB);
//get the image height,width and number of channles to convert into an array
int const img_height = img_rev.rows;
int const img_width = img_rev.cols;
int const img_channels = img_rev.channels();
//printing out the dimenesions
cout << img_height << ", " << img_width << ", " << img_channels; //256,512,3
//starting the conversion to array
uchar image_array[256 * 512 * 3];
//uchar image_array[img_rev.rows * img_rev.cols * img_rev.channels()]; error:expression must have a constant value
//uchar image_array[img_height * img_width * img_channels]; error:expression must have a constant value

for (int i = 0; i < img_rev.rows; i++)
{
    for (int j = 0; j < img_rev.cols; j++)
    {
        if(i==200 && j==200)
            cout << endl << "value at (200,200) of green in MAT is :" << (int)img_rev.at<Vec3b>(i, j)[1] << endl; //printing the value at (200,200) of green channel
    }
}

//conversion from image to 1d array
for (int i = 0; i < img_rev.rows; i++)
{
    for (int j = 0; j < img_rev.cols; j++)
    {
        image_array[(i*img_rev.rows) + (j * 3)] = img_rev.at<Vec3b>(i, j)[0]; //R  
        image_array[(i*img_rev.rows) + (j * 3) + 1] = img_rev.at<Vec3b>(i, j)[1]; //G
        image_array[(i*img_rev.rows) + (j * 3) + 2] = img_rev.at<Vec3b>(i, j)[2]; //B
    }
}
cout << endl << "value at (200,200) of green in array is :" << (int)image_array[(200*img_rev.cols) + 200 +1];
cout << endl << "done";
waitKey(100000);

I would be really grateful if someone can provide me some assistance with this. Thanks in advance.

Burak
  • 2,251
  • 1
  • 16
  • 33

1 Answers1

3

If the array does not have a fixed-size, like in your example, you should use dynamically allocated array. Declaring uchar* image_array = new uchar[img_rev.total() * img_rev.channels()] can be a solution but you need to delete it manually to free memory when it is used no more.

In order not to deal with keeping track of deletion, I suggest using std::vector.

std::vector<uchar> image_array(img_rev.total() * img_rev.channels());

And you can use your method once the array is dynamically allocated.


There is an easier method for converting cv::Mat to std::vector. In you case, since img_rev is created by imread, we are sure that the data is continuous, so we can do the following:

std::vector<uchar> image_array = img_rev.data;
Burak
  • 2,251
  • 1
  • 16
  • 33
  • Thank you for your suggestions, it helped. Also can you please provide some suggestions for the second part of the question on how to access a 3d array as 1d array – mutyala mahesh Jul 21 '20 at 13:33
  • There is a member function named `reshape` for Mat class. You can use it to turn a 3D image into 1D. I bet that question is already asked. You can find it on this site. – Burak Jul 21 '20 at 15:48
  • @AnoopKrishna There is another answer from the link converting Mat to vector, which says [it can be done in two lines](https://stackoverflow.com/questions/26681713/convert-mat-to-array-vector-in-opencv#answer-56600115). It uses `reshape`. – Burak Jul 23 '20 at 09:04