LINUX.ORG.RU

Зачем оно надо?

anonymous
()

Алгоритм там такой, что не выйдет:

function [H S V] = im2HSV(im)
	R = double(im(:,:,1))/255.;
	G = double(im(:,:,2))/255.;
	B = double(im(:,:,3))/255.;
	Imax = max(max(R,G), B);
	Imin = min(min(R,G), B);
	V = Imax;
	S = zeros(size(Imax));
	idx = (find(Imax != 0));
	S(idx) = 1 - Imin(idx) ./ Imax(idx);
	H = zeros(size(Imax));
	idx = find(Imax == R & G >= B);
	H(idx) = 60. * (G(idx) - B(idx)) ./ (Imax(idx) - Imin(idx));
	idx = find(Imax == R & G < B);
	H(idx) = 60. * (G(idx) - B(idx)) ./ (Imax(idx) - Imin(idx)) + 360.;
	idx = find(Imax == G);
	H(idx) = 60. * (B(idx) - R(idx)) ./ (Imax(idx) - Imin(idx)) + 120.;
	idx = find(Imax == B);
	H(idx) = 60. * (R(idx) - G(idx)) ./ (Imax(idx) - Imin(idx)) + 240.;
	H = uint8(H * 255 / max(max(H)));
	S = uint8(S * 255 / max(max(S)));
	V = uint8(V * 255 / max(max(V)));
endfunction
Без оперирования с плавающей точной нормализовать не получится. А вот если нормализация не нужна, просто конвертируем char -> int, считаем (умножение, естесвтенно, в первую очередь), конвертируем -> char.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Без оперирования с плавающей точной нормализовать не получится

А почему бы не перейти к unsigned long long? Оперировать с ними. А потом - нормализовать целочисленным делением?

pacify ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

S(idx) = 1 - Imin(idx) ./ Imax(idx);

А на другом сайте я видел формулу:
S = 1.0-(MAX-MIN)/(float)MAX;

Мне кажется, на Википедии ошибка, так как с (MAX-MIN) результат выдается, совпадающий с картинками: http://ru.wikipedia.org/wiki/Файл:Barns_grand_tetons_HSV_separation.jpg
Проверь на этом домике.

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

Какой-то там латех дурацкий: без русского языка, даже \text{} не помогает... Сделал абы как.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Хм, там регистрация не нужна, оказывается. Исправляю.

То есть, ориентироваться надо на английские формулы?

Я проверил по формулам с русской википедии - они тоже как бы корректные.
В том смысле, что обратное преобразование работает, и возвращает обратно (R,G,B).

pacify ★★★★★
() автор топика
Ответ на: Чьорт побьери! от Eddy_Em

В английской педивикии действительно написано S=min/max!

На самом деле, там написано:
S_{HSV} = C/V = (MAX-MIN)/MAX = 1-MIN/MAX

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

В общем, у одних V==0 соответствует черноте, а у других - светлоте :)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Тьфу ты. Вона что...

Исправляй обратно. ))

Щас буду пересчитывать все по-новой )

pacify ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Попробовал с твоей картинкой - то же самое получилось.

Ты матлабовской программой пробовал Lenna.png?

Кстати, если инвертировать saturation (про что ты выше упоминал - «черное»/«белое»), то получается:
http://pacify.ru/images/Lenna-s inv.PNG

pacify ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Вот


А мои картинки, это:

1. r = 255-h
   g = 255-h
   b = h

2. r = s

3. r = v

Попробуй так же. Я в Матлабе не понимаю.

pacify ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

пробовал своей программкой, которую выше показывал.

Попробуй заменить разницу MAX-MIN на Chroma(delta).
Тогда будет S = Chroma/MAX;

pacify ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Ну и чем по-твоему отличаются формулы S=1-MIN/MAX и S=(MAX-MIN)/MAX?


В Си'шной реализации, если использовать Chroma - быстрее все эти
формулы будут вычисляться (теоретически) :)

Кстати, вот мой код:

void rgb_hsv_if(int r, int g, int b, float *phf, float *psf, float *pvf) {
  int MAX = max(max(r,g),b);
  int MIN = min(min(r,g),b);
  float maxf = MAX;
  float minf = MIN;
  float delta = (maxf-minf); // Chroma
  float sf; // Saturation (отношение минимума к максимуму)
  if (MAX == 0) sf = 0.0;
  else sf = delta/maxf;
  float vf = maxf; // Value (максимальный компонент)
  float hf = 0.0; // Hue (тон)
  if ((MAX == r) && (g >= b)) {
    hf = 0.0 + (60.0*(g-b))/delta;
  }
  if ((MAX == r) && (g < b)) {
    hf = 360.0 + (60.0*(g-b))/delta;
  }
  if ((MAX == g)) {
    hf = 120.0 + (60.0*(b-r))/delta;
  }
  if ((MAX == b)) {
    hf = 240.0 + (60.0*(r-g))/delta;
  }
  *phf = hf;
  *psf = sf;
  *pvf = vf;
  return;
}

