Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2014.07.06;
Скачать: [xml.tar.bz2];

Вниз

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

 
Вова   (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.005 c
2-1378390770
DZM
2013-09-05 18:19
2014.07.06
проверка изменения значения поля


15-1387524120
DevilDevil
2013-12-20 11:22
2014.07.06
Ассемблерщикам: CF/ZF


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


15-1387139402
Юрий
2013-12-16 00:30
2014.07.06
С днем рождения ! 16 декабря 2013 понедельник


15-1386322461
Пит
2013-12-06 13:34
2014.07.06
система контроля версий для БД





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский