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

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

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

Сообщение DropSoft » 27.08.2018 15:38:46

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

Или перефразирую вопрос: как на TImage с выведенной картинкой наложить другую картинку в режиме, аналогичном PEN.MODE := pmMask, то есть в режиме логического И между картинками?
DropSoft
новенький
 
Сообщения: 19
Зарегистрирован: 31.03.2013 13:47:40

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

Сообщение olegy123 » 28.08.2018 06:22:52

Для этого придумали всякие 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.
olegy123
энтузиаст
 
Сообщения: 980
Зарегистрирован: 25.02.2016 12:10:20

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

Сообщение Снег Север » 28.08.2018 07:50:43

Graphics libraries: http://wiki.freepascal.org/Graphics_libraries

Как верно заметили выше, на TImage самая тормозная реализация из всех возможных. Лично я рекомендовал бы начать с Graphics32, как самой простой в освоении, а если не хватит производительности или нужен линукс, то Andorra 2D.
Аватара пользователя
Снег Север
энтузиаст
 
Сообщения: 1160
Зарегистрирован: 27.11.2007 16:14:47

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

Сообщение Alex2013 » 29.08.2018 00:22:53

Народ, что вы всех сразу "в дебри" отсылаете? Вполне возможно это куда более простой случай ! :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 ).
Alex2013
энтузиаст
 
Сообщения: 978
Зарегистрирован: 03.04.2013 11:59:44

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

Сообщение iskander » 29.08.2018 07:45:50

А простой Canvas.CopyRect() не пойдет?
iskander
постоялец
 
Сообщения: 105
Зарегистрирован: 08.01.2012 18:43:34

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

Сообщение Alex2013 » 29.08.2018 13:50:45

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% при скоростной обработке видео-потока практически незаметно на глаз но скорости прибавит вполне ощутимо.
Alex2013
энтузиаст
 
Сообщения: 978
Зарегистрирован: 03.04.2013 11:59:44

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

Сообщение iskander » 29.08.2018 15:18:14

Только что проверил, 5 миллисекунд.
iskander
постоялец
 
Сообщения: 105
Зарегистрирован: 08.01.2012 18:43:34

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

Сообщение Alex2013 » 29.08.2018 16:43:17

iskander писал(а):Только что проверил, 5 миллисекунд.

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


Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 0

Рейтинг@Mail.ru