espvolt
espvolt

Reputation: 58

How can I change the hue of a certain area with OpenCV-Python

i want to edit the hsv value of a certain area The picture I want to change color of

I to change all the purple parts of the image to green. Here is the result I made in an image editing software just to show a example.The Result Yeah i made it darker for no reason but i just wanna make the blade green but not the handle

Upvotes: 2

Views: 10286

Answers (2)

fmw42
fmw42

Reputation: 53182

Here is a way to do that in Python/OpenCV by shifting hues.

Input:

enter image description here

import cv2
import numpy as np

# load image with alpha channel
img = cv2.imread('sword_purple.png', cv2.IMREAD_UNCHANGED)

# extract alpha channel
alpha = img[:,:,3]

# extract bgr channels
bgr = img[:,:,0:3]

# convert to HSV
hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)
#h = hsv[:,:,0]
#s = hsv[:,:,1]
#v = hsv[:,:,2]
h,s,v = cv2.split(hsv)

# purple is 276 in range 0 to 360; so half in OpenCV
# green is 120 in range 0 to 360; so half in OpenCV
purple = 138
green = 60

# diff color (green - hue)
diff_color = green - purple

# modify hue channel by adding difference and modulo 180
hnew = np.mod(h + diff_color, 180).astype(np.uint8)

# recombine channels
hsv_new = cv2.merge([hnew,s,v])

# convert back to bgr
bgr_new = cv2.cvtColor(hsv_new, cv2.COLOR_HSV2BGR)

# put alpha back into bgr_new
bgra = cv2.cvtColor(bgr_new, cv2.COLOR_BGR2BGRA)
bgra[:,:,3] = alpha

# save output
cv2.imwrite('sword_alpha.png', alpha)
cv2.imwrite('sword_bgr.png', bgr)
cv2.imwrite('sword_bgr_new.png', bgr_new)
cv2.imwrite('sword_green.png', bgra)

# Display various images to see the steps
cv2.imshow('alpha',alpha)
cv2.imshow('bgr',bgr)
cv2.imshow('bgr_new',bgr_new)
cv2.imshow('bgra',bgra)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:

enter image description here

Upvotes: 4

fmw42
fmw42

Reputation: 53182

The simple way in Python/OpenCV is to create a mask where the image is purple using inRange() and then change the image to green where the mask is white using Numpy.

Input:

enter image description here

import cv2
import numpy as np

# load image with alpha channel
img = cv2.imread('sword_purple.png', cv2.IMREAD_UNCHANGED)

# extract alpha channel
alpha = img[:,:,3]

# extract bgr channels
bgr = img[:,:,0:3]

# select purple
lower_purple = (140,40,110)
upper_purple = (170,60,130)
mask = cv2.inRange(bgr, lower_purple, upper_purple)

# change the image to make it green where the mask is white
bgr_new = bgr.copy()
bgr_new[mask==255] = (0,255,0)

# put alpha back into rgb_new
bgra = cv2.cvtColor(bgr_new, cv2.COLOR_BGR2BGRA)
bgra[:,:,3] = alpha

# save output
cv2.imwrite('sword_alpha.png', alpha)
cv2.imwrite('sword_bgr.png', bgr)
cv2.imwrite('sword_mask.png', mask)
cv2.imwrite('sword_masked_green.png', bgr_new)
cv2.imwrite('sword_green.png', bgra)

# Display various images to see the steps
cv2.imshow('alpha',alpha)
cv2.imshow('mask',mask)
cv2.imshow('bgr_new',bgr_new)
cv2.imshow('bgra',bgra)
cv2.waitKey(0)
cv2.destroyAllWindows()

Alpha channel:

enter image description here

BGR channels:

enter image description here

Mask:

enter image description here

Recolored BGR channels:

enter image description here

Result with alpha channel put back:

enter image description here

Alternately, you can do the same by converting BGR to HSV and changing the purple to green the same way. Then convert back to BGR and put the alpha channel back.

Upvotes: 1

Related Questions