7

here's the problem: I load an grayscale Image with OpenCV v.2.4.2. Now I want to know for example value of pixel at position (0,0). I've tried:

Mat image=imread("00001.jpg",1);
cvtColor(image,image,CV_RGB2GRAY);
int a=image.at<unsigned>(0,1);
printf("%d ",a);

This actually doesn't work. How to get the pixel value with any data type (CV_8U, CV_32S ...)?

Thanks!!!

Robert Kirchhoff
  • 517
  • 3
  • 7
  • 16

4 Answers4

4

You are making two mistakes here.

While reading the image, you are specifying 1 as input arguments. As explained for imread, the function can read image in three different formats.

CV_LOAD_IMAGE_UNCHANGED (<0) loads the image as is (including the alpha channel if present) CV_LOAD_IMAGE_GRAYSCALE ( 0) loads the image as an intensity one
CV_LOAD_IMAGE_COLOR (>0) loads the image in the RGB format

for your case you will have to use CV_LOAD_IMAGE_GRAYSCALE as the second argument

In the next step where you are using: image.at<unsigned>(0,1); which does not correspond to anything. you use <unsigned> but the compiler says "UNSIGNED? UNSIGNED what???"

I believe a better way to do this is to use correct labels like CV_LOAD_IMAGE_COLOR or CV_LOAD_IMAGE_GRAYSCALE. In the example below, I am reading the image into one channel (CV_LOAD_IMAGE_GRAYSCALE), which automatically converts it to grayscale.

#include <cv.h>
#include <highgui.h>

#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat gImg = imread("img.png", CV_LOAD_IMAGE_GRAYSCALE);

    uchar val;
    val = gImg.at<uchar>(0,0);

    cout << (int)val << endl;

    imshow("showImg",gImg);
    cvWaitKey(0);

    return 1;
}
masad
  • 1,547
  • 1
  • 18
  • 40
  • Right, ok, this works, but have you tried what this actually outputs? In my case I get -89 for pixel (0,0). How is this possible when the image is 8bit unsigned? next I'd like to ask why do you use uchar? – Robert Kirchhoff Sep 20 '12 at 14:20
  • ofcourse I have tried it. I dont know why you are not getting the output correctly. I have used UCHAR exactly for that same reason which is explained in the comment above by @count0, i.e. it can represent a value between 0 to 255 – masad Sep 20 '12 at 15:25
  • 1
    You cannot use imread this way. The second argument is a flag that is either 0, >0 or <0 depending on if you want to read the image grayscale, 3-channel color or as is. You cannot specify the type exactly. It just runs in the specific case because CV_8U==0 – Sassa Sep 20 '12 at 16:47
  • Thanks for correcting my mistake bob. I will edit the answer now. – masad Sep 20 '12 at 18:38
1

There is an easy way to do this.

Mat has Mat.data gives a pointer which refers to the original data matrix.

To get pixel values of nth row and mth column,

Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
unsigned char *input = (unsigned char*)(img.data);

int i,j,r,g,b;
for(int i = 0;i < img.cols;i++){
    for(int j = 0;j < img.rows;j++){
         b = input[img.cols * j + i ] ;
         g = input[img.cols * j + i + 1];
         r = input[img.cols * j + i + 2];
     }
 }

So, this is about a colored image. for grayscale images,

Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
Mat g;
cvtColor(img, g, CV_BGR2GRAY);
unsigned char *input = (unsigned char*)(g.data);

int i,j,r,g,b;
for(int i = 0;i < img.cols;i++){
    for(int j = 0;j < img.rows;j++){
         g = input[img.cols * j + i];
     }
 }

Read more on this blogpost.

Froyo
  • 17,947
  • 8
  • 45
  • 73
0

You could try to find out what opencv did represent it with to have a better idea what type to use:

cout << image.depth() << ", " << image.channels() << endl;

Also check out this discussion about element access.

Community
  • 1
  • 1
count0
  • 2,537
  • 2
  • 22
  • 30
  • Well, I know the depth and channels, but if I know that the matrix is for usual image 8bit and unsigned integer so that the matrix is CV_8UC1, which parameter should I pass onto Mat::at? exactly to here: image.at??????>(0,1); – Robert Kirchhoff Sep 20 '12 at 13:43
  • CV_8UC1 means an 8-bit unsigned single-channel, so that would be `unsigned char` which represents values from 0..255. Unsigned integer would represent values from 0..65536 which would be CV_16UC1. – count0 Sep 20 '12 at 14:48
0

First of all, there is no generic way to get the pixel value this way. Meaning you always have to specify the correct type of of your values if you are going to use at. In this case, you should do a=image.at<uchar>(0,1); since you convert your image to 8-bit unsigned grayscale (1-channel).

You should also probably use CV_BGR2GRAY instead of RGB2GRAY since OpenCV uses BGR as as the channel order.

You could also read your image as grayscale from the start and use uchar again:

Mat image = imread("00001.jpg",0);    // note the 0 flag
int a=image.at<uchar>(0,1);
printf("%d ",a);
Sassa
  • 3,294
  • 2
  • 28
  • 42