Быстрый метод масштабирования цветных изображений. Аннотация. Масштабирование изображений – важный этап любой цепочки обработки изображений, содержащей сенсор камеры и дисплей. Хотя разрешения современных мобильных дисплеев с развитием технологий увеличились до приемлемого для отображения качественных фотографий уровня, разрешения самих фотографий намного превосходит разрешения экранов мобильных устройств. В этой статье предложен алгоритм быстрого и качественного масштабирования изображений, пригодный для реализации на мобильных устройствах. Ниже будет приведено подробное описание алгоритма и приведены результаты его работы с реальными фотографиями. 1) Введение. Камеры разрешением 5 МПикс и более стали теперь уже обычным явлением. Технологии не стоят на месте, разрешения камер растут, но разрешения дисплеев мобильных устройств по понятным причинам не могут быть настолько же большими, следовательно, полученное камерой изображение должно быть вписано в меньший по разрешению экран, а это предполагает применение алгоритмов децимации. Бывают также случаи, когда размер изображения меньше размера экрана, или же требуется увеличить рисунок, чтобы рассмотреть интересующие детали. В таких случаях требуется увеличение изображения, а это можно осуществить интерполяционными методами. Известные методы децимации и интерполяции имеют низкую сложность и могут быть эффективно реализованы, однако очертания объектов изображения пострадают от эффекта зубчатости краёв и появившихся артефактов, поэтому хотелось бы получить алгоритм качественного масштабирования без нежелательных артефактов, неровных краёв, чрезмерного сглаживания и пикселизации. К сожалению, в мобильных операционных системах память и вычислительные ресурсы, необходимые для обработки изображений с наименьшими потерями качества, ограничены, большие изображения требуют большого объёма памяти и вычислений, количество которых зависит от числа пикселей изображения линейно (а в некоторых случаях даже экспоненциально). Преобразование сигналов – важный раздел теории обработки сигналов, рассмотренный в литературе [1], где представлено несколько возможностей увеличения и уменьшения изображений [2, 3]. При уменьшении несколько пикселей источника соответствуют одному пикселю приёмника, при увеличении всё наоборот. В простейшем алгоритме уменьшения масштаба один из нескольких пикселей источника «претендует» стать прообразом пикселя приёмника. Данный подход называется методом «ближайшего соседа», недостаток его в выраженном эффекте зубчатых краёв и артефактах, поэтому основные методы масштабирования используют фильтрацию и передискретизацию. «Уменьшенные» данные обычно получают как линейную комбинацию входных дискретных данных и некоторого ядра. Иногда нас может интересовать не всё изображение целиком, а только некоторая его область. Увеличение этой области требует увеличения масштаба и панорамирования. Первое может быть осуществлено простейшим способом копирования пикселей, однако в результате получится изображение с блочными артефактами и пикселизацией. Несколько лучших результатов можно достичь более совершенными методами, использующими пространственную фильтрацию. Разные способы имеют разную сложность. Из-за произвольности размеров источника и приёмника необходимы методы дробного масштабирования. К таким методам относится билинейная интерполяция. Пиксель приёмника вычисляется как взвешенное среднее смежных пикселей источника. Веса могут быть вычислены по простым формулам для любого масштаба. Данный способ – хороший компромисс между сложностью и качеством. Взвешенные средние значения используются и при децимации. В данной статье представлен новый и эффективный с точки зрения вычислений алгоритм масштабирования изображений, усредняющий веса пикселей и обращающийся к данным предварительно заполненной таблицы. Он быстр и пригоден для мобильных устройств. Ниже будет дано подробное описание его работы. 2) Предлагаемые методы. В этом разделе дано описание нового метода масштабирования изображений, пригодного для реализации на мобильных устройствах. Вычислительные процессы увеличения и уменьшения масштаба, а также панорамирования и обрезки границ изложены в подробной форме. Алгоритм уменьшения масштаба. Предложенный алгоритм уменьшения изображений разработан так, чтобы избежать бесполезных повторяющихся вычислений, что положительно сказывается на скорости. Так как коэффициенты масштабирования по горизонтали и вертикали постоянны для каждой строки и каждого столбца изображения, все веса, индексы, значения начальных и конечных пикселей могут быть вычислены один раз и помещены в таблицу, а внутри цикла, проходящего по пикселям изображения и при самом масштабировании занесённые в таблицу веса и индексы считываются из неё вместо повторного перерасчёта. За одну итерацию цикла алгоритм сканирует одну строку изображения. Как только обработка строки закончена, сканируется следующая строка. Для определённости опишем работу алгоритма по горизонтали, однако выбор направления непринципиален. Сначала вычисляются значения начального и конечного пикселей источника (см. рис. 1). Рис. 1. Выравнивание начального и конечного пикселей. Вычисления проводятся по следующим формулам: Здесь input_image_size – размер источника, output_image_size – размер приёмника, panning – величина панорамирования, а zoom_factor определяет отношение размера источника к размеру приёмника. Panning – очень важная величина, которую следует учитывать в случаях, если изображение не помещается на экран полностью, а просматривается только некоторая «внутренность» границы, при этом её «внешность» обрезается, находясь за пределами экрана. Рис. 2. Значение пикселя уменьшенного изображения – взвешенное среднее пикселей источника, которые «принадлежат» области этого пикселя. Теперь определим индикаторы (0, 0, 1, 0, …) и верхние индексы (1, 2, 3, …) так, как показано на рис. 2 и 3. Рис. 3. Верхние индексы и индикаторы. Индикатор определяет, необходим ли пиксель для расчёта двух пикселей приёмника. Индикаторы считаются по следующей формуле: Следовательно, индикатор равен 1, если пиксель источника требуется для вычисления двух пикселей приёмника, и 0 в противном случае. При вычислении индикаторов верхний индекс увеличивается каждый раз, когда индикатор равен 1. Далее алгоритм вычисляет 2 горизонтальных веса (в общей сложности требуется 4 весовых коэффициента на пиксель приёмника: 2 горизонтальных и 2 вертикальных) для каждого из верхних индексов, определённых на предыдущем шаг (см. рис 4). Рис. 4. Веса Весовые коэффициенты пропорциональны площади пересечения пикселя источника с пикселем приёмника. Веса вычисляются так: Здесь 1 ≤ x ≤ end. Weight1 считаем левым весом, weight2 – правым. Сумма левого и правого весов должна равняться 1. Заметим, что веса и индексы вычисляем в целых числах. Это сделано для упрощения вычислений и сокращения объёма необходимой памяти. В формуле, приведённой выше, использована 10-разрядная точность (множитель 1024) для преобразования вещественных значений в целые. Индикатор первого пикселя источника равен 0, когда он не лежит на границе с первым уменьшенный пикселем или в случае, когда пиксель источника «проецируется» только на один из пикселей приёмника. Если же «проекция» приходится на 2 пикселя или левые границы пикселей источника и приемника идут точно по границе изображения, то индикатор устанавливается равным 1. Векторы index(x), weight1(x) и weight2(x) хранятся в таблице, что помогает избежать их повторного вычисления при переходе на следующую после текущей строку. Коэффициент масштабирования постоянен для каждой строки. Обращение к таблице значительно повышает быстродействие, и в предлагаемом алгоритме таблицы используются во всех удобных случаях. Как только веса и индексы по направлению х вычислены, приступаем к вычислению величин по у, пользуясь вышеприведёнными формулами. На заключительном этапе алгоритма выполняется собственно масштабирование – вычисление значений пикселей приёмника. Для этого берутся значения пикселей с начального по конечный, а из таблицы считываются веса и индексы. Ниже приведены формулы, по которым производится расчёт: Так как алгоритму требуются только пиксели с индикатором 1, то можно вычислять значения только одного или двух пикселей вместо четырёх. Тем самым нам удастся ускорить работу алгоритма, особенно в случае небольшого коэффициента масштабирования (большая часть индикаторов при таком раскладе равна 0). Значения пикселей каждой строки приёмника получаются путём сложения значений пикселей источника со значениями выходных буферов в каждой итерации цикла (см. рис. 5). Рис. 5. Буферизация. Один пиксель источника затрагивает до четырёх пикселей приёмника (A, B, C, D) в зависимости от значений indexX и indexY. Если indexX = 0 и indexY = 0, то само значение пикселя источника добавляется в буфер (пиксель А, рис. 5). При indexX = 1 и indexY = 0, пиксель В вычисляется как взвешенное среднее пикселей источника и добавляется в соответствующий буфер. Если indexX = 0, а indexY = 1, то пиксель С вычисляется как взвешенное среднее входных пикселей и добавляется во второй буфер. Ну а в случае, если indexX и indexY равны одновременно 1, вычисляется пиксель D и добавляется во второй буфер. Как только алгоритм пройдёт целиком по строке изображения, значения первого буфера преобразуются в 8-битные целые числа (0…255) делением на 1024 и записываются в выходной буфер. Если текущая строка источника влияет на две строки приёмника (indexY = 1) и если уменьшенная строка полностью занесена в буфер, её можно вывести уже на приёмник. После этого буферы 1 и 2 обмениваются своими значениями, и процесс повторяется для следующей строки. Заметим, что в рисунках с RGB-моделью представления цвета каждая из компонент должна обрабатываться отдельно, т. е. алгоритм выполнится 3 раза по каждой из компонент. Помимо низкой вычислительной нагрузки предлагаемый алгоритм использует только одну строку источника, 2 строки приёмника, 2 выходных буфера, 2 вектора верхних индексов (по одному на ширину и высоту) и 4 весовых вектора (по 2 на ширину и высоту источника). Как видим, алгоритм нетребователен к объёму памяти и очень удобен для портативных устройств. Алгоритм увеличения масштаба основан на методе билинейной интерполяции и устроен так, чтобы избежать ненужных вычислений. Так как коэффициенты масштабирования по х и у равны для каждой строки и каждого столбца, то все веса и индексы могут быть занесены в память. В нашем примере рассмотрено растяжение изображения по оси х. Рис. 6. Начальный и конечный пиксели. Первый шаг алгоритма – определение начальных и конечных пикселей источника (см. рис. 6). Начальный пиксель вычисляется так: Так как увеличенное изображение может быть панорамировано, то позиция начального пикселя зависит от коэффициента масштабирования и позиции панорамирования. Начало координат панорамирования должно находиться в центральном пикселе приёмника. Нет необходимости рассчитывать индикатор конечного пикселя, так как алгоритм разработан так, что процесс представляет собой цикл обработок увеличенных пикселей вместо обработки пикселей самого источника; кроме того, просматриваемое изображение может быть меньше увеличенного из-за обрезки границ. Каждый увеличенный пиксель получается из четырёх усреднённых пикселей источника (как в билинейной интерполяции). Алгоритм сканирует сразу 2 строки источника, используя фильтр 2*2 для расчёта интерполированных пикселей. Масштабирование может быть осуществлено отдельно по горизонтали и вертикали во время сканирования строк источника. Индексы и веса по горизонтали рассчитываются по формулам , где 0 < x < destination_image_size. Индикатор равен 1, если значение очередного интерполированного пикселя получается из очередной пары пикселей источника (т. е. центр очередного интерполированного пикселя расположен справа от центра правого пикселя текущей пары пикселей источника) и 0 в противном случае. Приведённые выше формулы используются и для расчёта индексов и весов по вертикали. Веса и индексы являются целыми числами. В нашем примере использована 10-битная точность как пример перевода вещественных чисел в целые. Заметим, что когда центр пикселя приёмника расположен слева или выше центра первого пикселя источника (start + x/zoom_factor < 0), алгоритму не хватает левых (верхних) пикселей для расчёта весов. Только первый пиксель источника используется для вычисления левого (верхнего) веса, а правый (нижний) вес полагается равным 0. Если же центр пикселя приёмника расположен справа или ниже центра последнего пикселя источника (input_image_size – 1 < start_pixel + x/zoom_factor), алгоритму не хватает правого (или нижнего) пикселя источника для расчёта весов. Последний пиксель источника используется для расчёта левого (или верхнего) веса, а правый (нижний) полагается равным 0. Когда строка изображения полностью обработана по ширине, увеличенные пиксели делением на 1024 переводятся в 8-разрядные числа (0…255) и записываются в выходной буфер. Применение таблиц снижает вычислительную сложность. Для увеличения масштаба изображения используется 2 строки источника и 1 строка приёмника. Дополнительно в памяти хранятся 2 вектора индексов пикселей (по одному на обработку изображения по ширине и высоте), а также 4 весовых вектора (2 на ширину и 2 на высоту). Отсюда видно, что предлагаемый метод не требует больших объёмов памяти и эффективен с вычислительной точки зрения, следовательно, идеален для мобильных устройств. Панорамирование и обрезка границ. Когда рисунок отображается в 100%-м масштабе (1:1), один пиксель источника соответствует одному пикселю экранного изображения. В этом случае источник обрезается до соответствующих размеров (если это необходимо), а вместо коэффициента масштаба следует учитывать позицию панорамирования. Алгоритм начинается с вычисления первого и последнего пикселей в обоих направлениях (горизонтальном и вертикальном): Обработка в таком случае заключается в выборе необходимого количества пикселей источника и их копировании в приёмник. Как видим, алгоритм очень быстр – кроме копирования данных в памяти ничего не требуется. А т. к. для обработки нужна только одна строка источника и соответствующая ей строка приёмника, этот способ и в отношении необходимого объёма памяти. 3) Результаты. Вычислительная сложность предложенных методов была оценена подсчётом числа операций на пиксель. Результаты отражены в табл. 1 и сравнены с результатами работы других алгоритмов масштабирования (см. [4, 5]). Согласно полученным результатам, реализация алгоритма не требует больших вычислительных затрат. Табл. 1. Сравнение результатов тестирования различных методов. (а), (b) – минимальное и максимальное число операций на пиксель при уменьшения области 2*2 соответственно, (с) – число операций на пиксель при увеличении области 2*2. Другие способы фильтрации (например, бикубический) могут быть реализованы на основе предложенного метода путём вычисления весов, используемых фильтром, и применения таблиц. Таким образом, изменение фильтрации не увеличит вычислительные затраты предложенных методов. Был также оценён объём необходимой памяти. Так как таблицы фильтрации заполняются до самого процесса масштабирования, то для процесса потребуется память только под 2 строки изображения вне зависимости от метода фильтрации, будь то метод ближайшего соседа, билинейная или бикубическая фильтрация. К примеру, масштабирование 8разрядного цветного VGA-изображения потребует 2*3*640*8 бит памяти, а изображение разрешением 1 МПикс – 2*3*1024*8 бит. Визуальное качество представленных алгоритмов соответствует качеству работы алгоритмов билинейной интерполяции и линейной фильтрации для увеличения и уменьшения изображений соответственно. Рис. 7. Пример работы алгоритма уменьшения масштаба. На рис. 7 представлено 2 рисунка. Сверху показан пример работы представленного алгоритма, снизу – метод усреднения весов, применённый в коммерческом графическом процессоре. Результаты показывают, что предложенный метод лучше методов, описанных в литературе (см. список литературы). Визуальное качество этого метода (при 10-битной точности) сравнимо с показателями реализаций различных алгоритмов, применённых в коммерческих программных продуктах. 4) Заключение. В данной статье был представлен быстрый метод масштабирования изображений, основанный на усреднении весов смежных пикселей. Алгоритму не присущи блочные артефакты и эффект зубчатых краёв; как результат – хорошее качество изображения. Алгоритм основан на применении таблиц, заполняемых только однажды, тем самым излишние вычисления сведены к минимуму. Данные таблиц в процессе работы алгоритма только считываются. Цикл обработки изображения очень прост, а его дальнейшее усовершенствование может быть осуществлено, например, ассемблерными средствами. Данный алгоритм не требует большого количества буферов строк изображения и таблиц, т. е. экономичен с точки зрения объёма потребляемой памяти, а кроме того, эффективен в плане необходимых вычислений. Качество получаемых изображений очень хорошее. Преимущества алгоритма идеальны для реализации в мобильных телефонах и прочих маломощных карманных мультимедиа-устройствах.