Hi!
I am testing gray scale conversion of RGB using OpenCV. The documentation says OpenCV combines RGB in ratio of {0.299,0.587,0.114} respectively. I have tried that in a custom loop and combined the channels in mentioned ratio to form a gray image. For comparison with OpenCV inbuilt function cv::cvtColor() and my loop generated gray image I took Sum of absolute error between them and found a difference with very large value (approx. 1 lakh for a 480p image). May i know what is exact ratio been used by OpenCV.
Thank you.
I ensure i put ratio as BGR and not RGB. I am attaching my code.
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <iostream>
#include <chrono>
#include <filesystem>
int main(){
std::filesystem::path inpath = "../test/synthetic/colored480/"; // Input path
// std::string otpath = "../test/output/CPP/480/";
for (const auto & entry : std::filesystem::directory_iterator(inpath)){
std::cout<<"file: "<<entry.path()<<std::endl;
cv::Mat input = cv::imread(entry.path()); // Reading image from path
cv::Mat Gray1 = cv::Mat::zeros(input.rows, input.cols, CV_8UC1); // for inbuilt function result
cv::Mat Gray2 = cv::Mat::zeros(input.rows, input.cols, CV_8UC1); // for custom loop result
cv::cvtColor(input, Gray1, cv::COLOR_BGR2GRAY); // gray image using inbuilt function
// color convertion to gray without using function
for (int i = 0; i < input.rows; i++) { // loop through all pixels rowwise and column wise
for (int j = 0; j < input.cols; j++) {
Gray2.at<uchar>(i, j) = int(0.114*input.at<cv::Vec3b>(i, j)[0] // B
+ 0.587*input.at<cv::Vec3b>(i, j)[1] // G
+ 0.299*input.at<cv::Vec3b>(i, j)[2]); // R
}
}
cv::Mat diff = cv::Mat::zeros(input.rows, input.cols, CV_8UC1); // difference image
cv::absdiff(Gray1, Gray2, diff); // absolute difference between inbuilt and custom gray image
// sum all the absolute difference
double sum = cv::sum(diff)[0];
std::cout<<"sum: "<<sum<<std::endl;
}
return 0;
}
remember you’re speaking to an international audience. nobody here knows what a “lakh” is, except those of us who deal with indians regularly, and even we may feign ignorance
100e3 / (640*480) = 0.1
so you’re talking about differences of a fraction of a single count per pixel. that is imperceptible.
you might want to investigate rounding modes. or dig into OpenCV source to find the specific coefficients.
you should also visually compare (look at) your Gray1 and Gray2 pictures, or the diff
Mat. see any single differences that are perceptible? that is just to make sure there is no integer overflow/wraparound happening.
1 lakh = 100,000
Next time I will keep that in mind.
I have solved this problem!
I found there is a round() operation after computing the grayscale value.
// color convertion to gray without using function
for (int i = 0; i < input.rows; i++) { // loop through all pixels rowwise and column wise
for (int j = 0; j < input.cols; j++) {
Gray2.at<uchar>(i, j) = round(0.114*input.at<cv::Vec3b>(i, j)[0] // B
+ 0.587*input.at<cv::Vec3b>(i, j)[1] // G
+ 0.299*input.at<cv::Vec3b>(i, j)[2]); // R
}
}