Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2014.07.06;
Скачать: CL | DM;

Вниз

Оптимизация кода   Найти похожие ветки 

 
Вова   (2013-06-25 20:17) [0]

Есть процедура задачей которой является приведения пикселя любого цвета к цвету одного из диапазонов. Но скорость ее работы огорчает меня, можно ли ее как нибудь ускорить?


function almostEqual(a, b: byte): Boolean;
begin
 if ABS(a - b) < 10 then
   result := true
 else
   result := false;
end;

Function ConvertColorToRGBColorMap(color: LongInt; ColSel: String = "None")
 : TColorWithName;
var
 RGBV: trgbcolor;
begin

 RGBV.red := color;
 RGBV.green := color shr 8;
 RGBV.blue := color shr 16;

 with RGBV do

   if almostEqual(red, green) and almostEqual(red, blue) and
     almostEqual(blue, green) then // тогда это серый или черный или белый
   begin
     if almostEqual(red, 255) then // белый
     begin
       result.color := RGB(255, 255, 255);
       result.Name := "White";
     end
     else if red > 120 then
     begin
       result.color := RGB(190, 190, 190);
       result.Name := "LightGray";
     end
     else if (red > 92) then // темно серый
     begin
       result.color := RGB(100, 100, 100);
       result.Name := "DarkGray";
     end
     else
     begin
       result.color := RGB(0, 0, 0);
       result.Name := "Black";
     end // черный
   end
   else
   begin
     if (red < green) and (red < blue) and almostEqual(green, blue) and
       (blue > 130) then
     begin
       result.color := RGB(0, 0, 255);
       result.Name := "Blue";
     end // result:= rgb(0,255,255)//голубой
     else if (green < red) and (green < blue) and almostEqual(red, blue) and
       (red > 130) then
     begin
       result.color := RGB(255, 0, 255);
       result.Name := "Pink";
     end // розовый
     else if (blue < green) and (blue < red) and almostEqual(green, red) and
       (green > 130) then
     begin
       result.color := RGB(255, 255, 0);
       result.Name := "Yellow";
     end // желтый
     else if (red > green) and (red > blue) and (red > 130) then
     begin
       result.color := RGB(255, 0, 0);
       result.Name := "Red";
     end // красный
     else if (blue > green) and (blue > red) and (blue > 130) then
     begin
       result.color := RGB(0, 0, 255);
       result.Name := "Blue";
     end // синий
     else if (green > blue) and (green > red) and (green > 130) then
     begin
       result.color := RGB(0, 255, 0);
       result.Name := "Green";
     end // зеленый
     else
     begin
       result.color := RGB(0, 0, 0);
       result.Name := "Black";
     end
   end;

   if not (ColSel = "None") then
     if not (ColSel = Result.Name) then
     begin
       result.color := RGB(255, 255, 255);
       result.Name := "White"; //Если выборка только по одному цвету, то
       //все остальные цвета переводим в белый
     end
     else
     begin
       result.color := RGB(0, 0, 0);
       result.Name := "Black"; //Если выборка только по одному цвету, то
       //этот цвет переводим в черный
     end

end;


 
Sha ©   (2013-06-25 21:22) [1]

этот алгоритм был дан свыше сразу в таком виде, или ему предшествовало какое-то описание?


 
RWolf ©   (2013-06-25 23:14) [2]


> можно ли ее как нибудь ускорить?

выкинуть всё, связанное со строками.
возвращать только получившийся цвет или код диапазона.


 
Вова   (2013-06-26 06:09) [3]

он не был дан свыше я его накалякал сам )
а что тут описывать?
смотрим в каком диапазоне цвет и приводим цвет к значению конца этого диапазона


 
Sha ©   (2013-06-26 08:06) [4]

> я его накалякал сам )

О том, и речь, что одному описанию могут соответствовать несколько разных алгоритмов.
И совершенно непонятно, почему надо оптимизировать именно этот вариант алгоритма.

