Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import warnings | |
| def rgb_to_hsv(rgb): | |
| with warnings.catch_warnings(): | |
| # Suppress the specific RuntimeWarning | |
| warnings.filterwarnings( | |
| "ignore", category=RuntimeWarning, message="invalid value encountered in divide") | |
| # Ensure the input is a float numpy array and in the range [0, 1] | |
| rgb = np.asarray(rgb) | |
| # Separate the R, G, B channels | |
| r, g, b = rgb[..., 0], rgb[..., 1], rgb[..., 2] | |
| # Max and min of RGB values | |
| max_rgb = np.max(rgb, axis=-1) | |
| min_rgb = np.min(rgb, axis=-1) | |
| delta = max_rgb - min_rgb | |
| # Hue calculation | |
| hue = np.zeros_like(max_rgb) | |
| # Avoid division by zero: Only calculate where delta is non-zero | |
| mask = delta != 0 | |
| # Red is max | |
| idx = (max_rgb == r) & mask | |
| hue[idx] = (60 * ((g - b) / delta % 6))[idx] | |
| # Green is max | |
| idx = (max_rgb == g) & mask | |
| hue[idx] = (60 * ((b - r) / delta + 2))[idx] | |
| # Blue is max | |
| idx = (max_rgb == b) & mask | |
| hue[idx] = (60 * ((r - g) / delta + 4))[idx] | |
| # Saturation calculation | |
| saturation = np.zeros_like(max_rgb) | |
| saturation[mask] = delta[mask] / max_rgb[mask] | |
| # Handle the edge case where max_rgb is 0 (black pixels) | |
| saturation[max_rgb == 0] = 0 | |
| # Value calculation | |
| value = max_rgb | |
| # Stack the HSV components together | |
| hsv = np.stack((hue, saturation, value), axis=-1) | |
| return hsv | |
| def hsv_to_rgb(hsv): | |
| # Ensure the input is a float numpy array and in the range [0, 1] | |
| hsv = np.asarray(hsv) | |
| # Separate the H, S, V channels | |
| h, s, v = hsv[..., 0], hsv[..., 1], hsv[..., 2] | |
| # Chromaticity component | |
| c = v * s | |
| x = c * (1 - np.abs((h / 60) % 2 - 1)) | |
| m = v - c | |
| # Initialize RGB | |
| r, g, b = np.zeros_like(h), np.zeros_like(h), np.zeros_like(h) | |
| # Compute the RGB components based on the hue range | |
| h0_60 = (h >= 0) & (h < 60) | |
| r[h0_60], g[h0_60], b[h0_60] = c[h0_60], x[h0_60], 0 | |
| h60_120 = (h >= 60) & (h < 120) | |
| r[h60_120], g[h60_120], b[h60_120] = x[h60_120], c[h60_120], 0 | |
| h120_180 = (h >= 120) & (h < 180) | |
| r[h120_180], g[h120_180], b[h120_180] = 0, c[h120_180], x[h120_180] | |
| h180_240 = (h >= 180) & (h < 240) | |
| r[h180_240], g[h180_240], b[h180_240] = 0, x[h180_240], c[h180_240] | |
| h240_300 = (h >= 240) & (h < 300) | |
| r[h240_300], g[h240_300], b[h240_300] = x[h240_300], 0, c[h240_300] | |
| h300_360 = (h >= 300) & (h < 360) | |
| r[h300_360], g[h300_360], b[h300_360] = c[h300_360], 0, x[h300_360] | |
| # Add m to each component and stack them together | |
| rgb = np.stack((r + m, g + m, b + m), axis=-1) | |
| return rgb | |
| def test_conversion(): | |
| # RGB array example (range [0, 1]) | |
| rgb = np.array([[[0.5, 0.4, 0.7], [0.1, 0.2, 0.3]], | |
| [[0.8, 0.7, 0.6], [0.9, 0.1, 0.2]]]) | |
| # rgb = np.random.rand(1000, 100, 3) | |
| # Convert RGB to HSV | |
| hsv = rgb_to_hsv(rgb) | |
| print(hsv.shape) | |
| # Convert HSV back to RGB | |
| rgb_back = hsv_to_rgb(hsv) | |
| assert np.allclose(rgb, rgb_back), "Conversion failed!" | |
| if __name__ == "__main__": | |
| test_conversion() | |