2011-09-16 20 views
12

Stavo cercando una funzione di supporto per calcolare l'intersezione di due linee in OpenCV. Ho cercato la documentazione API, ma non ho trovato una risorsa utile.OpenCV 2d linea intersezione helper funzione

Ci sono funzioni di base di supporto geometrico per i calcoli di intersezione/distanza su linee/segmenti di linea in OpenCV?

risposta

38

Non ci sono alcuna funzione in OpenCV API per calcolare le linee di intersezione, ma la distanza è:

cv::Point2f start, end; 
double length = cv::norm(end - start); 

Se avete bisogno di un pezzo di codice per calcolare le intersezioni di linea, allora qui è:

// Finds the intersection of two lines, or returns false. 
// The lines are defined by (o1, p1) and (o2, p2). 
bool intersection(Point2f o1, Point2f p1, Point2f o2, Point2f p2, 
         Point2f &r) 
{ 
    Point2f x = o2 - o1; 
    Point2f d1 = p1 - o1; 
    Point2f d2 = p2 - o2; 

    float cross = d1.x*d2.y - d1.y*d2.x; 
    if (abs(cross) < /*EPS*/1e-8) 
     return false; 

    double t1 = (x.x * d2.y - x.y * d2.x)/cross; 
    r = o1 + d1 * t1; 
    return true; 
} 
+0

Solo per chiarimenti. Le linee nel tuo esempio sono definite da due punti o come un vettore di direzione e di punto? – tisch

+0

Sono definiti da due punti. 'd1' e' d2' calcolati all'interno della funzione sono vettori di direzione. –

+0

Grazie alla funzione di aiuto! – tisch

1

Ecco la mia implementazione per EmguCV (C#).

static PointF GetIntersection(LineSegment2D line1, LineSegment2D line2) 
{ 

    double a1 = (line1.P1.Y - line1.P2.Y)/(double)(line1.P1.X - line1.P2.X); 
    double b1 = line1.P1.Y - a1 * line1.P1.X; 

    double a2 = (line2.P1.Y - line2.P2.Y)/(double)(line2.P1.X - line2.P2.X); 
    double b2 = line2.P1.Y - a2 * line2.P1.X; 

    if (Math.Abs(a1 - a2) < double.Epsilon) 
     throw new InvalidOperationException(); 

    double x = (b2 - b1)/(a1 - a2); 
    double y = a1 * x + b1; 
    return new PointF((float)x, (float)y); 
} 
0

mia implementazione in Python (usando matrice NumPy) con line1 = [[x1, y1], [x2, y2]] & line2 = [[x1, y1], [x2, y2]]

def getIntersection(line1, line2): 
    s1 = numpy.array(line1[0]) 
    e1 = numpy.array(line1[1]) 

    s2 = numpy.array(line2[0]) 
    e2 = numpy.array(line2[1]) 

    a1 = (s1[1] - e1[1])/(s1[0] - e1[0]) 
    b1 = s1[1] - (a1 * s1[0]) 

    a2 = (s2[1] - e2[1])/(s2[0] - e2[0]) 
    b2 = s2[1] - (a2 * s2[0]) 

    if abs(a1 - a2) < sys.float_info.epsilon: 
     return False 

    x = (b2 - b1)/(a1 - a2) 
    y = a1 * x + b1 
    return (x, y) 
+0

x1, y1 & x2, y2 deve essere float come (0.0, 1.0) e (2.0, 1.0) – afiah

+0

Questo codice non funziona in presenza di una linea verticale, a causa delle divisioni per (si [0] - ei [0]) –

2

Uso coordinate omogenee semplifica la vita:

cv::Mat intersectionPoint(const cv::Mat& line1, const cv::Mat& line2) 
{ 
    // Assume we receive lines as l=(a,b,c)^T 
    assert(line1.rows == 3 && line1.cols = 1 
      && line2.rows == 3 && line2.cols == 1); 

    // Point is p=(x,y,w)^T 
    cv::Mat point = line1.cross(line2); 

    // Normalize so it is p'=(x',y',1)^T 
    if(point.at<double>(2,0) != 0) 
    point = point * (1.0/point.at<double>(2,0)); 
} 

noti che se la terza coordinata è 0 le linee sono parallele e non c'è soluzione in R² ma in P^2, e quindi il poin t indica una direzione in 2D.

+0

Qual è la forma di 'point'? Nulla viene restituito da questa funzione. – Geoff

1

Un algoritmo per la ricerca di intersezione linea è descritto molto bene nel post How do you detect where two line segments intersect?

Il seguente è il mio OpenCV C++ attuazione. Utilizza la stessa notazione di cui sopra post

bool getIntersectionPoint(Point a1, Point a2, Point b1, Point b2, Point & intPnt){ 
    Point p = a1; 
    Point q = b1; 
    Point r(a2-a1); 
    Point s(b2-b1); 

    if(cross(r,s) == 0) {return false;} 

    double t = cross(q-p,s)/cross(r,s); 

    intPnt = p + t*r; 
    return true; 
} 

double cross(Point v1,Point v2){ 
    return v1.x*v2.y - v1.y*v2.x; 
}