Не говоря уже о том, что можно выбрать другие константы и правила сравнения.

И, наконец, что-то там с голубым напутано.


 
Вова   (2013-06-26 09:50) [5]

эм, а какой вариант оптимизирвать? у меня только один есть...

голубой  поначалу был голубым, но потом я решил что он тоже будет синим, так что так и задумано

можно изменить через tbmp.PixelFormat := pf8bit; количество цветов но все же это не то что нужно, картинка после этого выглядит неудобо варимой, а свой алгоритм можно еще и поднастроить под конкретную ситуацию (ну вот как я захотел и убрал голубой)


 
Sha ©   (2013-06-26 09:54) [6]

> эм, а какой вариант оптимизирвать? у меня только один есть...

ты б задачу описал, может другие варианты и появились бы )

а то получается, спрашиваешь, в мешке какого цвета лучше бегать стометровку


 
Sha ©   (2013-06-26 10:20) [7]

например, вот такой вариант:

Color:=ColorMap[Color shr 12 and $F0F or Color and $F0];


 
Вова   (2013-06-26 10:37) [8]

Задача взять TBitmap 24 битный и поменять в нем цвета каждого пикселя. т.e. в картинке все цвета должны преобразоваться к: Белому, Светлосерому, Темносерому,черному, синему,красному, зеленому, розовому, желтому.

делается это для того чтобы четко выделить объекты на картинке, например, буквы светлосерые, но на 24 битном изображении это куча разных значений цветов. пороговое преобразование работает в данном случае ненадежно, т.к. яркость фона непостоянна (т.е. определять границы объектов по разцице яркостей), но зато оно работает в 2 раза быстрее этого алгоритма ( несмотря на то что я всю картинку раз 5 прохожу пороговым, а этим всего 1 )

т.е. я могу сказать что после фильтрации на картинке должен остаться только светлосерый цвет и искать после этого текст отбросив все остальное.

понятно, что на разных картинках диапазоны цветов приводящие к желаемому результату могут быть разные, поэтому желательно очень, чтобы их можно было настраивать.

как то так.


 
Вова   (2013-06-26 10:44) [9]


> например, вот такой вариант:
>
> Color:=ColorMap[Color shr 12 and $F0F or Color and $F0];
>


вау, я ничо не понял. где нибудь есть букварь по такому алгоритму?


 
Sha ©   (2013-06-26 10:57) [10]

Количество градаций каждой составляющей цвета уменьшаем до 16, оставляя по 4 старших бита от каждой.
Итого получаем 16*16*16 разных цветов. Будем использовать их как индекс в массиве.

Где-то в самом начале программы для инициализируем массив результирующих цветов.

Осталось вычислить индекс входного цвета в нашем массиве и извлечь оттуда результат.


 
Sha ©   (2013-06-26 11:09) [11]

Инициализация выглядит так:

for i:=0 to 15 do for j:=0 to 15 do for k:=0 to 15 do ColorMap[i*256+16*k+j]:=YourSuperFunc(i*256*256+j*256+k);


 
Sha ©   (2013-06-26 11:11) [12]

Нет не так, а вот так:

for i:=0 to 15 do for j:=0 to 15 do for k:=0 to 15 do ColorMap[i*256+16*k+j]:=YourSuperFunc((i*256*256+j*256+k)*16);


 
han_malign   (2013-06-27 09:34) [13]


>  на разных картинках диапазоны цветов приводящие к желаемому результату могут быть разные

- для уменьшения глубины цвета(квантизации) - используется обычно октантное дерево...
У Фень Юаня есть есть описание алгоритма, и здесь -
http://www.efg2.com/Lab/Graphics/Colors/ShowDemoOne.htm


 
Sha ©   (2013-06-27 09:58) [14]

в варианте [7,12] перенастройка выполняется аналогично инициализации,
только производится вызов другой YourSuperFunc2 или той же, но с другими параметрами


 
Sapersky   (2013-06-27 11:26) [15]

