如何使用C ++从opencv中的磁盘仅读取一个图像颜色通道

Posted

技术标签:

【中文标题】如何使用C ++从opencv中的磁盘仅读取一个图像颜色通道【英文标题】:how to read only one channel of image color from disk in opencv with C++ 【发布时间】:2017-12-13 08:10:48 【问题描述】:

我需要读取大量具有高速要求的图像,并且只需要处理彩色图像的蓝色通道。 如果我用cv::imread(imgName, CV_LOAD_IMAGE_COLOR); 读取图像会很长时间,所以我只想读取一个彩色图像通道。怎么做 ???非常感谢!!

【问题讨论】:

请添加您的代码示例。 如果你知道图像数据是如何存储的,那么你就不会问这样的问题了。 要加载图像,大多数都需要在获得像素值之前进行解码......但即使它是原始的,使用opencv也是不可能的......也许你可以做到这一点一个 SSD 驱动器可以更快地完成它.... 【参考方案1】:

OpenCV 不提供任何仅加载特定通道的方法。但是,您有几个选择。


加载为彩色图像并提取您需要的通道

cv::Mat3b img("path/to/image", cv::IMREAD_COLOR);
cv::Mat1b blue;
cv::extractChannel(img, blue, 0);

这比使用split 方法快一点,但您仍然需要加载彩色图像。


在预处理阶段,加载所有图像(您可以使用glob 将所有图像检索到文件夹中),提取蓝色通道并将其存储为灰度。然后您可以将图像加载为灰度。

// Preprocessing

cv::String folder = "your_folder_with_images/*.jpg";
std::vector<cv::String> filenames;
cv::glob(folder, filenames);

for (size_t i = 0; i < std::filenames.size(); ++i)

    cv::Mat3b img = cv::imread(filenames[i], cv::IMREAD_COLOR);
    cv::Mat1b blue;
    cv::extractChannel(img, blue, 0);
    cv::imwrite("some/other/name", blue);


// Processing

cv::Mat1b blue = imread("path/to/image", cv::IMREAD_UNCHANGED);

您可以通过saving / loading the image in binary format提高速度:

// Preprocessing
...
matwrite("some/other/name", blue);

// Processing
cv::Mat1b blue = matread("path/to/image");

【讨论】:

【参考方案2】:

我认为你不能这样做,至少在 OpenCV 中是这样。如果您查看cv::imread 的文档,您会发现没有选项只能读取一个颜色通道:

IMREAD_UNCHANGED:如果设置,则按原样返回加载的图像(使用 alpha 通道,否则会被裁剪)。 IMREAD_GRAYSCALE:如果设置,则始终将图像转换为单通道灰度图像。 IMREAD_COLOR:如果设置,则始终将图像转换为 3 通道 BGR 彩色图像。 IMREAD_ANYDEPTH:如果设置,则在输入具有相应深度时返回 16 位/32 位图像,否则将其转换为 8 位。 IMREAD_ANYCOLOR:如果设置,则以任何可能的颜色格式读取图像。 IMREAD_LOAD_GDAL:如果设置,则使用 gdal 驱动程序加载图像。 IMREAD_REDUCED_GRAYSCALE_2:如果设置,则始终将图像转换为单通道灰度图像,图像尺寸缩小 1/2。 IMREAD_REDUCED_COLOR_2:如果设置,则始终将图像转换为 3 通道 BGR 彩色图像,并且图像尺寸缩小 1/2。 IMREAD_REDUCED_GRAYSCALE_4:如果设置,则始终将图像转换为单通道灰度图像,图像尺寸缩小 1/4。 IMREAD_REDUCED_COLOR_4:如果设置,则始终将图像转换为 3 通道 BGR 彩色图像,并且图像尺寸缩小 1/4。 IMREAD_REDUCED_GRAYSCALE_8:如果设置,则始终将图像转换为单通道灰度图像,图像尺寸缩小 1/8。 IMREAD_REDUCED_COLOR_8:如果设置,则始终将图像转换为 3 通道 BGR 彩色图像,并且图像尺寸缩小 1/8。 IMREAD_IGNORE_ORIENTATION:如果设置,则不要根据 EXIF 的方向标志旋转图像。

如果你愿意,你可以在加载矩阵后使用Mat::split分割通道:

Mat src = imread("img.png",CV_LOAD_IMAGE_COLOR); //load  image

Mat bgr[3];   //destination array
split(src,bgr);//split source  

//Note: OpenCV uses BGR color order
imwrite("blue.png",bgr[0]); //blue channel
imwrite("green.png",bgr[1]); //green channel
imwrite("red.png",bgr[2]); //red channel

【讨论】:

是的,我知道 mat::split。但我需要读取具有高速要求的图像。 这样你就可以解释如何进行 CV_LOAD_IMAGE_GRAYSCALE 动作了。如果我用 CV_LOAD_IMAGE_GRAYSCALE 读取图像,速度会提高很多。但我需要蓝色通道颜色来处理图像, 恐怕我的回答不能比这更进一步,这是我所拥有的知识。我刚刚发布了这个信息,因为你没有提到你已经知道了。如果这里没有人回答您的问题,您也可以在OpenCV forum 中尝试。 可能您还有另一个选择,那就是挖掘cv::imread 的源代码并尝试查看如何更改它并仅加载您需要的内容。 我相信这回答了 Q-“我只能在一个频道中阅读”A-否

以上是关于如何使用C ++从opencv中的磁盘仅读取一个图像颜色通道的主要内容,如果未能解决你的问题,请参考以下文章

C中的OpenCV拼接器例程,如何获得像素变换?

如何从c ++中的文件中读取双精度

如何使用C从键盘读取字符串?

c语言 如何读取中文字符串

如何仅使用命令行参数读取唯一行?

如何用C语言统计一个数据文件中的数据个数