【OPENCV】cv::Mat像素遍历方法比较
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【OPENCV】cv::Mat像素遍历方法比较相关的知识,希望对你有一定的参考价值。
参考技术A 像素级别遍历是我们在图像任务中经常遇到的问题,在实时的图像处理中,能够高效的访问像素数据是很重要的。OpenCV中的数据容器是cv::Mat,cv::Mat提供了三种数据访问的方式分别是下标寻址,指针访问,迭代器访问。下面我们对比下这几种不同方式的访问速度。对比这几种方式我们可以发现,最为高效的还是直接使用指针计算地址偏移量, 然而这种方式必须保证Mat在内存的存储是连续的,可以通过cv::Mat::isContinous()函数检测,如果是连续的则可以处理为单行向量,使用最为高效的方式访问。如果不想这么麻烦,其实method5是一种较为可取的方式,通过从cv::Mat::ptr()得到每一行的首地址,这样就不需要保证连续存储,速度和纯粹使用指针也差不了多少。
实际上对于method5,不使用中间指针进行改写的话:
重新测试下:
时间上已经十分接近method6,实际操作的时候直接使用method5,不使用中间指针即可。
opencv::Mat,从原始数据中获取像素值?
【中文标题】opencv::Mat,从原始数据中获取像素值?【英文标题】:opencv::Mat, get pixel value from the raw data? 【发布时间】:2018-01-31 14:25:09 【问题描述】:我有一张图片,cv::Mat
。我正在从中获取原始数据,其中:
uchar* data = (uchar *)pImg.data;
我需要将此数据传递给一个函数,然后循环遍历图像的每个像素。我会做的:
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
//pixel = cv::Point(i,j);
使用uchar*
数据,这相当于什么?
【问题讨论】:
取决于pImg
的像素类型。什么是像素类型?
我实际上需要做两个 Mats,一个 uchar
和一个 int。
【参考方案1】:
这很简单,但你需要记住一件事,这个image.elemSize()
表示每个像素有多少字节(这个函数取自 OpenCV mat)。所以对于不同的图像格式,这个循环看起来会有点不同。循环里面有个例子
for (auto i = 0; i < image.rows * image.cols; i+=image.elemSize())
//for CV_8UC1
//auto pixel = *(image.data + i)
//for RGB as CV_8UC3
auto r = *(image.data + i)
auto g = *(image.data + i + 1)
auto b = *(image.data + i + 2)
【讨论】:
我认为这相当于:(对于 CV_8UC1)data[x * step + y * channels]
【参考方案2】:
只要知道以下参数,就可以从原始数据中获取正确的像素值:
像素的X坐标(列号) 像素的Y坐标(行号) 图像深度(单个像素的实际数据类型,即uchar
、ushort
、float
等)
图像的通道数
图像步长(以字节为单位)
鉴于以上信息,可以通过如下方式访问像素(对于CV_8UC3
类型):
uchar* data = (uchar *)pImg.data;
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
uchar b = data[i * pImg.step + pImg.channels() * j + 0];
uchar g = data[i * pImg.step + pImg.channels() * j + 1];
uchar r = data[i * pImg.step + pImg.channels() * j + 2];
【讨论】:
谢谢。我仍然有问题。以下将崩溃:int* tri = new int[width * height];
for (int i = 0; i < height; ++i) for (int j = 0; j < width; ++j) tri[i * step + j * channels] = 0;
我做错了什么?
更具体地说,我正在运行这个:int* tData = new int[trimap.cols * trimap.rows];
for (auto i = 0; i < trimap.rows * trimap.cols; i += trimap.elemSize()) //for CV_8UC1 auto pixel = *(trimap.data + i); tData[i] = pixel;
然后访问数据:tData [i * step + j * channel
将崩溃
啊,在存储步骤和通道之前,我需要将其转换为灰色。运行良好。再次感谢。
@anti.. uchar
的step
值不适用于int
。如果tri
只是一个简单的数组,那么它的step
将等于width
。换句话说,在访问元素之前,必须将步长除以数据类型的大小。以上是关于【OPENCV】cv::Mat像素遍历方法比较的主要内容,如果未能解决你的问题,请参考以下文章
cv::Mat 中 cv::Point 的 OpenCV rgb 值
opencv 报错:Error: Assertion failed (data) in cv::Mat::at, file ... mat.inl.hpp, line 897(访问了不存在矩阵的像素)