如何将单个图像从图像矢量复制到临时 cv::Mat?

Posted

技术标签:

【中文标题】如何将单个图像从图像矢量复制到临时 cv::Mat?【英文标题】:How to copy single image from vector of images to a temporary cv::Mat? 【发布时间】:2013-06-04 12:47:10 【问题描述】:

我调用函数 rgbTOgray 并尝试使用 for 循环将“图像矢量”(这是彩色图像的矢量)中的每个图像复制到临时 cv::Mat。并且,使用 cvtColor 将其转换为灰度。代码如下:

std::vector<cv::Mat> rgbTOgray(std::vector<cv::Mat>& rgb_image)

  cv::Mat temp_gray, temp_rgb;
  std::vector<cv::Mat> gray_image;
  std::vector<cv::Mat>::iterator itr;

  for ( itr = rgb_image.begin() ; itr < rgb_image.end() ; itr++) 
  
    temp_rgb = *itr;
    cvtColor(temp_rgb, temp_gray, CV_RGB2GRAY);
    gray_image.push_back(temp_gray);
  

  return gray_image;

编辑:我正在返回灰度图像“gray_image”的矢量。但这似乎不起作用。

EDIT_2: OpenCV 错误:cvtColor 中的断言失败 (scn == 3 || scn == 4)

有人可以帮帮我吗?我是新手,正在学习所有这些东西。 谢谢!

【问题讨论】:

什么不起作用?您能否提供错误消息或预期/实际输出? @JBL 请检查 EDIT_2 是否有错误 这可能会有所帮助:***.com/questions/6884660/… @JBL 是行:“ temp_rgb = *itr ”对吗?我也试过 *itr.copyTo(temp_rgb) 不起作用... 【参考方案1】:

一个问题是您忘记了 cv::Mat 是使用“副本”进行引用计数的,而不是真正复制任何内容,只是一个指针。push_back(temp_grey) 不断将相同的图像推送到您的阵列中。 您应该在循环内声明 cv::Mat temp_gray 以确保您获得每个元素的新副本。

另外,检查“rgb”图像的通道数 (temp_rgb.channels())。断言基本上说它们不是 3/4 通道。

【讨论】:

如何查看频道数? @user2151446 谢谢!!通道数确实是1。有没有办法将单通道图像转换为3通道图像? @AdiShavit 也感谢你!!通道数确实是 1。有没有办法将单通道图像转换为 3 通道图像?我认为这些是单通道 rgb 图像....我需要将它们转换为灰度图像才能让我的其余代码完美运行.... 如果图像只有 1 个通道,则表示它不是 RGB 图像(据我所知)。你确定这些图像还没有灰度吗?使您的函数对灰色和 rgb 图像有效的一种方法是仅使用单个通道复制图像。 我发现我可以直接将图像读取为灰度:imread(path, CV_LOAD_IMAGE_GRAYSCALE)) 现在不需要上面的函数了!! :D 谢谢大家!!!【参考方案2】:

您不是将灰度图像存储在矢量gray_image 中,而是在cv::Mat 标头中存储指向首先由temp_gray 分配的单个内存数据块的指针。您必须克隆这些数据以不覆盖您的图像:

gray_image.push_back(temp_gray.clone());

顺便说一句,我会在你的循环之前添加gray_image.reserve(rgb_image.size());

【讨论】:

这行:'temp_rgb = *itr' 正确吗?我也试过 *itr.copyTo(temp_rgb) 不起作用... 没关系,但您实际上并不需要它。你可以写 cvtColor(*itr, temp_gray, CV_RGB2GRAY);【参考方案3】:

我不知道确切原因(我也是一个学习者),但在我的情况下,当您将临时图像推回只是灰度转换时,它仅适用于 .clone()

不管怎样,你代码中的迭代器行是正确的。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

std::vector<cv::Mat> rgb2gray(std::vector<cv::Mat>& rgb_image)

  cv::Mat temp_gray;
  std::vector<cv::Mat> gray_image;
  std::vector<cv::Mat>::iterator itr;

  gray_image.reserve(rgb_image.size());
  for ( itr = rgb_image.begin() ; itr < rgb_image.end() ; itr++)
  
    cvtColor(*itr, temp_gray, CV_RGB2GRAY);
    gray_image.push_back(temp_gray.clone());
  
  return gray_image;


int main(int /*argc*/, char** /*argv*/) 
    Mat imgA, imgB;   
    imgA = imread("test1.jpg");
    imgB = imread("test2.jpg");

    vector<Mat> input;
    input.push_back(imgA);
    input.push_back(imgB);

    vector<Mat> output;
    output = rgb2gray(input);

    stringstream ss;
    for(size_t i = 0; i<input.size(); i++) 
        ss.str(""); ss << "in" << i;
        imshow( ss.str(), input[i] );

        ss.str(""); ss << "out" << i;
        imshow( ss.str(), output[i] );
    

    while( true ) 
        char c = (char)waitKey(10);
        if( c == 27 )
             break; 
    
    return 0;

【讨论】:

我发现我可以直接读取灰度图像:imread(path, CV_LOAD_IMAGE_GRAYSCALE)) 谢谢!

以上是关于如何将单个图像从图像矢量复制到临时 cv::Mat?的主要内容,如果未能解决你的问题,请参考以下文章

使用从缓冲区复制的图像更改 cv::Mat 会影响原始图像

如何将 cv::mat 标头和数据部分转换为单个 qbytearray?

如何将多个(超过 4 个)`CV::Mat` 图像`Size(M, N), CV_8UC1` 加入到一个 RGBA 图像中?

如何直接在boost共享内存中编写opencv cv :: Mat图像

从 3d 数组创建 cv::Mat 图像

将 Magick::Image 转换为 cv::Mat