To illustrate, I've opened up this same color JPEG image:

once using the conversion

img = cv2.imread(path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

and another by loading it in gray scale mode

img_gray_mode = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

Like you've documented, the diff between the two images is not perfectly 0, I can see diff pixels in towards the left and the bottom

I've summed up the diff too to see

import numpy as np
np.sum(diff)
# I got 6143, on a 494 x 750 image

I tried all cv2.imread() modes

Among all the IMREAD_ modes for cv2.imread(), only IMREAD_COLOR and IMREAD_ANYCOLOR can be converted using COLOR_BGR2GRAY, and both of them gave me the same diff against the image opened in IMREAD_GRAYSCALE

The difference doesn't seem that big. My guess is comes from the differences in the numeric calculations in the two methods (loading grayscale vs conversion to grayscale)

Naturally what you want to avoid is fine tuning your code on a particular version of the image just to find out it was suboptimal for images coming from a different source.

In brief, let's not mix the versions and types in the processing pipeline.

So I'd keep the image sources homogenous, e.g. if you have capturing the image from a video camera in BGR, then I'd use BGR as the source, and do the BGR to grayscale conversion cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Vice versa if my ultimate source is grayscale then I'd open the files and the video capture in gray scale cv2.imread(path, cv2.IMREAD_GRAYSCALE)

Answer from bakkal on Stack Overflow
🌐
OpenCV
forum.opencv.org › c++
RAW to Grayscale - C++ - OpenCV
June 23, 2022 - Hello, I am new to opencv here, can anyone help me here to convert RAW to Grayscale Image. My camera (OV2311) outputs RAW data encapsulated in YUV2 format. Kindly let me know if in case of more details required. Than…
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-grayscaling-of-images-using-opencv
Python | Grayscaling of Images using OpenCV - GeeksforGeeks
September 23, 2025 - In this method, we can directly load an image in grayscale mode by passing the flag 0 to cv2.imread(). This saves us from having to convert the image separately after loading.
Discussions

python - Opencv - Grayscale mode Vs gray color conversion - Stack Overflow
I can't think of any reason to ever convert to grayscale in imread. 2019-10-23T18:53:33.97Z+00:00 ... What @MichaelGallacher said. The coefficients used by cvtColor are here: github.com/opencv/opencv/blob/master/modules/imgproc/src/… 2021-05-11T21:23:03.9Z+00:00 More on stackoverflow.com
🌐 stackoverflow.com
c++ - How can I convert a cv::Mat to a gray scale in OpenCv? - Stack Overflow
OpenCV 3 is rolling out soon, it will be useful. 2015-01-27T07:50:05.027Z+00:00 ... @sansuiso Thanks, do you know how I can get a grayscaled image with the same channels as the input image? currently this method, converts the whole image into 1 channeled balck and white image. More on stackoverflow.com
🌐 stackoverflow.com
Convert RGB into Grayscale - C++ - OpenCV
Hello! I am opening images from a folder using glob function. The images are RGB. I am trying to convert them to Grayscale using the cv::cvColor(RGB, GRAY, cv::COLOR_RGB2GRAY). For some reason memory problem appears in Visual Studio 2019 as shown in image above. Could someone help me ? More on forum.opencv.org
🌐 forum.opencv.org
0
June 29, 2021
How does one convert a grayscale image to RGB in OpenCV (Python)? - Stack Overflow
I'm learning image processing using OpenCV for a realtime application. I did some thresholding on an image and want to label the contours in green, but they aren't showing up in green because my image is in black and white. Early in the program I used gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) to convert from RGB to grayscale... More on stackoverflow.com
🌐 stackoverflow.com
🌐
DataFlair
data-flair.training › blogs › image-conversion-using-opencv
Image Conversion using OpenCV - Colored, Grayscale and Binary - DataFlair
March 2, 2024 - By using cv2.cvtColor() with cv2.COLOR_BGR2GRAY , we can efficiently transform a color image into a grayscale representation, making it easier to perform various image processing tasks that do not require colour information.
Top answer
1 of 2
90

To illustrate, I've opened up this same color JPEG image:

once using the conversion

