2017-07-19 1 views
2

Ich versuche, die Mean Shift-Funktion von OpenCV in einem Programm namens Processing, eine Sprache auf Java basiert verwenden. Bisher weiß ich, dass die Funktion zwei Matts und zwei Double benötigt, [pyrMeanShiftFiltering (Mat, Mat, Double, Double)] und die Matte muss 8 Bit und 3 Kanäle haben. Aber wenn ich es leite, scheint es nur für das obere Viertel des Bildes zu funktionieren und schneidet den Rest aus.OpenCV PyrMeanShiftFilter in Verarbeitung - Probleme mit Matrix

Weiß jemand wie man diese Funktion bekommt, um auf dem ganzen Bild zu laufen?

Beispielbild: cat.jpg

import gab.opencv.*; 
import java.nio.*; 
import org.opencv.imgproc.Imgproc; 
import org.opencv.core.Mat; 
import org.opencv.core.CvType; 
import org.opencv.core.Core; 

OpenCV opencv; 
Imgproc imgproc; 

PImage canny; 
PImage src, out; 
Mat one, two; 
double a = 20.0; 
double b = 10.0; 

void setup() { 
    src = loadImage("cat.jpg"); 
    size(429, 360); 

    System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
    one = new Mat(width, height, CvType.CV_8UC3); 
    two = new Mat(width, height, CvType.CV_8UC3); 

    one = toMat(src); 
    imgproc.pyrMeanShiftFiltering(one, two, a, b); 
    out = toPImage(two); 
} 

void draw() { 
    image(out, 0, 0, width, height); 
} 

Mat toMat(PImage image) { 
    int w = image.width; 
    int h = image.height; 
    Mat mat = new Mat(h, w, CvType.CV_8UC3); 
    byte[] data8 = new byte[w*h*4]; 
    int[] data32 = new int[w*h]; 
    arrayCopy(image.pixels, data32); 
    ByteBuffer bBuf = ByteBuffer.allocate(w*h*4); 
    IntBuffer iBuf = bBuf.asIntBuffer(); 
    iBuf.put(data32); 
    bBuf.get(data8); 
    mat.put(0, 0, data8); 
    return mat; 
} 

PImage toPImage(Mat mat) { 
    int w = mat.width(); 
    int h = mat.height(); 
    PImage image = createImage(w, h, ARGB); 
    byte[] data8 = new byte[w*h*4]; 
    int[] data32 = new int[w*h]; 
    mat.get(0, 0, data8); 
    ByteBuffer.wrap(data8).asIntBuffer().get(data32); 
    arrayCopy(data32, image.pixels); 
    return image; 
} 

Antwort

0

Das Problem ist, dass Sie Zeilen verwenden, wo die Spalten sollten und Spalten, wo die Zeilen sein sollte. Überprüfen Sie die Mat documentation für weitere Informationen.

so, wann immer Sie haben diesen:

new Mat(width, height, CvType.CV_8UC3); 

Invertzucker den Auftrag

new Mat(height, width, CvType.CV_8UC3); 

Auch ich feststellen, dass Sie ein 4-Kanal-Bilder (ARGB) haben und die toMat Funktion hat auch 4 Kanäle , aber Sie erstellen eine Matte mit nur 3 CV_8UC3, sollten Sie 4 CV_8UC4 verwenden (nicht sicher in Java), und Vorsicht, normalerweise opencv verwendet ist BGRA !! daher müssen Sie die Kanäle möglicherweise richtig mischen.

Ich hoffe, das hilft Ihnen

+0

Wenn ich die Reihenfolge umkehren, ist das Bild verzerrt und immer noch an der Unterseite abgeschnitten. Für die Kanäle benötigt die Funktion einen 8 Bit und 3 Kanal und gibt mir einen Fehler, wenn ich 4 benutze. Weißt du, wie ich die toMat Funktion ändern könnte, so dass sie drei Kanäle haben? – Qwerty

+0

@Qwerty Der einfachste Weg (nicht unbedingt der effizienteste) wäre die Verwendung der Funktionen [split] (http://docs.opencv.org/java/2.4.2/org/opencv/core/Core.html#split) und [fusionieren] (http://docs.opencv.org/java/2.4.2/org/opencv/core/Core.html#merge) oder [mixChannels] (http://docs.opencv.org/java /2.4.2/org/opencv/core/Core.html#mixChannels). Split gibt dir jeden Kanal als Matte und dann können Joins oder Mix-Kanäle eine 3-Kanal-Matte mit den gewünschten erzeugen. Über die Breite und Höhe sollte es sich überall ändern – api55