4

I try to convert a RGB image to grayscale using python as a function but the problem is I give it a RGB image that have height, width and channel but after the code I should have an image with just height and width but it gives me an image with height, width and channel why?

def RGBtoGRAY(img):
    height, width, channels = img.shape
    grayimg = img
    for i in range(height):
        for j in range(width):
            grayimg[i,j] = 0.3 * image[i,j][0] + 0.59 * image[i,j][1] +  0.11 * image[i,j][2]
    return grayimg

the size of the input image is

image.shape 
(533, 541, 3)

the size of the output image is

grayimage.shape 
(533, 541, 3)

normally I want to find in the size of the output image

(533, 541)
2
  • 2
    grayimg = img isn't creating a new image. It just takes the reference of the input. You want to create a new image with the same dimensions. Commented Mar 9, 2020 at 20:47
  • Does e.g. stackoverflow.com/questions/37203970/… help? Commented Mar 9, 2020 at 20:50

2 Answers 2

3

You should avoid using for loops when performing image processing since it is very slow. Instead you can use Numpy which is highly optimized for vector operations. Using this grayscale conversion formula:

gray = R * .299 + G * .587 + B * .114

Method #1: apply_along_axis:

import cv2
import numpy as np

def grayscale(colors):
    r, g, b = colors
    return 0.299 * r + 0.587 * g + 0.114 * b

# Create image of size 100x100 of random pixels
# Convert to grayscale
image = np.random.randint(255, size=(100,100,3),dtype=np.uint8)
gray = np.apply_along_axis(grayscale, 2, image)

# Display
cv2.imshow('image', image)
cv2.imshow('gray', gray)
cv2.waitKey()

Before -> After

enter image description here enter image description here

Method #2: cv2.cvtColor

You could use OpenCV directly and read in the image as grayscale with cv2.imread by passing in the cv2.IMREAD_GRAYSCALE or 0 flag to load the image as grayscale.

image = cv2.imread('img.png', cv2.IMREAD_GRAYSCALE) # OR
# image = cv2.imread('img.png', 0)

If you already have the image loaded, you can convert the RGB or BGR image to grayscale using cv2.cvtColor

image = cv2.imread('img.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Sign up to request clarification or add additional context in comments.

Comments

0

Assuming you are using a for loop, because you intent to solve it "manually" (like C code), there are number of issues with your implementation:

  • The assignment grayimg = img in Python does not create a copy of img (the result is that grayimg referencing img).
    You meant to use: grayimg = img.copy().
  • img has 3 dimensions, so when using grayimg = img, grayimg also has 3 dimensions.
    You need to create grayimg with two dimensions.
    Example for creating grayimg and initialize to zeros:

    grayimg = np.zeros((height, width), img.dtype)
    
  • Inside the for loop, you are using image instead of img.

Here is a corrected version of RGBtoGRAY:

def RGBtoGRAY(img):
    height, width, channels = img.shape
    #grayimg = img
    # Create height x width array with same type of img, and initialize with zeros.
    grayimg = np.zeros((height, width), img.dtype)
    for i in range(height):
        for j in range(width):
            grayimg[i,j] = 0.3 * img[i,j][0] + 0.59 * img[i,j][1] +  0.11 * img[i,j][2]
    return grayimg

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.