4
votes

I am working with images in C++ with OpenCV.

I wrote code with an uchar array of two dimensions where I can read pixel values of an image, uploaded with imread in grayscale using .at< uchar>(i,j).

However I would like to do the same thing for color images. Since I know that to access the pixels values I now need .at< Vec3b>(i,j)[0], .at< Vec3b>(i,j)[1] and .at< Vec3b>(i,j)[2], I made a similar Vec3b 2d arrays.

But I don't know how to fill this array with the pixel values. It has to be a 2D array.

I tried:

array[width][height].val[0]=img.at< Vec3b>(i,j)[0]

but that didn't work.

Didn't find an answer on the OpenCV doc or here neither.

Anybody has an idea?

I've included some of my code. I need an array because I already have my whole algorithm working, using an array, for the images in grayscale with only one channel.

The grayscale code is like that:

for(int i=0;i<height;i++){
    for(int j=0;j<width;j++){
        image_data[i*width+j]=all_images[nb_image-1].at< uchar>(i,j);
    }
}

Where I read from:

std::vector< cv::Mat> all_images

each image (I have a long sequence), retrieves the pixel values in the uchar array image_data, and processes them.

I want now to do the same but for RGB images, and I can't manage to read the data pixel of each channel and put them in an array.

This time image_data is a Vec3b array, and the code I'm trying looks like this:

for(int i=0;i<height;i++){
    for(int j=0;j<width;j++){
        image_data[0][i*width+j]=all_images[nb_image-1].at<cv::Vec3b>(i,j)[2];
        image_data[1][i*width+j]=all_images[nb_image-1].at<cv::Vec3b>(i,j)[1];
        image_data[2][i*width+j]=all_images[nb_image-1].at<cv::Vec3b>(i,j)[0];
    }
}

But this doesn't work, so I am now at loss I don't know how to succeed to fill the image_data array with the values of all three channels, without changing the code structure as this array is then used on my image processing algorithm.

3

3 Answers

2
votes

Here is the code I just tested, and it works.

#include <iostream>
#include <cstdlib>
#include <opencv/cv.h>
#include <opencv/highgui.h>

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

  cv::Mat img = cv::imread("image.jpg",1);
  cv::imshow("image",img);
  cv::waitKey(0);
  cv::Vec3b firstline[img.cols];
  for(int i=0;i<img.cols;i++){
    // access to matrix
    cv::Vec3b tmp = img.at<cv::Vec3b>(0,i);
    std::cout << (int)tmp(0) << " " << (int)tmp(1) << " " << (int)tmp(2) << std::endl;
    // access to my array
    firstline[i] = tmp;
    std::cout << (int)firstline[i](0) << " " << (int)firstline[i](0) << " " << (int)firstline[i](0) << std::endl;
  }
  return EXIT_SUCCESS;
}
3
votes

I don't understand exactly what you are trying to do. You can directly read a color image with:

cv::Mat img = cv::imread("image.jpeg",1);

Your matrix (img) type will be CV_8UC3, then you can access to each pixel like you said using:

img.at<cv::Vec3b>(row,col)[channel].

If you have a 2D array of Vec3b as Vec3b myArray[n][m]; You can access the values like that:

myArray[i][j](k) where k={1,2,3} since Vec3b is a row matrix.

0
votes

In you edited first message, this line is strange:

image_data[0][i*width+j]=all_images[nb_image-1].at<cv::Vec3b>(i,j)[2];

If image data is your colored image, then it should be written like this:

image_data[i][j] = all_images[nb_image-1].at<cv::Vec3b>(i,j);