Выполнение геометрических операций

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

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

геометрия vImage обычно преобразовывает взгляд лучше, чем, что Вы получаете от Кварца, 2D или Базовое Изображение с тех пор vImage использует методы передискретизации Lanczos по умолчанию (а не более простые подходы как линейная интерполяция). Это делает преобразования vImage менее восприимчивыми к Муаровым образцам, и предложите лучшую точность изображения.

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

Геометрический обзор операций

Несмотря на то, что часто простой концептуально, геометрические операции (такие как вращение изображения произвольным углом) могут быть в вычислительном отношении дорогими. vImage обеспечивает и высокоуровневые и низкоуровневые функции для выполнения этих операций эффективно. vImage предлагает несколько типов геометрических операций, каждый предназначенный для искажения геометрии начального изображения по-другому.

Вот некоторые геометрические операции, доступные в vImage:

Аффинная Деформация показывает одну из доступных функций масштабирования.

  Масштабирование рисунка 3-1

Эта функция масштабирует изображения в ARGB8888 формат:

vImageScale_ARGB8888( inBuffer, outBuffer, NULL, flags );

Функция масштабирует изображение путем сравнения высоты, и ширина исходного изображения (прошел inBuffer параметр) и высота и ширина конечного изображения (прошел outBuffer параметр).

Все геометрические операции, которые обеспечивает vImage, являются примерами аффинных преобразований. Аффинное преобразование является самым общим из линейных преобразований на изображении. При этой трансформации все параллельные строки в изображении остаются параллельными. Рисунок 3-2 показывает основное аффинное преобразование (уведомление, как весь параллелизм сохраняется).

Рисунок 3-2  аффинное преобразование

Аффинные преобразования работают путем отображения каждого пикселя в исходном изображении (на основе [x, y] координатное расположение) к новому расположению [x’, y’] в конечном изображении на основе этой простой арифметической формулы:

../Art/affine.jpg

Аффинные преобразования могут также быть описаны с точки зрения матричной арифметики. Трансформация определяется матрицей аффинного преобразования

../Art/matrix1.gif

согласно формуле

../Art/matrix3.gif

tx и ty - каждый символы для отдельных значений. Дополнительный компонент «1» на правой стороне не является частью расположения исходного пикселя; это добавляется здесь для представления аффинного преобразования как умножения матриц. Фактически, это обычно, чтобы добавить дополнительную координату к итоговому вектору и представлять аффинное преобразование как

../Art/matrix4.gif

Это упрощает вычислять обратное преобразование, начиная с 3 x, 3 матрицы могут быть инвертированы.

Аффинное преобразование может анализироваться в две менее общих трансформации: линейное преобразование, сопровождаемое переводом (в обоих направления x и y). Линейное преобразование определяется как

../Art/matrix5.gif

Перевод просто добавляет tx к x-координате и ty к y-координате.

vImage_AffineTransform структура, содержащая матрицу аффинного преобразования, совпадает с CGAffineTransform тип данных. Посмотрите Ссылку CGAffineTransform для функций, используемых для создания и управления матрицами.

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

Рисунок 3-3  Аффинно деформируется

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

Передискретизация

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

Однако в геометрических операциях, ядро передискретизации должно самостоятельно передискретизироваться во время процесса соединяющихся значений ядра против выбранных пиксельных данных. vImage должен оценить ядро в дробных пиксельных расположениях («промежуточные» пиксели), в дополнение к интегральным пиксельным расположениям. Следовательно, вместо того, чтобы использовать M x N матрица для ядра (поскольку операции свертки делают), операции используют функцию ядра, которая может быть оценена и в дробных и в интегральных пиксельных расположениях. Эта функция ядра передискретизации вызвана фильтр передискретизации, или просто фильтр.

Для почти всех геометрических операций vImage предоставляет фильтр передискретизации значения по умолчанию. Фильтры передискретизации значения по умолчанию являются реализациями обычно используемого метода передискретизации Lanczos. Lanczos передискретизация метода обычно приводит к лучше выглядящим результатам, чем более простые подходы, такие как линейная интерполяция. Однако метод Lanczos может произвести звонящие эффекты около областей высокочастотных сигналов (таких как штриховая графика). vImage обеспечивает два изменения для выбора из. Если Вы не устанавливаете kvImageHighQualityResampling флаг для вызова, vImage использует a Lanczos3 фильтр. При установке флага vImage использует a Lanczos5 фильтр. A Lanczos5 фильтр делает передискретизацию более высокого качества, чем a Lanczos3 отфильтруйте, но медленнее для использования.

Rotate передискретизация использования функций. Rotate90 функции не делают.

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

Перечисление 3-1  , Создающее передискретизацию значения по умолчанию, фильтрует для функции сдвига

ResamplingFilter filter = vImageNewResamplingFilter( float scale, vImage_Flags kvImageNoFlags )

