Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: andrew.k от Декабрь 18, 2010, 18:29



Название: QPixmap blur effect
Отправлено: andrew.k от Декабрь 18, 2010, 18:29
С рисованием плохо знаком. У меня есть QPixmap на нем граб главной формы, мне нужно применить к нему эффект размытия или в принципе любой другой, но чтобы содержимое стало нечитаемым.
Qt 4.4.3 поэтому QGraphicsBlurEffect там нет.
Вторая проблема, я не могу понять, как полученным пиксмапом зарисовать форму.
Пиксмап который я отрисовываю в paintEvent оказывается как бы на заднем плане. А почти все элементы управления все равно отрисовывают себя поверх.


Название: Re: QPixmap blur effect
Отправлено: Drafter от Декабрь 19, 2010, 00:02
Цитировать
Пиксмап который я отрисовываю в paintEvent оказывается как бы на заднем плане. А почти все элементы управления все равно отрисовывают себя поверх.

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


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 19, 2010, 02:37
Цитировать
Пиксмап который я отрисовываю в paintEvent оказывается как бы на заднем плане. А почти все элементы управления все равно отрисовывают себя поверх.

Эта проблема решается написанием своего виджета (с нужной полупрозрачностью), который размещается поверх других (и включается-выключается по необходимости). Что же касается эффектов - боюсь, Вам придётся "размывать" ручками, если нет возможности перейти на более современную версию Qt.
Так зачем мне делать свой виджет, если все что от него требуется это отобразить картинку. С этим прекрасно справляется QLabel. Некоторое подобие размытия я сделал (для каждого пиксела посчитал среднее значение его и всех соседних). И таких три прохода. Получилось уродское подобие размытия. Пока сойдет. Другого не слишком сложного алгоритма не нашел.
Так что вопрос в том, каким образом теперь разместить этот QLabel "поверх других" и чтобы он растягивался по размеру формы, как будто в лэйауте?


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 19, 2010, 13:02
Некоторое подобие размытия я сделал (для каждого пиксела посчитал среднее значение его и всех соседних). И таких три прохода. Получилось уродское подобие размытия. Пока сойдет. Другого не слишком сложного алгоритма не нашел.
Все размывают Гауссом и никому от этого плохо не стало. Два и более прохода не нужно, просто возьмите больше соседей для осреднения. А самое главное - не "каждый пиксель" (долго) а сначала "по строкам" а затем "по столбцам" (ну или наоборот, дело вкуса)


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 19, 2010, 21:49
Некоторое подобие размытия я сделал (для каждого пиксела посчитал среднее значение его и всех соседних). И таких три прохода. Получилось уродское подобие размытия. Пока сойдет. Другого не слишком сложного алгоритма не нашел.
Все размывают Гауссом и никому от этого плохо не стало. Два и более прохода не нужно, просто возьмите больше соседей для осреднения. А самое главное - не "каждый пиксель" (долго) а сначала "по строкам" а затем "по столбцам" (ну или наоборот, дело вкуса)
Я знаю, про размытие Гаусса, я думал, что его реализация не тривиальная, а так как для меня качество результата вообще не имеет значения, то сделал как пришло в голову. Сейчас посмотрел алгоритм Гаусса, в принципе не на много сложнее реализовать, так что сейчас буду пробовать.


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 20, 2010, 18:22
Повторюсь: блюрьте сначала строки, потом столбцы (а не всех соседей - это медленно)


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 20, 2010, 21:43
Гаусс тоже медленный на самом деле. Чтобы заблюрить до нормального уровня, нужно много времени.
Сделал через т.н. быстрый блюр. Центральный пиксел игнорируется, берется среднее значение 8 пикселов вокруг центрального.
Работает очень быстро. 10 проходов изображение 1280х1024 (4Метра РГБА) фильтруется за 0.5 сек.


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 21, 2010, 10:36
Гаусс тоже медленный на самом деле. Чтобы заблюрить до нормального уровня, нужно много времени.
Проход 1: создаете новый имедж (по размерам такой же). Каждый пиксель нового имеджа вычисляется как среднее по строке старого имеджа. (напр сумма 4 слева и 4 справа, итого 9). Новый имедж будет заблюрен "по строкам"

Проход 2: используя имедж первого прохода повторяете все то же по столбцам (напр 4 сверху и 4 снизу)

