2015-09-01 4 views
5

Ich möchte ein offenes Polygon mit sagen 50 Seiten zeichnen. Jetzt bin ich auf der Suche nach einer Möglichkeit, auf jeder Seite eine andere Farbe zu haben, abhängig von einem Index, zB:Wie kann ich für jede Seite eines Polygons eine andere Farbe verwenden?

polygon_coordinates = [ [5, 10], [7, 9], [8, 11], [11, 20] ] 
color_index = [100, 75, 200] 

Ich suche etwas wie

import cv2 
for i in range (0, len(polygon_coordinates)-1): 
    cv2.polylines([polygon_coordinates[i],polygon_coordinates[i+1]], color=[color_index[i], color_index[i], color_index[i]]) 

Gibt es eine Möglichkeit dafür, am besten ohne eine Schleife? Danke für die Hilfe

+1

Wenn Sie einige Pakete verwenden, dann sollten Sie wahrscheinlich Tag, das als gut, oder zumindest erwähnen es. – Roope

+1

Da Sie die Verex-Koordinaten haben, können Sie nicht einfach für jeweils zwei aufeinander folgende Vertices eine andere Farbe zeichnen? Warum 3 Farbindizes für ein 4-seitiges Polygon? – Miki

+0

Es ist ein offenes Polygon, deshalb 4 Ecken und nur drei Farben (Linien). Ich könnte wahrscheinlich auch einzelne Linien zeichnen und sie alle anders färben, aber da der Polylinienbefehl existiert, gab es vielleicht eine Möglichkeit, die Farben mit jedem verkreuzten Punkt etwas zu ändern. – ninehundred

Antwort

3

Dies ist wahrscheinlich nicht die Antwort, die Sie suchen sind :)

Kurze Antwort ist nicht wirklich. Das kannst du in cv2 nicht machen. Ich habe auch über 5 oder 6 andere Bibliotheken überprüft und es ist das gleiche für sie (ich bin mir sicher, dass du das auch getan hast).

