将cv::Scalar的值设置为opencv中cv::Mat中的一个像素的正确(最佳)方法是什么?

What is the correct (best) way to set the value of cv::Scalar to a pixel in a cv::Mat in opencv?

本文关键字:cv 像素 一个 最佳 是什么 方法 opencv 设置 Scalar Mat      更新时间:2023-10-16

我有一个cv::Mat对象,

cv::Mat _a ...

…和cv::Scalar对象

cv::Scalar _b ...

_b的值设置为_a中一个像素(在位置(x, y))的正确(最佳)方法是什么?

注意对象_a可以有1、2、3、4个通道,但是代码应该在所有情况下都工作,即:
  • _a有一个通道时,_b的第一个元素应该被分配到各自的位置
  • _a有两个通道时,_b的第一个元素应该分配给第一个通道,_b的第二个元素应该分配给第二个通道,两者都在各自的位置
  • (…)

cv::Mat有一个重载的operator=,它接受一个cv::Scalar。这正是你想要的行为。不幸的是,没有直接的方法将Scalar分配给像素值。但是,您可以在坐标(x, y)处创建一个包含单个像素的兴趣区域,并将Scalar分配给该区域:

cv::Mat a; // contains data
cv::Scalar b(1,2,3,4);
cv::Range xr(x, x + 1);
cv::Range yr(y, y + 1);
a(xr, yr) = b;

这不是很好或简洁,但您可以切换Mat的可能类型并迭代Mat的通道以创建/分配Scalar。像这样:

void getPixel(Mat m, int x, int y, Scalar &pixel) {
    switch (m.depth()) {
    case 0:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<uchar>(x, y);
        break;
    case 1:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<char>(x, y);
        break;
    case 2:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<ushort>(x, y);
        break;
    case 3:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<short>(x, y);
        break;
    case 4:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<long>(x, y);
        break;
    case 5:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<float>(x, y);
        break;
    case 6:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<double>(x, y);
        break;
    }
}

我不会使用opencv的。at函数。当你迭代一个大的画面时,它很慢。准备一些结构体,例如RGB图像:

 #pragma pack(push, 2)
  struct RGB {        //members are in "bgr" order!
     uchar blue;
     uchar green;
     uchar red;  };

然后创建一个指向图像扫描线的指针,如下所示:

RGB& rgb = image.ptr<RGB>(y)[x]; //y = row, x = col

你可以这样赋值:

cv::Scalar(image.ptr<RGB>(y)[x].value[0], image.ptr<RGB>(y)[x].value[1], image.ptr<RGB>(y)[x].value[2]);