Итого каждый пиксель потребовал 9 + 9 = 18 сложений. Если же Вы просто "осредняете всех соседей", то надо 9 * 9 = 81 сложений



Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 21, 2010, 10:58
Гаусс тоже медленный на самом деле. Чтобы заблюрить до нормального уровня, нужно много времени.
Проход 1: создаете новый имедж (по размерам такой же). Каждый пиксель нового имеджа вычисляется как среднее по строке старого имеджа. (напр сумма 4 слева и 4 справа, итого 9). Новый имедж будет заблюрен "по строкам"

Проход 2: используя имедж первого прохода повторяете все то же по столбцам (напр 4 сверху и 4 снизу)

Итого каждый пиксель потребовал 9 + 9 = 18 сложений. Если же Вы просто "осредняете всех соседей", то надо 9 * 9 = 81 сложений
Какая-то невероятно хитрая математика.
интересно откуда у пиксела 81 сосед? у тебя 5D монитор или 6D?
На моем двумерном мониторе у каждого пиксела (если не считать крайних) по 8 соседей.
Соответственно пиксел нового изображения формируется сложением из этих 8 соседей и вместо деления на 8, можно использовать сдвиг вправо <<3, для скорости.
Откуда 81? Загадка.


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 21, 2010, 12:00
Какая-то невероятно хитрая математика.
интересно откуда у пиксела 81 сосед? у тебя 5D монитор или 6D?
На моем двумерном мониторе у каждого пиксела (если не считать крайних) по 8 соседей.
Соответственно пиксел нового изображения формируется сложением из этих 8 соседей и вместо деления на 8, можно использовать сдвиг вправо <<3, для скорости.
Откуда 81? Загадка.
8 = "число ближайших" соседей, + сам пиксель, итого 9. То есть Вы осредняете матрицу 3х3. Чтобы заблюрить больше, надо взять матрицу больше, напр 9x9. Но складывать не все 81 точки а 18 как писалось выше


Название: Re: QPixmap blur effect
Отправлено: Kolobok от Декабрь 21, 2010, 12:02
Откуда 81? Загадка.

Igors взял по 4 пикселя с каждой стороны. Это квадрат 9х9. Правда сложений будет 80 ( это я так, занудствую ). В твоем случае квадрат 3х3 = 9 пикселей - 8 сложений * 10 проходов = те же 80 сложений.


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 21, 2010, 18:45
Тогда я вообще не понял о чем был его пост.
И так понятно, что если взять меньше точек, то будет быстрее работать, чем если взять больше точек :)


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 22, 2010, 11:39
Igors взял по 4 пикселя с каждой стороны. Это квадрат 9х9. Правда сложений будет 80
Да НЕТ же, всего 18, (9 в первом проходе и 9 во втором). Сначала (первый проход) блюрите каждый пиксель только по (одной) строке, потом, используя результат первого прохода, только по (одному) столбцу.
Устал я объяснять  :)


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 22, 2010, 12:17
Главное, чтобы ты понимал, что ты с чем складываешь.
В алгоритме блюра по Гауссу, делается точно так же. Сначала по строкам, потом по столбцам. Конечно матрицу никто не общитывает. Он не из-за этого медленный, а из-за коэффициентов на которые приходится умножать соседние пикселы.


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 22, 2010, 12:50
В алгоритме блюра по Гауссу, делается точно так же. Сначала по строкам, потом по столбцам. Конечно матрицу никто не общитывает.
Если не обсчитывает, то чего Вы складываете 8 соседей (хотя можете сложить 2 + 2)? И чего вы берете 3х3 и делаете 10 проходов если можно просто взять матрицу больше? Гаусс здесь значит просто "колокольчик" (ближние пиксели берутся с большим весом, дальние с меньшим). А сама техника блюра (по строкам, потом по столбцам) используется с любым типом фильтра, напр. "box" (просто осреднение).

Он не из-за этого медленный, а из-за коэффициентов на которые приходится умножать соседние пикселы.
Так может Вы их просто не предвычислили? Или натыкали классов в цикле по пикселю? Если хотите давайте посмотрим код - явно что-то не так, PShop блюрит в real-time даже на скромной машине


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 22, 2010, 13:24
В алгоритме блюра по Гауссу, делается точно так же. Сначала по строкам, потом по столбцам. Конечно матрицу никто не общитывает.
Если не обсчитывает, то чего Вы складываете 8 соседей (хотя можете сложить 2 + 2)? И чего вы берете 3х3 и делаете 10 проходов если можно просто взять матрицу больше? Гаусс здесь значит просто "колокольчик" (ближние пиксели берутся с большим весом, дальние с меньшим). А сама техника блюра (по строкам, потом по столбцам) используется с любым типом фильтра, напр. "box" (просто осреднение).

