2016-10-04 4 views
1

У меня есть набор метеорологических RGB-типов BufferedImage s. Я хочу получить средний имидж. Под этим я подразумеваю получение среднего значения каждого пикселя и создание нового изображения из этих значений. Что я пробовал:получить среднее изображение набора изображений в java

public void getWaveImage(BufferedImage input1, BufferedImage input2){ 
    // images are of same size that's why i'll use first one's width and height 
    int width = input1.getWidth(), height = input1.getHeight(); 

    BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 

    int[] rgb1 = input1.getRGB(0, 0, width, height, new int[width * height], 0, width); 
    int[] rgb2 = input2.getRGB(0, 0, width, height, new int[width * height], 0, width); 
    for(int i=0; i<width; i++){ 
     for(int j=0; j<height; j++){ 
     int rgbIndex = i * width + j; 
     rgb1[rgbIndex] = (rgb1[rgbIndex] + rgb2[rgbIndex])/2; 
     } 
    } 

    output.setRGB(0, 0, width, height, rgb1, 0, width); 
    return output; 
} 

Что я делаю неправильно? Заранее спасибо.

input1:

enter image description here

input2:

enter image description here

выход:

enter image description here

+0

Сначала определите, что вы подразумеваете под средним значением ... – Tschallacka

+1

Я не думаю, что использование '' rgb1 [rgbIndex] + rgb2 [rgbIndex])/2'' даст вам цвет между двумя цветами ввода. – f1sh

+0

@Tschallacka Извините, что я добавил. – halil

ответ

5

Вы хотите среднем каждый ком цветность, средний красный, средний зеленый, средний синий.

Вместо этого вы усредняете весь int.

Color c1 = new Color(rgb1[rgbIndex]); 
Color c2 = new Color(rgb2[rgbIndex]); 
Color cA = new Color((c1.getRed() + c2.getRed())/2, 
        (c1.getGreen() + c2.getGreen())/2, 
        (c1.getBlue() + c2.getBlue())/2); 
rgb1[rgbIndex] = cA.getRGB(); 

Это не может быть наиболее эффективным из-за создания так много объектов, поэтому более прямой подход следующим образом:

public static int average(int argb1, int argb2){ 
    return (((argb1  & 0xFF) + (argb2  & 0xFF)) >> 1)  | //b 
      (((argb1 >> 8 & 0xFF) + (argb2 >> 8 & 0xFF)) >> 1) << 8 | //g 
      (((argb1 >> 16 & 0xFF) + (argb2 >> 16 & 0xFF)) >> 1) << 16 | //r 
      (((argb1 >> 24 & 0xFF) + (argb2 >> 24 & 0xFF)) >> 1) << 24; //a 
} 

Использование:

rgb1[rgbIndex] = average(rgb1[rgbIndex], rgb2[rgbIndex]); 
3

Если у вас есть:

int rgb1, rgb2; //the rgb value of a pixel in image 1 and 2 respectively 

«Средний» цвет был бы :

int r = (r(rgb1) + r(rgb2))/2; 
int g = (g(rgb1) + g(rgb2))/2; 
int b = (b(rgb1) + b(rgb2))/2; 

int rgb = ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0); 

со следующими методами «хелперов»:

private static int r(int rgb) { return (rgb >> 16) & 0xFF; } 
private static int g(int rgb) { return (rgb >> 8) & 0xFF; } 
private static int b(int rgb) { return (rgb >> 0) & 0xFF; } 

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

1

другое решение может быть заменить

rgb1[rgbIndex] = (rgb1[rgbIndex] + rgb2[rgbIndex])/2; 

с

rgb1[rgbIndex] = ((rgb1[rgbIndex]>>1)&0x7f7f7f7f)+((rgb2[rgbIndex]>>1)&0x7f7f7f7f)+(rgb1[rgbIndex]&rgb2[rgbIndex]&0x01010101); 

бинарного сдвиг вправо, чтобы разделить на 2, последний член суммы обрабатывать случай двух нечетных чисел.

+0

Ницца бит-twiddling! – weston

Смежные вопросы