2009-11-13 1 views
0

Какой алгоритм используется для масштабирования 32-битного изображения RGB IMAGE для пользовательского разрешения? Алгоритм должен иметь средние пиксели.Самый быстрый алгоритм для масштабирования 32Bit RGB IMAGE

например Если у меня есть изображение 100x100, и я хочу новое изображение размера 20x50. Среднее число первых пяти пикселей первой строки источника даст первый пиксель dest, а средний первый пиксель первого столбца источника даст первый пиксель детонационного столбца.

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

Есть ли какой-либо оптимизированный для вас метод?

+0

Вас интересует качество? – teabot

+0

В каком направлении? Меньше бит или меньше пикселей? Или каким-то другим способом? –

ответ

1

Это усредняет соответствующие пиксели.

w_ratio = src.w/dest.w 
h_ratio = src.h/dest.h 

dest[x,y] = 
    AVG(src[x * w_ratio + xi, y * h_ratio + yi]) 
     where 
      xi in range (0, w_ratio - 1), inc by 1 
      yi in range (0, h_ratio - 1), inc by 1 

Для граничных условий выполните отдельный цикл (нет, если в цикле).

Вот несколько С, как код:

SRC и Dest являются растровыми, что:
* свойство SRC [х, у] для пикселя
* Свойство src.w для ширины
* собственности SRC.ч по высоте была определена

пикселей, так что

добавления

p1 = p1 + p2  
is same as 
p1.r = p1.r + p2.r 
p1.g = p1.g + p2.g 
... 

разделением

p1 = p1/c 
p1.r = p1.r/c 
p1.g = p1.g/c 

оценки с постоянной 0

p1 = 0 
p1.r = 0 
p1.g = 0 
... 

для simplici ти ради я не буду рассматривать проблему, когда компонент пикселя целочисленные переполнения ...

float w_ratio = src.w/dest.w; 
float h_ratio = src.h/dest.h; 
int w_ratio_i = floor(w_ratio); 
int h_ratio_i = floor(h_ratio); 

wxh = w_ratio*h_ratio; 

for (y = 0; y < dest.w; y++) 
for (x = 0; x < dest.h; x++){ 
    pixel temp = 0;  

    int srcx, srcy; 
    // we have to use here the floating point value w_ratio, h_ratio 
    // otherwise towards the end it can get a little wrong 
    // this multiplication can be optimized similarly to Bresenham's line 
    srcx = floor(x * w_ratio); 
    srcy = floor(y * h_ratio); 

    // here we use floored value otherwise it might overflow src bitmap 
    for(yi = 0; yi < h_ratio_i; yi++) 
    for(xi = 0; xi < w_ratio_i; xi++) 
      temp += src[srcx + xi, srcy + yi]; 
    dest[x,y] = temp/wxh; 
} 

Bresenham's line optimization

+0

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

1

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

2

Вы забываете упомянуть наиболее важный аспект вопроса: , насколько вы заботитесь о качестве.. Если вы не заботитесь точно о том, как значения пикселей источников разбиты вместе, чтобы создать пиксель назначения, самый быстрый (по крайней мере, почти во всех случаях) тот, который производит наихудшее качество.

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

И вы уже изложили свою первоначальную идею алгоритма:

Avg первых пять пикселей первого исходного ряда дадут первый пиксель из Dest,

Расчета среднего значения для каждый канал на исходных пикселях можно рассматривать как тривиальный, вы ищете пример кода, который это делает?

Или вы ищете кого-то, кто бросит вызов вашему первоначальному проекту алгоритма чем-то еще быстрее?

+0

Я написал код для логики, который я описал в вопросе. Я хочу что-то более быстрое, В моем текущем методе, когда я хочу масштабировать изображение как в x, так и в y. Я должен делать их отдельно. Я сначала уменьшаю изображение в X на временном буфере, а затем из этого временного буфера, который я масштабирую в Y. После этого я получаю качественное изображение, но мне не нравится идея временного буфера. Я хочу качество stretchBlt без tempbuffer, есть ли какой-нибудь метод для него? – SunnyShah

0

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

+0

Я написал эту версию в первый раз, но когда я растягиваю изображение с текстом, текст стал нечитаемым, поэтому я реализовал новую функцию с пиксельным средним. Но stretchBlt с пиксельным avg занимает на 300% больше времени, чем обычно. Для меня уже создана оптимизированная сборка. Я хочу качество с большей скоростью и хочу удалить мою потребность в временном буфере. – SunnyShah

+0

Нет, его путь не самый быстрый. Он делает одно измерение, а затем другое. Выполнение всего этого происходит быстрее, потому что это меньше операций с памятью. – Nosredna

+0

Выполнение этого способа - это 7 операций памяти, и все это сразу равно 10. Это O (n) против O (n^2), поэтому разница возрастает по мере увеличения коэффициента сжатия. –

6

Термин вы ищете «Resampling.» В вашем случае вы хотите передискретизировать изображение. Кажется, вы уже делаете линейную интерполяцию, которая должна быть самой быстрой. Вот ~ 6 базовых алгоритмов. Если вы действительно хотите вникать в предметный взгляд на «передискретизирующие ядра».

2

После выполнения стандартных оптимизаций C (POIN ter арифметика, математика с фиксированной точкой и т. д.) Есть еще несколько умных оптимизаций. A (очень) давным-давно я видел реализацию масштабирования, которая сначала масштабировала направление X. В процессе записи горизонтально масштабированного изображения он поворачивал изображение на 90 градусов в памяти. Это было так, что когда пришло время делать считывания для шкалы Y-направления, данные в памяти были бы лучше ориентированы на кеш.

Этот метод сильно зависит от процессора, на котором он будет работать.

+0

Ничего себе, очень хорошая техника, Спасибо за ваш ответ. – SunnyShah

1

Это действительно соотношение скорости и качества.

Прежде всего, вы правы, делая одно измерение, а другое медленнее, чем должно быть. Слишком много памяти читает и пишет.

Ваш большой выбор - поддерживать ли дробные пиксели или нет. Ваш пример - от 100x100 до 20x50. Таким образом, 10 пикселей отображают 1. Что делать, если вы собираетесь от 100x100 до 21x49? Готовы ли вы работать с границами пикселов источника или хотите вывести дробные пиксели? Что бы вы сделали для 100x100 - 99x99?

Вы должны сказать нам, что вы готовы принять, прежде чем мы сможем сказать, что быстрее.

А также рассказать о возможных крайностях усадки. Сколько порядков может быть разница между источником и пунктом назначения? В какой-то момент выборка представительских пикселей внутри источника будет не намного хуже, чем усреднение всех пикселей. Но вы должны быть осторожны при выборе репрезентативных пикселей, или вы получите псевдонимы со многими распространенными шаблонами.