img = cv2.imread(path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

and another by loading it in gray scale mode

img_gray_mode = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

Like you've documented, the diff between the two images is not perfectly 0, I can see diff pixels in towards the left and the bottom

I've summed up the diff too to see

import numpy as np
np.sum(diff)
# I got 6143, on a 494 x 750 image

I tried all cv2.imread() modes

Among all the IMREAD_ modes for cv2.imread(), only IMREAD_COLOR and IMREAD_ANYCOLOR can be converted using COLOR_BGR2GRAY, and both of them gave me the same diff against the image opened in IMREAD_GRAYSCALE

The difference doesn't seem that big. My guess is comes from the differences in the numeric calculations in the two methods (loading grayscale vs conversion to grayscale)

Naturally what you want to avoid is fine tuning your code on a particular version of the image just to find out it was suboptimal for images coming from a different source.

In brief, let's not mix the versions and types in the processing pipeline.

So I'd keep the image sources homogenous, e.g. if you have capturing the image from a video camera in BGR, then I'd use BGR as the source, and do the BGR to grayscale conversion cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Vice versa if my ultimate source is grayscale then I'd open the files and the video capture in gray scale cv2.imread(path, cv2.IMREAD_GRAYSCALE)

2 of 2
2

cv2.imread(path, 0) (or rather cv2.imread(path, cv2.IMREAD_GRAYSCALE)) asks the image file reading code to load the image as grayscale. For most file types, some 3rd party library is used to read them. If this library supports grayscale conversion, we’ll be using that library’s conversion routine.

Otherwise, we’re using OpenCV’s implementation of the conversion to grayscale.

There’s no reason to assume one implementation is better than the other, the differences observed are likely due to a different computation order, or to a different assumption about the whitepoint. But note that if the file has a color profile embedded, the 3rd party library might be able to use it to do the conversion, and so will have whitepoint information available. This color profile does not get loaded into OpenCV, so OpenCV will always make an assumption about the whitepoint.

Reading the image directly as grayscale is possibly a bit more efficient. If the 3rd party library converts each pixel as it’s read, we won’t need a temporary memory space to store the full color image (which takes up 3x as much memory as the grayscale image). For a format such as JPEG, which stores intensity and color information separately, reading as grayscale also avoids a lot of computation (we’re directly outputting the intensity value, rather than computing the RGB values and then converting those back to intensity).

Reading directly as grayscale has the possibility of giving different results if the image file gets converted to a different format, as then a different grayscale conversion will be used. Say, you convert your JPEG file to PNG, then using IMREAD_GRAYSCALE will use different libraries to do the grayscale conversion, using OpenCV’s conversion code will ensure both files read identically.

Top answer
1 of 2
100

Using the C++ API, the function name has slightly changed and it writes now:

#include <opencv2/imgproc/imgproc.hpp>

cv::Mat greyMat, colorMat;
cv::cvtColor(colorMat, greyMat, CV_BGR2GRAY);

The main difficulties are that the function is in the imgproc module (not in the core), and by default cv::Mat are in the Blue Green Red (BGR) order instead of the more common RGB.

OpenCV 3

Starting with OpenCV 3.0, there is yet another convention. Conversion codes are embedded in the namespace cv:: and are prefixed with COLOR. So, the example becomes then:

#include <opencv2/imgproc/imgproc.hpp>

cv::Mat greyMat, colorMat;
cv::cvtColor(colorMat, greyMat, cv::COLOR_BGR2GRAY);

As far as I have seen, the included file path hasn't changed (this is not a typo).

2 of 2
2

May be helpful for late comers.

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"

using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
  if (argc != 2) {
    cout << "Usage: display_Image ImageToLoadandDisplay" << endl;
    return -1;
}else{
    Mat image;
    Mat grayImage;

    image = imread(argv[1], IMREAD_COLOR);
    if (!image.data) {
        cout << "Could not open the image file" << endl;
        return -1;
    }
    else {
        int height = image.rows;
        int width = image.cols;

        cvtColor(image, grayImage, CV_BGR2GRAY);


        namedWindow("Display window", WINDOW_AUTOSIZE);
        imshow("Display window", image);

        namedWindow("Gray Image", WINDOW_AUTOSIZE);
        imshow("Gray Image", grayImage);
        cvWaitKey(0);
        image.release();
        grayImage.release();
        return 0;
    }

  }

}
🌐
MathWorks
mathworks.com › computer vision toolbox
Convert RGB Image to Grayscale Image by Using OpenCV Importer - MATLAB & Simulink
The converter converts an RGB image to a grayscale image by eliminating the hue and saturation information while retaining the luminance. First import an OpenCV function into Simulink® by using the Install and Use Computer Vision Toolbox Interface for OpenCV in Simulink.
🌐
OpenCV
forum.opencv.org › c++
Convert RGB into Grayscale - C++ - OpenCV
June 29, 2021 - Hello! I am opening images from a folder using glob function. The images are RGB. I am trying to convert them to Grayscale using the cv::cvColor(RGB, GRAY, cv::COLOR_RGB2GRAY). For some reason memory problem appears …
Find elsewhere
🌐
TutorialsPoint
tutorialspoint.com › opencv › opencv_colored_images_to_grayscale.htm
OpenCV - Colored Images to GrayScale
You can convert colored images to gray scale by passing the code Imgproc.COLOR_RGB2GRAY along with the source and destination matrices as a parameter to the cvtColor() method. The following program demonstrates how to read a colored image as ...
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 34028 › easy-bgr-to-grayscale-conversion
Easy BGR to Grayscale conversion - OpenCV Q&A Forum
Let me guide you in a simple way , it looks that you want to move from command line input to the input with in program (I don't know what to call it :) ) , you simple need to do the following in your code · Mat img = imread ("E:\\lena.jpg"); // input image Mat gray_img; // image where result will save cvtColor(img , gray_img ,CV_BGR2GRAY) ; // this line convert your image from BGR2GRAY imwrite("E:\\gray_img.jpg" , gray_img); // is used to save the image in your directory imshow("img" , gray_img) ; // this line show you the gray image as output
🌐
TutorialsPoint
tutorialspoint.com › converting-an-image-from-colour-to-grayscale-using-opencv
Converting an image from colour to grayscale using OpenCV
March 17, 2021 - Step 1: Import OpenCV. Step 2: Read the original image using imread(). Step 3: Convert to grayscale using cv2.cvtcolor() function.
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 58257 › convert-cv_16uc3-color-image-to-cv_8u-grayscale
Convert CV_16UC3 color image to CV_8U grayscale - OpenCV Q&A Forum
#include <opencv2/opencv.hpp> using namespace cv; // Your CV_16U3 Mat Mat image16u3 = //$your data$; // Convert it to CV_8U3 Mat Mat image8u3; image16u3.convertTo(image8U3, CV_8UC3); // CV_8U should work as well // Convert color to grayscale Mat image8u1; cvtColor(image8u3, image8u1, COLOR_RGB2GRAY);
🌐
Python Geeks
pythongeeks.org › python geeks › learn opencv › color, grayscale and binary image conversion in opencv
Color, Grayscale and Binary Image Conversion in OpenCV - Python Geeks
September 19, 2022 - Your opinion matters Please write ... image conversion in OpenCVconverting Color image to Grayscale using OpenCVcv2.cvtColor() method in OpenCVcv2.imread() function with flag=0 in OpenCVGrayscale to binary conversion in ...
🌐
GeeksforGeeks
geeksforgeeks.org › converting-color-video-to-grayscale-using-opencv-in-python
Converting Color video to grayscale using OpenCV in Python - GeeksforGeeks
January 3, 2023 - OpenCV is a huge open-source library for computer vision, machine learning, and image processing. It can process images and videos to identify objects, faces, or even the handwriting of a human. In this article, we will see how to convert a colored video to a gray-scale format.
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 165296 › im-trying-to-convert-rgb-video-to-grayscale-using-opencv-in-c-but-im-getting-an-error-in-my-code-can-anyone-help-me-with-the-code
I'm Trying to convert RGB video to Grayscale using OpenCV in C++, but i'm getting an error in my code. Can anyone help me with the code? - OpenCV Q&A Forum
July 10, 2017 - Mat float_mat; graymat.convertTo( float_mat,CV_32F); // do something with float_mat .. edit flag offensive delete link more · Yes, that is exactly what i wanted, this is working fine! Thank You so much! @berak · rohitmulay ( 2017-07-10 03:33:25 -0600 )edit · add a comment · Official site · GitHub · Wiki · Documentation · Follow · 1 follower · subscribe to rss feed · Asked: 2017-07-10 02:58:44 -0600 · Seen: 3,224 times · Last updated: Jul 10 '17 · OpenCV DescriptorMatcher matches ·
🌐
techtutorialsx
techtutorialsx.wordpress.com › 2018 › 06 › 02 › python-opencv-converting-an-image-to-gray-scale
Python OpenCV: Converting an image to gray scale – techtutorialsx
January 25, 2025 - You also need to install Numpy, which can be done with pip, the Python package manager, by sending the following command on the command line: ... To get started, we need to import the cv2 module, which will make available the functionalities ...
Top answer
1 of 5
216

I am promoting my comment to an answer:

The easy way is:

You could draw in the original 'frame' itself instead of using gray image.

The hard way (method you were trying to implement):

backtorgb = cv2.cvtColor(gray,cv2.COLOR_GRAY2RGB)

is the correct syntax.

2 of 5
18

Alternatively, cv2.merge() can be used to turn a single channel binary mask layer into a three channel color image by merging the same layer together as the blue, green, and red layers of the new image. We pass in a list of the three color channel layers - all the same in this case - and the function returns a single image with those color channels. This effectively transforms a grayscale image of shape (height, width, 1) into (height, width, 3)

To address your problem

I did some thresholding on an image and want to label the contours in green, but they aren't showing up in green because my image is in black and white.

This is because you're trying to display three channels on a single channel image. To fix this, you can simply merge the three single channels

image = cv2.imread('image.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_three = cv2.merge([gray,gray,gray])

Example

We create a color image with dimensions (200,200,3)

image = (np.random.standard_normal([200,200,3]) * 255).astype(np.uint8)

Next we convert it to grayscale and create another image using cv2.merge() with three gray channels

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_three = cv2.merge([gray,gray,gray])

We now draw a filled contour onto the single channel grayscale image (left) with shape (200,200,1) and the three channel grayscale image with shape (200,200,3) (right). The left image showcases the problem you're experiencing since you're trying to display three channels on a single channel image. After merging the grayscale image into three channels, we can now apply color onto the image

contour = np.array([[10,10], [190, 10], [190, 80], [10, 80]])
cv2.fillPoly(gray, [contour], [36,255,12])
cv2.fillPoly(gray_three, [contour], [36,255,12])

Full code

import cv2
import numpy as np

# Create random color image
image = (np.random.standard_normal([200,200,3]) * 255).astype(np.uint8)

# Convert to grayscale (1 channel)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Merge channels to create color image (3 channels)
gray_three = cv2.merge([gray,gray,gray])

# Fill a contour on both the single channel and three channel image
contour = np.array([[10,10], [190, 10], [190, 80], [10, 80]])
cv2.fillPoly(gray, [contour], [36,255,12])
cv2.fillPoly(gray_three, [contour], [36,255,12])

cv2.imshow('image', image)
cv2.imshow('gray', gray)
cv2.imshow('gray_three', gray_three)
cv2.waitKey()
🌐
Lindevs
lindevs.com › convert-rgb-image-to-grayscale-image-using-opencv
Convert RGB Image to Grayscale Image using OpenCV | Lindevs
April 2, 2023 - import cv2 img = cv2.imread('test.jpg') grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imshow('RGB image', img) cv2.imshow('Grayscale image', grayImg) cv2.waitKey(0) cv2.destroyAllWindows() #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat img = imread("test.jpg"); Mat grayImg; cvtColor(img, grayImg, COLOR_BGR2GRAY); imshow("RGB image", img); imshow("Grayscale image", grayImg); waitKey(0); destroyAllWindows(); return 0; }
🌐
Jeremy Morgan
jeremymorgan.com › tutorials › opencv › how-to-grayscale-image
Grayscaling Images Made Simple with OpenCV
We combine the three RGB channels into a single channel to convert an image to grayscale. To accomplish this, a weighted average is calculated taking into account each color’s sensitivity in the human eye. The formula is: ... Interesting right? That’s how we come up with grayscale images. OpenCV is an open-source computer vision library that provides a wide range of tools and techniques for image processing, including grayscaling.
🌐
Reddit
reddit.com › r/opencv › [question] how to turn a 3 channel grayscale image into a 1 channel grayscale image?
r/opencv on Reddit: [Question] How to turn a 3 channel grayscale image into a 1 channel grayscale image?
February 19, 2022 -

Hello

I have a 3 channel Grayscale image (28 by 28 pixel, .jpg) I want to turn it into 1 channel image, which means keep it grayscale, keep all the details and simply get rit of the 2 extra channels here is an example of what I have:

 file = r"path"  
test_image = cv2.imread(file)  
# Preview sample image  
plt.imshow(test_image) 

results:

image example
 print('shape of test_image: ', test_image.shape , ' height :',test_image.shape[0] , ' width :', test_image.shape[1]) 

 shape of test_image:  (28, 28, 3)  height : 28  width : 28 

PS: I m using OpenCV for image preprocessing and python 3.8

Thank you for your time!