Convert Color Image to 16-bit Grayscale in OpenCV?

110 views Asked by At

I wish to convert a color image to a 16-bit grayscale image using C++'s OpenCV library. I'm using OpenCV 4.1.2 and C++ 17.

I'm able to load a color image & save it as 8-bit grayscale with the following minimal example code:

#include <iostream>
#include <string>

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>

int main()
{
    cv::Mat image = cv::imread("test.jpg", -1);

    cv::Mat imageGray;
    cv::cvtColor(image, imageGray, cv::COLOR_BGR2GRAY);

    std::cout << "First pixel: " + std::to_string(imageGray.at<uchar>(0, 0)) + "\n";

    cv::imwrite("gray.jpg", imageGray);

    return 0;
}

Alongside saving the grayscale image using cv::imwrite, I also wish to be able to access the pixels inside the image with the at function.

Currently I am able to convert the color image into an 8-bit grayscale using the cvtColor function and access the pixels inside of it using the uchar type template.

test.jpg:

enter image description here

gray.jpg:

enter image description here

However, I wish to convert the image into a 16-bit grayscale for a more detailed grayscale gradient.

Simply attempting to use the ushort type template with the at function instead of uchar results in a memory exception inside at.

Doing something like this instead from the following post answer:

#include <iostream>
#include <string>

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>

int main()
{
    cv::Mat image = cv::imread("test.jpg", -1);

    cv::Mat imageGray;
    cv::cvtColor(image, imageGray, cv::COLOR_BGR2GRAY);
    image.convertTo(imageGray, CV_16U, 255);

    std::cout << "First pixel: " + std::to_string(imageGray.at<ushort>(0, 0)) + "\n";

    cv::imwrite("gray.jpg", imageGray);

    return 0;
}

doesn't cause an exception, however it appears to break gray.jpg:

enter image description here

Plus, wouldn't this also cause the image data to not be upscaled & interpolated to 16-bit properly?

What is the proper way to convert a color image to a 16-bit grayscale in OpenCV?

Thanks for reading my post, any guidance is appreciated.

0

There are 0 answers