Вопрос

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

Используя встроенный оператор свертки с гауссовым фильтром, я получил это изображение.ссылка на сайт

Теперь я запускаю то же изображение, используя свой код

public static int convolve(BufferedImage a,int x,int y){
 int red=0,green=0,blue=0;
      float[] matrix = { 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 0.2196956447338621f, 0.28209479177387814f, 0.2196956447338621f, 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 };
      for(int i = x;i<x+3;i++){
          for(int j = y;j<y+3;j++){
              int color = a.getRGB(i,j);
              red += Math.round(((color >> 16) & 0xff)*matrix[(i-x)*3+j-y]);
              green += Math.round(((color >> 8) & 0xff)*matrix[(i-x)*3+j-y]);
              blue += Math.round(((color >> 0) & 0xff)*matrix[(i-x)*3+j-y]);

          }
      }

    return (a.getRGB(x, y)&0xFF000000) | (red << 16) | (green << 8) | (blue);
}

И результат, который я получил, это это.ссылка на сайт

Также как мне оптимизировать код, который я написал. Встроенный оператор свертки занимает 1 ~ 2 секунды, в то время как мой код, даже если он не служит точной цели, как предполагается, занимает 5 ~ 7 секунд!

Я случайно повернул исходное изображение при загрузке. Так что, пожалуйста, игнорируйте это.

Это было полезно?

Решение

Прежде всего, вы без необходимости (и ошибочно) преобразуете свой результат из Float в Int в каждом цикле цикла. Ваш red, green а также blue Должен быть типа, и должен быть отменен в целое число только после свертки (при преобразовании обратно в RGB):

  float red=0.0f, green = 0.0f, blue = 0.0f
  for(int i = x;i<x+3;i++){
      for(int j = y;j<y+3;j++){
          int color = a.getRGB(i,j);
          red += ((color >> 16) & 0xff)*matrix[(i-x)*3+j-y];
          green += ((color >> 8) & 0xff)*matrix[(i-x)*3+j-y];
          blue += ((color >> 0) & 0xff)*matrix[(i-x)*3+j-y];

      }
  }

return (a.getRGB(x, y)&0xFF000000) | (((int)red) << 16) | (((int)green) << 8) | ((int)blue);

Кровотечение цветов в вашем результате вызвано потому, что ваши коэффициенты в matrix не правы:

0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f + 
0.2196956447338621f + 0.28209479177387814f + 0.2196956447338621f +
0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f =

1.8452741

Сумма коэффициентов в размывающейся матрице свертки должна быть 1,0. Когда вы применяете эту матрицу к изображению, вы можете получить цвета более 255. Когда это происходит, каналы «кровоточат» в следующем канале (синий - зеленый и т. Д.). Полностью зеленое изображение с этой матрицей приведет к:

 green = 255 * 1.8452741 ~= 471 = 0x01D7;
 rgb = 0xFF01D700;

Который является менее интенсивным зеленым с оттенком красного.

Вы можете исправить это, разделяя коэффициенты на 1.8452741, но вы хотите убедиться, что:

 (int)(255.0f * (sum of coefficients)) = 255

Если нет, вам нужно добавить чек, который ограничивает размер каналов до 255, и не позволяйте им обернуться. Например:

if (red > 255.0f)
   red = 255.0f;

Относительно эффективности/оптимизации:
Может случиться так, что разница в скорости может быть объяснена этим ненужным кастингом и вызовом математики, но более вероятным кандидатом является то, как вы получаете доступ к изображению. Я недостаточно знаком с BufferedImage и Raster, чтобы советовать вам по наиболее эффективному способу получить доступ к базовому буферу изображения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top