是否有一种有效的算法可以从未排序的x / y坐标集合中找到直线? 如果符合以下条件,那将是理想的:
是否有某种标准方法可以解决这个问题?也许任何(java)库?你会如何解决它?
答案 0 :(得分:0)
我建议使用两张地图,一张用于水平线,另一张用于垂直线。
对于每个点,键是X或Y坐标,值是点(使用点列表作为值)。现在浏览一下地图,如果有多个点,每个键显示点数,对于每个键,你还应该计算下一个键中的点数(如99和100的情况)。
答案 1 :(得分:0)
除非你已经知道这些点之间的某些关系,否则我不确定它是否是一种有效的算法。 我想在下面概述的算法将在n ^ 4时间运行。
你有
之类的东西public class Line
{
static float tolerance;
float m, cLower, cUpper;
ArrayList<Point> onThisLine = new ArrayList<Point>();
public Line(double m, double c)
{
this.m = m;
cLower = c-tolerance;
cUpper = c+tolerance;
}
public boolean fitsInLine(Point xy)
{...}
public void addToList(Point xy)
{...}
}
其中m和c代表我们在高中学到的直线的梯度和常数。
对于每个点,您必须将其与其他每个点进行比较,生成一个Line对象,然后将新的Line对象与每个现有的Line进行比较,如果它还不存在,则添加它。请注意,由于您允许的轻微容差,因此必须允许线之间的相似性。 例如,y = -x / 10 + 101和y = 100是非常相似的线方程。
最后,对于每个Line对象,您可以获得ArrayList的大小,保持适合它的Point,并丢弃Point比您想要的更少的行。
答案 2 :(得分:0)
如果你取一对点P i 和P j ,你可以在O(n)时间检查哪些点位于P i P j 。有O(n 2 )对,因此您得到的算法是O(n 3 )。当然,如果P k 正好在P i P j 的行上,则不应再检查P i P k 和P j P k ,因为它们将包含与P i P <相同的点子>Ĵ子>。但是,如果P k 接近P i P j ,则情况并非如此。
答案 3 :(得分:0)
我已经将算法显示在下面。它的作用是计算线的公式:y = kx + l;然后它产生两条平行于那条线的线,一条略微抬起,一条稍微降低 - >(y = kx + 1-d,y = kx + 1 + d,d =公差)。然后它通过其余的点并计算y为上下平行的x。如果它的实际值在计算值之间,那么它就算在线上。这是O(n ^ 3)。 代码:
public static void main(String[] args) {
Point[] points = generatePoints(5);
List<Set<Point>> lines = findLines(points,2,3);
lines.forEach((line)->{
System.out.println(Arrays.toString(line.toArray()));
});
}
private static List<Set<Point>> findLines(Point[] points,int tolerance,int minNumberOfPoints) {
List<Set<Point>> lines = new LinkedList<>();
for(int i=0;i<points.length;i++){
for(int j=i+1;j<points.length;j++){
//check if that line was all ready found
boolean hasBoth = false;
for(Set<Point> line:lines){
hasBoth =Boolean.logicalAnd(line.contains(points[i]),line.contains(points[j]));
if(hasBoth)
break;
}
if(hasBoth)
break;
int x1 = points[i].getX();
int y1 = points[i].getY();
int x2 = points[j].getX();
int y2 = points[j].getY();
double k = (double)(y1-y2)/(double)(x1-x2);
double l = y1-k*x1;
//y = kx + l -> line
//y1 = kx + l - tolerance -> lower parallel line
//y2 = kx + l + tolerance -> upper parallel line
//take a third point if for its x it gives a y3 where y1<=y3<=y2 then it should be part of the line
Set<Point> line = new HashSet<>();
line.add(points[i]);
line.add(points[j]);
for(int z=j+1;z<points.length;z++){
int x3 = points[z].getX();
int y3 = points[z].getY();
double y1Line = k*x3+l-tolerance;
double y2Line = k*x3+l+tolerance;
if(y1Line<=y3 && y3<=y2Line)
line.add(points[z]);
}
lines.add(line);
}
}
lines = lines.stream().filter((set)->{
return set.size()>=minNumberOfPoints;
}).collect(Collectors.toList());
return lines;
}
private static Point[] generatePoints(int number) {
Point[] points = new Point[number];
Random r = new Random();
for(int i=0;i<number;i++){
points[i] = new Point(r.nextInt(10), r.nextInt(10));
}
return points;
}
private static class Point{
private int x;
private int y;
public Point(int x,int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public String toString() {
return "("+x+","+y+")";
}
}
答案 4 :(得分:0)
您可以使用Hough变换来检测线条。我在检测图像中的特征时经历了霍夫转换。它基本上使用线的极坐标来检测它们。虽然我认为opencv不符合你想要做的事情,但我仍然希望与你分享hough line检测页面,这非常清楚地解释了算法。
http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html
我发现这个来源也很有用: