How to improve/optimize a color image conversion code to grayscale

Asked

Viewed 269 times

5

I am testing turn a black and white image on the nail and managed using the following code.

import cv2

imagem = cv2.imread("goku-jr.jpg")


for coluna in imagem:
    for pixel in coluna:
        media = int(sum(pixel)/3)
        pixel [0] = media
        pixel [1] = media
        pixel [2] = media

cv2.imwrite("teste_cinza.jpg",imagem)

inserir a descrição da imagem aqui

inserir a descrição da imagem aqui

I know this isn’t the best way to turn it into grayscale, but I used this method for study. What bothered me was the inside out, there is some possibility to write this code in a more performative and elegant way?

Note: I don’t know if I can use this type of image , anything I delete.

  • What would be the object imagem2?

  • I got the name wrong.

  • 2

    About the for within the for: there is no problem with this. In the amount of pixels, your program runs in linear time. It just so happens that to see the pixels, you need to navigate the columns separately, but this does not imply that your program runs in quadratic time relative to the number of pixels. I talk about it more in that reply

  • I think you can use the itertools module, it has the chain, but it will only decrease a line in your code, or even that, if you count the import

  • "On the nail" means that cv2.cvtColor(imagem, cv2.COLOR_BGR2GRAY) does not serve?

1 answer

3


Problem

An image is an array, so you can use Python or a library, like Numpy, to avoid using for loops.

Gazing the grayscale Wiki, it is possible to check the following formula: Y = 0.2126 * R + 0.7152 * G + 0.0722 * B.

Python can be used with Slice in the matrix. Where each pixel of an image is composed as follows [linha, coluna, canal]. And an image in the RGB color space has three channels, R,G and B. Therefore, each pixel has an array representing the channel (R,G,B).

But note that Opencv uses BGR by default ((B,G,R))

Then it is possible to check the optimization with the following code:

import time
import cv2
import numpy as np
import urllib.request


# Carregar imagem da internet
resp = urllib.request.urlopen("https://i.stack.imgur.com/OWQJc.jpg")
imagem = np.asarray(bytearray(resp.read()), dtype="uint8")
imagem = cv2.imdecode(imagem, cv2.IMREAD_COLOR)

# Carregar imagem do PC
# imagem = cv2.imread("goku-jr.jpg")

# FOR LOOPS

start_time = time.time()

for coluna in imagem:
    for pixel in coluna:
        media = int(sum(pixel)/3)
        pixel [0] = media
        pixel [1] = media
        pixel [2] = media

cv2.imwrite("OWQJc1.jpg",imagem)
print("--- %s segundos ---" % (time.time() - start_time))

# MATRIZES E ARRAYS

# Carregar imagem da internet
resp = urllib.request.urlopen("https://i.stack.imgur.com/OWQJc.jpg")
imagem = np.asarray(bytearray(resp.read()), dtype="uint8")
imagem = cv2.imdecode(imagem, cv2.IMREAD_COLOR)

# Carregar imagem do PC
# imagem = cv2.imread("goku-jr.jpg")

start_time = time.time()

imagem = 0.0722 * imagem[:, :, 0] + 0.7152 * imagem[:, :, 1] + 0.2126 * imagem[:, :, 2]
imagem = imagem.astype(np.uint8)

cv2.imwrite("OWQJc2.jpg",imagem)
print("--- %s segundos ---" % (time.time() - start_time))

Upshot

On my computer, the following result was obtained:

--- 0.2000114917755127 segundos ---
--- 0.008000612258911133 segundos ---

It is possible to verify that the method using the for loops is slightly wrong by comparing the following images:

Result 1:

resultado for loops

Score 2:

Resultado Matrizes

Browser other questions tagged

You are not signed in. Login or sign up in order to post.