Имеется на TImage1 ч/б картинка (градации серого)
И такого же размера TImage2, залитый градиентной цветной маской.
Надо получить итоговое изображение, где цвет пикселя равен маске, а яркость пикселя - ч/б картинке.
В цикле по X,Y попиксельно получается дико медленно, у меня прорисовка заняла около 5 сек на FullHD картинке.
Есть ли какой метод быстрее?
Или перефразирую вопрос: как на TImage с выведенной картинкой наложить другую картинку в режиме, аналогичном PEN.MODE := pmMask, то есть в режиме логического И между картинками?
как раскрасить изображение цветной маской?
Модератор: Модераторы
Re: как раскрасить изображение цветной маской?
Для этого придумали всякие 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.
TImage о таких инструкций может не подозревать. Разработчикам Lazarus главное сделать одинаковый функции в разных средах (Windows/Linux/OSX..). А ускорение это уже более глубокая задача, даже у одного производителя Intel инструкции одного поколения процессоров могут сильно отличатся - Celeron/Intel/Xeon/Atom у них инструкции разные, а есть же AMD/ немыслимый зоопарк ARMов.
Вот чтобы как то облегчить задачу Intel придумала библиотеку Integrated Performance Primitives.
Но даже и этих скоростей может не хватить при обработки HD/4K видео - тогда нужно задействовать графические ускорители. DirectX/OpenGL/OpenCL/CUDA.
- Снег Север
- долгожитель
- Сообщения: 3067
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Re: как раскрасить изображение цветной маской?
Graphics libraries: http://wiki.freepascal.org/Graphics_libraries
Как верно заметили выше, на TImage самая тормозная реализация из всех возможных. Лично я рекомендовал бы начать с Graphics32, как самой простой в освоении, а если не хватит производительности или нужен линукс, то Andorra 2D.
Как верно заметили выше, на TImage самая тормозная реализация из всех возможных. Лично я рекомендовал бы начать с Graphics32, как самой простой в освоении, а если не хватит производительности или нужен линукс, то Andorra 2D.
Re: как раскрасить изображение цветной маской?
Народ, что вы всех сразу "в дебри" отсылаете? Вполне возможно это куда более простой случай !
Тут недавно уже похожая тема пробегала...
Быстрая отрисовка
Суть, если кратко, в том, что "попиксельно" несмотря на все ухищрения медленно будет всегда .
Но есть способы достаточно быстро нарисовать именно то что нужно ...
Единственное исключение где ПРИХОДИТСЯ работать "попиксельно" обработка "живого видеопотока" в реальном времени или фильтрация произвольных изображений .
Глянь на мой проект "Цифровая оптика" . и загляни в модуль
"UCanny.pas"(Хорош тем что ничего внешнего не нужно ) и посмотри как там фильтры устроены . (Возможно скорости хватит ... разумеется обработку нужно производить на "теневом битмапе", а на Timage кидать например через BitBlt )
Для более сложных (в плане скоростной обработки) случаев например есть библиотека OpenCV ... ( в моем проекте OpenCV тоже используется но пока в качестве дополнительных и "экспериментальных функций " )
Зы
Простые логические операции умеет BitBlt (хотя придется повозится с "подбором логики" , но если сработает то лучше способа найти трудно!
)
Зы Зы
Кстати в UCanny.pas есть вот что ...

Это именно "прозрачность" то есть "смешение" . но все очень легко упростит до смешения "по ключевому цвету"
При размере кадра 640х480х24 без видимых тормозов работает в "риал тайм" на достаточно чахлом ноте (+ там еще видео с камеры и модель в OpenGL ).
Тут недавно уже похожая тема пробегала...
Суть, если кратко, в том, что "попиксельно" несмотря на все ухищрения медленно будет всегда .
Но есть способы достаточно быстро нарисовать именно то что нужно ...
Единственное исключение где ПРИХОДИТСЯ работать "попиксельно" обработка "живого видеопотока" в реальном времени или фильтрация произвольных изображений .
Глянь на мой проект "Цифровая оптика" . и загляни в модуль
Для более сложных (в плане скоростной обработки) случаев например есть библиотека OpenCV ... ( в моем проекте OpenCV тоже используется но пока в качестве дополнительных и "экспериментальных функций " )
Зы
Простые логические операции умеет BitBlt (хотя придется повозится с "подбором логики" , но если сработает то лучше способа найти трудно!
Зы Зы
Кстати в 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: как раскрасить изображение цветной маской?
А простой Canvas.CopyRect() не пойдет?
Re: как раскрасить изображение цветной маской?
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: как раскрасить изображение цветной маской?
Только что проверил, 5 миллисекунд.
Re: как раскрасить изображение цветной маской?
iskander писал(а):Только что проверил, 5 миллисекунд.
Поздравляю ! Но.. "5 миллисекунд" что?
Для BitBlt как-бы даже много для Blend2 нормально ... или это про Canvas.CopyRect() ?
...если да то не плохо но BitBlt - почти всегда быстрее.