Он не из-за этого медленный, а из-за коэффициентов на которые приходится умножать соседние пикселы.
Так может Вы их просто не предвычислили? Или натыкали классов в цикле по пикселю? Если хотите давайте посмотрим код - явно что-то не так, PShop блюрит в real-time даже на скромной машине
Я подозреваю, что ты очень умный. А так же я подозреваю, что ты не один такой в этом мире. Поэтому имей это ввиду как можно чаще.
Теперь по теме.
Я поясню, для тебя, потому что ты тему читал по диагонали.
Экскурс. Когда мне потребовалось отфильтровать, я сделал среднее значение из 9 пикселов. Так как при одном проходе было размыто слабо, сделал несколько проходов. Конкретно 3. А не 10.
Если расширять квадрат квадрат, то расширять нужно до 5х5 или больше, чтобы достигнуть того же уровня размытия.
И прироста скорости это совсем не даст.
Дальше я решил попробовать блюр гаусса, чтобы улучшить вид размытия. Там сделал естественно по строчкам и столбцам.
И естественно коэффициенты не рассчитываются в цикле двадцать тысяч раз. А один раз в начале.
Но понятно, что умножение на float не способствует производительности. А хорошее размытие получается только при больших сигма и соответственно большем окне (в районе 15 точно не помню сколько меня устроило).
В любом случае все варианты выполнялись дольше секунды.
Потом пришел мой товарищ и сказал мне да сделай "обычным" быстрым фильтром.
Там берется 8 соседних точек, значение самого пиксела отбрасывается. А так как соседей восем, то вместо деления можно использовать сдвиг на 3 вправо. Это быстрее, чем деление.
Сила размытия, достигается количеством проходов.
Этот фильтр я и стал использовать. Требуемый уровень размытия достигался за 10 проходов. Эти 10 проходов выполняются меньше половины секунды. В принципе скорость приемлемая так и оставил. Или ты можешь еще ускорить? :)


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 22, 2010, 13:32
Сейчас не могу посмотреть реальные цифры (на реальной машине). Под виртуалкой все тормозит.
Под виртуалкой цифры такие: быстрый блюр: 1.3 сек (10 проходов). Гаусс: 5.4 ( сигма = 3 ), Гаусс: 6.9 (сигма = 4)


Вот код Гаусса. Оптимизируй.
void blurGauss( QImage &img, float sigma, bool horisontalOnly = false )
{
    QTime begin = QTime::currentTime();
    QImage newimg( img.size(), img.format() );
    int n = (int)ceil( sigma * 3 );
    double * window = new double[ n + 1 ];
    window[ 0 ] = 1.0;
    for ( int i = 1; i < n + 1; ++i )
   window[ i ] = exp( -i * i / ( 2 * sigma * sigma ) );

    unsigned short r, g, b;
    unsigned int pixel;
    float sum;
    int width = img.width();
    int height = img.height();
    unsigned int * src = ( unsigned int * )img.bits();
    unsigned int *data = new unsigned int[ width * height ];
    for ( int y = 0; y < height; ++y )
   for ( int x = 0; x < width; ++x )
        {
       sum = 0;
       r = g = b = 0;
       for ( int k = -n; k < n + 1; ++k )
       {
      if ( x + k >= 0 && x + k < width )
      {
          pixel = src[ y * width + x + k ];
          r += (unsigned short ) ( qRed( pixel ) * window[ abs( k ) ] );
          g += (unsigned short ) ( qGreen( pixel ) * window[ abs( k ) ] );
          b += (unsigned short ) ( qBlue( pixel ) * window[ abs( k ) ] );
          sum += window[ abs( k ) ];
      }
       }
       r = (unsigned short )( r / sum );
       g = (unsigned short )( g / sum );
       b = (unsigned short )( b / sum );
       data[ y * width + x] = qRgba( r, g, b, 255 );
        }
    img = QImage( (uchar *) data, width, height, QImage::Format( 4 ) ).copy();
    src = ( unsigned int *)img.bits();
    if ( horisontalOnly )
    {
   delete[] window;
   delete[] data;
   return;
    }

    for ( int x = 0; x < width; ++x )
   for ( int y = 0; y < height; ++y )
        {
       sum = 0;
       r = g = b = 0;
       for ( int k = -n; k < n + 1; ++k )
       {
      if ( y + k >= 0 && y + k < height )
      {
          pixel = src[ ( y + k ) * width + x ];
          r += (unsigned short ) ( qRed( pixel ) * window[ abs( k ) ] );
          g += (unsigned short ) ( qGreen( pixel ) * window[ abs( k ) ] );
          b += (unsigned short ) ( qBlue( pixel ) * window[ abs( k ) ] );
          sum += window[ abs( k ) ];
      }
       }
       r = (unsigned short )( r / sum );
       g = (unsigned short )( g / sum );
       b = (unsigned short )( b / sum );
       data[ y * width + x] = qRgba( r, g, b, 255 );
        }

    img = QImage( (uchar *) data, width, height, QImage::Format( 4 ) ).copy();
    delete[] window;
    delete[] data;
    qDebug() << "Blur time(sec): " << QString( "%1.%2" ).arg( begin.secsTo( QTime::currentTime() ) )
                     .arg( begin.msecsTo( QTime::currentTime() ) % 1000 );
}


Название: Re: QPixmap blur effect
Отправлено: Kolobok от Декабрь 22, 2010, 13:58
Igors взял по 4 пикселя с каждой стороны. Это квадрат 9х9. Правда сложений будет 80
Да НЕТ же, всего 18, (9 в первом проходе и 9 во втором). Сначала (первый проход) блюрите каждый пиксель только по (одной) строке, потом, используя результат первого прохода, только по (одному) столбцу.
Устал я объяснять  :)

Всё я понял правильно. 80 будет если всю матрицу 9х9 обсчитывать. А если строки/столбцы то 16. Сложений на одно меньше, чем слагаемых. Это я имел ввиду. :)


Название: Re: QPixmap blur effect
Отправлено: Igors от Декабрь 22, 2010, 16:19
Под виртуалкой цифры такие: быстрый блюр: 1.3 сек (10 проходов). Гаусс: 5.4 ( сигма = 3 ),
У меня такие результаты

Цитировать
image 2048 x 2048

Gauss size = 19 x 19
Gauss Blur time(sec):  "2.81"

Box size = 19 x 19
Box Blur time(sec):  "1.313"

Simple blur passes = 10
Simple Blur time(sec):  "2.18"

Gauss size = 13 x 13
Gauss Blur time(sec):  "1.633"

Box size = 13 x 13
Box Blur time(sec):  "1.173"
И если Вы хотите рассказать что, мол, Гаусс дает качество хуже - то не стоит, это Ваш косяк. А больше с человеком который хамит, я разговаривать не стану. Будьте здоровы


Название: Re: QPixmap blur effect
Отправлено: andrew.k от Декабрь 22, 2010, 17:58
Во-первых, я ни разу не хамил.
Во-вторых, я нигде не сказал, что гаусс дает качество хуже. Я сказал, что Гаусс работает медленнее, чем Quick Blur.
Читать надо внимательно. Мне требуется размыть до состояния, чтобы текст не читался, а качество не важно.
Соответственно, я сравниваю результат и время его достижения разными методами. Так один проход гаусса с сигма=3 работает дольше, чем 10 проходов быстрого блюра, а получаемый результат примерно сопоставим (качество не в счет).
В-третьих, твоя таблица не позволяет сделать полезных выводов. Зачем ты потратил на это время?
Что такое Гаусс 19х19??? У Гаусса есть параметр сигма, который влияет на степень размытия и соответственно время выполнения. В самом начале темы, я написал, что я в этом не разбираюсь, но по ходу развития темы искал материал, разбирался. Поэтому что ты подразумеваешь под SimpleBlur, я могу только догадываться и чем он отличается от box blur.
Ты сказал, давай сюда код, у тебя классов понатыкано, я мол лучше могу сделать.
Я тебе дал. В результате, какая-то бесполезная таблица. Тебя не учили в универе, что нужно после лабораторной работы писать обоснованный вывод?
И подпись под таблицей гласящая: "да ты там вообще у себя поковыряй лучше и вообще мудак ты". <- Это хамство вместе с таблицей без объяснений.