【问题标题】:Drawing Blob edges that are on sketch edge in Processing在处理中绘制草图边缘上的斑点边缘
【发布时间】:2017-06-02 02:54:42
【问题描述】:

我一直在使用 blobDetection library 进行处理,从高度图制作等高线图。 我现在将每一层导出为用于激光切割的 SVG,但草图边缘的斑点不完整,边缘顶点未绘制。

这是一个简化的例子:

  1. 我开始的图像,白色区域会变成斑点

  1. SVG 输出,缺少边缘

import processing.svg.*;
import blobDetection.*;
import peasy.*;
import processing.pdf.*;
PeasyCam cam;

PImage img;

float levels = 10;

BlobDetection[] contours = new BlobDetection[int(levels)];

//Creating array to store the blob objects
ArrayList<Ring> rings = new ArrayList<Ring>();

void setup() {

  size(480, 360, P3D);
  surface.setResizable(true);

  img = loadImage("maptest2.jpg");
  surface.setSize(img.width, img.height);

  cam = new PeasyCam(this, img.width, img.height, 0, 1500);
  colorMode(HSB, 360, 100, 100);

  for (int i=0; i<levels; i++) {
    contours[i] = new BlobDetection(img.width, img.height);
    contours[i].setThreshold(i/levels);
    contours[i].computeBlobs(img.pixels);
  }

  for (int i = 0; i < rings.size(); i++) {
    System.out.println("id: " + rings.get(i).getId());
    System.out.println("lvl: " + rings.get(i).getLvl());
    System.out.println("x: " + rings.get(i).getX());
    System.out.println("y: " + rings.get(i).getY());
    System.out.println();
  }

  noLoop();
}


void draw() {

  for (int i=0; i<levels; i++) {  

    beginRecord(SVG, "level-"+i+".svg");

    drawContours(i);
    println("drew level " + i);

    println("saved as: level-"+i+".svg");
    endRecord();
    println();

    if(i == levels-1){
      println("finished");
    }

  }

  System.out.println("Number of blobs (rings.size()): " + rings.size());
   println();

   for (int i = 0; i < rings.size(); i++){
   System.out.println("id: " + rings.get(i).getId());
   System.out.println("lvl: " + rings.get(i).getLvl());
   System.out.println("x: " + rings.get(i).getX());
   System.out.println("y: " + rings.get(i).getY());
   System.out.println();
   }

}

void drawContours(int i) {
  Blob b;
  EdgeVertex eA, eB;
  for (int n=0; n<contours[i].getBlobNb(); n++) {
    b=contours[i].getBlob(n);

    //Condition for drawing only blobs bigger than 5% of width and 5% of height
    if(b.w*width>.05*width && b.h*height>.05*height){

      if (b!=null) {
        stroke(250, 75, 90);

        for (int m=0; m<b.getEdgeNb(); m++) {
          eA = b.getEdgeVertexA(m);
          eB = b.getEdgeVertexB(m);

          //This part draws the blobs.

          if (eA !=null && eB !=null)
           line(
           eA.x*img.width, eA.y*img.height, 
           eB.x*img.width, eB.y*img.height 
           );

           println("eA.x: " + eA.x);
           println("eA.y: " + eA.y);
           println("eB.x: " + eB.x);
           println("eB.y: " + eB.y);
           println();

           ////////////
           //Here are my various attempts at drawing these rogue edges!
           //I commented them out

           /*      
           //Checking if vertex has a point at x=0
           if (b.getEdgeVertexA(m).x == 0 && b.getEdgeVertexB(b.getEdgeNb()).x == 0){


                 line(  b.getEdgeVertexA(0).x*img.width, b.getEdgeVertexA(0).y*img.height, 
                        b.getEdgeVertexA(m).x*img.width, b.getEdgeVertexA(m).y*img.height   );

                 println("////");
                 println("x making line (scaled 0-1): ");
                 //println(eA.x, eA.y, eB.x, eB.y);
                 println(  b.getEdgeVertexA(0).x, b.getEdgeVertexA(0).y, 
                           b.getEdgeVertexA(m).x, b.getEdgeVertexA(m).y   );

                 println("////");
           }

           //Checking if vertex has a point at y=0
           if (b.getEdgeVertexA(m).y == 0 && b.getEdgeVertexB(b.getEdgeNb()).y == 0){

             line(  b.getEdgeVertexA(0).x*img.width, b.getEdgeVertexA(0).y*img.height, 
                    b.getEdgeVertexA(m).x*img.width, b.getEdgeVertexA(m).y*img.height   );

                 println("////");
                 println("y making line (scaled 0-1): ");
                 //println(eA.x, eA.y, eB.x, eB.y);
                 println(  b.getEdgeVertexA(0).x, b.getEdgeVertexA(0).y, 
                           b.getEdgeVertexA(m).x, b.getEdgeVertexA(m).y   );

                 println("////");

           }

           if (b.getEdgeVertexA(m).x == 0 && b.getEdgeVertexB(b.getEdgeNb()).y == 0){

             line(  b.getEdgeVertexA(0).x*img.width, b.getEdgeVertexA(0).y*img.height, 0, 0   );
             println("drew to 0,0");
           }

           if (b.getEdgeVertexA(m).y == 0 && b.getEdgeVertexB(b.getEdgeNb()).x == 0){

             line(  b.getEdgeVertexA(m).x*img.width, b.getEdgeVertexA(m ).y*img.height, 0, 0   );
             println("drew to 0,0");
           }
           */
           ////////////

        }

        //Adding objects to the rings ArrayList
        rings.add(new Ring(String.valueOf(rings.size()+1), (int) i, (double) b.x*100, (double) b.y*100));
        }
    }
  }
}

