我非常感谢您的所有努力,但很遗憾,他们没有回答问题。 我在上面说过bruteForce方法,我的问题是如何进一步优化它。 这是我的蛮力方法的回顾:
我希望能够获得图像中尽可能少的垂直和水平线。我的想法是得到最长的线(垂直或水平),然后再获得第二长的线,依此类推(我认为)可以解决该问题。
这些图像看起来将类似于8位图像,但是看起来更大,更详细: Mario 8Bit
到目前为止,我已经提出了对整个图像进行迭代,提取最长的行,进行存储并重新生成图像的方案,但是避免访问已经访问过的行。如果没有其他路线可供参观,它将停止。
由于这是蛮力的,所以花的时间比我需要的时间长。我正在寻找一种方法来优化整个方法,而不仅仅是代码内部的微小优化。
答案 0 :(得分:0)
这是用于查找所有水平线的示例伪代码:
List lineList;
for(v : [0, imageHeight-1]) {
int streakStart = 0;
Color lastColor = colorAt(0, v);
for(u : [1, imageWidth-1]) {
Color currentColor = colorAt(u, v);
if(currentColr != lastColor) {
lineList.insert(Line(streakStart, u-1));
streakStart = u;
lastColor = currentColor;
}
}
lineList.insert(streakStart, imageWidth-1);
}
您可以通过切换u和v来获得垂直线。
答案 1 :(得分:0)
从描述中看,您似乎正在寻找的行包含完全相同颜色且完全水平或垂直的像素。< / p>
我创建了一个示例,该示例在图像中生成了一堆随机的红线:
蓝色突出显示已找到的行,绿色突出显示已找到的最长行。
通过简单的方法检测线条:
检查附近像素。也就是说,检查当前像素的“北”,“南”,“东”和“西”像素与当前像素的颜色是否相同
如果当前像素为红色,像素 west 为白色,像素 east 为红色,则开始<此时,水平> strong 行。这基本上是寻找这种模式:
. ? .
W R R
. ? .
如果当前像素为红色,像素 north 为白色,像素 south 为红色,则开始<此时,strong>垂直线。这基本上是寻找这种模式:
. W .
? R ?
. R .
当检测到这样的行开始时,水平或垂直走动,直到找到该行的末尾,并存储结果行
请注意,这里有一些假设和特殊情况。尽管确实找到了合理的结果,但是当两条直线并排时,事情变得棘手。这么说:当您有这样的红色像素图案时...
. . . . .
. R R R .
. R R R .
. R R R .
. . . . .
那么严格来说,就不可能说这些是否是
但是,此MCVE中显示了建议的方法:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FindLinesInImage {
public static void main(String[] args) {
int w = 100;
int h = 100;
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
int numLines = 30;
int lineRgb = Color.RED.getRGB();
Random random = new Random(0);
drawSomeLines(image, numLines, lineRgb, random);
List<Line2D> lines = findLines(image, lineRgb);
Comparator<Line2D> comparator = (line0, line1) -> {
double length0 = line0.getP1().distance(line0.getP2());
double length1 = line1.getP1().distance(line1.getP2());
return Double.compare(length1, length0);
};
Collections.sort(lines, comparator);
SwingUtilities.invokeLater(() -> createAndShowGui(image, lines));
}
private static void createAndShowGui(BufferedImage image, List<Line2D> lines) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
double scaling = 5.0;
AffineTransform lineTransform = AffineTransform.getScaleInstance(scaling, scaling);
lineTransform.translate(0.5, 0.5);
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics gr) {
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr;
AffineTransform oldAt = g.getTransform();
g.scale(scaling, scaling);
g.drawImage(image, 0, 0, null);
g.setTransform(oldAt);
g.setColor(new Color(0, 128, 0, 64));
g.setStroke(new BasicStroke((float) (3 * scaling)));
for (int i = 0; i < lines.size(); i++) {
Line2D line = lines.get(i);
g.draw(lineTransform.createTransformedShape(line));
g.setColor(new Color(0, 0, 255, 64));
}
};
};
f.getContentPane().add(panel);
f.setSize(800, 800);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static List<Line2D> findLines(BufferedImage image, int rgb) {
List<Line2D> lines = new ArrayList<Line2D>();
int w = image.getWidth();
int h = image.getHeight();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
boolean atC = pixelHasColor(image, x, y, rgb);
boolean atN = pixelHasColor(image, x, y - 1, rgb);
boolean atS = pixelHasColor(image, x, y + 1, rgb);
boolean atE = pixelHasColor(image, x + 1, y, rgb);
boolean atW = pixelHasColor(image, x - 1, y, rgb);
if (atC) {
if (atE && !atW) {
Line2D line = computeLine(image, x, y, 1, 0, rgb);
System.out.println("Line " + line.getP1() + " " + line.getP2());
lines.add(line);
}
if (atS && !atN) {
Line2D line = computeLine(image, x, y, 0, 1, rgb);
System.out.println("Line " + line.getP1() + " " + line.getP2());
lines.add(line);
}
if (!atS && !atN & !atW && !atE) {
Line2D line = new Line2D.Double(x, y, x, y);
lines.add(line);
}
}
}
}
return lines;
}
private static Line2D computeLine(BufferedImage image, int x, int y, int dx, int dy, int rgb) {
int cx = x;
int cy = y;
while (pixelHasColor(image, cx, cy, rgb)) {
cx += dx;
cy += dy;
}
return new Line2D.Double(x, y, cx - dx, cy - dy);
}
private static boolean pixelHasColor(BufferedImage image, int x, int y, int rgb) {
if (x < 0 || y < 0) {
return false;
}
int w = image.getWidth();
int h = image.getHeight();
if (x >= w || y >= h) {
return false;
}
return image.getRGB(x, y) == rgb;
}
private static void drawSomeLines(BufferedImage image, int n, int rgb, Random random) {
int w = image.getWidth();
int h = image.getHeight();
Graphics2D g = image.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, w, h);
g.setColor(new Color(rgb));
for (int i = 0; i < n; i++) {
int x0 = random.nextInt(w / 2) * 2;
int y0 = random.nextInt(h / 2) * 2;
int x1 = x0;
int y1 = y0;
boolean horizontal = random.nextBoolean();
if (horizontal) {
x1 = x0 + random.nextInt(w - x0);
} else {
y1 = y0 + random.nextInt(h - y0);
}
g.drawLine(x0, y0, x1, y1);
}
g.dispose();
}
private static void drawLine(BufferedImage image, int x0, int y0, int x1, int y1, int rgb) {
Graphics2D g = image.createGraphics();
g.setColor(new Color(rgb));
g.drawLine(x0, y0, x1, y1);
g.dispose();
}
}