2017-07-19 4 views
2

J'essaie d'utiliser la fonction de décalage moyen d'OpenCV dans un programme appelé Processing, qui est un langage basé sur Java. Jusqu'à présent, je sais que la fonction nécessite deux mat et deux doubles, [pyrMeanShiftFiltering (Mat, Mat, Double, Double)] et le tapis doit être de 8 bits et 3 canaux. Mais, quand je l'exécute, cela ne semble fonctionner que pour les 3/4 supérieurs de l'image et coupe le reste.OpenCV pyrMeanShiftFilter en cours de traitement - problèmes avec la matrice

Est-ce que quelqu'un sait comment faire fonctionner cette fonction sur toute l'image?

image échantillon: 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; 
} 

Répondre

0

Le problème est que vous utilisez les lignes où les colonnes doivent être et des colonnes où les lignes doivent être. Vérifiez le Mat documentation pour plus d'informations.

donc, chaque fois que vous avez ceci:

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

Inverser l'ordre

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

, je remarque aussi que vous avez une image 4 canaux (ARGB) et la fonction toMat également 4 canaux , mais vous créez un tapis avec seulement 3 CV_8UC3, vous devez utiliser 4 CV_8UC4 (pas sûr en java), et méfiez-vous, normalement les utilisations d'opencv est BGRA !! Vous devrez peut-être mélanger correctement les canaux.

+0

Lorsque j'inverse la commande, l'image est déformée et toujours coupée en bas. Pour les canaux, la fonction nécessite un 8 bits et 3 canaux et me donne une erreur si j'utilise 4. Savez-vous comment je pourrais changer la fonction toMat afin qu'ils aient trois canaux? – Qwerty

+0

@Qwerty le moyen le plus simple (pas nécessairement le plus efficace) serait d'utiliser les fonctions [split] (http://docs.opencv.org/java/2.4.2/org/opencv/core/Core.html#split) et [fusionner] (http://docs.opencv.org/java/2.4.2/org/opencv/core/Core.html#merge) ou [mixChannels] (http://docs.opencv.org/java /2.4.2/org/opencv/core/Core.html#mixChannels). Split vous donnera chaque canal comme un tapis, puis rejoindre ou mélanger les canaux peuvent créer un tapis 3 canaux avec ceux que vous voulez. A propos de la largeur et la hauteur, il devrait être changer partout – api55