使用指向图像数据的指针访问R、G和B像素值

时间:2023-02-01 22:27:30

I have read an image in Mat format.

我已经阅读了一张Mat格式的图片。

Mat image = imread("image.png", 1);

I declare a pointer to its data using

我使用它的数据声明一个指针

unsigned char *ptr_source = image.data

Now, I want to access the value of R,G and B values at each pixel in a for loop. I already know the method to do it with img.at<Veb3b>(i,j) or similar things but now, I have to do it using a pointer of unsigned char type.

现在,我想访问a for循环中每个像素的R、G和B值的值。我已经知道使用img.at (I,j)或类似的方法,但是现在,我必须使用一个无符号char类型的指针。

uchar R_value = ptr_source[ i*?? + ??? ];
uchar G_value = ptr_source[ i*?? + ??? ];
uchar B_value = ptr_source[ i*?? + ??? ];

IMPORTANT: Some people here have mentioned to use the following:

重要提示:这里有些人提到使用以下内容:

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

which makes sense to me as per the openCV docs but unfortunately it is not working in my case. The other method posted at SO says to use the following:

根据openCV文档,这对我来说是有意义的,但不幸的是,它在我的案例中不起作用。在SO发布的另一种方法是使用以下方法:

uchar b = frame.data[frame.channels()*(frame.cols*y + x) + 0];    
uchar g = frame.data[frame.channels()*(frame.cols*y + x) + 1];
uchar r = frame.data[frame.channels()*(frame.cols*y + x) + 2];

Basic Question: Though, it seems to be working but I do not understand it logically. Why do we need to multiply (frame.cols*y + x) with frame.channels() ??

基本问题:虽然它似乎在起作用,但我不理解它的逻辑。为什么我们需要乘(坐标系)使用框架。通道()??

1 个解决方案

#1


2  

The cv::Mat::channels() method returns the number of channels in an image.
In a 8UC3 three-channel color image, channels() returns 3, and the pixels are stored in consecutive byte-triplets: BGRBGRBGRBGRBGR....

channel()方法返回图像中通道的数量。在一个8 uc3三通道彩色图像、通道()返回3和像素存储在连续byte-triplets:BGRBGRBGRBGRBGR ....

To access pixel (x,y) given a unsigned char* ptr_source pointer, you need to calculate the pixel offset. The image width is frame.cols. Each pixel is channels() == 3 bytes, so the pixel's unsiged char* offset will be ptr_source + frame.channels()*(frame.cols*y + x). This unsigned char* would usually be the blue channel with the following 2 chars the green and red.

要访问给定无符号char* ptr_source指针的像素(x,y),需要计算像素偏移量。图像宽度为frame.cols。每个像素都是channel() == 3字节,因此像素的未标记char*偏移将是ptr_source + frame.channel()*(帧)。这个无符号字符*通常是蓝色通道,绿色和红色分别代表以下两个字符。

For example, given a 3x4 image, the pixels in memory would look like this (spaces for clarity only):

例如,给定一个3x4的图像,内存中的像素将如下所示(仅为清晰空间):

r\c  0   1   2   
 0  BGR BGR BGR
 1  BGR BGR BGR
 2  BGR>BGR<BGR
 3  BGR BGR BGR

So if you count bytes you'll see that the blue channel byte of pixel (1,2) is exactly at byte offset 3*(2*3+1) = 21

所以如果你计算字节,你会看到像素(1,2)的蓝色通道字节恰好在字节偏移3*(2*3+1)= 21

It is actually advisable to use img.step instead of the raw computation since some images have padding at the end of each pixel row so that it is not always true that img.step[0] == img.channels()*img.cols.
In this case you should use ptr_source[img.step[0]*y + img.channels()*x].

实际上建议使用img。不要进行原始计算,因为有些图像在每个像素行末尾都有填充,因此img并不总是正确的。步[0]= = img.channels()* img.cols。在这种情况下,您应该使用ptr_source[img]。步[0]* y + img.channels()* x]。

Additionally, your question assumes that the pixel depth is 8U which may not be correct for all images. If it is not, you will need to multiply everything by the depth (bytes per pixel) as well.
And this is essentially what cv::Mat:at<> does...

此外,您的问题假设像素深度为8U,这可能并不适用于所有的图像。如果不是,您还需要将所有内容乘以深度(每个像素的字节)。这就是cv:::Mat:在<>处…

#1


2  

The cv::Mat::channels() method returns the number of channels in an image.
In a 8UC3 three-channel color image, channels() returns 3, and the pixels are stored in consecutive byte-triplets: BGRBGRBGRBGRBGR....

channel()方法返回图像中通道的数量。在一个8 uc3三通道彩色图像、通道()返回3和像素存储在连续byte-triplets:BGRBGRBGRBGRBGR ....

To access pixel (x,y) given a unsigned char* ptr_source pointer, you need to calculate the pixel offset. The image width is frame.cols. Each pixel is channels() == 3 bytes, so the pixel's unsiged char* offset will be ptr_source + frame.channels()*(frame.cols*y + x). This unsigned char* would usually be the blue channel with the following 2 chars the green and red.

要访问给定无符号char* ptr_source指针的像素(x,y),需要计算像素偏移量。图像宽度为frame.cols。每个像素都是channel() == 3字节,因此像素的未标记char*偏移将是ptr_source + frame.channel()*(帧)。这个无符号字符*通常是蓝色通道,绿色和红色分别代表以下两个字符。

For example, given a 3x4 image, the pixels in memory would look like this (spaces for clarity only):

例如,给定一个3x4的图像,内存中的像素将如下所示(仅为清晰空间):

r\c  0   1   2   
 0  BGR BGR BGR
 1  BGR BGR BGR
 2  BGR>BGR<BGR
 3  BGR BGR BGR

So if you count bytes you'll see that the blue channel byte of pixel (1,2) is exactly at byte offset 3*(2*3+1) = 21

所以如果你计算字节,你会看到像素(1,2)的蓝色通道字节恰好在字节偏移3*(2*3+1)= 21

It is actually advisable to use img.step instead of the raw computation since some images have padding at the end of each pixel row so that it is not always true that img.step[0] == img.channels()*img.cols.
In this case you should use ptr_source[img.step[0]*y + img.channels()*x].

实际上建议使用img。不要进行原始计算,因为有些图像在每个像素行末尾都有填充,因此img并不总是正确的。步[0]= = img.channels()* img.cols。在这种情况下,您应该使用ptr_source[img]。步[0]* y + img.channels()* x]。

Additionally, your question assumes that the pixel depth is 8U which may not be correct for all images. If it is not, you will need to multiply everything by the depth (bytes per pixel) as well.
And this is essentially what cv::Mat:at<> does...

此外,您的问题假设像素深度为8U,这可能并不适用于所有的图像。如果不是,您还需要将所有内容乘以深度(每个像素的字节)。这就是cv:::Mat:在<>处…