пороговое преобразование работает в данном случае ненадежно, т.к. яркость фона непостоянна

http://locv.ru/wiki/5.7.1_Адаптивное_пороговое_преобразование


 
Jeer ©   (2013-06-27 12:33) [16]

Да, адаптивное - рулит.
Когда-то было надо, сделал свой вариант:

Константный threshold:
http://s018.radikal.ru/i503/1306/11/a134e2eddde4.jpg

Адаптивный threshold:
http://s14.radikal.ru/i187/1306/2a/8325f2f04dd5.jpg


 
Вова   (2013-06-27 14:49) [17]

ща сделал как Sha  написал - скорость стала как у порогового, может даж немного быстрее. if then - конкретно тормозят, даже если одно условие вставить то уже +30 милисекунд на картинку (


 
Вова   (2013-06-28 13:28) [18]

эх, только вот обнаружилось, что белого при такой инициализации нет в массиве (

Во всяком случае цвет 255 255 255 получается в результате светло серым.


 
Вова   (2013-06-28 14:05) [19]

Вообщем после преобразования такого Color shr 12 and $F0F or Color and $F0

разбиение на RGB такого вида:

RGBV.red := color;
RGBV.green := color shr 8;
RGBV.blue := color shr 16;

на выходе дает лажу (  как то например белый превращается в красный

беда в том что я в этих сдвигах битов ничего не понимать, помогите.


 
Вова   (2013-06-28 14:38) [20]

Color shr 12 and $F0F or Color and $F0 - как это расшифровать, что это значит?)


 
MBo ©   (2013-06-28 14:39) [21]

>RGBV.red := color;
>RGBV.green := color shr 8;
>RGBV.blue := color shr 16;

После каждой из этих операций наложи маску $FF для выделения млвдшего байта
(color shr 8) and $FF

>я в этих сдвигах битов ничего не понимать
так разберись, пригодится
Вот, например:
http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=838


 
Sha ©   (2013-06-28 14:47) [22]

ничего этого (разбивать и понимать) не требуется

1. просто объяви таблицу для хранения вычисленных результатов

var
 ColorMap: array[0..16*16*16-1] of integer;

2. заранее помести результаты вызова любой своей функции для 4k цветов в таблицу (см.[12])

3. когда требуется, вместо вызова своей функции бери результат из таблицы (см.[7])


 
Вова   (2013-06-28 14:54) [23]


> ничего этого (разбивать и понимать) не требуется1. просто
> объяви таблицу для хранения вычисленных результатовvar  
> ColorMap: array[0..16*16*16-1] of integer;2. заранее помести
> результаты вызова любой своей функции для 4k цветов в таблицу
> (см.[12])3. когда требуется, вместо вызова своей функции
> бери результат из таблицы (см.[7])


я так и делал, и обнаружил что  в инициализированном массиве белого цвета нет ( а если я ищу в массиве белый цвет, то он мне возвращает светлосерый.


 
Sha ©   (2013-06-28 14:55) [24]

не верю, код давай


 
Sha ©   (2013-06-28 15:06) [25]

Максимальный цвет получается при r=g=b=240 т.к. 4 младших бита обнуляются при инициализации. Для этого цвета твоя функция должна вернуть белый.

Или второй способ - установить эти биты при инициализации, например так:

for i:=0 to 15 do for j:=0 to 15 do for k:=0 to 15 do ColorMap[i*256+16*k+j]:=YourSuperFunc((i*16+15)*256*256+(j*16+15)*256+(k*16+15));


 
Вова   (2013-06-28 15:10) [26]



TColorMap = array[0..16*16*16-1] of TColorWithName;

var
 ColorMap:TColorMap;

Procedure InitColorMap();
var
 i, j, k: byte;
begin
 for i := 0 to 15 do
   for j := 0 to 15 do
     for k := 0 to 15 do
       ColorMap[i * 256 + 16 * k + j] := ConvertColorToRGBColorMap
         ((i * 256 * 256 + j * 256 + k) * 16);
end;

Function FindConvertedColor(color: LongInt; ColSel: String = "None")
 : TColorWithName;
begin

 result := ColorMap[color shr 12 and $F0F or color and $F0];

 if not(ColSel = "None") then
   if not(ColSel = result.Name) then
   begin
     result := ColorMap[0];
   end
   else
   begin
     result := ColorMap[Length(ColorMap)-1];
   end;
end;


 
Sha ©   (2013-06-28 15:17) [27]

Последнюю строчку в InitColorMap спиши из [25] - и будет тебе щастье без черного цвета.

Ты специально тормозишь программу???
Выкинь нафиг вторую функцию. Просто бери элемент массива в нужном месте программы.
А уж если когда понадобится название цвета, тогда вызывай хоть черта с рогами.


 
MBo ©   (2013-06-28 15:17) [28]

Я бы так скобками обложил:
(Color shr 12) and $F0F or Color and $F0

причина - приоритет and выше, чем у  shr

или для читабельности (и при паранойе) вообще так:
((Color shr 12) and $F0F) or (Color and $F0)


 
Sha ©   (2013-06-28 15:23) [29]

> приоритет and выше, чем у  shr

у меня вроде одинаковый)


 
Sha ©   (2013-06-28 15:34) [30]

> Вова   (28.06.13 15:10) [26]

В качестве домашнего задания можешь написать инициализацию таблицы для случая ColSel<>"None".
И со сдвигами разберешься и польза для работы опять же.


 
Sha ©   (2013-06-28 15:40) [31]

> Вова   (28.06.13 15:10) [26]

И эта. Не надо хранить имена. Правильное объявление ColorMap в [22].


 
Вова   (2013-06-28 16:04) [32]

таки вы уже хотите сказать что лучше 9 массивов забубенить по 4к элементов?


 
Вова   (2013-06-28 16:05) [33]

даж 10, 1 универсальный и 9 по штуке на каждый цвет.


 
Sha ©   (2013-06-28 16:08) [34]

Где?
Лучше 1 массив инициализировать каждый раз, когда надо.
Все твои случаи сводятся к этому.
И все будет просто летать, т.к. вызовов функции при работе с картинками вообще не будет.


 
Вова   (2013-06-28 16:12) [35]

да но по сути это
1)  видеопоток
2)  ищутся разные объекты в разном цвете


 
Sha ©   (2013-06-28 16:13) [36]

Тогда 10 массивов лучше


 
Sha ©   (2013-06-28 16:21) [37]

искомый цвет задается не именем, а адресом массива


 
Sha ©   (2013-06-28 16:24) [38]

и размер элемента массива становится 1 байт (или даже бит - это можно сделать, если размер имеет значение)


 
MBo ©   (2013-06-28 16:25) [39]

>у меня вроде одинаковый)

:)
Это я, балбес, с прямым углом перепутал (с or, xor)


 
Вова   (2013-06-29 00:08) [40]

дауш, то что вызывать сразу из массива, а не из фунции, то это если что то и дало, то я не заметил. а вот когда я убрал текст, производительность выросла в несколько раз.



Страницы: 1 2 3 4 5 6 вся ветка

Текущий архив: 2014.07.06;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.01 c
15-1386273085
Rouse_
2013-12-05 23:51
2014.07.06
о вреде курения


15-1387202271
Token
2013-12-16 17:57
2014.07.06
XE3 Как добавить форму в репозиторий?


15-1387088458
SKIPtr
2013-12-15 10:20
2014.07.06
как переслать письмо из рамблера


15-1387225805
Юрий
2013-12-17 00:30
2014.07.06
С днем рождения ! 17 декабря 2013 вторник


2-1372177061
Вова
2013-06-25 20:17
2014.07.06
Оптимизация кода