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

Вниз

Blur, реализация   Найти похожие ветки 

 
Илья_666   (2015-05-29 22:04) [0]

Доброго времени суток, товарищи!
Мне необходимо сделать размытие изображения. Маленького, 100х100 максимум. Но необходимо делать это программно (т.е. в Фотошопе не сделать).
Вообщем, полистал описания алгоритмов попробовал реализовать, но ничего не получилось. На басурманском сайте нашел один любопытный код (правда, не знаю, на каком языке):
   
   function Blur (source, dest, radius) {
       for (y = 0; y < height; ++y) {
           for (x = 0; x < width; ++x) {
               total = 0
               for (ky = -radius; ky <= radius; ++ky)
                   for (kx = -radius; kx <= radius; ++kx)
                       total += source(x + kx, y + ky)
               dest(x, y) = total / (radius * 2 + 1) ^ 2  
           }
       }
   }

Автор утверждает, что данный код:
This function blurs a source image and places the result in the destination image.

Я попробовал переписать его в делфи, но либо напутал чего-то, либо код изначально не рабочий:

procedure Blur(source, dest: TBitmap; radius: integer);
var
 x, y, kx, ky: integer;
 total: integer;
begin
 source.PixelFormat := pf24Bit;
 dest.PixelFormat := pf24Bit;
 for y:=0 to source.height do begin
   for x:=0 to source.width do begin
     total := 0;
       for ky:=-radius to radius do
         for kx:=-radius to radius do
           total := source.canvas.Pixels[x + kx, y + ky];
           dest.canvas.Pixels[x, y] := Round(Sqr(total / (radius * 2 + 1)));
   end;
 end;
end;


В общем, интересует следующее:
1)На каком языке написан исходный код, взятый с сайта (просто из любопытства, может кто знает)?
2)Корректно ли я перевел его в делфи?
3)Каким макаром эта чертова свертка делается?! Никак не пойму, как эти чертовы коэффициенты из ядра перемножать с пикселями битмапа.

Заранее спасибо за дельные советы.

З.Ы.
Протестируйте, пожалуйста, код, который указан в самом начале сообщения. хочется знать, работает ли он вообще.


 
MBo ©   (2015-05-29 22:23) [1]

1. C-образный псевдокод
2. Циклы по x,y неправильные. Во-первых, лишняя единица в конце, во-вторых, как и в исходном коде, не учтены краевые эффекты - что, будешь из минус пятого пиксела строки читать? Возможный вариант:
for y:= radius to source.height - radius - 1
Pixels - это цвет. Как представляешь себе сложение цветов, представленных rgb составляющими? Проще всего работать с монохромными изображениями, с яркостью.

Приведенный код выполняет свертку с квадратным окном, заменяя значение в точке на среднее по указанной окрестности


 
Dimka Maslov ©   (2015-05-30 09:09) [2]

На "непонятном" языке ^ не возведение в степень, а xor.


 
Илья_666   (2015-05-30 20:44) [3]


> Pixels - это цвет. Как представляешь себе сложение цветов,
>  представленных rgb составляющими? Проще всего работать
> с монохромными изображениями, с яркостью.

Действительно? (Интонацию не передать, но это не издевка)
На одном форуме видел такое:


> составляющие цвета надо получить не только для этого пикселя,
>  но и для соседних.
> а дальше каждый из них умножить на соответствующий коэффициент
> (из "окна") и сложить.
> Коэффициенты "окна" задают пропорции, в которых каждый из
> соседей влияет на вычисляемый пиксель. Чтобы не вылезать
> из интервала 0..255 просто нормализацию надо выполнить (обычно
> - разделить на сумму коэффициентов).

Я ж и думал, что с цветами надо работать. Ну, не с только с цветом, сколько с его составляющими.


> Приведенный код выполняет свертку с квадратным окном, заменяя
> значение в точке на среднее по указанной окрестности

Да, этого мне вполне хватило бы.


> На "непонятном" языке ^ не возведение в степень, а xor.

Спасибо, но с xor та же история. Хотя, не в xor дело, видимо.

З.Ы.
Хотел уже было отправить ответ, но решил еще поэкспериментировать.
В общем, сотворил такое:

procedure MakeBlur(ABitmap: TBitmap);
var
 A, B, C: PRGBArray;
 x, y: integer;
begin
 ABitmap.PixelFormat := pf24bit;
 for y:=2 to ABitmap.Height - 2 do
   begin
     A := ABitmap.ScanLine[y-1];
     B := ABitmap.ScanLine[y];
     C := ABitmap.ScanLine[y+1];
     for x:=2 to ABitmap.Width - 2 do
       begin
         B[x].Red := Trunc(C[x+1].Red + A[x-1].Red + B[x].Red) div 3;
         B[x].Green := Trunc(C[x].Green + A[x].Green + B[x].Green) div 3;
         B[x].Blue := Trunc(C[x+1].Blue + A[x-1].Blue + B[x].Blue) div 3;
       end;
   end;
end;


Работает))
Только теперь есть проблема: изображение размывается по вертикали, а хотелось и по горизонтали тоже. В чем может быть проблема?


 
MBo ©   (2015-05-30 21:47) [4]

>Я ж и думал, что с цветами надо работать. Ну, не с только с цветом, сколько с его составляющими.
Тогда нужно применять фильтрацию к каждой составляющей отдельно.

> В чем может быть проблема?
В логике. Сколько точек должно участвовать в формировании значения, например, B[x].Red ?


 
Илья_666   (2015-05-31 11:18) [5]


> В логике. Сколько точек должно участвовать в формировании
> значения, например, B[x].Red ?

Думаю, что 3 точки. R,G,B или не прав?


 
brother ©   (2015-05-31 11:48) [6]

если блур кубический, то не менее 4х близлежащих... а у Вас 3и...


 
brother ©   (2015-05-31 11:50) [7]

rgb это не 3 точки, а цветовая составляющая (красный, зеленый, синий) 1й точки...


 
MBo ©   (2015-05-31 11:55) [8]

>Думаю, что 3 точки
Для radius = 1 исходный код получает среднее по квадрату из 9 точек (3x3)


 
Илья_666   (2015-05-31 13:33) [9]


> если блур кубический, то не менее 4х близлежащих... а у
> Вас 3и...

Ну да, квадрат же.


> Для radius = 1 исходный код получает среднее по квадрату
> из 9 точек (3x3)

Что это значит? Если radius = 2, то будет 6х6 и 36 точек соответственно?

Если я правильно все понял, то вот переделанный вариант:

procedure MakeBlur(ABitmap: TBitmap);
var
 A, B, C, D: PRGBArray;
 x, y: integer;
begin
 ABitmap.PixelFormat := pf24bit;
 for y:=2 to ABitmap.Height - 2 do
   begin
     A := ABitmap.ScanLine[y-1];
     B := ABitmap.ScanLine[y];
     C := ABitmap.ScanLine[y+1];
    D := ABitmap.ScanLine[y];
     for x:=1 to ABitmap.Width - 2 do
       begin
         B[x].Red   := Trunc(C[x].Red   + A[x].Red   + B[x-1].Red   + D[x+1].Red)   div 4;
         B[x].Green := Trunc(C[x].Green + A[x].Green + B[x-1].Green + D[x+1].Green) div 4;
         B[x].Blue  := Trunc(C[x].Blue  + A[x].Blue  + B[x-1].Blue  + D[x+1].Blue)  div 4;
       end;
   end;
end;


Теперь ничего не сдвигается (относительно примера в [0]), на глаз - все корректно.
Или это не самое правильное решение?


 
Inovet ©   (2015-05-31 14:09) [10]

> [9] Илья_666   (31.05.15 13:33)
> Что это значит? Если radius = 2, то будет 6х6 и 36 точек
> соответственно?

5*5=25



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2017.01.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.001 c
2-1432656290
cr@nk
2015-05-26 19:04
2017.01.29
WebBrowser: вставить текст в поля на странице


2-1432926299
Илья_666
2015-05-29 22:04
2017.01.29
Blur, реализация


2-1433181587
e5431
2015-06-01 20:59
2017.01.29
ComboBox: кнопки для удаления на элементах выпадающего списка


15-1457459219
Eraser
2016-03-08 20:46
2017.01.29
Тест выключения монитора


2-1432211338
Сергей
2015-05-21 15:28
2017.01.29
SQL запрос





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский