MeoWorley.

It draws Worley noise on the image.
Example result with the 'Gray Tabby Cat With Flowers'
http://www.photos-public-domain.com/2010/09/03/gray-tabby-cat-with-flowers/

Description of this Image Manipulation code.

It's a Image Manipulation type creative coding made with Processing. It draws Worley noise on the image.

I watched Mr. Shiffman's YouTube video 'Coding in the Cabana 4: Worley Noise' and I tried to apply it to image manipulation.


I use my 'Meowsh.' code and changed drawing part to use Worley noise. It worked easily! And I love its results!
You can use your photo.
example : your photo file = ./data/your_photo.jpg
          PImage img = loadImage("your_photo.jpg");

An example code of Processing.

This code does not display any images on the screen but generates image file in frames directory.
Please feel free to use this example code.
To see other works based on my code is my pleasure. And my honor.



/**
 * MeoWorley.
 * image manipulation with Worley noise.
 * reference. https://www.youtube.com/watch?v=4066MndcyCk&feature=youtu.be
 *
 * Processing 3.5.3
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2020.05.10
 */

import java.util.Collections;

void setup() {

  size(1080, 1080);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noLoop();

}

void draw() {

  int caseWidth  = 30;
  int baseCanvas = width - caseWidth * 2;

  PImage img = loadImage("your_photo.jpg");
  float rateSize = baseCanvas * 1.0 / max(img.width, img.height);
  img.resize(floor(img.width * rateSize), floor(img.height * rateSize));

  background(0.0, 0.0, 90.0, 100.0);
  translate((width - img.width) / 2, (height - img.height) / 2);

  // Worley noise drawing with detected edges.
  ArrayList<PVector> edges = detectEdge(img);
  Collections.shuffle(edges);
  drawWorley(img, plotNodes(edges, img), 0.6, 2);

  casing(caseWidth, img.width, img.height);
  saveFrame("frames/0001.png");

  exit();
  
}

/**
 * plotNodes : locate Nodes with some distance each other.
 * @param ArrayList<PVector> _adds : location point candidates.
 * @param PImage             _img  : original image to get color.
 * @return ArrayList<Node> : holds nodes.
 */
public ArrayList<Node> plotNodes(ArrayList<PVector> _adds, PImage _img) {

  float gap = 10.0;
  ArrayList<Node> nodes = new ArrayList<Node>();
  _img.loadPixels();

  for (int i = 0; i < _adds.size(); i++) {

    int fX = floor(_adds.get(i).x);
    int fY = floor(_adds.get(i).y);
    
    // add new node
    boolean inner = false;
    for (Node f : nodes) {
      if (dist(fX, fY, f.x, f.y) < gap) {
        inner = true;
        break;
      }
    }
    if (!inner) {
      int pixIndex = floor(fY * _img.width + fX);
      nodes.add(new Node(
                          fX,
                          fY,
                          hue(_img.pixels[pixIndex]),
                          saturation(_img.pixels[pixIndex]),
                          brightness(_img.pixels[pixIndex])
                          ));
    }
  }

  return nodes;

}

/**
 * Node : draw and hold location and color.
 */
public class Node {

  public  int   x, y;   // coordinate of node
  private float hueVal; // hue value of node
  private float satVal; // saturation value of node
  private float briVal; // brightness value of node

  Node(int _x, int _y, float _c, float _s, float _b) {
    x = _x;
    y = _y;
    hueVal = _c;
    satVal = _s;
    briVal = _b;
  }

}

/**
 * drawWorley : draw lines between nodes that have the same color and have some distance.
 * @param ArrayList<Node> _nodes  : holds Circle Packing results.
 * @param float           _range  : range ratio to draw line.
 * @param float           _detail : drawing plot interval value.
 */