Если Вы хотите обеспечить пользовательский фильтр передискретизации, процедура отличается. Поскольку функции сдвига воздействуют на линию за линией основание, ядро передискретизации, используемое с функцией сдвига, одномерно, 1 x N матрица. Следовательно, фильтр передискретизации для функции сдвига может быть смоделирован как одномерная функция y = f (x). При использовании пользовательского фильтра необходимо обеспечить подпрограмму, оценивающую функцию f (x) на массиве значений x. Одновременно можно при желании нормализовать фильтр по данному массиву значений x. (Это - главная причина, Ваша подпрограмма требуется, чтобы оценивать Ваш фильтр на массиве значений x, а не единственного значения x. Это также улучшает производительность.) Для нормализации фильтра по массиву значений x Вы масштабируете значения фильтра так, чтобы они составили в целом 1.0. Если Вы не делаете этого, интерференционные узоры могут появиться в получающемся изображении.

Создание фильтра передискретизации

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

Если Вы хотите использовать фильтр передискретизации значения по умолчанию, Вы создаете его путем вызова vImageNewResamplingFilter (как ранее замечено в Перечислении 3-1). Это создает новое ResamplingFilter объект, представляющий фильтр по умолчанию — a Lanczos3 отфильтруйте, если Вы не устанавливаете kvImageHighQualityResampling флаг или a Lanczos5 отфильтруйте при установке того флага. Вы не должны обеспечивать функцию фильтра при совершении этого вызова.

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

Когда Вы сделаны с помощью a ResamplingFilter объект, создаваемый вызовом к vImageNewResamplingFilter, избавьтесь от него путем вызова vImageDestroyResamplingFilter. Не пытайтесь непосредственно освободить память объекта сами.

Если Вы хотите создать a ResamplingFilter объект, представляющий Ваш пользовательский фильтр передискретизации, Вы создаете его путем вызова vImageNewResamplingFilterForFunctionUsingBuffer. Необходимо передать указатель на пользовательскую функцию фильтра. vImageNewResamplingFilterForFunctionUsingBuffer создает ResamplingFilter объект в буфере, который Вы выделяете непосредственно. См. vImage Ссылку Геометрии для подробных данных использования. Когда Вы сделаны с помощью объекта, необходимо освободить его память сами. Не передавайте a ResamplingFilter объект, создаваемый vImageNewResamplingFilterForFunctionUsingBuffer к vImageDestroyResamplingFilter.

Получить размер буфера, требуемого для пользовательского ResamplingFilter объект, вызвать vImageGetResamplingFilterSize. Оба значение по умолчанию ResamplingFilter и пользовательское ResamplingFilter объекты включают масштабный коэффициент, который Вы обеспечиваете. Этот масштабный коэффициент используется для масштабирования преобразованного изображения в работе сдвига.

Демонстрационный пользовательский фильтр передискретизации

Перечисление 3-2 показывает, как объявить и использовать пользовательскую функцию фильтра передискретизации. Базовая функция фильтра y = 1.0 – |x|. Пользовательский фильтр должен оценить ту функцию на массиве значений x. Фильтр не может быть нормализован по тому диапазону значений x. Можно нормализовать его в подпрограмме путем деления на сумму значений результата, как показано. Эта подпрограмма не использует userData.

Перечисление 3-2  Используя пользовательскую функцию фильтра

void MyLinearInterpolationFilterFunc(const float* xArray,
 float* yArray,
 int count,
 void* userData )
{
    int i;
    float sum = 0.0f;
    //Calculate kernel values
    for( i = 0; i < count; i++ )
    {
        float unscaledResult = 1.0f - fabs( xArray[i] );    //LERP
        yArray[i] = unscaledResult;
        sum += unscaledResult;
    }
    //Make sure the kernel values sum to 1.0. You can use some other  value here.
    //Values other than 1.0 will cause the image to lighten or darken.
    sum = 1.0f / sum;
    for( i = 0; i < count; i++ )
        yArray[i] *= sum;
}

Часто используемые операции

Вращения и масштабирование являются наиболее распространенными геометрическими операциями, и функции масштабирования и вращения vImage особенно подходят для разработчиков, которым нужны эти scalings для взгляда максимально чистыми. Приложения, управляющие макетом фотопроектов (как цифровые фото книги iPhoto) являются совершенными кандидатами на это. Перечисление 3-3 показывает, как повернуть изображение, которое находится в ARGB8888 формат.

Перечисление 3-3  , Вращающееся изображение указанным углом с помощью vImageRotate_ARGB8888

