Искажение изображения с помощью синуса/косинуса

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

Если да, то как.

PHP является предпочтительным языком, но это может быть любой...


person Mark Lalor    schedule 23.08.2010    source источник
comment
вы, кажется, намерены сделать что-то с триггерными функциями. может домашнее задание?   -  person Byron Whitlock    schedule 24.08.2010
comment
ЧРЕЗВЫЧАЙНОЕ любопытство... они меня интересуют.   -  person Mark Lalor    schedule 24.08.2010
comment
Возможна реализация капчи?   -  person Nate Zaugg    schedule 24.08.2010
comment
Цветной, но если он должен быть черно-белым, это нормально   -  person Mark Lalor    schedule 24.08.2010
comment
Что такое реализация капчи?   -  person Mark Lalor    schedule 24.08.2010
comment
Если вы хотите узнать больше о том, как синус и косинус связаны с единичным кругом, вы можете попробовать нарисовать с их помощью круг. Если вы хотите исказить изображение, вы можете попробовать эффект полярной ряби.   -  person Skurmedel    schedule 24.08.2010
comment
Марк: Это то, что подтверждает вашу человечность; это затрудняет злоупотребление сайтом роботами.   -  person Skurmedel    schedule 24.08.2010
comment
@Mark: en.wikipedia.org/wiki/CAPTCHA   -  person Merlyn Morgan-Graham    schedule 24.08.2010
comment
Для некоторых ответов на уровне пикселей здесь вы можете сделать то же самое с текстурированной геометрией, применяя вместо этого преобразования к вершинам. Если вы все еще хотите делать рябь на уровне пикселей, но только по одной оси, вы можете использовать функции blt и сдвигать целые срезы, а не перебирать все пиксели.   -  person Merlyn Morgan-Graham    schedule 24.08.2010


Ответы (3)


Да, это возможно. Изображение — это всего лишь двумерный массив пикселей, и их можно свободно реорганизовывать. Одним из простых способов является создание нового изображения и выборка пикселей из исходного изображения с помощью некоторой функции искажения.

$original = read_image_pixels(); // using GD or some other way
for ($x = 0; $x < $width; $x++) {
  for ($y = 0; $y < $height; $y++) {
    // we are adding $height and taking modulo
    // to insure that $distorted_y is positive and less then $height.
    $distorted_y = ($y + round(10*sin($x/20)) + $height) % $height;

    $distorted[$x][$y] = $original[$x][$distorted_y];
  }
}

Изменить: это можно обобщить еще больше. Многие знакомые эффекты, такие как размытие и снижение резкости, представляют собой сверточные фильтры. Они довольно хорошо объясняются в статье GameDev. Вышеупомянутое синус-искажение можно рассматривать как сверточный фильтр с пространственно переменным ядром (матрицей коэффициентов).

person phadej    schedule 23.08.2010

Используя ответ phadej, я получил решение...

Картина такая...

альтернативный текст

Код —

<?php
    header("Content-type: image/png");
    $im = imagecreatefrompng('pic.png');
    $newim = imagecreatetruecolor(imagesx($im),imagesy($im));
    for ($x = 0; $x < imagesx($im); $x++) {
        for ($y = 0; $y < imagesy($im); $y++) {

        $rgba = imagecolorsforindex($im, imagecolorat($im, $x, $y));
        $col = imagecolorallocate($newim, $rgba["red"], $rgba["green"], $rgba["blue"]);


        $distorted_y = ($y + round(100*sin($x/50)) + imagesy($im)) % imagesy($im);
        imagesetpixel($newim, $x, $distorted_y, $col);
        }
    }

    imagepng($newim);
    ?>

Вывод

альтернативный текст

person Mark Lalor    schedule 24.08.2010

Это во многом зависит от того, как работает ваш образ. Я не говорю на PHP, так что это общее решение.

Если мы можем перемещать отдельные пиксели, концептуально самый простой способ сделать это — сказать

yold = старое положение y пикселя
yновое = новое положение y пикселя
x = положение x пикселя
L = длина изображения в пикселях
N = количество применяемых тригонометрических циклов (т. е. количество синусоидальных волн)

Затем мы просто перебираем изображение. Для каждого значения x мы перемещаем y-пиксель:

yновый = yстарый * (1+sin(Nπx/L)) / 2

person spencer nelson    schedule 23.08.2010