Преобразование цветов RGB в HSL с использованием Core Image Kernel Language - PullRequest
0 голосов
/ 03 октября 2018

Я пытаюсь создать фильтр изображений, который будет смещать цвет изображения.Для этого мне нужно конвертировать цвет rgb в hsl и после сдвига конвертировать hsl обратно в rgb.Я провел некоторые исследования и нашел формулы, которые могут помочь мне с этой задачей.

Я внедряю их на своей игровой площадке, используя Swift, просто чтобы проверить, надежны ли они и есть.Я не буду публиковать здесь код Swift, чтобы сохранить чистоту, но я покажу результаты моего теста:

input: rgb (61, 117,237) или (0.24,0.46,0.93)

результат:

rgb2hsl [0.613527 0.831325 0.585] or (221, 83, 58.5) //hsl
hsl2rgb [0.24 0.46 0.93] //back to rgb

#3D75ED

Отлично!Пока все хорошо.

Теперь нам нужно преобразовать наш код Swift в Core Image Kernel Language (CIKL).И вот оно:

float hue2rgb(float f1, float f2, float hue) {
   if (hue < 0) {
      hue += 1.0;
   }
   else if (hue > 1) {
      hue -= 1.0;
   }

   float res;
   if (6*hue<1) {
      res = f1 + (f2 - f1) * 6 * hue;
   }
   else if (2*hue<1) { 
      res = f2;
   }
   else if (3*hue<2) {
      res = f1 + (f2 - f1) * (2.0/3.0 - hue) * 6;
   }
   else {
       res = f1;
   }
   return res;
}


vec3 hsl2rgb(vec3 hsl) {
   vec3  rgb;
   if (hsl.y == 0) {
      rgb = vec3(hsl.z,hsl.z,hsl.z);
   }
   else {
      float f2;
      if (hsl.z < 0.5) {
         f2 = hsl.z * (1.0 + hsl.y);
      } 
      else {
         f2 = hsl.z + hsl.y - hsl.y * hsl.z;
      }

      float f1 = 2 * hsl.z - f2;

      float r = hue2rgb(f1, f2, hsl.x + 1.0/3.0);
      float g = hue2rgb(f1, f2, hsl.x);
      float b = hue2rgb(f1, f2, hsl.x - 1.0/3.0);

      rgb = vec3(r,g,b);
   }
   return rgb;
}



vec3 rgb2hsl(vec3 rgb) {

   float maxC = max(rgb.x, max(rgb.y,rgb.z));
   float minC = min(rgb.x, min(rgb.y,rgb.z));

   float l = (maxC + maxC)/2.0;

   float h = 0;
   float s = 0;

   if (maxC != minC) {
      float d = maxC - minC;
      s = l > 0.5 ? d / (2.0 - maxC - minC) : d / (maxC + minC);

      if (maxC == rgb.x) {      
         h =  (rgb.y - rgb.z) / d + (rgb.y < rgb.z ? 6.0 : 0);
      } else if (maxC == rgb.y) {
         h = (rgb.z - rgb.x) / d + 2.0;
      }
      else {
         h = (rgb.x - rgb.y) / d + 4.0;
      }

      h /= 6.0;
   }

   return vec3(h,s,l);
}

И тут возникает проблема.Я не могу получить правильные значения, используя эти функции в моем фильтре.Чтобы проверить все, я сделал Quartz Composer Patch.Поскольку в CIKL я не нашел ни одной опции печати / журнала, я сделал это, чтобы проверить, правильно ли работают мои преобразования:

enter image description here

Логика этогоpatch: мой фильтр принимает цвет в качестве входных данных, конвертирует его в hsl и обратно в rgb и возвращает его;ввод изображения пока игнорируется.

Функция ядра моего фильтра:

kernel vec4 kernelFunc(__sample pixel, __color color) {
   vec3 vec = color.rgb;

   vec3 hsl = rgb2hsl(vec);

   return vec4(hsl2rgb(hsl), 1);
}

Фильтр включает функции, перечисленные выше.

Результат, который я вижу в программе просмотра:

enter image description here Изображение справа - это обрезанное постоянное цветное изображение из входного цвета.Левое изображение - это выходной сигнал нашего фильтра.

Цифровой инструмент выбора цвета возвращает rgb (237, 239,7, 252) для левого изображения.

У меня больше нет идей, как отладить эту проблему и найти проблему.Любая помощь будет высоко оценена.Спасибо.

1 Ответ

0 голосов
/ 04 октября 2018

Я нашел проблему.Именно я, конвертируя код из Swift в CIKL, я совершил глупую ошибку, которую было очень трудно найти, потому что у вас нет инструментов для печати / записи в CIKL или я не знаю об этом.В любом случае, проблема была в функции rgb2hsl:

float l = (maxC + maxC)/2.0; // WRONG

должно быть:

float l = (maxC + minC)/2.0;

Надеюсь, это поможет кому-то в будущем.

...