Nicht alles ist jedoch verloren. Ich habe das starke Gefühl, dass die Polylinien in cv2 mithilfe der Linienfunktion implementiert werden. Von meinen rostigen cpp Jahren, hier ist etwas entnahm ich, wenn ich in den Quellcode für OpenCV für Linux und Mac (https://github.com/Itseez/opencv/archive/3.0.0.zip) forschte:

In opencv-3.0.0/modules/imgproc/src/drawing.cpp

Polylinien nennen PolyLine die Zeichnung am Ende des Codeblocks

void polylines(Mat& img, const Point* const* pts, const int* npts, int ncontours, bool isClosed, 
       const Scalar& color, int thickness, int line_type, int shift) 
{ 
    if(line_type == CV_AA && img.depth() != CV_8U) 
     line_type = 8; 

    CV_Assert(pts && npts && ncontours >= 0 && 
       0 <= thickness && thickness <= MAX_THICKNESS && 
       0 <= shift && shift <= XY_SHIFT); 

    double buf[4]; 
    scalarToRawData(color, buf, img.type(), 0); 

    for(int i = 0; i < ncontours; i++) 
     PolyLine(img, pts[i], npts[i], isClosed, buf, thickness, line_type, shift); 
} 

PolyLine ruft ThickLine zu tun Segmente zu zeichnen, indem Looping.

PolyLine(Mat& img, const Point* v, int count, bool is_closed, 
      const void* color, int thickness, 
      int line_type, int shift) 
{ 
    if(!v || count <= 0) 
     return; 

    int i = is_closed ? count - 1 : 0; 
    int flags = 2 + !is_closed; 
    Point p0; 
    CV_Assert(0 <= shift && shift <= XY_SHIFT && thickness >= 0); 

    p0 = v[i]; 
    for(i = !is_closed; i < count; i++) 
    { 
     Point p = v[i]; 
     ThickLine(img, p0, p, color, thickness, line_type, flags, shift); 
     p0 = p; 
     flags = 2; 
    } 
} 

ThickLine wiederum ruft verschiedene Leitungsfunktionen seine Implementierungen zu tun, hier abgeschnitten, da es eine lange Funktion ist aber nur Blick auf, was es tut, wenn Linien mit einer Dicke von 1 oder weniger zeichnen, ruft es die Linienfunktion

ThickLine(Mat& img, Point p0, Point p1, const void* color, 
      int thickness, int line_type, int flags, int shift) 
{ 
    static const double INV_XY_ONE = 1./XY_ONE; 

    p0.x <<= XY_SHIFT - shift; 
    p0.y <<= XY_SHIFT - shift; 
    p1.x <<= XY_SHIFT - shift; 
    p1.y <<= XY_SHIFT - shift; 

    if(thickness <= 1) 
    { 
     if(line_type < CV_AA) 
     { 
      if(line_type == 1 || line_type == 4 || shift == 0) 
      { 
       p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT; 
       p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT; 
       p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT; 
       p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT; 
       Line(img, p0, p1, color, line_type); 
      } 
      else 
       Line2(img, p0, p1, color); 
     } 
     else 
      LineAA(img, p0, p1, color); 
    } 
    ... 

und schließlich Line (und seine Varianten wie Netz2 usw.) nur Plotpunkte:

Line(Mat& img, Point pt1, Point pt2, 
     const void* _color, int connectivity = 8) 
{ 
    if(connectivity == 0) 
     connectivity = 8; 
    else if(connectivity == 1) 
     connectivity = 4; 

    LineIterator iterator(img, pt1, pt2, connectivity, true); 
    int i, count = iterator.count; 
    int pix_size = (int)img.elemSize(); 
    const uchar* color = (const uchar*)_color; 

    for(i = 0; i < count; i++, ++iterator) 
    { 
     uchar* ptr = *iterator; 
     if(pix_size == 1) 
      ptr[0] = color[0]; 
     else if(pix_size == 3) 
     { 
      ptr[0] = color[0]; 
      ptr[1] = color[1]; 
      ptr[2] = color[2]; 
     } 
     else 
      memcpy(*iterator, color, pix_size); 
    } 
} 

das bedeutet, dass es nicht zu viel von einem Performance hallo sein sollte t zum Aufrufen von Linien über Polylinien, weil der C++ - Code mehr oder weniger das Gleiche macht: iterieren über eine Linienzeichnungsfunktion.

Wenn Sie dies testen möchten, können Sie wahrscheinlich ein einzelnes farbiges Polygon mit einer Anzahl von Seiten zeichnen, die nahe bei dem sind, was Sie in Ihrer Anwendung verwenden müssen, indem Sie Polylinien und Linien aufrufen und diese zeitlich steuern. Hier ist ein sehr schnelles und schmutziges Beispiel dafür, wie man Sachen in Python von Learning Python 5th Edition Seite 630 einer Zeit können:

import time 
def timer(func, *args): 
    start = time.clock() 
    for i in range(1000): 
     func(*args) 
    return time.clock() - start 

Ich bin sicher, dass Sie viele bessere Werkzeuge finden können, als dies allerdings zu testen :)

Einen letzte gedacht: Wenn ich falsch liege und zwischen zwei Methoden ein Leistungsunterschied besteht, kannst du deinen Code danach für mehr Geschwindigkeit optimieren. Es gibt Unmengen von Tools, um Python-Tools zu beschleunigen. Sie können mit PyPy beginnen.

+0

Gut, ich werde das ausprobieren, gut, um auch eine gute Möglichkeit zu kennen, die Geschwindigkeit zu messen. – ninehundred

1

Ich versuche, eine einfache Funktion mit Matplotlib-Modul, basierend auf Ihrer Eingabestruktur.Ich wünsche, es Ihre Frage etwas antworten konnte:

import matplotlib.pyplot as plt 

def color_segment(pc, col=[]): 
    n_segment = len(pc)-1 
    for i in range(0,n_segment): 
     if col: 
      c = col[i]  
      # I suppose the list col contains tuples for (r,g,b) color code for every segment. 
     else: 
      c = (float(i)/n_segment, 0.0, float(n_segment-i)/n_segment) 

     plt.plot([pc[i][0], pc[i+1][0]], [pc[i][1], pc[i+1][1]], color=c) 

    plt.show() 

polygon_coordinates = [ [5, 10], [7, 9], [8, 11], [11, 20] ] 
color_segment(polygon_coordinates) 

Das Bild, https://cdn.getdatajoy.com/gq2rp3/output.png

+0

Ich kann das ausprobieren, das sieht gut aus. – ninehundred

Verwandte Themen