【问题标题】:OpenCV get pixel channel value from Mat imageOpenCV 从 Mat 图像中获取像素通道值
【发布时间】:2011-12-15 11:50:59
【问题描述】:

也许我看起来不够努力,但似乎一切都希望我使用数组。因此,如果 foo 类似于Mat foo = imread("bar.png"),我如何获取 foo 的特定像素的通道值?

【问题讨论】:

标签: c++ opencv getpixel


【解决方案1】:

假设类型是 CV_8UC3,你会这样做:

for(int i = 0; i < foo.rows; i++)
{
    for(int j = 0; j < foo.cols; j++)
    {
        Vec3b bgrPixel = foo.at<Vec3b>(i, j);

        // do something with BGR values...
    }
}

Here 是 Vec3b 的文档。希望有帮助!另外,不要忘记 OpenCV 在内部将内容存储为 BGR 而不是 RGB。

编辑:
出于性能原因,您可能希望使用对数据缓冲区的直接访问来处理像素值:

您可以这样做:

uint8_t* pixelPtr = (uint8_t*)foo.data;
int cn = foo.channels();
Scalar_<uint8_t> bgrPixel;

for(int i = 0; i < foo.rows; i++)
{
    for(int j = 0; j < foo.cols; j++)
    {
        bgrPixel.val[0] = pixelPtr[i*foo.cols*cn + j*cn + 0]; // B
        bgrPixel.val[1] = pixelPtr[i*foo.cols*cn + j*cn + 1]; // G
        bgrPixel.val[2] = pixelPtr[i*foo.cols*cn + j*cn + 2]; // R

        // do something with BGR values...
    }
}

或者:

int cn = foo.channels();
Scalar_<uint8_t> bgrPixel;

for(int i = 0; i < foo.rows; i++)
{
    uint8_t* rowPtr = foo.row(i);
    for(int j = 0; j < foo.cols; j++)
    {
        bgrPixel.val[0] = rowPtr[j*cn + 0]; // B
        bgrPixel.val[1] = rowPtr[j*cn + 1]; // G
        bgrPixel.val[2] = rowPtr[j*cn + 2]; // R

        // do something with BGR values...
    }
}

【讨论】:

  • 如果我的原始矩阵是 CV_32FC3 呢?
  • 因为使用 Vec3f 并计算它们,我得到了奇怪的结果,例如:327880373263237315260312545394688.0000 1058748366848.0000 -0.0000
  • 我发了一个帖子:stackoverflow.com/questions/9811420/…
  • @mevatron,我注意到您的访问函数中没有像素大小,如 bgrPixel.val[0] = pixelPtr[i*foo.cols*4 + j*4 + 0 ];对于 bgra 数据,这是故意的吗?
  • @MarkEssel 好收获!我采用了一些灰度处理代码,并没有更新它。我更新了代码以利用矩阵中的通道数。假设需要三个类似 OP。
【解决方案2】:

以下代码适用于我,用于访问和更改像素值。

用于访问像素的通道值:

for (int i = 0; i < image.cols; i++) {
    for (int j = 0; j < image.rows; j++) {
        Vec3b intensity = image.at<Vec3b>(j, i);
        for(int k = 0; k < image.channels(); k++) {
            uchar col = intensity.val[k]; 
        }   
    }
}

用于改变通道的像素值:

uchar pixValue;
for (int i = 0; i < image.cols; i++) {
    for (int j = 0; j < image.rows; j++) {
        Vec3b &intensity = image.at<Vec3b>(j, i);
        for(int k = 0; k < image.channels(); k++) {
            // calculate pixValue
            intensity.val[k] = pixValue;
        }
     }
}

`

来源:Accessing pixel value

【讨论】:

  • 我使用您的代码更改像素值并尝试显示它。不知何故,只有部分图像发生了变化,其余部分仍然保持不变。有什么理由吗?代码为:intensity.val[k]=(i+j)%256;
  • 再次想到上述问题仅在使用 PNG 图像格式时出现。对于 JPEG 格式,整个图像的像素值都在正确变化。
  • 这看起来不正确。如果 image.channels() 不是 3,则 Vec3b 不是存储矩阵条目的正确类型。
【解决方案3】:

像素数组存储在 cv::Mat 的“data”属性中。假设我们有一个 Mat 矩阵,其中每个像素有 3 个字节 (CV_8UC3)。

对于这个例子,让我们在位置 100x50 处绘制一个 RED 像素。

Mat foo;
int x=100, y=50;

解决方案 1:

创建一个宏函数,从数组中获取像素。

#define PIXEL(frame, W, x, y) (frame+(y)*3*(W)+(x)*3)
//...
unsigned char * p = PIXEL(foo.data, foo.rols, x, y);
p[0] = 0;   // B
p[1] = 0;   // G
p[2] = 255; // R

解决方案 2:

使用ptr方法获取像素。

unsigned char * p = foo.ptr(y, x); // Y first, X after
p[0] = 0;   // B
p[1] = 0;   // G
p[2] = 255; // R

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-04
    • 2018-09-19
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 2013-03-14
    相关资源
    最近更新 更多