Casm
Casm

Reputation: 65

How can I change background color to red of an image using Python

I have the following code that works great but it doesn't fill all background. I played with numbers but it either makes all image red or not changing the background.
How can I change the background color of the image?

Picture i want to change its background]:
enter image description here

import cv2
import numpy as np
from google.colab import drive
drive.mount('/content/drive')
image=cv2.imread('/content/drive/MyDrive/tulips.jpg')
r = 720.0 / image.shape[1]
dim = (720, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
lower_white = np.array([80, 1, 1],np.uint8) #lower hsv value
upper_white = np.array([130, 255, 255],np.uint8) #upper hsv value
hsv_img = cv2.cvtColor(resized,cv2.COLOR_BGR2HSV)#rgb to hsv color space
#filter the background pixels 

frame_threshed = cv2.inRange(hsv_img, lower_white, upper_white) 

kernel = np.ones((5,5),np.uint8) 

dilation = cv2.dilate(frame_threshed,kernel,iterations = 2)
resized[dilation==255] = (0,0,255) #convert background color
cv2_imshow(resized)

after this code i get this image:
enter image description here

Upvotes: 4

Views: 9871

Answers (1)

Rotem
Rotem

Reputation: 32144

I thought we can simply use cv2.floodFill, and fill the white background with red color.
The issue is that the image is not clean enough - there are JPEG artifacts, and rough edges.

Using cv2.inRange may bring us closer, but assuming there are some white tulips (that we don't want to turn into red), we may have to use floodFill for filling only the background.

I came up with the following stages:

  • Convert from RGB to HSV color space.
  • Apply threshold on the saturation channel - the white background is almost zero in HSV color space.
  • Apply opening morphological operation for removing artifacts.
  • Apply floodFill, on the threshold image - fill the background with the value 128.
    The background is going to be 128.
    Black pixels inside the area of the tulips is going to be 0.
    Most of the tulips area stays white.
  • Set all pixels where threshold equals 128 to red.

Code sample:

import cv2
import numpy as np
image = cv2.imread('tulips.jpg')

# Fill the black background with white color
#cv2.floodFill(image, None, seedPoint=(0, 0), newVal=(0, 0, 255), loDiff=(2, 2, 2), upDiff=(2, 2, 2))  # Not working!

hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # rgb to hsv color space

s_ch = hsv_img[:, :, 1]  # Get the saturation channel

thesh = cv2.threshold(s_ch, 5, 255, cv2.THRESH_BINARY)[1]  # Apply threshold - pixels above 5 are going to be 255, other are zeros.
thesh = cv2.morphologyEx(thesh, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7)))  # Apply opening morphological operation for removing artifacts.

cv2.floodFill(thesh, None, seedPoint=(0, 0), newVal=128, loDiff=1, upDiff=1)  # Fill the background in thesh with the value 128 (pixel in the foreground stays 0.

image[thesh == 128] = (0, 0, 255)  # Set all the pixels where thesh=128 to red.

cv2.imwrite('tulips_red_bg.jpg', image)  # Save the output image.

s_ch (saturation color channel):
enter image description here

thesh after morphological opening, and floodFill:
enter image description here

Output image:
enter image description here

Upvotes: 3

Related Questions