Convert BGR to RGB (Opencv)

Asked

Viewed 559 times

0

I have a code that finds the edges around what was labeled in the image and places the value of -1 in the pixels of that border found. I’m having trouble converting the image already with the edges -1 in its value, from BGR to RGB. because when trying to convert, the value -1 is lost and only find values 0 (rest) and 255 (labeled) in the saved image. I wanted to keep the values 0, -1, 255 when saving the image in RGB format.

Follows code:

import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib
import urllib.request
from PIL import Image

def mostrar_imagem(img):
    plt.imshow(img)
    plt.colorbar()
    plt.show()

img = cv2.imread('framepng/frame24.png',0)

kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img, kernel, iterations = 1)
img = cv2.dilate(erosion, kernel, iterations = 1)

_, binario = cv2.threshold(img, 90, 255, cv2.THRESH_BINARY)

copia = img.copy()

tmp = cv2.findContours(binario, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contornos = tmp[0] if len(tmp) == 2 else tmp[1]

img_contornos = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
mostrar_imagem(img_contornos)

cv2.drawContours(img_contornos, contornos, -1, (0, 255, 0), 1)
mask = cv2.inRange(img_contornos, (0, 254, 0), (0, 255, 0))
mostrar_imagem(mask)

binario = np.int16(binario)
binario[mask == 255] = -1
binario = np.ma.masked_where(binario == -1, binario)

cmap = matplotlib.cm.Greys  # Can be any colormap that you want after the cm
cmap.set_bad(color='red')

plt.show()
matplotlib.image.imsave('framepng-1/teste3.png', binario)
  • Try to convert the image to RGB before the use matplotlib to save the image.

  • I did just that, but as I said after doing that the value of -1 that is the edge that I mentioned above is lost. The current image I have inside the binary variable is with the colors purple (rest), white (border), yellow (labeled), my intention is only to change the colors, putting as purple = black, white and yellow = white.

1 answer

1


Problem

With img = cv2.imread('framepng/frame24.png',0) the image is converted to grayscale, because the flag 0 is used. With this, you lose all the color information that was present in the image.

Follow function mode flags imread():

cv::ImreadModes {
  cv::IMREAD_UNCHANGED = -1,
  cv::IMREAD_GRAYSCALE = 0,
  cv::IMREAD_COLOR = 1,
  cv::IMREAD_ANYDEPTH = 2,
  cv::IMREAD_ANYCOLOR = 4,
  cv::IMREAD_LOAD_GDAL = 8,
  cv::IMREAD_REDUCED_GRAYSCALE_2 = 16,
  cv::IMREAD_REDUCED_COLOR_2 = 17,
  cv::IMREAD_REDUCED_GRAYSCALE_4 = 32,
  cv::IMREAD_REDUCED_COLOR_4 = 33,
  cv::IMREAD_REDUCED_GRAYSCALE_8 = 64,
  cv::IMREAD_REDUCED_COLOR_8 = 65,
  cv::IMREAD_IGNORE_ORIENTATION = 128
}

Solution

If your image is in BGR and you want to convert to RGB, just use the following Python function:

img = img[:,:,::-1]

Or to improve the understanding of the code:

img_bgr = img_rgb[:,:,::-1]

Because an image is a matrix, with intensity values at each pixel coordinate. In the case of the RGB color space, each pixel will have a vector with 3 color channels, that is, 3 values. Then ::-1 is used to reverse the order of these values.

Or conversion directly by Opencv function:

img_rgb= cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

But I believe that this would not solve your problem the way the code is presented, what should be done is to read the image as colored img = cv2.imread('framepng/frame24.png',1) or the original image img = cv2.imread('framepng/frame24.png',-1). And then convert this image to grayscale with another variable name, for example, cinza = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY). So the color/original image is kept in memory and can be manipulated later.

That is, the color space used in the code is grayscale (1 channel) and not BGR (3 channels). Because the functions used, such as morphological operations (erode and dilate), among others, are used in grayscale and need an image in this color space as input. Then converting from BGR to RGB wouldn’t solve your problem, because that’s not the problem.

And when adding the value of -1 to the color image of 3 channels, it would not be possible to use the functions of Opencv, because its matrix would be hybrid with some pixels with 3 components and others with 1 component. Generating more errors in future processing in this image, what can be accomplished is the insertion of -1 in one of the channels or in the 3 channels, to maintain the image with 3 channels.

Read a little about the spaces of colors

  • Doing a full debug, I believe my image inside binary is grayscale, the real intention was to return the original colors to black and white, but keeping the changes made like putting the border a value of -1. Would it be possible to change the colours? I tried several ways but I can not keep the value, I think because I try to convert a 1 channel image into 3 channels and this value end up getting lost, as you said in the last paragraph. It would then be necessary to work and maintain a 3 channel image?

  • 1

    Yeah, keep it on three channels. But you are inserting -1, because it probably uses a function of some library that needs as input an image of only 1 channel.

  • Yeah, that’s the thing. You have some suggestion to change this code so that it continues working, but with 3 channels (keeping the value of -1 in the contours), I’m still at the beginning of image processing and I don’t have much notion.

Browser other questions tagged

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