如何访问 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 也不应该有任何不同,不需要任何 IplImage
s。无论如何,你不能用它跨越行边界,因为在 OpenCV 中行不需要是连续的(这适用于cv::Mat
s,就像IplImage
s 一样)。所以嵌套循环仍然存在,但是好的,你可以像你说的那样优化 widthStep
的乘法(如果编译器不这样做的话)。以上是关于如何访问 Opencv 中的 RGB 值?的主要内容,如果未能解决你的问题,请参考以下文章