Я пытаюсь наложить эффект мозаики на изображение при обработке, но изображение остается прежним?

Я очень новичок в обработке.

Я пытаюсь создать программу, которая применяет эффект мозаики к нормальному изображению. Я пытаюсь добиться, чтобы изображение создало блоки размером фильтра (например, 30 пикселей) и заменило его средним значением r,g,b, цветов этого блока.

Вот что я сделал до сих пор:

class ME {

  PImage image;

  ME(String imagename) {
    this.image = loadImage(imagename);
  }


  void display(int length, int height ) {
    image.resize(length, height);
    image(this.image, 0, 0);
  }


  void effect(int filterationSize) {
  print("smth");
    image.loadPixels(); 
    float r, g, b;

    for (int v = 0; v < (width*height ); v += filterationSize*width) 
    {
      for (int h = 0; h < width; h+=filterationSize)
      {
        r = g = b = 0;

        for (int bH = 0; bH<filterationSize; bH++)
        {
           for (int bV = 0; bV<filterationSize; bV++)
        {

        int p = v+h+bH+bV*width;

        if ( p < width*width)
          {


            r += (red(this.image.pixels[p]) / (filterationSize*filterationSize));
            g += (green(this.image.pixels[p]) / (filterationSize*filterationSize));
            b += (blue(this.image.pixels[p]) / (filterationSize*filterationSize));
          }


        }


        }



         for (int blockH = 0; blockH<filterationSize; blockH++)
      {
        for (int blockV = 0; blockV<filterationSize; blockV++)
        {
          int p = v+h+blockH+blockV*width;

          if ( p < width*width)
          {

            this.image.pixels[p] = color(r, g, b);
          }
        }
      }
      }
    }

    this.image.updatePixels();

  }
}

И вот мой основной класс:

ME img ;

void setup(){
  size(500 ,500);
  img = new ME("image.png");
  img.display(width , height);

}



void draw(){

   img.effect(30);

}

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

1 ответ

Решение

Вы пропустили отображение изображения после того, как применили эффект к изображению:

void draw(){
    img.effect(30);
    img.display(width , height);
}

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

    ME img;

void setup(){
   size(500 ,500);
   img = new ME("image.png");
   img.display(width , height);
   img.effect(30);
}

void draw(){
    img.effect(30);
    img.display(width, height);
}

В дальнейшем вы можете улучшить effect алгоритм.

Рассчитайте количество плиток, но обратите внимание, что последний фрагмент в строке или столбце может быть обрезан:

int tiles_x = width / filterationSize;
if ( width % filterationSize > 0 ) 
    tiles_x += 1;

int tiles_y = height / filterationSize;
if ( height % filterationSize > 0 ) 
    tiles_y += 1;

Вычислите начальные конечные координаты и "размер" плитки внутри цикла:

int start_x = tile_x*filterationSize;
int start_y = tile_y*filterationSize;
int end_x   = min(start_x+filterationSize, width); 
int end_y   = min(start_y+filterationSize, height);
int size    = (end_x-start_x) * (end_y-start_y); 

Теперь легко рассчитать среднее значение пикселей одной плитки. Полный алгоритм может выглядеть так:

void effect(int filterationSize) {
    image.loadPixels(); 

    int tiles_x = width / filterationSize;
    if ( width % filterationSize > 0 ) 
        tiles_x += 1;
    int tiles_y = height / filterationSize;
    if ( height % filterationSize > 0 ) 
        tiles_y += 1;

    print( tiles_x, tiles_y );
    for ( int tile_y = 0; tile_y < tiles_x; tile_y ++ ) {
        for ( int tile_x = 0; tile_x < tiles_y; tile_x ++ ) {

            int start_x = tile_x*filterationSize;
            int start_y = tile_y*filterationSize;
            int end_x   = min(start_x+filterationSize, width); 
            int end_y   = min(start_y+filterationSize, height);
            int size    = (end_x-start_x) * (end_y-start_y);

            float r = 0, g = 0, b = 0;
            for (int by = start_y; by < end_y; by++ ) {
                for (int bx = start_x; bx < end_x; bx++ ) {
                    int p = by * width + bx;
                    r += red(this.image.pixels[p])   / size;
                    g += green(this.image.pixels[p]) / size;
                    b += blue(this.image.pixels[p])  / size;
                }
            }

            for (int by = start_y; by < end_y; by++ ) {
                for (int bx = start_x; bx < end_x; bx++ ) {
                    int p = by * width + bx;
                    this.image.pixels[p] = color(r, g, b);
                }
            }
        }
    }
    this.image.updatePixels();
}

Смотрите эффект, примененный к изображению 256*256 и длине плитки 32:

Другие вопросы по тегам