Из описания кажется, что вы ищете линии, состоящие из пикселей, которые имеют точно того же цвета, и которые идеально горизонтальны или вертикальны.
Я создал пример, который генерирует несколько случайных красных линий на изображении:
Синяя подсветка указывает на найденные линии, а зеленая подсветка показывает самую длинную найденную линию.
Линии обнаруживаются простым способом:
- Пройдите по всем пикселям (x, y), поканайден пиксель с цветом линии
Проверьте соседние пиксели.То есть проверьте, имеют ли пиксели «север», «юг», «восток» и «запад» текущего пикселя тот же цвет, что и текущий
Если текущий пикселькрасный, и пиксель запад его белого цвета, а пиксель восток его красного цвета, тогда в этой точке начинается линия горизонтальная .В основном это выглядит для этого шаблона:
. ? .
W R R
. ? .
Если текущий пиксель красный, а пиксель север его белый, а пиксель юг красного цвета, затем в этой точке начинается вертикальная линия.По сути, это выглядит следующим образом:
. W .
? R ?
. R .
При обнаружении такого начала линии, проходите горизонтально или вертикально, пока не будет найден конец линии,и сохраните полученную строку
- Наконец, сортируйте строки по их длине
Обратите внимание, что здесь есть некоторые предположения и угловые случаи.Хотя находит приемлемые результаты, все становится непросто, когда две линии расположены рядом друг с другом.Проще говоря: если у вас есть образец красных пикселей, как этот ...
. . . . .
. R R R .
. R R R .
. R R R .
. . . . .
, то, строго говоря, невозможно сказать, являются ли они
- три горизонтальные линии длиной 3
- три вертикальные линии длиной 3
- три горизонтальные линии длиной 2 и одна вертикальная линия длиной 3
- или что угодно ...
Однако предлагаемый подход показан в этом 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();
}
}