What does cv2.COLOR_GRAY2RGB do? - opencv

I happened to encounter this API cv2.COLOR_GRAY2RGB. I found it strange because there should have no way to convert an grey scale image to RGB image. So I tried something like this:
I took an image like this:
The image is shown by plt.imshow(img) (with default arguments).
Then I convert it into grey scale with cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) and get this:
I know it does not appear grey-scale looking is because imshow() by default is not displaying grey-scale image (more like heat-map I think). So I used cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) and got this:
It appears grey to out eyes despite it has three channels now. So I conclude that cv2.COLOR_GRAY2RGB is a walk-around to display grey-scale image in grey-scale fashion without changing the settings for imshow().
Now my question is, when I use cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) again to convert this three-channel gray image back to one channel, the pixel value is exactly the same as the first time I converted the original image into one channel with cv2.cvtColor(img, cv2.COLOR_BGR2GRAY):
In other words, cv2.COLOR_BGR2GRAY can do a many-to-one mapping. I wonder how is that possible.

COLOR_BGR2GRAY color mode estimates a gray value for each pixel using a weighted sum of B, G, R channels, w_R*R+w_G*G+w_B*B=Y per pixel. So any 3 channel image becomes 1 channel.
COLOR_GRAY2BGR color mode basically replaces all B, G, R channels with the gray value Y, so B=Y, G=Y, R=Y. It converts a single channel image to multichannel by replicating.
More documentation about color modes are here.

Related

Calculating image brightness using BGR color and B channel

