Страница 1 из 1

как раскрасить изображение цветной маской?

СообщениеДобавлено: 27.08.2018 15:38:46
DropSoft
Имеется на TImage1 ч/б картинка (градации серого)
И такого же размера TImage2, залитый градиентной цветной маской.
Надо получить итоговое изображение, где цвет пикселя равен маске, а яркость пикселя - ч/б картинке.
В цикле по X,Y попиксельно получается дико медленно, у меня прорисовка заняла около 5 сек на FullHD картинке.
Есть ли какой метод быстрее?

Или перефразирую вопрос: как на TImage с выведенной картинкой наложить другую картинку в режиме, аналогичном PEN.MODE := pmMask, то есть в режиме логического И между картинками?

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 28.08.2018 06:22:52
olegy123
Для этого придумали всякие MMX, SSE, SSE2, SSE3, SSSE3, SSE4 инструкции которые ускоряют работу с массивами чисел. MMX за одну инструкцию позволяет обработать 8 данных. в том числе логических — И, инверсия прямой импликации, ИЛИ и исключающее ИЛИ;.
TImage о таких инструкций может не подозревать. Разработчикам Lazarus главное сделать одинаковый функции в разных средах (Windows/Linux/OSX..). А ускорение это уже более глубокая задача, даже у одного производителя Intel инструкции одного поколения процессоров могут сильно отличатся - Celeron/Intel/Xeon/Atom у них инструкции разные, а есть же AMD/ немыслимый зоопарк ARMов.
Вот чтобы как то облегчить задачу Intel придумала библиотеку Integrated Performance Primitives.
Но даже и этих скоростей может не хватить при обработки HD/4K видео - тогда нужно задействовать графические ускорители. DirectX/OpenGL/OpenCL/CUDA.

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 28.08.2018 07:50:43
Снег Север
Graphics libraries: http://wiki.freepascal.org/Graphics_libraries

Как верно заметили выше, на TImage самая тормозная реализация из всех возможных. Лично я рекомендовал бы начать с Graphics32, как самой простой в освоении, а если не хватит производительности или нужен линукс, то Andorra 2D.

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 29.08.2018 00:22:53
Alex2013
Народ, что вы всех сразу "в дебри" отсылаете? Вполне возможно это куда более простой случай ! :idea:

Тут недавно уже похожая тема пробегала... :arrow: Быстрая отрисовка
Суть, если кратко, в том, что "попиксельно" несмотря на все ухищрения медленно будет всегда .
Но есть способы достаточно быстро нарисовать именно то что нужно ...

Единственное исключение где ПРИХОДИТСЯ работать "попиксельно" обработка "живого видеопотока" в реальном времени или фильтрация произвольных изображений .
Глянь на мой проект "Цифровая оптика" . и загляни в модуль :arrow: "UCanny.pas"(Хорош тем что ничего внешнего не нужно ) и посмотри как там фильтры устроены . (Возможно скорости хватит ... разумеется обработку нужно производить на "теневом битмапе", а на Timage кидать например через BitBlt )

Для более сложных (в плане скоростной обработки) случаев например есть библиотека OpenCV ... ( в моем проекте OpenCV тоже используется но пока в качестве дополнительных и "экспериментальных функций " )
Зы
Простые логические операции умеет BitBlt (хотя придется повозится с "подбором логики" , но если сработает то лучше способа найти трудно! :idea: )
Зы Зы
Кстати в UCanny.pas есть вот что ...
Код: Выделить всё
procedure Blend2(Const Src1,Src2,Dst: TBitmap; CT: Integer;Amount: extended);
var w,h,x,y:integer;
    ps1,ps2,pd:pbytearray;
begin
w:=Src1.Width;
h:=Src1.Height;

for y:=0 to h-1 do begin
ps1:=Src1.ScanLine[y];
ps2:=Src2.ScanLine[y];
Dst.BeginUpdate; ;
pd:=Dst.ScanLine[y];
for x:=0 to w-1 do
If RGB(ps2[x*3+2],ps2[x*3+1],ps2[x*3])<>CT then
begin
If ABS(Amount-1)>=0.09   then begin
  pd[x*3]  :=round((1-Amount)*ps1[x*3]+Amount*ps2[x*3]);
  pd[x*3+1]:=round((1-Amount)*ps1[x*3+1]+Amount*ps2[x*3+1]);
  pd[x*3+2]:=round((1-Amount)*ps1[x*3+2]+Amount*ps2[x*3+2]);
  end else
  begin
   Move(ps2[x*3], pd[x*3],3);
  end
  end else Move(ps1[x*3], pd[x*3],3);
Dst.EndUpdate;
end;
end;

Изображение
Это именно "прозрачность" то есть "смешение" . но все очень легко упростит до смешения "по ключевому цвету"
При размере кадра 640х480х24 без видимых тормозов работает в "риал тайм" на достаточно чахлом ноте (+ там еще видео с камеры и модель в OpenGL ).

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 29.08.2018 07:45:50
iskander
А простой Canvas.CopyRect() не пойдет?

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 29.08.2018 13:50:45
Alex2013
iskander писал(а):А простой Canvas.CopyRect() не пойдет?


Ну не думаю что все на столько просто... (Все-же Full HD (Full High Definition) это 1920×1080 точек )
к тому-же BitBlt/StretchBlt отчетливее быстрее Canvas.CopyRect() при почти равной простоте использования .

Если "по функционалу" хватит BitBlt то дальше "изобретать велосипед" определенно смысла нет ...

Если не хватит скорости из за высокого разрешения (например для разрешения 4к ) то этому горю может помочь только использование 3д-акселерации(то бишь OpenGl / DirectX ).

Если нужен боле сложный метод обработки то поможет "быстрый доступ к пикселям" и оптимизированный алгоритм .
(всякие MMX, SSE, SSE2, SSE3, SSSE3, SSE4 по идее должны быть на совести компилятора или использоваться в виде ассемблеровской вставки (что большинства применений избыточно трудоемко и не факт, что результат будет сильно быстрее "стандартного кода") OpenCL/CUDA вещь приятная и полезная но доступна далеко не всюду и к тому же имеет ряд функциональных ограничений . )

+Есть простейшие "читерские приемы" например часть обработки можно производить в сниженном разрешении ( пример : поиск маски или бинаризация ), а конечный кадр пересчитывать в полном разрешении . К тому-же можно следить за изменениями на кадре (если кадр почти не изменился то можно смело использовать предыдущий результат, а если изменений очень много и они происходят быстро можно просто снизить разрешение/детализацию на входе (все равно не успеешь заметить разницу )+ ПОСТОЯННОЕ снижение входящего разрешения на 10-30% при скоростной обработке видео-потока практически незаметно на глаз но скорости прибавит вполне ощутимо.

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 29.08.2018 15:18:14
iskander
Только что проверил, 5 миллисекунд.

Re: как раскрасить изображение цветной маской?

СообщениеДобавлено: 29.08.2018 16:43:17
Alex2013
iskander писал(а):Только что проверил, 5 миллисекунд.

Поздравляю ! Но.. "5 миллисекунд" что? :idea:
Для BitBlt как-бы даже много для Blend2 нормально ... или это про Canvas.CopyRect() ?
...если да то не плохо но BitBlt - почти всегда быстрее. :idea: