Search code examples
pythonopencvcolorspicker

Changing color of a specific object in an image using Opencv


I want to change the color of sofa in the given image:

enter image description here

Background remains same, only color of the sofa need to be changed. I have tried with masking technique but couldn't get the needed color. I am giving sample color.

enter image description here

Please, let me know if there are any easy techniques to customise the color of sofa.

I have already tried by changing the hue. I am not able to get the needed color by changing the hue using openCV library. If that is possible using CSS and Javascript, that is also fine.

Thanks in advance.

FYI Code is below:

import cv2
import numpy as np
from google.colab.patches import cv2_imshow
 
image = cv2.imread('/content/bluesofa.jpg')
cv2_imshow(image)
 
result = image.copy()
 
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
 
# lower boundary Blue color range values; Hue (100 - 110)
lower1 = np.array([90, 100, 20])
upper1 = np.array([100, 255, 255])
 
# upper boundary Blue color range values; Hue (120 - 130)
lower2 = np.array([100,100,20])
upper2 = np.array([120,255,255])
 
lower_mask = cv2.inRange(image, lower1, upper1)
upper_mask = cv2.inRange(image, lower2, upper2)
 
full_mask = lower_mask + upper_mask;
 
result = cv2.bitwise_and(result, result, mask=full_mask)
 
cv2_imshow(full_mask)
cv2.imwrite('masked_object.jpg',result)

img= cv2.imread('/content/masked_object.jpg')

img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# extract the hue channel from the hsv image
hue = img_hsv[:,:,0]

# increment the hue values by 60(random number,could be any number)
hue = hue  + 60


# if pixel values become > 180, subtract 180 
cond_h = hue[:, :] > 180
hue[cond_h] = hue[cond_h] - 180

# assign the modified hue channel to hsv image

img_hsv[:,:,0] = hue


im = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)

result = cv2.bitwise_or(original_img,im)

cv2_imshow(result)

Solution

  • Here is a very basic example on how you can modify hue, saturation and value of a masked object:

    import cv2
    import numpy as np
    
    
    img = cv2.imread('bluesofa.jpg')
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
    lower = np.array([90, 100, 20])
    upper = np.array([120, 255, 255])
    
    mask = cv2.inRange(hsv, lower, upper)
    inv_mask = cv2.bitwise_not(mask)
    
    h, s, v = cv2.split(hsv)
    h = np.mod(h + 170, 180)
    s = np.clip(s - 100, 0, 255)
    v = np.clip(v + 40, 0, 255)
    hsv = cv2.merge([h, s, v])
    
    bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    
    result = cv2.bitwise_or(cv2.bitwise_and(img, img, mask=inv_mask), cv2.bitwise_and(bgr, bgr, mask=mask))
    
    cv2.imwrite("out.jpg", result)
    

    Output:

    enter image description here