2019-06-06 14:21:15 +02:00
|
|
|
/*******************************************************************************
|
|
|
|
* Copyright (c) 2015-2018 Skymind, Inc.
|
|
|
|
*
|
|
|
|
* This program and the accompanying materials are made available under the
|
|
|
|
* terms of the Apache License, Version 2.0 which is available at
|
|
|
|
* https://www.apache.org/licenses/LICENSE-2.0.
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
//
|
2019-07-20 07:58:44 +02:00
|
|
|
// @author raver119@gmail.com
|
|
|
|
// @author Yurii Shyrma (iuriish@yahoo.com)
|
2019-06-06 14:21:15 +02:00
|
|
|
//
|
|
|
|
|
|
|
|
#include <op_boilerplate.h>
|
|
|
|
#include <NDArray.h>
|
|
|
|
|
2019-07-20 07:58:44 +02:00
|
|
|
namespace nd4j {
|
|
|
|
namespace ops {
|
2019-06-06 14:21:15 +02:00
|
|
|
namespace helpers {
|
2019-07-20 07:58:44 +02:00
|
|
|
|
|
|
|
|
|
|
|
void adjustHue(nd4j::LaunchContext* context, const NDArray *input, const NDArray* deltaScalarArr, NDArray *output, const int dimC);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
|
|
FORCEINLINE _CUDA_HD void rgbToHsv(const T& r, const T& g, const T& b, T& h, T& s, T& v) {
|
|
|
|
|
|
|
|
// h values are in range [0, 360)
|
|
|
|
// s and v values are in range [0, 1]
|
|
|
|
|
|
|
|
const T max = nd4j::math::nd4j_max<T>(r, nd4j::math::nd4j_max<T>(g, b));
|
|
|
|
const T min = nd4j::math::nd4j_min<T>(r, nd4j::math::nd4j_min<T>(g, b));
|
|
|
|
const T c = max - min;
|
2019-12-20 06:48:30 +01:00
|
|
|
const T _p6 = (T)1 / (T)6;
|
2019-07-20 07:58:44 +02:00
|
|
|
// calculate h
|
|
|
|
if(c == 0) {
|
|
|
|
h = 0;
|
|
|
|
}
|
|
|
|
else if(max == r) {
|
2019-12-20 06:48:30 +01:00
|
|
|
h = _p6 * ((g - b) / c) + (g >= b ? (T)0 : (T)1);
|
2019-07-20 07:58:44 +02:00
|
|
|
}
|
|
|
|
else if(max == g) {
|
2019-12-20 06:48:30 +01:00
|
|
|
h = _p6 * ((b - r) / c + (T)2);
|
2019-07-20 07:58:44 +02:00
|
|
|
}
|
|
|
|
else { // max == b
|
2019-12-20 06:48:30 +01:00
|
|
|
h = _p6 * ((r - g) / c + (T)4);
|
2019-07-20 07:58:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// calculate s
|
|
|
|
s = max == (T)0 ? (T)0 : c / max;
|
|
|
|
|
|
|
|
// calculate v
|
2019-12-20 06:48:30 +01:00
|
|
|
v = max;// / 255.f;
|
2019-07-20 07:58:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
|
|
FORCEINLINE _CUDA_HD void hsvToRgb(const T& h, const T& s, const T& v, T& r, T& g, T& b) {
|
|
|
|
|
2019-12-20 06:48:30 +01:00
|
|
|
const float sector = h * 6.f;
|
2019-07-20 07:58:44 +02:00
|
|
|
const T c = v * s;
|
|
|
|
|
|
|
|
if(0.f <= sector && sector < 1.f) {
|
|
|
|
r = v;
|
|
|
|
g = v - c * (1 - sector);
|
|
|
|
b = v - c;
|
|
|
|
}
|
|
|
|
else if(1.f <= sector && sector < 2.f) {
|
|
|
|
r = v - c * (sector - 1);
|
|
|
|
g = v;
|
|
|
|
b = v - c;
|
|
|
|
}
|
|
|
|
else if(2.f <= sector && sector < 3.f) {
|
|
|
|
r = v - c;
|
|
|
|
g = v;
|
|
|
|
b = v - c * (3 - sector);
|
|
|
|
}
|
|
|
|
else if(3.f <= sector && sector < 4.f) {
|
|
|
|
r = v - c;
|
|
|
|
g = v - c * (sector - 3);
|
|
|
|
b = v;
|
|
|
|
}
|
|
|
|
else if(4.f <= sector && sector < 5.f) {
|
|
|
|
r = v - c * (5 - sector);
|
|
|
|
g = v - c;
|
|
|
|
b = v;
|
|
|
|
}
|
|
|
|
else { // 5.f <= sector < 6.f
|
|
|
|
r = v;
|
|
|
|
g = v - c;
|
|
|
|
b = v - c * (sector - 5);
|
|
|
|
}
|
|
|
|
|
2019-12-20 06:48:30 +01:00
|
|
|
// r *= 255;
|
|
|
|
// g *= 255;
|
|
|
|
// b *= 255;
|
2019-07-20 07:58:44 +02:00
|
|
|
}
|
|
|
|
|
2019-12-20 06:48:30 +01:00
|
|
|
|
2019-07-20 07:58:44 +02:00
|
|
|
/*////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
|
|
static FORCEINLINE _CUDA_HD void rgb_to_hv(T r, T g, T b, T* h, T* v_min, T* v_max) {
|
|
|
|
T v_mid;
|
|
|
|
int h_category;
|
|
|
|
// According to the figures in:
|
|
|
|
// https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
|
|
|
|
// For the conditions, we don't care about the case where two components are
|
|
|
|
// equal. It is okay to count it in either side in that case.
|
|
|
|
if (r < g) {
|
|
|
|
if (b < r) {
|
|
|
|
// b < r < g
|
|
|
|
*v_max = g;
|
|
|
|
v_mid = r;
|
|
|
|
*v_min = b;
|
|
|
|
h_category = 1;
|
|
|
|
} else if (b > g) {
|
|
|
|
// r < g < b
|
|
|
|
*v_max = b;
|
|
|
|
v_mid = g;
|
|
|
|
*v_min = r;
|
|
|
|
h_category = 3;
|
2019-06-06 14:21:15 +02:00
|
|
|
} else {
|
2019-07-20 07:58:44 +02:00
|
|
|
// r < b < g
|
|
|
|
*v_max = g;
|
|
|
|
v_mid = b;
|
|
|
|
*v_min = r;
|
|
|
|
h_category = 2;
|
2019-06-06 14:21:15 +02:00
|
|
|
}
|
2019-07-20 07:58:44 +02:00
|
|
|
} else {
|
|
|
|
// g < r
|
|
|
|
if (b < g) {
|
|
|
|
// b < g < r
|
|
|
|
*v_max = r;
|
|
|
|
v_mid = g;
|
|
|
|
*v_min = b;
|
|
|
|
h_category = 0;
|
|
|
|
} else if (b > r) {
|
|
|
|
// g < r < b
|
|
|
|
*v_max = b;
|
|
|
|
v_mid = r;
|
|
|
|
*v_min = g;
|
|
|
|
h_category = 4;
|
|
|
|
} else {
|
|
|
|
// g < b < r
|
|
|
|
*v_max = r;
|
|
|
|
v_mid = b;
|
|
|
|
*v_min = g;
|
|
|
|
h_category = 5;
|
2019-06-06 14:21:15 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-20 07:58:44 +02:00
|
|
|
if (*v_max == *v_min) {
|
|
|
|
*h = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto ratio = (v_mid - *v_min) / (*v_max - *v_min);
|
|
|
|
bool increase = ((h_category & 0x1) == 0);
|
|
|
|
*h = h_category + (increase ? ratio : (1 - ratio));
|
|
|
|
}
|
2019-06-06 14:21:15 +02:00
|
|
|
|
2019-07-20 07:58:44 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
|
|
static FORCEINLINE _CUDA_HD void hv_to_rgb(T h, T v_min, T v_max, T* r, T* g, T* b) {
|
|
|
|
int h_category = static_cast<int>(h);
|
|
|
|
T ratio = h - (T)h_category;
|
|
|
|
bool increase = ((h_category & 0x1) == 0);
|
|
|
|
if (!increase)
|
|
|
|
ratio = 1 - ratio;
|
|
|
|
|
|
|
|
T v_mid = v_min + ratio * (v_max - v_min);
|
|
|
|
// According to the figures in:
|
|
|
|
// https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
|
|
|
|
switch (h_category) {
|
|
|
|
case 0:
|
|
|
|
*r = v_max;
|
|
|
|
*g = v_mid;
|
|
|
|
*b = v_min;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
*r = v_mid;
|
|
|
|
*g = v_max;
|
|
|
|
*b = v_min;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
*r = v_min;
|
|
|
|
*g = v_max;
|
|
|
|
*b = v_mid;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
*r = v_min;
|
|
|
|
*g = v_mid;
|
|
|
|
*b = v_max;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
*r = v_mid;
|
|
|
|
*g = v_min;
|
|
|
|
*b = v_max;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
default:
|
|
|
|
*r = v_max;
|
|
|
|
*g = v_min;
|
|
|
|
*b = v_mid;
|
2019-06-06 14:21:15 +02:00
|
|
|
}
|
2019-07-20 07:58:44 +02:00
|
|
|
}
|
2019-06-06 14:21:15 +02:00
|
|
|
|
2019-07-20 07:58:44 +02:00
|
|
|
*/
|
2019-06-06 14:21:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|