在处理中绘制草图边缘上的 Blob 边缘
Drawing Blob edges that are on sketch edge in Processing
我一直在使用 blobDetection library 进行处理,从高度图制作等高线图。
我现在将每一层导出为 SVG 用于激光切割,但草图边缘的斑点不完整,边缘顶点未绘制。
这是一个简化的例子:
- 我开始的图像,白色区域会变成斑点
- 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(最大宽度或高度)
- 从斑点末端到草图左上角绘制一条直线,例如如果斑点与那个角重叠
- 还有很多其他条件,但是太多了我很困惑...
任何人都知道如何排序条件或如何解决问题...
非常感谢帮助!
我在处理过程中经常使用的一种将绘图限制在 window 范围内的方法是 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的window 是 >= 1,所以如果数字大于 window 的宽度,请将其限制为宽度。
我们最终得到一个介于 0
和 WIDTH
之间的数字,如果原始值已经在这些限制范围内,则它是未修改的。这应该绘制任何将沿着边缘绘制在 window 外侧的边缘。试一试,如果有效请告诉我!
我的一个同事偶然发现了一个聪明的解决这个问题的方法,就是将原始图像的大小每边增加一个像素,并将这些像素变成黑色。
所以如果图片是 100x100px,那么它就是 102x102px。我们在我们的例子中添加了黑色像素,但我认为最好的方法是计算决定是否绘制斑点的截止颜色,并为这些新的边界像素分配一种颜色或只是 below/above 那(取决于你的需要)。
除了导入和修改图像的部分外,代码与我原来的问题大部分相同:
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 输出,具有所需的外边框:
这不是我问这个问题时所期望的解决方案,但它工作得很好。它当然可以稍微完善一些,但我在我正在使用的一堆其他高度图上对其进行了测试,结果始终令人满意。
希望对您有所帮助!
我一直在使用 blobDetection library 进行处理,从高度图制作等高线图。 我现在将每一层导出为 SVG 用于激光切割,但草图边缘的斑点不完整,边缘顶点未绘制。
这是一个简化的例子:
- 我开始的图像,白色区域会变成斑点
- 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(最大宽度或高度)
- 从斑点末端到草图左上角绘制一条直线,例如如果斑点与那个角重叠
- 还有很多其他条件,但是太多了我很困惑...
任何人都知道如何排序条件或如何解决问题... 非常感谢帮助!
我在处理过程中经常使用的一种将绘图限制在 window 范围内的方法是 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的window 是 >= 1,所以如果数字大于 window 的宽度,请将其限制为宽度。
我们最终得到一个介于 0
和 WIDTH
之间的数字,如果原始值已经在这些限制范围内,则它是未修改的。这应该绘制任何将沿着边缘绘制在 window 外侧的边缘。试一试,如果有效请告诉我!
我的一个同事偶然发现了一个聪明的解决这个问题的方法,就是将原始图像的大小每边增加一个像素,并将这些像素变成黑色。 所以如果图片是 100x100px,那么它就是 102x102px。我们在我们的例子中添加了黑色像素,但我认为最好的方法是计算决定是否绘制斑点的截止颜色,并为这些新的边界像素分配一种颜色或只是 below/above 那(取决于你的需要)。
除了导入和修改图像的部分外,代码与我原来的问题大部分相同:
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 输出,具有所需的外边框:
这不是我问这个问题时所期望的解决方案,但它工作得很好。它当然可以稍微完善一些,但我在我正在使用的一堆其他高度图上对其进行了测试,结果始终令人满意。
希望对您有所帮助!