我正在尝试使用javafx制作一个程序,该程序将转换这样的图片:
在这张照片中,背景并不是我想要的那样,但是中间的鳄梨是我想要实现的一个很好的例子。我现在拥有的是两个滤镜,它们可以根据亮度在图片中找到边缘,如下所示:
public void processImage() {
ww = (int) Math.ceil(image.getWidth());
hh = (int) Math.ceil(image.getHeight());
pixelAmount = (long) ww * (long) hh;
pxDA = new pxInfo[ww][hh];
PixelReader pr = image.getPixelReader();
if(pr != null) {
System.out.println("pixel reader found");
WritableImage i = new WritableImage(ww, hh);
for(int x = 0; x < ww; x++) {
for(int y = 0; y < hh; y++) {
Color c = pr.getColor(x, y);
double a = c.getOpacity();
double r = c.getRed();
double g = c.getBlue();
double b = c.getBlue();
double[][] gray = new double[3][3];
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
if(!((j == 0 && x == 0) || (k == 0 && y == 0) || (j
== 2 && x == ww - 1) || (k == 2 && y == hh - 1))) {
Color cl = pr.getColor(x - 1 + j, y - 1 + k);
gray[j][k] = 0.299 * cl.getRed() + 0.587 *
cl.getGreen() + 0.114 * cl.getBlue();
}
}
}
// apply filter
double gray1 = 0, gray2 = 0;
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
gray1 += gray[j][k] * filter1[j][k];
gray2 += gray[j][k] * filter2[j][k];
}
}
double magnitude = clamp(0.0, 1.0 - Math.sqrt(gray1 * gray1 +
gray2 * gray2), 1.0);
Color color = new Color(magnitude, magnitude, magnitude, 1);
i.getPixelWriter().setColor(x, y, color);
}
}
stackPane.getChildren().add(new ImageView(i));
}
}
这部分代码可以很好地工作,这些是一些结果:
在过滤器之前: 过滤后: 但是问题是我不知道从这里到哪里。我正在互联网上寻找各种算法,但是我真的找不到任何有明确解释的东西,所以我想在这里问。因此,如果您知道可以应用某些算法/过滤器来改进此效果,我想听听。
然后还有我实际需要创建三角/多边形的部分。假设我已应用所有过滤器,等等,我该怎么办?就像我如何将形状与灰度图片区分开?任何帮助将不胜感激。
预先感谢
Lenardjee
答案 0 :(得分:3)
我对JavaFX特别不熟悉,但是我尝试使用 Python 和 OpenCV 来解决一个非常类似的问题:
https://github.com/tasercake/lowpolypy
这就是我要做的。
在继续进行关键点提取之前,对图像进行预处理有助于去除许多不必要的高频细节。
您可以使用诸如双边过滤器或高斯过滤器之类的过滤器来实现此目的。
您可能还希望在此处缩小图像以加快处理速度,但这并不是绝对必要的。
这可能是最困难的部分,也是最需要微调/实验的部分。
您可以尝试的一些方法是:
任何值得使用的图像处理/计算机视觉库(例如OpenCV)都应内置此功能。
此方法为您提供一个布尔图像,其中潜在边缘标记为“真”。然后,您可以选择这些点的随机子集,并将它们转换为(X,Y)坐标(或最适合您的格式)。
我发现这种方法与少量的随机化相结合,需要最少的调整。
这是另一种检测图像中显着特征的方法,但是它基于图像像素的二阶导数(与基于一阶导数的Canny滤镜相反)。
此过滤器返回一张图像,您可以对其进行标准化并将其用作权重蒙版,以从中随机采样一组关键点(也许有比这更好的使用过滤器的方法,但是我不为所动)。
一旦您通过其他所有方法积累了一组关键点,则可以选择用一组随机生成的关键点替换所有点的一小部分随机子集。
我发现这有助于在最终输出中引入一些美观的不规则性。
除了直接替换一小部分关键点外,我还对每个关键点“微动”(随机翻译)非常少量。这有助于引入更多的随机性,并允许您多次运行程序以获得一个可能良好的输出。
注意:请不要忘记将图像的4个角添加为关键点,否则最终将在输出周围出现空白区域。
Delaunay Triangulation是一种算法,该算法以使这样形成的每个三角形中的最小角度最大化的方式连接平面中的一组点。 (很明显,如果您不仅仅想要三角形,这是行不通的。)
对于每个多边形,您需要获取多边形所包围的区域内所有图像像素的平均值。 OpenCV具有(cv2.mean(image, mask)
)函数,通过将多边形作为二进制掩码传递,您可以在很少的行中完成此操作。
一些结果: