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):

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

is the correct syntax.

Answer from Anoop K. Prabhu on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › computer vision › how-to-convert-a-grayscale-image-to-rgb-in-opencv
How to convert a grayscale image to RGB in OpenCV - GeeksforGeeks
July 23, 2025 - # Load the grayscale image ... grayscale_image is None: print("Error: Could not load image.") Convert the grayscale image to RGB format using OpenCV's cvtColor function....
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):

Copybacktorgb = 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

Copyimage = 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)

Copyimage = (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

Copygray = 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

Copycontour = 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

Copyimport 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()
Discussions

python - Opencv - Grayscale mode Vs gray color conversion - Stack Overflow
For a format such as JPEG, which ... 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 ... More on stackoverflow.com
🌐 stackoverflow.com
[Question] Grayscale to bgr/rgb
How would you propose recovering the BGR values from a 0-255 channel? There is just not enough information to convert from a grayscale image to a true color image. There are reasons to perform operations on a grayscale image in BGR or color space and that is why the conversion function exists. All the conversation will do is make each channel in the BGR image the same gray image. More on reddit.com
🌐 r/opencv
3
1
November 15, 2023
Convert Image Color from Grayscale to RGB OpenCV C++ - Stack Overflow
Basically I am trying to convert the below output image to color(RGB). The image that this code currently outputs is grayscale, however, for my application I would like it to be output as color. Pl... More on stackoverflow.com
🌐 stackoverflow.com
Converting Grayscale to Color Image using Color Maps
Mathematically, you can't. Grayscale has 0-255 values. RGB has 256x256x256. The only way to map something is to use external information. For example, if your scene has sky, you can assume that a grayscale value where the sky is maps to a blue-ish tone. That would help resolve some ambiguity elsewhere. This is what AI does to re-colorize photographs. It makes guesses on pixel colors based on the structure of the image, which it learns from training. It can make mistakes. You can reverse calculate if you want. There is a formula to convert RGB to grayscale (easy to find on the internet). So from there, you can see where the same grayscale value will revert to two or more RGB values. Same goes with other colorspaces that use more than one channel to define a color. Edit: Looking at your other post, you seem to not really need accuracy, just straight conversion from 0-255 to whatever colormap you need. In this case, my answer above is not applicable (but keeping it here for other info on a general grayscale to RGB attempt). If the colormap are neighbors in the colorwheel (e.g., the H in HSV), you could try a basic ratio and proportion using the grayscale and pick the color from the H range. More on reddit.com
🌐 r/learnpython
3
2
February 11, 2024
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-grayscaling-of-images-using-opencv
Python | Grayscaling of Images using OpenCV - GeeksforGeeks
September 23, 2025 - This produces visually more accurate grayscale than simple averaging, but is still slower than OpenCV’s native conversions. This method converts an image to grayscale by averaging the contributions of color channels (RGB).
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 76466 › convert-grayscale-to-rgb
convert grayscale to RGB? - OpenCV Q&A Forum
November 16, 2015 - I tried using cvtColor but, i seem to get an black image as output. ... If you use cv::cvtColor(gray, color, cv::COLOR_GRAY2BGR) you should get a 3 channel image but there are no colors, because all the channels have the same value as the gray image. Except if your gray image is not a normal ...
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.

🌐
Dev-akash
dev-akash.in › blogs › how-to-convert-color-image-to-grayscale-in-opencv
How to convert color image to grayscale in OpenCV
import cv2 # Reading color image ... for key event cv2.waitKey(0) # destroying all windows cv2.destroyAllWindows() cvtColor() function in OpenCV is very helpful in converting color channels from one to another such as BRG ...
Find elsewhere
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 131161 › transform-16bit-grayscale-to-rgb-with-constants
transform 16bit grayscale to RGB with constants - OpenCV Q&A Forum
I have 3 constant values (all between 0-1) one for each of R, G and B, which when multiplied by the original grayscale value and scaled to 0-255, becomes the R, G and B values.
🌐
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 - Grayscale images contain varying shades of gray, representing intensity levels, while RGB images use red, green, and blue channels to depict a wider range of colors. Converting grayscale images to RGB is crucial for appli ... Creating videos from multiple images is a great way for creating time-lapse videos. In this tutorial, we’ll explore how to create a video from multiple images using Python and OpenCV.
🌐
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 - The grayscaling process simply translates to converting an image to shades of gray. The shade of gray varies between complete black and complete white. 1. Reducing the dimension of the images: RGB images have three color channels and constitute a three-dimensional matrix, while in grayscale images, there is no additional parameter for color channels and are only single-dimensional.
🌐
DataFlair
data-flair.training › blogs › image-conversion-using-opencv
Image Conversion using OpenCV - Colored, Grayscale and Binary - DataFlair
March 2, 2024 - The cv2.COLOR_BGR2GRAY flag is ... it maps the color image to a single-channel grayscale image by calculating the weighted sum of the RGB values for each pixel....
Top answer
1 of 4
24

This is currently set up to expect a grayscale image as input. I think that you are asking how to adapt it to accept a colour input image and return a colour output image. You don't need to change much:

cv::Mat CVCircles::detectedCirclesInImage(cv::Mat img, double dp, double minDist, double  param1, double param2, int min_radius, int max_radius) {

  if(img.empty())
        {
        cout << "can not open image " << endl;
        return img;
        }
  Mat img;

  if (img.type()==CV_8UC1) {
              //input image is grayscale
    cvtColor(img, cimg, CV_GRAY2RGB);

  } else {
              //input image is colour
    cimg = img;
    cvtColor(img, img, CV_RGB2GRAY);
  }

the rest stays as is.

If your input image is colour, you are converting it to gray for processing by HoughCircles, and applying the found circles to the original colour image for output.

2 of 4
1

The cvtImage routine will simply copy your gray element to each of the three elements R, G, and B for each pixel. In other words if the pixel gray value is 26, then the new image will have R = 26, G = 26, B = 26.

The image presented will still LOOK grayscale even though it contains all 3 color components, all you have essentially done is to triple the space necessary to store the same image.

If indeed you want color to appear in the image (when you view it), this is truly impossible to go from grayscale back to the ORIGINAL colors. There are however means of pseudo-coloring or false coloring the image.

http://en.wikipedia.org/wiki/False_color

http://blog.martinperis.com/2011/09/opencv-pseudocolor-and-chroma-depth.html

http://podeplace.blogspot.com/2012/11/opencv-pseudocolors.html

🌐
CloudxLab
cloudxlab.com › assessment › displayslide › 5526 › bgr-to-rgb-and-grayscale
BGR to RGB and Grayscale | Automated hands-on| CloudxLab
We could fix this issue by using cv2.COLOR_BGR2RGB transformation effect on the image. So, we shall define a function fixColor to return the RGB form of the given image. Also, let us get the gray-scle form of the two images.
🌐
Medium
korlakuntasaikamal10.medium.com › gray-scale-and-color-images-using-opencv-eda0c13c292a
Gray Scale and Color Images using OpenCV | by kamal_DS | Medium
January 24, 2023 - You can see RGB channels where the R channel is a grayscale individually, the G channel is grayscale and even the B channel is grayscale individually. for example in the above image, u can see the first value 255 in the R channel and 0 in the green channel, and 255 in the blue channel is going to check in the RGB color space
🌐
TutorialsPoint
tutorialspoint.com › opencv › opencv_colored_images_to_grayscale.htm
OpenCV - Colored Images to GrayScale
The class named Imgproc of the package org.opencv.imgproc provides methods to convert an image from one color to another. A method named cvtColor() is used to convert colored images to grayscale. Following is the syntax of this method.
🌐
MathWorks
mathworks.com › computer vision toolbox
Convert RGB Image to Grayscale Image by Using OpenCV Importer - MATLAB & Simulink
To build the OpenCV libraries, identify a compatible C++ compiler for your operating system, as described in Portable C Code Generation for Functions That Use OpenCV Library. Configure the identified compiler by using the mex -setup c++ command. For more information, see Choose a C++ Compiler. This example uses the Simulink model ToGrayScale.slx. In this model, the subsystem_slwrap_toGrayScale subsystem resides in the RGBtoGRAY_Lib library.
🌐
TutorialsPoint
tutorialspoint.com › converting-an-image-from-colour-to-grayscale-using-opencv
Converting an image from colour to grayscale using OpenCV
March 17, 2021 - In this program, we will change the color scheme of an image from rgb to grayscale Algorithm Step 1: Import OpenCV. Step 2: Read the original image using imread(). Step 3: Convert to grayscale using cv2.c
🌐
OpenCV
docs.opencv.org › 3.4 › d8 › d01 › group__imgproc__color__conversions.html
OpenCV: Color Space Conversions
The function converts an input image from one color space to another. In case of a transformation to-from RGB color space, the order of the channels should be specified explicitly (RGB or BGR). Note that the default color format in OpenCV is often referred to as RGB but it is actually BGR (the ...
🌐
Jeremy Morgan
jeremymorgan.com › tutorials › opencv › how-to-grayscale-image
Grayscaling Images Made Simple with OpenCV
March 23, 2023 - You’ve successfully grayscaled an image using OpenCV and Python. Grayscaling converts a colorful image into a monochrome representation by assigning each pixel a single intensity value.