【问题标题】:Getting pixel values of images in p5js在 p5js 中获取图像的像素值
【发布时间】:2019-02-15 10:43:01
【问题描述】:

我一直在研究一些应该在每个黑色像素上绘制一个点(椭圆)的代码。我是 get 函数的新手,我怀疑我在使用它时可能犯了一个错误。有谁知道为什么我的代码无法成功“点”印度地图?

function setup() {
  createCanvas(400, 400);
}
                  
window.onload = function() {
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  var img = document.getElementById("map");
  ctx.drawImage(img, 10, 10, 150000, 1800000);
}

function draw() {
  for (var x = 0; x < 100; x++){
    for (var y = 0; y < 100; y++){
      if(black(get(x,y))==255){
        ellipse(x , y, 10, 100); 
      }
    }
  }
}
    
<style>

  p {
    position:absolute;
    z-index:3;
  }

  img {
    position:absolute;
    z-index: -1;
  }
</style>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <!-- PLEASE NO CHANGES BELOW THIS LINE (UNTIL I SAY SO) -->
  <script language="javascript" type="text/javascript" src="libraries/p5.min.js"></script>
  <script language="javascript" type="text/javascript" src="p5js-temp-sadfsfdsad8981306098870070843.js"></script>
  <!-- OK, YOU CAN MAKE CHANGES BELOW THIS LINE AGAIN -->

  <!-- This line removes any default padding and style.
       You might only need one of these values set. -->
  <style> body { padding: 0; margin: 0; } </style>
</head>

<body>
  <img id="map" width="220" height="277" src="https://geology.com/world/india-map.gif" alt="The map">
  <!--<img src="https://geology.com/world/india-map.gif">-->
  <p id="area"></p> <br>
  <p id="perimeter"></p>
</body>
</html>

编辑:我将代码更改为

  window.onload = function() {
  var c = canvas;
  var ctx = c.getContext("2d");
  var img = document.getElementById("map");
  ctx.drawImage(img, 10, 10, 150000, 1800000);
}

                  

function draw() {


for (var x = 0; x < 100; x++){
  for (var y = 0; y < 100; y++){
  if(black(get(x,y))==255){
   ellipse(x , y, 10, 100);
  
}
}
}
  

    }
    
<style> body { padding: 0; margin: 0; } </style>
</head>

<body>
<img id="map" width="220" height="277" src="https://geology.com/world/india-map.gif" alt="The map">
<!--<img src="https://geology.com/world/india-map.gif">-->
<p id="area"></p> <br>
<p id="perimeter"></p>
</body>
</html>
<style>

p{
position:absolute;
z-index:3;

}
img{
 position:absolute;
 z-index: -1;
  
}
</style>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">


  <script language="javascript" type="text/javascript" src="libraries/p5.min.js"></script>
  <script language="javascript" type="text/javascript" src="p5js-temp-sadfsfdsad1466343293693433275.js"></script>


  <!-- This line removes any default padding and style.
       You might only need one of these values set. -->
  

但是,我在地图上看到了一个黑色矩形,没有点。有谁知道为什么会这样?

【问题讨论】:

  • 你没有id为“myCanvas”的元素,所以document.getElementById("myCanvas");返回null
  • 在p5js中你不需要获取画布,你可以使用canvas引用它
  • 这是 p5.js 和非 p5.js 图形编程方法的奇怪混合。
  • 我是 javascript 和 p5js 的新手,使用了一些来自互联网的代码 sn-ps。
  • 还有——black() 是什么?这不是 p5.js 函数。就学习 p5.js 而言,我强烈推荐 Dan Shiffman 在 Coding Train 频道上的 YouTube 视频

标签: javascript p5.js


【解决方案1】:

对尼克·帕森 (Nick Parson) 的出色答案稍作调整,但使用 pixels 而不是 get。它runs almost instantly,说明get()是罪魁祸首。

//tweak of Code from Nick Parsons

