Mewze.


With the image from
Two Tabby Cats
http://www.photos-public-domain.com/2016/11/15/two-tabby-cats/





Description.

Made with Processing.

I wrote some blog about Turing Pattern in Japanese.
https://note.mu/deconbatch/n/n8b2626043631
I like it and I wanted to applly Turing Pattern on image processing.

You can use your own photo.
You can hard coding the path of your photo image file or you can give command line parameter like this.

/your_processing_installed_path/processing-java --force --sketch=/your_sketch_path/ --run /your_photo_file_path


Code.

Please feel free to use it, if you like it.
To see another works based on my code is my pleasure. And my honor.



// Mewze.
// @author @deconbatch
// @version 0.2
// Processing 3.2.1
// 0.1 2018.08.08
// 0.2 2018.12.23

/* main -------------------- */
void setup() {
  size(1080, 1080);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  blendMode(DIFFERENCE);
  rectMode(CENTER);
  smooth();
  noLoop();
  noStroke();
}

void draw() {

  int   calcCntMax = 50000;
  float baseWH     = 980;
  float enlarge    = 4.0;

  PImage imgInit;

  if (args == null) {
    // you can use your photo in ./data/your_image.jpg
    imgInit = loadImage("your_image.jpg");
  } else {
    // args[0] must be image path
    imgInit = loadImage(args[0]);
  }

  // fit to canvas size
  float rateSize = baseWH / max(imgInit.width, imgInit.height) / enlarge;
  int   canvasW  = floor(imgInit.width * rateSize);
  int   canvasH  = floor(imgInit.height * rateSize);
  imgInit.resize(canvasW, canvasH);
  imgInit.loadPixels();
  println(ceil(canvasW * enlarge));
  println(ceil(canvasH * enlarge));
  
  // cell initialize
  Cell[][] cells         = new Cell[canvasW][canvasH];
  for (int x = 0; x < canvasW; x++) {
    for (int y = 0; y < canvasH; y++) {
      color pix = imgInit.pixels[y * canvasW + x];
      cells[x][y] = new Cell(
                             map(brightness(pix), 0.0, 100.0, -1.0, 1.0),
                             map(saturation(pix), 0.0, 100.0, -1.0, 1.0),
                             0.0,
                             0.0
                             );
    }
  }

  // set neighbor cells
  for (int x = 0; x < canvasW; x++) {
    for (int y = 0; y < canvasH; y++) {
      cells[x][y].setNeighbor(new Cell[] {
          cells[x][max(y-1,0)],
          cells[x][min(y+1,canvasH-1)],
          cells[max(x-1,0)][y],
          cells[min(x+1,canvasW-1)][y]
        });
    }
  }

  // calculate Turing Pattern
  for (int calcCnt = 0; calcCnt < calcCntMax; calcCnt++) {
    for (int x = 0; x < canvasW; x++) {
      for (int y = 0; y < canvasH; y++) {
        cells[x][y].delta();
      }
    }
    for (int x = 0; x < canvasW; x++) {
      for (int y = 0; y < canvasH; y++) {
        cells[x][y].sum();
      }
    }
  }

  background(0.0, 0.0, 0.0, 100.0);
  translate((width - canvasW * enlarge) / 2.0, (height - canvasH * enlarge) / 2.0);

  // draw original image
  for (int x = 0; x < canvasW; x++) {
    for (int y = 0; y < canvasH; y++) {
      color pix = imgInit.pixels[y * canvasW + x];
      fill(
           hue(pix),
           saturation(pix),
           brightness(pix),
           100.0
           );
      rect(
           x * enlarge,
           y * enlarge,
           enlarge,
           enlarge
           );
    }
  }

  // draw Turing Pattern
  for (int x = 0; x < canvasW; x++) {
    for (int y = 0; y < canvasH; y++) {
      color pix = imgInit.pixels[y * canvasW + x];

      fill(
           hue(pix),
           saturation(pix) * cells[x][y].getStandardU01(),
           brightness(pix) * cells[x][y].getStandardU02(),
           100.0
           );
      rect(
           x * enlarge,
           y * enlarge,
           enlarge * cells[x][y].getStandardU02(),
           enlarge * cells[x][y].getStandardU02()
           );
    }
  }

  saveFrame("frames/####.png");
  exit();
  
}

/*  -------------------- */
public class Cell {

  private float paramA   = 0.001;
  private float paramB   = 0.005;
  private float paramTau = 0.1;
  private float paramK   = -0.001;
  private float dt       = 0.001;
  private float dx       = 0.03;
  
  private float valueV01;
  private float valueV02;
  private float valueU01;
  private float valueU02;
  private float deltaV01;
  private float deltaV02;
  private float deltaU01;
  private float deltaU02;

  private Cell[] neighbor;

  Cell (float initV01, float initV02, float initU01, float initU02) {
    valueV01 = initV01;
    valueV02 = initV02;
    valueU01 = initU01;
    valueU02 = initU02;
    resetDelta();
  }

  private void resetDelta() {
    deltaV01 = 0.0;
    deltaV02 = 0.0;
    deltaU01 = 0.0;
    deltaU02 = 0.0;
  }

  public void setNeighbor(Cell[] pNeighbor) {
    neighbor = new Cell[pNeighbor.length];
    for (int i = 0; i < pNeighbor.length; ++i) {
      neighbor[i] = pNeighbor[i];
    }
  }

  public float getStandardU01() {
    return map(valueU01, -1.0, 1.0, 0.3, 1.8);
  }

  public float getStandardU02() {
    return map(valueU02, -1.0, 1.0, 0.5, 1.5);
  }

  public void delta() {
    float sumV01 = 0.0;
    float sumV02 = 0.0;
    float sumU01 = 0.0;
    float sumU02 = 0.0;
    for (int i = 0; i < neighbor.length; ++i) {
      sumV01 += neighbor[i].valueV01;
      sumV02 += neighbor[i].valueV02;
      sumU01 += neighbor[i].valueU01;
      sumU02 += neighbor[i].valueU02;
    }
    deltaV01 = (sumV01 - valueV01 * neighbor.length) / (dx*dx);
    deltaV02 = (sumV02 - valueV02 * neighbor.length) / (dx*dx);
    deltaU01 = (sumU01 - valueU01 * neighbor.length) / (dx*dx);
    deltaU02 = (sumU02 - valueU02 * neighbor.length) / (dx*dx);
  }

  public void sum() {
    float postV01 = valueV01 + dt * (paramB * deltaV01 + valueU01 - valueV01) / paramTau;
    float postV02 = valueV02 + dt * (paramB * deltaV02 + valueU02 - valueV02) / paramTau;
    float postU01 = valueU01 + dt * (paramA * deltaU01 + valueU01 - pow(valueU01, 3) - valueV01 + paramK);
    float postU02 = valueU02 + dt * (paramA * deltaU02 + valueU02 - pow(valueU02, 3) - valueV02 + paramK);
    valueV01 = constrain(postV01, -1.0, 1.0);
    valueV02 = constrain(postV02, -1.0, 1.0);
    valueU01 = constrain(postU01, -1.0, 1.0);
    valueU02 = constrain(postU02, -1.0, 1.0);
    resetDelta();
  }
  
}

/*
Copyright (C) 2018- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
*/




No comments :

Post a Comment