0

I need to read large numbers of images with high speed requirements, and just need to handle the Blue channel of a color image. If I read image with cv::imread(imgName, CV_LOAD_IMAGE_COLOR); It will be very long time, so I want to read only one color image channel. How to do it ??? thanks very much !!

Albert Einstein
  • 7,472
  • 8
  • 36
  • 71
Rice
  • 3
  • 1
  • 2

2 Answers2

5

OpenCV doesn't provide any method to load only a specific channel. However, you have a few options.


Load as color image and extract the channel you need

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

This is a little faster than using the split approach, but you still need to load the color image.


In a preprocessing stage, load all your images (you can use glob to retrieve all images into a folder), extract the blue channel and store it as grayscale. Then you can load the image as grayscale.

// 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);

You can improve speed by saving / loading the image in binary format:

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

// Processing
cv::Mat1b blue = matread("path/to/image");
Miki
  • 40,887
  • 13
  • 123
  • 202
4

I think you can not do this, at least with OpenCV. If you check the documentation of cv::imread you will see that there is no option to read only one color channel:

  • IMREAD_UNCHANGED: If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
  • IMREAD_GRAYSCALE: If set, always convert image to the single channel grayscale image.
  • IMREAD_COLOR: If set, always convert image to the 3 channel BGR color image.
  • IMREAD_ANYDEPTH: If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
  • IMREAD_ANYCOLOR: If set, the image is read in any possible color format.
  • IMREAD_LOAD_GDAL: If set, use the gdal driver for loading the image.
  • IMREAD_REDUCED_GRAYSCALE_2: If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
  • IMREAD_REDUCED_COLOR_2: If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
  • IMREAD_REDUCED_GRAYSCALE_4: If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
  • IMREAD_REDUCED_COLOR_4: If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
  • IMREAD_REDUCED_GRAYSCALE_8: If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
  • IMREAD_REDUCED_COLOR_8: If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
  • IMREAD_IGNORE_ORIENTATION: If set, do not rotate the image according to EXIF's orientation flag.

If you want, you can split the channels of a matrix after loading it usin 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
apalomer
  • 1,895
  • 14
  • 36
  • yes, I know mat::split. But i need read images with high speed requirements. – Rice Dec 13 '17 at 08:20
  • So you can explain how to CV_LOAD_IMAGE_GRAYSCALE action. if i read image with CV_LOAD_IMAGE_GRAYSCALE , the speed is improved very stronger. But I need blue channel color to process image, – Rice Dec 13 '17 at 08:23
  • I am afraid my answer cannot go further than this, which is the knowledge that I have. I just posted this information because you were not mentioning that you were aware of it already. If nobody answers your question here, you can try in the [OpenCV forum](http://answers.opencv.org/questions/) as well. – apalomer Dec 13 '17 at 08:26
  • Probably you have another option which is dig through the source code of [`cv::imread`](https://github.com/opencv/opencv/blob/a2120263deefe309dcefeccaf169c9ff1e609caa/modules/imgcodecs/src/loadsave.cpp) and try to see how you can change it and load only what you need. – apalomer Dec 13 '17 at 08:39
  • 1
    I believe this answers the question as written Q- "Can I read in only one channel" A- No – GPPK Dec 13 '17 at 08:46