void hsv_rgb_fi(float hf, float sf, float vf, int *pr, int *pg, int *pb) {
  int hi = ((int)floor(hf/60.0))%6;
  float f = hf/60.0-floor(hf/60.0);
  float p = vf*(1-sf);
  float q = vf*(1-f*sf);
  float t = vf*(1-(1-f)*sf);
  float r,g,b; r = g = b = 0.0;
  switch(hi) {
    case 0: r = vf; g = t; b = p; break;
    case 1: r = q; g = vf; b = p; break;
    case 2: r = p; g = vf; b = t; break;
    case 3: r = p; g = q; b = vf; break;
    case 4: r = t; g = p; b = vf; break;
    case 5: r = vf; g = p; b = q; break;
  }
  *pr = r;
  *pg = g;
  *pb = b;
  return;
}

В картинке изменяю hue:

      float hf,sf,vf;
      rgb_hsv_if(r00,g00,b00,&hf,&sf,&vf);
      int h = (int)floor((hf*255.0)/360.0);
      int s = (int)floor(255.0*sf);
      int v = (int)floor(vf);

      int r,g,b; r = g = b = 0;
      hsv_rgb_fi(hf+20,sf,vf,&r,&g,&b);

Получаются выбитые пиксели: http://pacify.ru/images/IMG_Turkie-hue-L25p.jpg

Почему?

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

Не гоже на каждый пиксель функцию вызывать. Да и if'ов слишком много - надо хоть немного else'ами разбавить.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Возможно и «выбитые» пиксели из-за if'ов без else'ов возникают.

Я с сишной реализацией не возился, т.к. с цветными изображениями обычно не работаю, а HSV-преобразование делал на досуге: хотел статейку написать, как «капчи» распознавать.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Не гоже на каждый пиксель функцию вызывать.

У меня это - исследовательские утилитки, быстродействие здесь не так
важно. Потом можно будет объединить код функций с основной процедурой ...

Я вот не могу понять - почему при изменении компонентов H или S -
обратное преобразование дает выбитые пиксели ...

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

Советую опыты в Octave делать, а потом уже рабочую реализацию алгоритма на С переносить. Я сам поначалу алгоритмы сразу пытался в сях реализовать - неудобно, много времени на отладку тратится.

Либо где-то «косяк», либо не хватает точности float. Сам столкнулся в своей программке как-то с такой «фишкой»: считаю вроде по правильной формуле, а отображается хрень какая-то. Расставил скобочки по-другому, получилось нормально.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Возможно и «выбитые» пиксели из-за if'ов без else'ов возникают.
Либо где-то «косяк», либо не хватает точности float.

Одну ошибку нашел - не рассмотрел случай MAX == MIN для H (H = 0).

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

Что-то где-то явно не так. Обратное восстановление какое-то кривое. Сравни попиксельно, в чем там косяк.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Тьфу, не разобрался: думал сначала, что это просто восстановление HSV->RGB.

Нет, там я попробовал снижение насыщенности: S = S/2.0;

А так - вполне прилично :)

Ага. «Раскололи» ещё один алгоритм.

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

Кстати, можно ускорить процесс, если использовать openmp. И функции преобразования заинлайнить или вообще в цикл вставить.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Кстати, можно ускорить процесс, если использовать openmp.

Насколько помню - это аналог MPI?

Зачем, если можно просто использовать POSIX threads?

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

POSIX threads

POSIX threads это же просто палеозой какой-то. Если речь идёт о С++, то есть же boost::thread, std::thread. Чем они не нравятся?

anonymous
()
Ответ на: комментарий от anonymous

Если речь идёт о С++, то есть же boost::thread, std::thread. Чем они не нравятся?

Я программирую на том, что знаю. Это - C with classes.

POSIX threads это же просто палеозой какой-то.

Как быстро течёт время ... Нам в 1996 году на курсе системного программирования даже threads не рассказывали.
Курс был по UNIX, X Window API, BSD sockets, C/C++ и т.д. Программировали на IBM PC RT примерно 1984 года выпуска (BSD 4.3).

pacify ★★★★★
() автор топика
Ответ на: комментарий от pacify

Зачем, если можно просто использовать POSIX threads?

Ну, дам примерное сравнение: POSIX threads и openmp соотносятся примерно как openCL и CUDA, т.е. в первом случае очень многое нужно писать руками, а во втором часть «грязной работы» выполняет компилятор.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от pacify

Я программирую на том, что знаю. Это - C with classes.

Ты - мой кумир! :)

// сам принципиально кроме С ничего не знаю и знать не хочу

Нам в 1996 году на курсе системного программирования даже threads не рассказывали.

Мне вообще ничего не рассказывали (я - не программист), а о потоках и т.п. узнал, почитав Стивенса.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

POSIX threads это же просто палеозой какой-то. Если речь идёт о С++, то есть же boost::thread, std::thread. Чем они не нравятся?

POSIX threads есть в куче языков. Твой буст - нет. Про std::thread - это откуда?

Rzhepish
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.