我读取了Mat
格式的图像。
Mat image = imread("image.png", 1);
我使用声明指向其数据的指针
unsigned char *ptr_source = image.data
现在,我想访问for loop
中每个像素的R、G和B值我已经知道用img.at<Veb3b>(i,j)
或类似的东西来完成它的方法,但现在,我必须使用unsigned char
类型的指针来完成它
uchar R_value = ptr_source[ i*?? + ??? ];
uchar G_value = ptr_source[ i*?? + ??? ];
uchar B_value = ptr_source[ i*?? + ??? ];
重要信息:这里有些人提到要使用以下内容:
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];
}
}
根据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];
基本问题:虽然它似乎有效,但我不太理解它的逻辑为什么我们需要将(frame.cols*y + x)
与frame.channels()
相乘
cv::Mat::channels()
方法返回图像中的通道数
在8UC3
三通道彩色图像中,channels()
返回3,并且像素存储在连续的字节三元组中:BGRBGRBGRBGRBGR...
。
要访问给定unsigned char* ptr_source
指针的像素(x,y)
,需要计算像素偏移。图像宽度为frame.cols
。每个像素都是channels() == 3
字节,因此像素的unsiged char*
偏移量将是ptr_source + frame.channels()*(frame.cols*y + x)
。这个unsigned char*
通常是蓝色通道,后面的2个char
是绿色和红色通道
例如,给定一张3x4的图像,内存中的像素看起来是这样的(仅为清晰起见):
rc 0 1 2
0 BGR BGR BGR
1 BGR BGR BGR
2 BGR>BGR<BGR
3 BGR BGR BGR
因此,如果你计算字节,你会看到像素(1,2)
的蓝色通道字节正好位于字节偏移3*(2*3+1) = 21
处
实际上,使用CCD_ 21而不是原始计算是可取的,因为一些图像在每个像素行的末尾都有填充,因此CCD_
在这种情况下,您应该使用ptr_source[img.step[0]*y + img.channels()*x]
。
此外,您的问题假设像素深度为8U
,这可能不适用于所有图像。如果不是,您还需要将所有内容乘以深度(每个像素的字节数)
这基本上就是cv::Mat:at<>
所做的。。。