Какой алгоритм я мог бы использовать, чтобы применить искажение «рыбий глаз» к изображению?

Может ли кто-нибудь помочь мне наилучшим образом разработать алгоритм фильтра для обработки видео?

Скажем, например, я хотел применить фильтр объектива «рыбий глаз» к изображению, как мне обработать пиксели, чтобы он имитировал этот эффект?

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

Этот вид искажения — это больше, чем просто обработка цвета, поэтому я хотел бы знать, как правильно манипулировать пикселями, чтобы имитировать фильтр объектива «рыбий глаз» или, скажем, пинч-фильтр и так далее.

ИЗМЕНИТЬ:

Алгоритм фильтра для ВИДЕООБРАБОТКИ*


person Pavan    schedule 17.05.2012    source источник


Ответы (2)


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

Например, для создания искажения щипка, показанного в этом ответе, я использую фрагментный шейдер OpenGL ES, который выглядит следующим образом: :

 varying highp vec2 textureCoordinate;

 uniform sampler2D inputImageTexture;

 uniform highp vec2 center;
 uniform highp float radius;
 uniform highp float scale;

 void main()
 {
     highp vec2 textureCoordinateToUse = textureCoordinate;
     highp float dist = distance(center, textureCoordinate);
     textureCoordinateToUse -= center;
     if (dist < radius)
     {
         highp float percent = 1.0 + ((0.5 - dist) / 0.5) * scale;

         textureCoordinateToUse = textureCoordinateToUse * percent;
     }
     textureCoordinateToUse += center;

     gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse );

 }

Этот код GLSL применяется к каждому пикселю выходного изображения. Что он делает, так это вычисляет расстояние от центра сжимаемой области до текущей координаты пикселя. Затем он берет это входное расстояние и масштабирует его на основе входного параметра scale. Это новое масштабированное расстояние используется для смещения координат во входном изображении, откуда будет считываться выходной цвет.

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

person Brad Larson    schedule 17.05.2012
comment
я ценю ваш пост. Я проверил ваш ответ в другом посте, и изображения выглядят великолепно, я хочу иметь возможность применить, например, щипковый фильтр к видео. чтобы пользователь мог снять видео, а затем применить к нему фильтр. после завершения обработки, скажем, если обработка занимает 1 минуту, они могут сохранить ее. это то, что я пытаюсь сделать. Я не знаю, лучше ли захватывать каждый отдельный кадр, а затем применять к нему фильтр, как если бы это было изображение... какие-нибудь рекомендации? - person Pavan; 18.05.2012
comment
@Pavan - это будет зависеть от платформы, о которой вы говорите. Учитывая, что в прошлом вы задавали несколько вопросов об iOS, если вы ориентируетесь на эти устройства, вы можете использовать мою платформу с открытым исходным кодом: github.com/BradLarson/GPUImage, чтобы сделать это в прямом эфире. Нет необходимости записывать видео, а затем обрабатывать его, так как фильтры, которые я применяю, работают достаточно быстро, чтобы искажать видео при захвате камерой. Вы также можете записывать и затем обрабатывать записанное видео, но я полагаю, что было бы предпочтительнее отображать и записывать видеокадры по мере их поступления. - person Brad Larson; 18.05.2012
comment
Привет, Брэд, я использую платформу openframeworks для устройств iOS, поэтому, программируя на C++, я сделал несколько основных цветовых эффектов для входных данных, поступающих с камеры. Он захватывает пиксели в кадре, а затем с помощью цикла for выполняет итерацию по каждому пикселю, а затем добавляет цветовой эффект, например, смещает красные и т. д. или выполняет фильтр нижних частот для одного из цветов. Мне интересно, как я могу интегрировать вашу библиотеку с текущей настройкой, которая у меня есть? в любом случае я могу передать свой массив пикселей как текстуру или что-то еще в ваш класс, который добавляет фильтр и возвращает что-то обратно - person Pavan; 19.05.2012
comment
продолжение: чтобы я мог отобразить это на экране? atm после того, как я сделал цветовой эффект на пикселях, я просто вывожу обратно на экран с помощью доступных методов. Но я хотел бы иметь вашу библиотеку между этими шагами и использовать ваши существующие фильтры. Я вижу, что вы используете шейдеры, так что в любом случае я могу передать что-то в вашу библиотеку или, тем не менее, это удобно, чтобы я мог использовать ваши фильтры в моей текущей настройке? - person Pavan; 19.05.2012
comment
@Pavan - я только что добавил класс ввода необработанных данных, который теперь позволяет вам принимать байты, фильтровать их, а затем извлекать байты в конце. Посмотрите пример RawDataTest, чтобы увидеть, как это работает. Тем не менее, вы потеряете огромное количество производительности, читая данные с камеры в ЦП, а затем загружая их в OpenGL ES через мою структуру только для того, чтобы снова извлечь их в ЦП для отображения. Если вы используете ввод с камеры из моего фреймворка, обрабатываете с помощью его фильтров, а затем выводите через его представление, вы можете захватывать, фильтровать и отображать кадры 640x480 за 2,5 мс на iPhone 4. - person Brad Larson; 22.05.2012
comment
Привет, Брэд, я начал использовать твой фреймворк. это действительно что-то, так как это приятно и быстро по сравнению с тем, как я это делал через openframeworks. похоже на шейдеры, и открытый gl - это путь. Есть ли место, где я могу связаться с вами по любым вопросам, которые у меня возникнут во время разработки с использованием вашего фреймворка? - person Pavan; 24.05.2012
comment
продолжение: Например, у меня есть вопрос прямо сейчас: в вашем проекте multiviewfilter я пытаюсь остановить обработку этих четырех конкретных представлений view1,2,3 и 4, чтобы, когда координаты этих представлений выходят за пределы экрана, я хочу остановить обработку этих конкретных фильтров, чтобы я мог начать обработку другого набора из 4 фильтров без запуска предыдущих 4 фильтров в фоновом режиме за пределами экрана. - person Pavan; 24.05.2012
comment
продолжение: они должны быть завершены, и когда фильтры 5, 6, 7, 8 исчезнут с экрана, а фильтры просмотра 1, 2, 3 и 4 снова будут возвращены на экран, они могут снова начать обработку в обычном режиме. какие методы я использую? я пытался сделать [view4 endProcessing]; на основе касания пальцем, но это не останавливает обработку фильтра view4.. он все еще работает.. все остальное работает нормально, я просто хотел узнать, какие методы использовать, что позволит мне остановить и начать обработку любого фильтра представления, который мне нравится. какое-нибудь руководство? - person Pavan; 24.05.2012

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

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

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

person Martin Beckett    schedule 17.05.2012
comment
просто скопируйте пиксель = интерполируйте. - person koan; 17.05.2012