【问题标题】:Using gradient orientations to direct brush stroke effect in Javascript在Javascript中使用渐变方向来指导画笔描边效果
【发布时间】:2014-10-15 22:22:43
【问题描述】:

我正在尝试在 Javascript(特别是使用 p5.js)中重新创建其他人似乎已经使用 Mathematica 套件成功实现的效果,如此处所示https://mathematica.stackexchange.com/a/39049

我对 Mathematica 100% 一无所知,但我看到他们正在使用一种名为 GradientOrientationFilter 的方法来创建一个遵循图像渐变方向的笔画图案。

我的结果仍然不令人满意。

我正在尝试的逻辑

  • 创建一个定向梯度直方图,评估亮度值,然后找到水平和垂直梯度,以及它的方向和幅度;
  • 在每个像素处画一条线,用随机灰度颜色表示渐变方向。 稍后我将使用这些线条,与实际图片混合。

代码:

var img, vectors;

var pixelsToSkip = 2; // for faster rendering we can stroke less lines
var linesLength = 20;
var strokeThickness = 1; 

function preload() { 
  img = loadImage('http://lorempixel.com/300/400/people/1');
  img2 = loadImage('http://lorempixel.com/300/400/people/1');

  /* you can test in local if the directions are correct using a simple gradient as image
  img = loadImage('http://fornace.io/jstests/img/gradient.jpg');
  img2 = loadImage('http://fornace.io/jstests/img/gradient.jpg');
  */
}

function setup() {  
  createCanvas(img.width, img.height);
  noLoop();
  img.loadPixels();


  makeLumas();
  makeGradients();
  makeVectors();

  for ( var xx = 0; xx < img.width; xx = xx + pixelsToSkip) {
    for ( var yy = 0; yy < img.height; yy = yy + pixelsToSkip) {
      push();
        stroke(random(255));  // to color with pixel color change to stroke(img.get(xx, yy));
        strokeWeight(strokeThickness);
        translate(xx,yy);
        rotate( vectors[yy][xx].dir ); // here we use the rotation of the gradient
        line(-linesLength/2, 0, linesLength/2, 0);
      pop();
    }
  }

//      adding the image in overlay to evaluate if the map is good
//      tint(255, 255, 255, 100);
//      image(img2,0,0);


}

function draw() {
}




function makeLumas() {
// calculate the luma for each pixel to get a map of dark/light areas ("Rec. 601") https://en.wikipedia.org/wiki/Luma_(video)
  lumas = new Array(img.height);
  for (var y = 0; y < img.height; y++) {
    lumas[y] = new Array(img.width);

    for (var x = 0; x < img.height; x++) {
      var i = x * 4 + y * 4 * img.width;
      var r = img.pixels[i],
          g = img.pixels[i + 1],
          b = img.pixels[i + 2],
          a = img.pixels[i + 3];

      var luma = a == 0 ? 1 : (r * 299/1000 + g * 587/1000
        + b * 114/1000) / 255;

      lumas[y][x] = luma;
    }
  }
}

function makeGradients() {
// calculate the gradients (kernel [-1, 0, 1])

  var horizontalGradient = verticalGradient = [];

  for (var y = 0; y < img.height; y++) {
    horizontalGradient[y] = new Array(img.width);
    verticalGradient[y] = new Array(img.width);

    var row = lumas[y];

    for (var x = 0; x < img.width; x++) {
      var prevX = x == 0 ? 0 : lumas[y][x - 1];
      var nextX = x == img.width - 1 ? 0 : lumas[y][x + 1];
      var prevY = y == 0 ? 0 : lumas[y - 1][x];
      var nextY = y == img.height - 1 ? 0 : lumas[y + 1][x];

      horizontalGradient[y][x] = -prevX + nextX;
      verticalGradient[y][x] = -prevY + nextY;
    }
  }
}

function makeVectors() {
// calculate direction and magnitude

  vectors = new Array(img.height);

  for (var y = 0; y < img.height; y++) {
    vectors[y] = new Array(img.width);

    for (var x = 0; x < img.width; x++) {
      var prevX = x == 0 ? 0 : lumas[y][x - 1];
      var nextX = x == img.width - 1 ? 0 : lumas[y][x + 1];
      var prevY = y == 0 ? 0 : lumas[y - 1][x];
      var nextY = y == img.height - 1 ? 0 : lumas[y + 1][x];

      var gradientX = -prevX + nextX;
      var gradientY = -prevY + nextY;

      vectors[y][x] = {
        mag: Math.sqrt(Math.pow(gradientX, 2) + Math.pow(gradientY, 2)),
        dir: Math.atan2(gradientY, gradientX)
      }
    }
  }
}

图片上的结果

我用 javascript 制作的领域比用 Mathematica 制作的领域嘈杂得多。

http://jsfiddle.net/frapporti/b4zxkcmL/

最后说明

我对 p5.js 还很陌生,也许我正在重新发明轮子。也请随时纠正我。

小提琴:http://jsfiddle.net/frapporti/b4zxkcmL/

【问题讨论】:

    标签: javascript canvas processing p5.js


    【解决方案1】:

    模糊那些像素!

    对我有用的解决方案只是在进行任何像素分析之前进行模糊处理,以平滑梯度方向过滤器的结果。

    如果您使用的是 p5.js,这可以像 img.filter("blur",5); 一样简单。否则,您可以使用您选择的任何其他模糊技术。

    您可以在此处查看代码:http://jsfiddle.net/frapporti/b4zxkcmL/21/

    如果有人有其他方法,我会在将此答案标记为接受之前等待。

    【讨论】:

      猜你喜欢
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      • 2014-07-06
      • 1970-01-01
      • 1970-01-01
      • 2016-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多