public void drawWorley(PImage _img, ArrayList<Node> _nodes, float _range, int _detail) {

  noStroke();
  for (int iX = 0; iX < _img.width; iX += _detail) {
    for (int iY = 0; iY < _img.height; iY += _detail) {

      int   minIndx = 0;
      float minDist = _img.width + _img.height;
      for (int i = 0; i < _nodes.size(); i++) {
        float distance = dist(iX, iY, _nodes.get(i).x, _nodes.get(i).y);
        if (minDist > distance) {
          minIndx = i;
          minDist = distance;
        }
      }

      Node n = _nodes.get(minIndx);
      fill(n.hueVal, n.satVal, n.briVal, constrain(100.0 * _range - minDist, 0, 100));
      ellipse(iX, iY, _detail + 1, _detail + 1);
    }
  }
}

/**
 * detectEdge : detect edges of photo image.
 * @param  _img : detect edges of this image.
 * @return ArrayList<PVector> : edges locations.
 */
public ArrayList<PVector> detectEdge(PImage _img) {

  ArrayList<PVector> edges = new ArrayList<PVector>();

  _img.loadPixels();
  for (int idxW = 1; idxW < _img.width - 1; ++idxW) {  
    for (int idxH = 1; idxH < _img.height - 1; ++idxH) {

      int pixIndex = idxH * _img.width + idxW;

      // saturation difference
      float satCenter = saturation(_img.pixels[pixIndex]);
      float satNorth  = saturation(_img.pixels[pixIndex - _img.width]);
      float satWest   = saturation(_img.pixels[pixIndex - 1]);
      float satEast   = saturation(_img.pixels[pixIndex + 1]);
      float satSouth  = saturation(_img.pixels[pixIndex + _img.width]);
      float lapSat = pow(
                         - satCenter * 4.0
                         + satNorth
                         + satWest
                         + satSouth
                         + satEast
                         , 2);

      // brightness difference
      float briCenter = brightness(_img.pixels[pixIndex]);
      float briNorth  = brightness(_img.pixels[pixIndex - _img.width]);
      float briWest   = brightness(_img.pixels[pixIndex - 1]);
      float briEast   = brightness(_img.pixels[pixIndex + 1]);
      float briSouth  = brightness(_img.pixels[pixIndex + _img.width]);
      float lapBri = pow(
                         - briCenter * 4.0
                         + briNorth
                         + briWest
                         + briSouth
                         + briEast
                         , 2);

      // hue difference
      float hueCenter = hue(_img.pixels[pixIndex]);
      float hueNorth  = hue(_img.pixels[pixIndex - _img.width]);
      float hueWest   = hue(_img.pixels[pixIndex - 1]);
      float hueEast   = hue(_img.pixels[pixIndex + 1]);
      float hueSouth  = hue(_img.pixels[pixIndex + _img.width]);
      float lapHue = pow(
                         - hueCenter * 4.0
                         + hueNorth
                         + hueWest
                         + hueSouth
                         + hueEast
                         , 2);

      // bright and saturation difference
      if (
          brightness(_img.pixels[pixIndex]) > 30.0
          && lapSat > 20.0
          ) edges.add(new PVector(idxW, idxH));

      // bright and some saturation and hue difference
      if (
          brightness(_img.pixels[pixIndex]) > 30.0
          && saturation(_img.pixels[pixIndex]) > 10.0
          && lapHue > 100.0
          ) edges.add(new PVector(idxW, idxH));

      // just brightness difference
      if (lapBri > 100.0) edges.add(new PVector(idxW, idxH));

    }
  }

  return edges;
}

/**
 * casing : draw fancy casing
 */
public void casing(int _casing, float _w, float _h) {
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(_casing + 4.0);
  stroke(0.0, 0.0, 30.0, 100.0);
  rect(-_casing * 0.5, -_casing * 0.5, _w + _casing, _h + _casing);
  strokeWeight(_casing);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(-_casing * 0.5, -_casing * 0.5, _w + _casing, _h + _casing);
  noStroke();
  noFill();
}


/*
Copyright (C) 2020- 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 <http://www.gnu.org/licenses/>
*/







Example result with the 'Tabby Cat With Long Fur'

http://www.photos-public-domain.com/2012/04/06/tabby-cat-with-long-fur/

It draws Worley noise on the image.










No comments :

Post a Comment