Просмотр полной версии : Привести цвет к одному из двух основных
Такая задачка.
Есть два цвета принятые как основные. Палитра 8bpp (rrrgggbb).
Нужно привести (приравнять) третий цвет к одному из основных цветов, который больше всего подходит.
Может кто подскажет алгоритм или направление куда рыть?
как вариант -покурить сырки bmp2scr или другого продвинутого конвертера. или, как вариант, почитать про квантизацию цветов например.
Ответ найден (но ещё не тестировал). Поиск ближайшего цвета в палитре. (http://algolist.manual.ru/graphics/find_col.php)
Этот алгоритм Вам может понадобиться когда например нужно перекодировать картинку с одной палитры на другую. Для решения рассмотрим более простую задачу - нужно найти в некоторой палитре из n цветов, цвет максимально похожий на некоторый заданный цвет.
Введем обозначения:
(R0,G0,B0) - цвет, аналог которого нужно найти в палитре.
(Ri,Gi,Bi) - i-тый цвет в палитре.
Различие цветов будем оценивать с помощью следующей функции:
fi = 30*(Ri-R0)2+59*(Gi-G0)2+11*(Bi-B0)2.
Множители 30;59;11 - отражают различную чувствительность человеческого глаза к красному,зеленому и синему цветам соответственно. Далее мы поочереди перебираем все цвета палитры и ищем цвет, для которого fi принимает минимальное значение. Это и будет искомый цвет.
// структуры
typedef struct RGB_type
{
char r,g,b;
} RGB;
typedef struct Pal_type
{
int n; // число цветов в палитре
RGB* C;
} Pal;
// это подпрограмма поиска
// P - палитра
// С - цвет, который требуется найти
// Возвращаемое значение - индекс цвета в палитре
int FindColor(Pal *P,RGB *C)
{
int i, fi, best_color, f_min=1000000;
for(i=0;i<P->n,i++)
{
fi=30*(P->C.r-C->r)*(P->C.r-C->r)+
59*(P->C.g-C->g)*(P->C.g-C->g)+
11*(P->C.b-C->b)*(P->C.b-C->b);
if(fi<f_min){best_color=i,f_min=fi;}
}
return(best_color); }
У меня была задача преобразовать полноцветные картинки RGB888
в палитру для Spec256. В палитре - 256 цветов в кодировке RGB888.
В картинках, где преобладал синий цвет, поиск минимума отличий
был лучше по формуле 1R+1G+1B вместо 3R+6G+1B.
В других наоборот.
67771
67772
67773
67774
67775
67776
Lethargeek
21.01.2019, 20:01
Множители 30;59;11 - отражают различную чувствительность человеческого глаза к красному,зеленому и синему цветам соответственно...
...отображаемым на устройстве древнего стандарта NTSC. Для других стандартов другие пр0центы:
http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html (в матрицах смотреть на вторую строку)
Lethargeek, И что лучше взять для Профи 5.06, палитра 16 из 256 (rrrgggbb) с выводом на жк монитор?
Я не спец по графике, можно для таких ткнуть пальцем? Была бы одна матрица, а там целый веер.
Lethargeek
22.01.2019, 16:26
tae1980, лучше - знать, на какой стандарт рассчитывал автор пикчи :)
да не парься, просто напиши конвертер с выводом кучи вариантов всех сразу
просматривай потом результаты и выбирай каждый раз один на свой вкус
В продолжении темы.
В текущей версии конвектора изображения под экран Profi реализованы две схемы выборки цветов для байта:
1. Находим два самых частых цвета, остальные приводим к ним.
2. То же, но если по краям находятся два самых светлых или самых темных цвета, приводом все цвета к ним.
Начитался про квантизацию изображений, но тут не много другая задача. Не вижу возможности применить её здесь. Или я не прав?
Вопрос: можно ли улучшить качество? Будут ли советы, рекомендации?
Вот два примера:
http://www.imageup.ru/img172/3266730/2019-01-23_15-44-58.png (http://www.imageup.ru/img172/3266730/2019-01-23_15-44-58.png.html)
http://www.imageup.ru/img172/3266731/2019-01-23_16-03-15.png (http://www.imageup.ru/img172/3266731/2019-01-23_16-03-15.png.html)
marinovsoft
23.01.2019, 17:06
Про дизеринг напомнить?
https://ru.wikipedia.org/wiki/Дизеринг
marinovsoft, думал о нем. Но для меня это сложно.
Поступаю так в фотошопе сначала индексирую цвет к 256 в палитре Профи. Потом делаю цвет снова 24 битным. После привожу к 16 цветам. Такая последовательность, так как фотошоп не позволяет привести к 16 цветам если загружена палитра 256 цветов.
если я правильно понимаю, то квантизацию и дизеринг изображения делает при этих манипуляциях фотошоп.
Я же беря подготовленный файл, привожу палитру 24bpp к палитре Профи и объединяю последовательность из 8 точек в байт. Так как у Профи 2 цвета на 8 точек. Для чего нужно выкинуть до 6 цветов, приведя их к двум основным (правила их выбора из 8 возможных описал выше). От сюда и вылазит "размазывание" картинок.
Думаю дизеринг в данной ситуации мог бы помочь "сгладить" изображение. Но вот как его организовать я не пойму.
Lethargeek
24.01.2019, 18:31
ну какбэ https://en.wikipedia.org/wiki/Dither
- - - Добавлено - - -
и далее по ссылкам под картинками, например
https://en.wikipedia.org/wiki/Floyd–Steinberg_dithering
формулы простые совсем
Lethargeek, формулы может и просты, только вот хорошо бы ещё и разбираться в теме, с чем у меня туго, так как от графики и разных художеств я очень далёк. Мозги заточены под другое. Тут просто выхода иного нет :)
Теорию уже немного начитался. Тут вот в чём вопрос: все статьи относятся к картинкам где у каждого пикселя свой цвет. На Профи же два цвета на 8 точек. То есть понятие "левый"/"нижний" пиксель не очевидное. Если пиксель в начале байта, какой пиксель считать "слева", тот который в этом байте или тот который уже в следующем байте?
Как теорию подтянуть под наши реали?
Изначально картинки готовятся во внешних программах, они всё это проделывают сами. "Размытие" получается уже после адаптации к экрану Профи. Когда применять теорию и какую? Не пойму как в теории перейти от цвета на точку, к двум цветам на байт.
Применять что-то после адаптации уже поздно, многие детали утеряны. Применять до - так оно как бы уже применялась (во внешних программах). ИМХО тут вопрос посложнее да же приведения к двум цветам. Тут как нужно и цвета сохранить, и пиксели встроить так что бы сохранить детали.
Мне не хватает теоретически-практических знаний. То что для художника очевидно, для меня темный лес.
Есть мысль сделать два прохода. На первом приводим как сейчас. На втором каждый пиксель результата сравниваем с оригиналом, если он стал темнее/светлее более чем на некий порядок, меняем его значение.
Lethargeek
24.01.2019, 19:27
при распределении ошибки попробуй выбирать внизу ближайший цвет из доступных двух
для начала сделай в один проход
Извини, если достал.
при распределении ошибки попробуй выбирать внизу ближайший цвет из доступных двух
для начала сделай в один проход
На первом этапе нет двух цветов на байт, у каждого пикселя свой цвет.
Нужно сначала привести всю картинку к двум цветам на байт? Но тогда теряются детали.
Или берем первые 8 точек, приводим их к двум цветам, и полученную общую ошибка на байт распределяем так же на 8 точек? А что делать с "деталями" в первом байте? Мы их теряем?
А может так, берем за основу два крайних цвета в байте, а для средних 6 из сочетания цвета и пикселей (дизеринга) пытаемся найти оптимальную комбинацию?
С одной стороны не вижу необходимости двигаться по вертикали, так как две соседние по вертикали точки могут иметь разные цвета и они уже обработаны по внешних программах.
С другой стороны, учет (и влияние) вертикальных соседей даст возможность применять более хитрые пиксельные маски (забыл правильно название) для цвета.
Нужна некая комбинация из методов поучения двухцветных и 16 цветных картинок. Когда часть цветов эмулирются плотностью пикселей с учетом деления на байты. Возможно стоит работать с исходными файлами с числом цветов более 16. Но от одной мысли об этом у меня начинаются головные боли.
Lethargeek
25.01.2019, 02:56
ну тогда переводи построчно в два цвета, а ошибку вниз сноси попиксельно
потом переходишь к этой уже изменённой нижней строке и повторяешь
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot