How to create the image of an hsv disk with python (opencv and numpy)

43 Views Asked by At

Can anyone create a code using only opencv and numpy that generates the image of an HSV disk of size 500 x 500, similar to the image below: HSV DISK

I tried a few times but I can't do it, the disc wasn't coming out with all the colors

1

There are 1 best solutions below

0
Mark Setchell On

Updated Answer

I found some time to make more of an answer. It is not perfect, but it should be 95% of what you want, and you can fiddle with it to get the rotation, scaling and saturation you want:

#!/usr/bin/env python3

import numpy as np
import cv2 as cv

# Define length of side
N = 600

# Make grid to calculate Hue angles and radius
xx, yy = np.meshgrid(np.linspace(-1, 1, N), np.linspace(-1, 1, N))
H = (np.arctan2(xx, yy) + np.pi) / (np.pi * 2)
R = np.sqrt(xx ** 2 + yy ** 2)
# Scale to range 0..180 because OpenCV likes Hue in that range for np.uint8
H = (H * 180).astype(np.uint8)

# Generate Saturation and Value channels
S = np.full((600,600), 255, np.uint8)   # Solid white
V = np.full((600,600), 128, np.uint8)   # Solid mid-grey

cv.imwrite('DEBUG-H.png', H)
cv.imwrite('DEBUG-S.png', S)
cv.imwrite('DEBUG-V.png', V)

# Stack depthwise and convert to BGR
HSV = np.dstack((H,S,V))
BGR = cv.cvtColor(HSV, cv.COLOR_HSV2BGR)

# Make everything black outside unit circle
BGR[R>1] = 0

cv.imwrite('result.png', BGR)

enter image description here

Original Answer

I don't have time at the minute to write the code for you, but you would want to make 3 separate grayscale images like this:

Hue (H):

enter image description here

Saturation (S): (solid white):

enter image description here

Value (V): (solid mid-grey):

enter image description here

Then depth-stack them together to make a 3-channel HSV from the three individual H, S and V channels:

HSV = np.dstack((H, S, V))

Then convert to BGR:

BGR = cv2.cvtColor(HSV, cv2.COLOR_HSV2BGR)

That will make this:

enter image description here


Remember that the Hue channel should be a np.uint8 and range from 0..180, rather than the 0..360 you might expect. This is to ensure it fits in the range of an unsigned char.