int MyRotateFilter(void *inData, unsigned int inRowBytes, void *outData, unsigned int outRowBytes, unsigned int height, unsigned int width, void *kernel, unsigned int kernel_height, unsigned int kernel_width, int colorChannel, vImage_Flags flags )
{
    vImage_Buffer in = { inData, height, width, inRowBytes };
    vImage_Buffer out = { outData, height, width, outRowBytes };
    TransformInfo *info = kernel;
    float angle = info->rotate * 2.0f * M_PI / 360.0f;
    Pixel_8888 backColor;
 
    backColor[0] = UCHAR_MAX * info->a;
    backColor[1] = UCHAR_MAX * info->r;
    backColor[2] = UCHAR_MAX * info->g;
    backColor[3] = UCHAR_MAX * info->b;
 
    return vImageRotate_ARGB8888( &in, &out, NULL, angle, backColor, flags );
}

Вращение

При выполнении вращения vImage отображает центральную точку исходного изображения к центральной точке конечного изображения. Никакое масштабирование не сделано. В зависимости от относительных размеров исходного изображения и конечного изображения, могут быть отсечены части исходного изображения, и области вне исходного изображения могут появиться в конечном изображении. Рисунок 3-4 показывает повернутую фотографию собаки, но части изображения кажутся отсеченными, так как они теперь находятся вне буфера изображения (эти области окрашены с предоставленным вызывающую сторону цветом фона).

Рисунок 3-4  Повернутое изображение с отсечением

Вращение на 90 градусов

Эта работа вращения поворачивает исходное изображение или на 0, 90, 180, или на 270 градусов (в зависимости от значения, которое Вы предоставляете). vImage отображает центральную точку исходного изображения к центральной точке конечного изображения. Никакое масштабирование или передискретизация не сделаны. В зависимости от относительных размеров исходного изображения и конечного изображения, части исходного изображения могут быть отсечены, и области вне исходного изображения (окрашенный с цветом фона, который Вы предоставляете), может появиться в конечном изображении (как замечено на рисунке 3-4).

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

  • При вращении изображения, 90 или 270 градусов, высота в пикселях исходного изображения и ширине конечного изображения должны оба быть даже, или оба нечетны; и ширина исходного изображения и высота конечного изображения должны оба быть даже или оба быть нечетными.

  • При вращении изображения 0 или 180 градусов высота в пикселях исходного изображения и конечного изображения должна оба быть даже, или оба нечетны; и ширина исходного изображения и конечного изображения должна оба быть даже или оба быть нечетной.

Если Ваши изображения не встречают эти ограничения, можно использовать генерала (более высокий уровень) Rotate функция вместо этого.

Горизонтальные отражения

Горизонтальное отражение создает зеркальное отображение входного изображения путем отражения об оси y изображения. Это может считаться размещением воображаемой строки от вершины изображения к нижней части и свопинга каждого пикселя на одной стороне с соответствующим пикселем с другой стороны. Рисунок 3-5 показывает пример горизонтальной отражательной работы.

Рисунок 3-5  Горизонтальное отражение

Вертикальные отражения

Вертикальное отражение идентично горизонтальному отражению, кроме него отражается об оси X вместо этого. Рисунок 3-6 показывает пример вертикальной отражательной работы.

Рисунок 3-6  Вертикальное отражение

Горизонтальный сдвиг

горизонтальная функция сдвига vImage делает сдвиг, перевод и масштабирование (только в измерении по горизонтали) на исходном изображении. Функции сдвига (и Rotate90) служите основой, на которую реализованы многие другие функции vImage. В простой горизонтальной работе сдвига (никакое масштабирование или перевод), прямоугольная область интереса отображается в параллелограм, верх и низ которого параллельны исходному прямоугольнику, и чьи стороны являются наклонными в определенном наклоне. Высота параллелограма совпадает с высотой исходного прямоугольника.

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

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

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

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

Размер (число строк и число столбцов) целевого буфера также используется для определения размера области интереса к исходному буферу. Источник и области интереса и целевого буфера, как предполагается, находится в нижнем левом углу. Если нет никакого перевода, то нижний левый угол области интереса (не обязательно исходного изображения, которое может отличаться) отображается на нижнем левом углу конечного изображения. ( vImage_Buffer указатель данных указывает на верхний левый угол изображения, как всегда.)

Рисунок 3-7 показывает фотографию после горизонтальной работы сдвига без компонента перевода.

  Горизонтальный сдвиг рисунка 3-7

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

вертикальная функция сдвига vImage делает сдвиг, перевод и масштабирование (только в измерении по вертикали) на исходном изображении. В простой вертикальной работе сдвига (никакое масштабирование или перевод), прямоугольная область интереса отображается в параллелограм, левые и правые края которого параллельны исходному прямоугольнику, и чьи верхние и нижние края являются наклонными в определенном наклоне. Ширина параллелограма совпадает с шириной исходного прямоугольника, и высота параллелограма (высота любого столбца) совпадает с высотой исходного прямоугольника.

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

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

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

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

Рисунок 3-8 показывает изображение после вертикальной работы сдвига.

Рисунок 3-8  Вертикальный сдвиг

Аффинная деформация

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