Rice
Rice

Reputation: 3

how to read only one channel of image color from disk in opencv with C++

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 !!

Upvotes: 0

Views: 4839

Answers (2)

Miki
Miki

Reputation: 41765

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

Upvotes: 5

apalomer
apalomer

Reputation: 1925

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

Upvotes: 4

Related Questions