Manoj
Manoj

Reputation: 971

Open CV - Python RGB to GRAY convertor

I wanted to code this RGB to grayscale convertor without any inbuilt Open-CV function. This is how my code looks like

import cv2 , numpy
def GrayConvertor(img):


    rows , cols , layers = img.shape

    matrix = numpy.zeros((rows , cols))

    for i in range(rows):
        for j in range(cols):
            val = 0.114 * (img[i][j][0]) + 0.587 * (img[i][j][1]) + 0.299 * (img[i][j][2])
            fraction = val - int(val)
            if fraction >= 0.5:
                matrix[i][j] = (int(val) + 1) 

            else: 
                matrix[i][j] = int(val) 
    cv2.imshow("gray" , matrix)
    cv2.waitKey(0)

However it shows a blank image , Any ideas?

Upvotes: 3

Views: 2063

Answers (2)

Jaime
Jaime

Reputation: 67497

When you create your matrix array with np.zeros it is, by default, assigned dtype=float. So even though you round and convert your values to int, when writing them into matrixthey get stored as floats. If you read the docs for cv.imshow you will find the following:

  • If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].

So everything in your image is getting multiplied by 255, thus messing up your final result.

You can do two things:

  1. Have a floating point matrix, skip all the rounding, and divide your values by 255.
  2. Explicitly create your matrix with dtype='uint8' and leave everything unchanged.

There is also the fact that you are doing a very poor use of numpy's capabilities. The two options I gave you above, you can code with no loops or matrix assignments, as

rgb2k = np.array([0.114, 0.587, 0.299])
matrix_int = np.round(np.sum(img * rgb2k, axis=-1)).astype('uint8')
matrix_float = np.sum(img * rgb2k, axis=-1) / 255

Upvotes: 5

Abhishek Thakur
Abhishek Thakur

Reputation: 17025

try:

import cv2 , numpy
def GrayConvertor(img):


    rows , cols , layers = img.shape

    matrix = numpy.zeros((rows , cols))

    for i in range(rows):
        for j in range(cols):
            val = 0.114 * (img[i][j][0]) + 0.587 * (img[i][j][1]) + 0.299 * (img[i][j][2])
                matrix[i][j] = round(val) 
    cv2.imshow("gray" , matrix)
    cv2.waitKey(0)

Upvotes: 0

Related Questions