| 68 | |
| 69 | template<typename T> |
| 70 | void rgb2hsv(Param<T> out, CParam<T> in) { |
| 71 | const af::dim4 dims = in.dims(); |
| 72 | const af::dim4 strides = in.strides(); |
| 73 | af::dim4 oStrides = out.strides(); |
| 74 | dim_t bCount = dims[3]; |
| 75 | |
| 76 | for (dim_t b = 0; b < bCount; ++b) { |
| 77 | const T* src = in.get() + b * strides[3]; |
| 78 | T* dst = out.get() + b * oStrides[3]; |
| 79 | |
| 80 | for (dim_t j = 0; j < dims[1]; ++j) { |
| 81 | // j steps along 2nd dimension |
| 82 | dim_t oj = j * oStrides[1]; |
| 83 | dim_t ij = j * strides[1]; |
| 84 | |
| 85 | for (dim_t i = 0; i < dims[0]; ++i) { |
| 86 | // i steps along 1st dimension |
| 87 | dim_t oIdx0 = i * oStrides[0] + oj; |
| 88 | dim_t oIdx1 = oIdx0 + oStrides[2]; |
| 89 | dim_t oIdx2 = oIdx1 + oStrides[2]; |
| 90 | |
| 91 | dim_t iIdx0 = i * strides[0] + ij; |
| 92 | dim_t iIdx1 = iIdx0 + strides[2]; |
| 93 | dim_t iIdx2 = iIdx1 + strides[2]; |
| 94 | |
| 95 | T R = src[iIdx0]; |
| 96 | T G = src[iIdx1]; |
| 97 | T B = src[iIdx2]; |
| 98 | T Cmax = std::max(std::max(R, G), B); |
| 99 | T Cmin = std::min(std::min(R, G), B); |
| 100 | T delta = Cmax - Cmin; |
| 101 | |
| 102 | T H = 0; |
| 103 | |
| 104 | if (Cmax != Cmin) { |
| 105 | if (Cmax == R) H = (G - B) / delta + (G < B ? 6 : 0); |
| 106 | if (Cmax == G) H = (B - R) / delta + 2; |
| 107 | if (Cmax == B) H = (R - G) / delta + 4; |
| 108 | H = H / 6.0f; |
| 109 | } |
| 110 | |
| 111 | dst[oIdx0] = H; |
| 112 | dst[oIdx1] = (Cmax == 0.0f ? 0 : delta / Cmax); |
| 113 | dst[oIdx2] = Cmax; |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | } // namespace kernel |
| 120 | } // namespace cpu |