How to fill an array of Vec3b

19,823

Solution 1

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;
}

Solution 2

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.

Share:
19,823
George
Author by

George

(your about me is currently blank) click here to edit

Updated on August 22, 2022

Comments

  • George
    George over 1 year

    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.

  • George
    George almost 12 years
    Yes what I want to do is your last suggestion, however this code doesn't work. Neither does myArray[i][j][k] I don't know how to do it!
  • Eric
    Eric almost 12 years
    Could you post your entire code plz, so we can debug it. Otherwise, why do you need absolutely an array since cv::Mat have an access to T* data.
  • George
    George almost 12 years
    I edited my first post with clearer explanations and pieces of code, it was too long and wouldn't fit here in a comment.
  • George
    George almost 12 years
    I found several time that the way to use it is: Vec3b intensity = img.at<Vec3b>(y, x); uchar blue = intensity.val[0]; uchar green = intensity.val[1]; uchar red = intensity.val[2]; But considering that I have an Vec3b array, I don't know how to use, as this doesn't work: Vec3b intensity[size_array]; intensity[i] = img.at<Vec3b>(y, x);
  • George
    George almost 12 years
    Erf, unfortunately it does not work with my code for some reason. I am not very willing to publish it full here, so I will solve my problem by finding another way around. Thanks for the help though, your solution does work so I will validate it.
  • George
    George almost 12 years
    although I find it that it should be (int)tmp[0] not (int)tmp(0) (and so on)
  • Eric
    Eric almost 12 years
    In official opencv documentation, operator(int) is implemented for row matrix cv::Matx. cv::Vec3b is derived from cv::Matx.
  • George
    George almost 12 years
    Somehow this doesn't work, I haven't figured out where the problem comes from yet but it seems like it is more from my memory allocation part, when the is and js are too high it crashes but otherwise works. And right now it puzzles me because I have the same code with same allocation that works fine when there is only one channel. I'm working on it, if I can't solve it soon I guess I'll take another method. Like three arrays similar to the one I use for grayscale, 1 for each channel. It sounds heavy &cumbersome though. &I think I am not being very clear either.. Sry about that &thx for trying