I was trying to calculate if an image is bright or dark using mean value and by mistake I forgot to convert my BGR image to LAB and extract the LAB channel. Instead I extracted the B channel in BGR image. What surprised me when I tested this method in my labeled images it shows high accuracy, recall and precision. So when I tried to show the image to check what color it is, it shows a grayscale image (I'm not sure why I expected an image with more blue color). When I read about BGR and calculating brightness of an image it always mentioned calculating the mean value for all the channels. So how is this possible?
The images are of underwater environment
img = cv2.imread("image.jpg")
#conv_image = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l_channel, _, _ = cv2.split(img)
img = l_channel
cv2.imshow("Result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Converting colored image to grayscale

I am working on processing images that consists of colors that have the same grayscale. In other words, each image is colored with random colors that have the same gray value.
When I converted the image using (rgb2grey() from skimage or cv2.cvtColor() from OpenCV), the resulted image has only one gray value (or slightly difference gray values (unperceivable by human eyes). Therefore, the resulted image details unrecognizable.
My questions are:
What are the best way to do before converting these images to grayscale ones? (Please note the colors of these images are not fixed)
Are there any color combinations for which the color-gray conversion algorithms won't work?
How about using YCbCr?
Y is intensity, Cb is the blue component relative to the green component and Cr is the red component relative to the green component.
So I think YCbCr can differentiate between multiple pixels with same grayscale value.

Convert image to grayscale with custom luminosity formula

I have images containing gray gradations and one another color. I'm trying to convert image to grayscale with opencv, also i want the colored pixels in the source image to become rather light in the output grayscale image, independently to the color itself.
The common luminosity formula is smth like 0.299R+0.587G+0.114B, according to opencv docs, so it gives very different luminosity to different colors.
I consider the solution is to set some custom weights in the luminosity formula.
Is it possible in opencv? Or maybe there is a better way to perform such selective desaturation?
I use python, but it doesnt matter
This is the perfect case for the transform() function. You can treat grayscale conversion as applying a 1x3 matrix transformation to each pixel of the input image. The elements in this matrix are the coefficients for the blue, green, and red components, respectively since OpenCV images are BGR by default.
im = cv2.imread(image_path)
coefficients = [1,0,0] # Gives blue channel all the weight
# for standard gray conversion, coefficients = [0.114, 0.587, 0.299]
m = np.array(coefficients).reshape((1,3))
blue = cv2.transform(im, m)
So you have custom formula,
Load source,
Mat src=imread(fileName,1);
Create gray image,
Mat gray(src.size(),CV_8UC1,Scalar(0));
Now in a loop, access BGR pixel of source like,
Vec3b bgrPixel=src.at<cv::Vec3b>(y,x); //gives you the BGR vector of type cv::Vec3band will be in row, column order
bgrPixel[0]= Blue//
bgrPixel[1]= Green//
bgrPixel[2]= Red//
Calculate new gray pixel value using your custom equation.
Finally set the pixel value on gray image,
gray.at<uchar>(y,x) = custom intensity value // will be in row, column order

Why do we convert from RGB to HSV

I have a image and i want to detect a blue rectange in it. My teacher told me that:
convert it to HSV color model
define a thresh hold to make it become a binary image with the color we want to detect
So why do we do that ? why don't we direct thresh hold the rgb image ?
thanks for answer
You can find the answer to your question here
the basic summary is that HSV is better for object detection,
OpenCV usually captures images and videos in 8-bit, unsigned integer, BGR format. In other words, captured images can be considered as 3 matrices, BLUE,RED and GREEN with integer values ranges from 0 to 255.
How BGR image is formed
In the above image, each small box represents a pixel of the image. In real images, these pixels are so small that human eye cannot differentiate.
Usually, one can think that BGR color space is more suitable for color based segmentation. But HSV color space is the most suitable color space for color based image segmentation. So, in the above application, I have converted the color space of original image of the video from BGR to HSV image.
HSV color space is consists of 3 matrices, 'hue', 'saturation' and 'value'. In OpenCV, value range for 'hue', 'saturation' and 'value' are respectively 0-179, 0-255 and 0-255. 'Hue' represents the color, 'saturation' represents the amount to which that respective color is mixed with white and 'value' represents the amount to which that respective color is mixed with black.
According to http://en.wikipedia.org/wiki/HSL_and_HSV#Use_in_image_analysis :
Because the R, G, and B components of an object’s color in a digital image are all correlated with the amount of light hitting the object, and therefore with each other, image descriptions in terms of those components make object discrimination difficult. Descriptions in terms of hue/lightness/chroma or hue/lightness/saturation are often more relevant.
Also some good info here
The HSV color space abstracts color (hue) by separating it from saturation and pseudo-illumination. This makes it practical for real-world applications such as the one you have provided.
R, G, B in RGB are all co-related to the color luminance( what we loosely call intensity),i.e., We cannot separate color information from luminance. HSV or Hue Saturation Value is used to separate image luminance from color information. This makes it easier when we are working on or need luminance of the image/frame. HSV also used in situations where color description plays an integral role.
Cheers

how to convert an image from BGR to LAB with opencv 2.4 python 2.7 and numpy

I am working with opencv 2.4 and numpy. I would like to open an image and get all the information about it (8 bit - if its RGB-BGR etc) and also try to change the color space.
I have this code:
if __name__ == '__main__':
img = cv2.imread('imL.png')
conv= cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
cv2.imwrite('lab.png', conv )
When I open the file lab.png I get the image with different colors!
I check the value of BGR to LAB in: http://www.brucelindbloom.com/
For this I would like to know all the information about one image.
That rigtht you will get a different image colour because imwrite() saves file in the format specified (PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with ‘BGR’ channel order). images can be saved using this function. imwrite() doesn't know the format LAB to save image as it always expect the image in BGR.
If the format, depth or channel order is different, use Mat::convertTo() , and cvtColor() to convert it before saving.
Lab is another color space, like the BGR color space which is gained from cv2.imread(). It just like you convert temperature from Fahrenheit to Celsius.
32 Fahrenheit and 0 Celsius is the same temperature but in different unit.
cv2.imwrite() dose not know if the values are in BGR color space or not. When it get a 3 dimension array, it assume that it is a BGR color space while your conv variable contains Lab color space. This is why your color of your image is changed.
For your information, Each layer of BGR color space contains blue, green and red colors while layers of Lab contains lightness (0-100), a* and b* respectively. For more information, please see "Lab color space" in Wikipedia.

Resources