现在我知道我知道我的代码不包含任何绘制这些边缘的代码,所以它们并没有真正丢失,但我有点不知道从哪里开始正确绘制这些边缘。

我想过:

  • 检查构成 blob 的顶点的任何坐标是否等于 0(最小宽度或高度)或 1(最大宽度或高度)
  • 例如,如果 blob 与该角重叠,则从 blob 末端到草图的左上角绘制一条直线
  • 许多其他条件,但我很困惑...

任何人都知道如何排序条件或如何解决问题... 非常感谢您的帮助!

【问题讨论】:

    标签: java processing detection edge-detection edges


    【解决方案1】:

    我的一位同事偶然发现了一个巧妙的解决方案,即在原始图像的每一侧增加一个像素,并将这些像素变为黑色。 因此,如果图像是 100x100px,那么它将是 102x102px。在我们的例子中,我们添加了黑色像素,但我认为最好的方法是计算决定是否绘制斑点的截止颜色,并为这些新的边框像素分配一个稍微或略低于/高于该颜色的颜色(取决于你的需要)。

    代码与我最初的问题中的代码基本相同,除了我们导入和修改图像的部分:

    PImage ref;
    PImage output;
    String filename = "maptest2.jpg";
    
    // // //
    
    //Here I skip some parts that are unchanged
    
    // // //
    
    void setup() {
    
      size(480, 360, P3D);
      surface.setResizable(true);
    
      ref = loadImage(filename);
      
      // create a copy of reference image with a black border
      output = createImage(ref.width+2, ref.height+2, RGB);
      
      for(int i=0; i < output.pixels.length; i++){
        output.pixels[i] = color(0);
      }
      
      output.updatePixels();
      output.set(1, 1, ref);
      
      surface.setSize(output.width, output.height);
    
      cam = new PeasyCam(this, output.width, output.height, 0, 1500);
    

    生成的 SVG 输出,带有所需的外边框:

    当我问这个问题时,这不是我所期望的解决方案,但它工作得很好。它当然可以完善一点,但我在我正在使用的一堆其他高度图上对其进行了测试,结果始终令人满意。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      我在处理过程中经常使用的一种方法来将我的绘图限制在窗口的范围内是 min 和 max 函数。它减少了我以前编写的 if 语句的不等式数量。

      在你的循环中试试这个,我没有测试过,所以我希望它能给你想要的输出,但它应该只是沿着你的图像边缘绘制边缘。

                eA = b.getEdgeVertexA(m);
                eB = b.getEdgeVertexB(m);
      
                //This part draws the blobs.
              if (eA !=null && eB !=null){
                float x1 = eA.x*img.width;
                float y1 = eA.y*img.height;
                float x2 = eB.x*img.width;
                float y2 = eB.y*img.height;
      
                x1 = min(max(0,x1),WIDTH);
                y1 = min(max(0,y1),HEIGHT);
                x2 = min(max(0,x2),WIDTH);
                y2 = min(max(0,y2),HEIGHT);
      
      
                line(x1, y1, x2, y2);
      
                 println("eA.x: " + eA.x + " x1: " + x1);
                 println("eA.y: " + eA.y + " y1: " + y1);
                 println("eB.x: " + eB.x + " x2: " + x2);
                 println("eB.y: " + eB.y + " y2: " + y2);
                 println();
               }
      

      逻辑如下:min(max(0,x1),WIDTH)

      首先我们找到max(0,x1),所以我们确保 x1 大于 0,如果它是负数,则将其设置为 0。

      然后我们把前面操作的结果,做下面的min(result,WIDTH) 所以试图找到两者之间的最小数,我们知道结果是>= 0,窗口的WIDTH是>= 1,因此如果数字大于窗口的宽度,则将其限制为宽度。

      我们最终得到一个介于0WIDTH 之间的数字,如果原始值已经在这些约束范围内,则它不会被修改。这应该绘制沿边缘绘制在窗口外部的任何边缘。试一试,让我知道它是否有效!

      【讨论】:

      • 我按原样尝试了代码,但它不起作用。我会稍微修改一下,然后再试一次,但我认为这不是我真正需要的。据我了解,您的代码会检查斑点是否越过草图的边缘,但由于我从高度图图像文件开始,边界就是图像,而斑点只是在想象中越过边缘。所以真的,代码应该检查一个 blob 是否完整(未关闭),然后沿着他的草图边缘关闭它。
      猜你喜欢
      • 2018-05-08
      • 1970-01-01
      • 1970-01-01
      • 2013-09-06
      • 2020-09-22
      • 1970-01-01
      • 1970-01-01
      • 2013-08-07
      • 2021-05-19
      相关资源
      最近更新 更多