2017-03-22 3 views
11

anzuwenden Ich versuche, die folgende Python-Funktion zu übersetzen, die eine Maske auf ein Bild bezieht, in Java:Übersetzen Python Funktion Maske Bild in Java

# Applies an image mask. 
def region_of_interest(img, vertices): 
    #defining a blank mask to start with 
    mask = np.zeros_like(img) 

    #defining a 3 channel or 1 channel color to fill the mask with depending on the input image 
    if len(img.shape) > 2: 
     channel_count = img.shape[2] # i.e. 3 or 4 depending on your image 
     ignore_mask_color = (255,) * channel_count 
    else: 
     ignore_mask_color = 255 

    #filling pixels inside the polygon defined by "vertices" with the fill color  
    cv2.fillPoly(mask, vertices, ignore_mask_color) 

    #returning the image only where mask pixels are nonzero 
    masked_image = cv2.bitwise_and(img, mask) 
    return masked_image 

Bisher ist dies, was ich habe:

public static opencv_core.Mat applyMask(opencv_core.Mat image, opencv_core.MatVector vertices) { 
    opencv_core.Mat mask = opencv_core.Mat.zeros(image.size(), opencv_core.CV_8U).asMat(); 

    opencv_core.Scalar color = new opencv_core.Scalar(image.channels()); // 3 
    double[] colors = new double[] { 
    255.0, 255.0, 255.0, 255.0, 
    255.0, 255.0, 255.0, 255.0, 
    255.0, 255.0, 255.0, 255.0}; 
    color.put(colors, 0, colors.length); 

    opencv_imgproc.fillPoly(mask, vertices, color); 

    opencv_core.Mat dst = new opencv_core.Mat(); 
    opencv_core.bitwise_and(image, mask, dst); 
    return dst; 
} 

Aber es funktioniert nicht. Beim Versuch, diese Methode aufgerufen wird, wie im folgenden Beispiel:

opencv_core.MatVector points = new opencv_core.MatVector(
    new opencv_core.Mat(2, 3, opencv_core.CV_32F, new IntPointer(1, 2, 3, 4, 5, 6)) 
); 

opencv_core.MatVector vertices = new opencv_core.MatVector(points); 
opencv_core.Mat masked = LaneManager.applyMask(src, vertices); 

(Ich gehe davon aus das der richtige Weg ist es, eine 2x3-Matrix von drei Punkten mit zwei Koordinaten jedes (1,2), (3, 4) und (5,6) zu bauen)

ich erhalte eine Ausnahme:

java.lang.RuntimeException: std::bad_alloc 
at org.bytedeco.javacpp.opencv_imgproc.fillPoly(Native Method) 

ich bin mit OpenCV wie org.bytedeco.javacpp-presets:opencv-platform:3.2.0-1.3 über Maven Zentrale zur Verfügung gestellt.

Ich muss zugeben, dass ich hier ratlos bin: Was ist die idiomatische Java-Art, das Gleiche wie die obige Python-Funktion zu machen?

+0

Ich denke, was Sie suchen, ist mit diesem anderen Stackoverflow Post http: // Stackoverflow verwandt.com/questions/221830/set-bufferedimage-alpha-maske-in-java. Hoffe, das kann helfen. –

+0

Wie initialisierst du die src-Variable, die du an applyMask sendest? – Daedalus

+0

Eine verdächtige Sache ist, dass Sie offenbar eine Farbe für ein 3-Kanal-Bild mit 12 Farbkomponenten definieren. Das kann nicht stimmen. – Dave

Antwort

1

Vielleicht hat irgendein whiz die vollständigen Antworten. Hier ist Stoff zum Nachdenken:

  1. Die Java-API ist eine direkte Kopie der CPP API: http://opencv.org/opencv-java-api.html
  2. Der Fehler tritt auf, wenn std::bad_alloc Sie nicht benötigte Speicherplatz zuzuweisen. (http://answers.opencv.org/question/28959/cascade-training-killed-and-bad_alloc/)

  3. Es gibt zwei CPP Methoden:
  4. Sie brauchen nicht von Mat zu konvertieren InputArray, aber Sie können (und sollten) nur ein Mat Objekt übergeben, wo ein InputArray angefordert (https://stackoverflow.com/a/32976883/1587329)

+0

Danke, dass Sie sich das angeschaut haben, aber das hilft nicht. Keine der 'fillPoly'-Methoden, die auf der Java-Seite verfügbar sind, nehmen ein' InputArray'. Sie nehmen entweder eine "Mat" oder eine "UMat". Ich denke, mein Problem besteht eher darin, die Liste der Punkte nicht richtig zu definieren. Zum Beispiel wäre es hilfreich, wenn Sie mir ein Beispiel geben könnten, wie man das Punkteargument mit beispielsweise einer Liste von 4 Punkten mit je 2 Koordinaten erstellt. – zugaldia

+0

@zugaldia: Vielen Dank für das Feedback. Haben Sie Speicheroptionen versucht, um die Größe des Heapspeichers zu erhöhen, wie z. '-Xmx512m'? –

+0

Ja. Ich glaube, sie geben an, dass ich die Methode 'public static native void fillPoly (Mat blackImg, MatVector points, Scalar whiteColor) verwenden möchte;' aber ich definiere 'MatVector points' nicht richtig. Wie würde ich einen neuen 'MatVector' für diesen Anwendungsfall erstellen? – zugaldia

1

Okay, ich dachte, es endlich heraus. Wenn Sie Ihre Koordinaten mit definieren:

int[] points = new int[] {x1, y1, x2, y2, ...}; 

Dann können Sie einfach eine Maske mit dem folgenden Code anwenden:

opencv_core.Mat mask = new opencv_core.Mat(image.size(), image.type()); 

// Array of polygons where each polygon is represented as an array of points 
opencv_core.Point polygon = new opencv_core.Point(); 
polygon.put(points, 0, points.length); 
opencv_imgproc.fillPoly(mask, polygon, new int[] {points.length/2}, 1, new opencv_core.Scalar(255, 255, 255, 0)); 

opencv_core.Mat masked = new opencv_core.Mat(image.size(), image.type()); 
opencv_core.bitwise_and(image, mask, masked); 

Wo image das Originalbild ist, und masked das maskierte Ergebnis.

Das Problem war, dass die ursprüngliche Liste der Punkte nicht richtig definiert wurde.

Verwandte Themen