【问题标题】:Extract one colour channel from 4-dimensional cv::Mat从 4 维 cv::Mat 中提取一个颜色通道
【发布时间】:2021-11-16 13:50:06
【问题描述】:

我正在使用 OpenCV 一段时间并尝试使用 DNN 扩展。我的模型具有像素深度为 uint8 的输入形状 [1, 3, 224, 244]。因此,我将具有 3 通道和 8 位像素深度的 m_inputImg 放入函数中:

cv::dnn::blobFromImage(m_inputImg, m_inputImgTensor, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);

现在我有兴趣了解我的输入图像如何“放置”在 cv::Mat 张量中。理论上我知道张量的样子,但我不明白 OpenCV 是如何做到的。所以为了理解这一点,我想提取一个颜色通道。我试过这个:

cv::Mat blueImg  = cv::Mat(cp->getModelConfigs().model[0].input.height,
                            cp->getModelConfigs().model[0].input.width,
                            CV_8UC3,
                            blob.ptr<uint8_t>(0, 0);

但我得到的是类似的东西(见图)。我真的很困惑,有人可以帮忙或有好的建议吗? 谢谢

【问题讨论】:

  • 您的原始图像看起来如何?如果您只想显示 1 个通道,为什么要使用 CV_8UC3 恕我直言,您当前将整个张量显示为 BGRBGRBGR ...但是您的数据应该排列为 RRR...GGG...BBB ...您可以尝试使用CV_8UC1?恕我直言,那么您应该获得 RRR ... 图像。但我不确定为什么你的 blob 中有 9 张图片。
  • 在你的 blob 创建中不应该是 cv::Size(224,224) 而不是 cv::Size()?
  • 当我尝试 CV_8UC1 时,我的图像中只会出现噪点,因此我的指针可能会显示在未定义的区域。
  • 对于尺寸参数 OpenCV 写这个:“尺寸:输出图像的空间尺寸”。所以在我看来 cv::Size(224, 224) 是错误的,因为输出“图像”是张量。但我不知道应该使用什么大小,所以我默认使用它(也许 OpenCV 知道我想要什么......:D)
  • 在您的图像中,图像的前 1/3 是 blob 的第一个通道。由于您将单块通道解释为 3 通道图像,因此它将在显示图像的 1/3 之后读取图像的第二行,在显示图像的 2/3 处读取第三行。因为您阅读的行数超出预期,所以第二个通道从显示图像行的 1/3 开始,第三个通道从 2/3 开始。

标签: c++ opencv


【解决方案1】:

cv::Size() 将使用原始图像大小。您对数据的解释是错误的。这里有 4 种方法来解释从 lenna 图像加载的 512x512 (cv::Size()) 加载的 blob-start:

输入(512x512):

  1. blob 以 512x512 单通道图像开始:

  1. blob 以 512x512 BGR 图像开始:

  1. blob 以 224x224 BGR 图像开始:

  1. blob 以 224x224 单通道启动:

代码如下:

int main()
{
    cv::Mat img = cv::imread("C:/data/Lenna.png"); // 8UC3
    cv::imshow("img", img);


    cv::Mat blob;
    cv::dnn::blobFromImage(img, blob, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);

    cv::Mat redImg = cv::Mat(img.rows,
        img.cols,
        CV_8UC1,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("blob 1", redImg);
    cv::imwrite("red1.jpg", redImg);

    cv::Mat redImg3C = cv::Mat(img.rows,
        img.cols,
        CV_8UC3,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("redImg3C", redImg3C);
    cv::imwrite("red3C.jpg", redImg3C);

    cv::Mat redImg224_3C = cv::Mat(224,
        224,
        CV_8UC3,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("redImg224_3C", redImg224_3C);
    cv::imwrite("redImg224_3C.jpg", redImg224_3C);

    cv::Mat redImg224_1C = cv::Mat(224,
        224,
        CV_8UC1,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("redImg224_1C", redImg224_1C);
    cv::imwrite("redImg224_1C.jpg", redImg224_1C);
    

    cv::waitKey(0);
}

恕我直言,您必须在代码中执行以下操作:

cv::dnn::blobFromImage(m_inputImg, blob, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);

cv::Mat blueImg  = cv::Mat(m_inputImg.rows,
                        m_inputImg.cols,
                        CV_8UC3,
                        blob.ptr<uint8_t>(0, 0);

cv::dnn::blobFromImage(m_inputImg, blob, 1.0, cv::Size(cp->getModelConfigs().model[0].input.width , cp->getModelConfigs().model[0].input.height), cv::Scalar(), false, false, CV_8U);

cv::Mat blueImg  = cv::Mat(cp->getModelConfigs().model[0].input.height,
                        cp->getModelConfigs().model[0].input.width,
                        CV_8UC3,
                        blob.ptr<uint8_t>(0, 0);

此外,这里是将空间 blob 图像大小设置为固定大小(例如所需的 DNN 输入大小)的版本:

    cv::Mat blob2;
    cv::dnn::blobFromImage(img, blob2, 1.0, cv::Size(224,224), cv::Scalar(), false, false, CV_8U);

    cv::Mat blueImg224_1C = cv::Mat(224,
        224,
        CV_8UC1,
        blob2.ptr<uint8_t>(0, 0));

    cv::imshow("blueImg224_1C", blueImg224_1C);
    cv::imwrite("blueImg224_1C.jpg", blueImg224_1C);

给出这张图片:

【讨论】:

  • 样本中有错误。这不是 RED 频道,因为我在 blobFromImage 期间没有交换频道。相反,它是 BLUE 频道,但基本信息仍然是相同的。
  • 我想我对这一点了解得更多了。但是在您的编辑中,您提供了一个用于提取“BLUE”通道的示例,但在结果图像中,它似乎很容易成为原始图像的灰度图像。
  • 绘制单个通道总是灰色的。如果要将其显示为彩色图像,则必须将单个通道与 2 个空通道合并。喜欢:std::vector&lt;cv::Mat&gt; bgrMerger; bgrMerger.push_back(blueMat); bgrMerger.push_back(emptyMat); bgrMerger.push_back(emptyMat); 然后 cv::merge(bgrMerger, bgrImage);cv::imshow("image", bgrImage);
  • 是的,你是对的。但在我看来,只会显示蓝色通道中值 >0 的像素。当我查看您的示例图片时,它似乎有所不同。
猜你喜欢
  • 2014-06-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-16
  • 2012-08-23
  • 1970-01-01
  • 2022-12-04
相关资源
最近更新 更多