如何访问 Opencv 中的 RGB 值?

Posted

技术标签:

【中文标题】如何访问 Opencv 中的 RGB 值?【英文标题】:How to access the RGB values in Opencv? 【发布时间】:2012-11-26 14:54:30 【问题描述】:

我对频道数量的使用感到困惑。 以下哪一项是正确的?

// roi is the image matrix

for(int i = 0; i < roi.rows; i++)

    for(int j = 0; j < roi.cols; j+=roi.channels())
    
        int b = roi.at<cv::Vec3b>(i,j)[0];
        int g = roi.at<cv::Vec3b>(i,j)[1];
        int r = roi.at<cv::Vec3b>(i,j)[2];
        cout << r << " " << g << " " << b << endl ;
    

或者,

for(int i = 0; i < roi.rows; i++)

    for(int j = 0; j < roi.cols; j++)
    
        int b = roi.at<cv::Vec3b>(i,j)[0];
        int g = roi.at<cv::Vec3b>(i,j)[1];
        int r = roi.at<cv::Vec3b>(i,j)[2];
        cout << r << " " << g << " " << b << endl ;
    

【问题讨论】:

第二个是正确的。查看文档了解详情 查看更多Ans 1和Ans 2 【参考方案1】:

第二个是正确的, Mat里面的rows和cols代表像素数, 而通道与行数和列数无关。 而CV默认使用BGR,所以假设Mat没有转换成RGB那么代码是正确的

参考,个人经验,OpenCV docs

【讨论】:

【参考方案2】:

从图像中获取颜色分量的更快方法是将图像表示为IplImage 结构,然后利用像素大小和通道数使用指针算法对其进行迭代。

例如,如果您知道您的图像是每像素 1 个字节的 3 通道图像,并且其格式为 BGR(OpenCV 中的默认值),则以下代码将访问其组件:

(在以下代码中,img 的类型为 IplImage。)

for (int y = 0; y < img->height; y++) 
    for(int x = 0; x < img->width; x++) 
        uchar *blue = ((uchar*)(img->imageData + img->widthStep*y))[x*3];
        uchar *green = ((uchar*)(img->imageData + img->widthStep*y))[x*3+1];
        uchar *red = ((uchar*)(img->imageData + img->widthStep*y))[x*3+2];
    

对于更灵活的方法,您可以使用types_c.h 中定义的CV_IMAGE_ELEM 宏:

/* get reference to pixel at (col,row),
   for multi-channel images (col) should be multiplied by number of channels */
#define CV_IMAGE_ELEM( image, elemtype, row, col )       \
    (((elemtype*)((image)->imageData + (image)->widthStep*(row)))[(col)])

【讨论】:

是什么让您认为这不是完全从他的第二个示例中编译的内容? 停止使用旧的 IplImage 实现。 “第二个”示例是有效的。然而,第二个例子不是超级快,但非常易读。您可以做的加速是首先拆分通道,然后使用指针读出。或者,如果您更聪明,请考虑步长和位大小,立即使用指针。【参考方案3】:

我猜第二个是正确的,但是获取这样的数据非常耗时。

一种更快的方法是使用 IplImage* 数据结构并使用 roi 中包含的数据的大小来递增指向的地址...

【讨论】:

"获取这样的数据非常耗时。更快的方法是使用IplImage*数据结构,并使用包含的数据大小递增指向的地址roi" - 你确定吗?不应该有任何显着差异(如果有任何差异的话)。无论如何,这些方法都会被内联。 我认为当你尝试访问元素 i,j 时,openCV 会计算元素在内存中的位置并返回(基于通道的宽度、nb 和每个矩阵的大小元素)。这种计算(完成的宽度 * 高度时间)比向您正在使用的地址添加 8 位更耗时。 不确定这真的很重要,除了编译器足够聪明。但是好的,很可能是这样,但话又说回来,使用指向 cv::Vec3b 数据的指针并将其增加 1 也不应该有任何不同,不需要任何 IplImages。无论如何,你不能用它跨越行边界,因为在 OpenCV 中行不需要是连续的(这适用于cv::Mats,就像IplImages 一样)。所以嵌套循环仍然存在,但是好的,你可以像你说的那样优化 widthStep 的乘法(如果编译器不这样做的话)。

以上是关于如何访问 Opencv 中的 RGB 值?的主要内容,如果未能解决你的问题,请参考以下文章

在openCV中访问某个图像中所有像素的RGB值

十六进制的OpenCV RGB值?

如何知道 OpenCV 中的图像是不是为 RGB?

opencv中Mat格式的数据访问.at

《OpenCV:访问Mat图像中每个像素值》

用opencv如何提取像素点的RGB分量