let img;

function preload() {
  img = loadImage('india-map.gif');
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  image(img, 0, 0, width, height);
  loadPixels();
  const d = pixelDensity();

  for (let x = 0; x < width; x++) {
    for (let y = 0; y < height; y++) {
      const i = 4 * d*(y * d*width + x);
      const [r, g, b] = [pixels[i], pixels[i + 1], pixels[i + 2]]; // get colors
      if (r <= 80 && b <= 80 && g <= 80) { // if r g b all less than 80 then color will appear black
        noStroke();
        fill(255, 0, 0);
        ellipse(x, y, 1);
      }
    }
  }
  noLoop();
}

【讨论】:

  • 很好的解决方法,我没想过使用loadPixels() :D
【解决方案2】:

由于您使用的是 p5js,因此您应该使用它所提供的方法和功能。使用 p5js 时无需像您一样获取画布。当你输入 canvas 时,p5js 会提供对它的引用。

目前您正在使用图像标签来显示您的图像。相反,您希望将图像显示到画布上。您可以通过使用 p5 的 preload 方法加载图像来做到这一点。然后,一旦加载完成,您就可以在 draw 方法中引用它。

您的draw 方法将不断循环运行。但是,您不需要循环,因为您只需要进行一次计算。因此,您可以使用 p5 的方法 noLoop() 来停止 draw 循环。

最后,要获得特定像素的颜色,您需要使用get(x, y)。这将为您提供一组红色、绿色和蓝色值。黑色像素是所有这三个值都是0。但是,您的图像具有并非严格黑色的像素。例如,如果您的 r g b(红、绿、蓝)颜色值为 1、1、1,您的颜色仍然看起来是黑色的。因此,要检查给定颜色是否为黑色,您需要检查所有这些值是否小于特定数字,例如 80

如果你将所有这些想法融入你的代码中,你最终应该会得到这样的结果:

let img;

function preload() {
  img = loadImage('india-map.gif');
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  image(img, 0, 0, width, height);
  for(let x = 0; x < width; x++) {
    for(let y = 0; y < height; y++) {
      const [r, g, b] = get(x, y); // get colors
      if(r <= 80 && b <= 80 && g <= 80) { // if r g b all less than 80 then color will appear black
        noStroke(); // remove black outline from thing we are about to draw (the ellipse)
        fill(255, 0, 0); // make the ellipse red
        ellipse(x, y, 1); // draw the ellipse at the pixle
      }
    }
  }
  noLoop();
}

您可以找到一个工作示例here。但请注意,这是出于演示目的。请花时间理解代码。此外,当我们使用get 查看画布上每个像素的颜色时,这需要很长时间来计算一次运行。 (考虑查看每 2 个像素并将椭圆画大一点)

【讨论】:

  • 感谢您的代码,但是当我运行它时,我收到一条错误消息。它说,“语法错误:jdk.nashoen.internal.ir.ForNode 无法转换为 jdk.nashorn.internal.ir.Block。”这是什么意思?
  • @BobTimmon 该错误与此代码无关,但与您尝试在网页中使用 p5.js 的方式有关。首次学习时使用 p5.js Web 编辑器(正如 Nick 在链接中所做的那样)可能是一个好主意,因为它会为您处理一些 HTML 样板。
  • @BobTimmon 您好 Bob,正如约翰所说,您似乎正试图以一种奇怪的方式使用 p5。也许尝试使用网络编辑器。
  • 400^2 只有 16,000。如果需要那么长时间,那么一定是某个瓶颈。事实证明get 有点贵。如果您首先加载像素并直接使用pixels,则代码几乎会立即运行。我调整了代码。评论太长了,所以我将其发布为答案,但这是您的想法 (+1)。
猜你喜欢
  • 1970-01-01
  • 2011-11-17
  • 2012-02-24
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
  • 2014-01-25
  • 1970-01-01
  • 2023-03-07
相关资源
最近更新 更多