2013-02-14 12 views
6

Sto cercando di accedere a Pixel di Pixel di un IplImage. Sto usando Java e Processing, ea volte ho bisogno di accedere pixel per pixel. Ho fatto questo fino ad ora, ma io non so che cosa c'è che non va:IplImage Pixel Access JavaCV

public IplImage PImageToIplImage(PImage imageSrc) 
    { 
     IplImage imageDst; 
     if(imageSrc.format==RGB) 
     { 
      imageDst = IplImage.create(imageSrc.width, imageSrc.height, IPL_DEPTH_8U, 3); 
      ByteBuffer imagePixels=imageDst.getByteBuffer(); 
      int locPImage, locIplImage, x, y; 
      for(y=0; y<imageSrc.height; y++) 
       for(x=0; x<imageSrc.width; x++) 
       { 
        locPImage = x + y * width; 
        locIplImage=y*imageDst.widthStep()+3*x; 
        imagePixels.put(locIplImage+2, (byte)(red(imageSrc.pixels[locPImage]))); 
        imagePixels.put(locIplImage+1, (byte)(green(imageSrc.pixels[locPImage]))); 
        imagePixels.put(locIplImage, (byte)(blue(imageSrc.pixels[locPImage]))); 
       } 
     } 
} 

Dopo Karlphilip sugestion, sono arrivato a questo, ancora doens't lavoro. Quando provo a mostrare, mi dà un'eccezione nullpointer:

imageDst = IplImage.create(imageSrc.width, imageSrc.height, IPL_DEPTH_8U, 3); 
CvMat imagePixels = CvMat.createHeader(imageDst.height(), imageDst.width(), CV_32FC1); 
cvGetMat(imageDst, imagePixels, null, 0); 
int locPImage, x, y; 
for(y=0; y<imageSrc.height; y++) 
    for(x=0; x<imageSrc.width; x++) 
    { 
     locPImage = x + y * width; 
     CvScalar scalar = new CvScalar(); 
     scalar.setVal(0, red(imageSrc.pixels[locPImage])); 
     scalar.setVal(1, green(imageSrc.pixels[locPImage])); 
     scalar.setVal(2, blue(imageSrc.pixels[locPImage])); 
     cvSet2D(imagePixels, y, x, scalar); 
    } 
    imageDst = new IplImage(imagePixels); 
+0

Quale linea fa scattare l'eccezione? – karlphillip

risposta

7

Il modo più veloce per iterare su ogni pixel in JavaCV è:

ByteBuffer buffer = image.getByteBuffer(); 

for(int y = 0; y < image.height(); y++) { 
    for(int x = 0; x < image.width(); x++) { 
     int index = y * image.widthStep() + x * image.nChannels(); 

     // Used to read the pixel value - the 0xFF is needed to cast from 
     // an unsigned byte to an int. 
     int value = buffer.get(index) & 0xFF; 

     // Sets the pixel to a value (greyscale). 
     buffer.put(index, value); 

     // Sets the pixel to a value (RGB, stored in BGR order). 
     buffer.put(index, blue); 
     buffer.put(index + 1, green); 
     buffer.put(index + 2, red); 
    } 
} 
+0

Questo è quello che sto cercando di fare, ma non funziona (la lettura di un pixel va bene, ma la scrittura non lo è). Nell'esempio, come si inserisce un valore RGB? –

+0

Ho aggiunto un esempio RGB. – ajshort

+0

Grazie. Questo è esattamente quello che ho fatto, ma non funziona. Potete per favore guardare il codice qui sopra e vedere cosa sto sbagliando? È il primo codice. Grazie. –

1

Il seguente codice carica un'immagine dal disco ed esegue una conversione in scala di grigi per scorrere il pixel dell'immagine:

IplImage image = cvLoadImage("pipeline.png", CV_LOAD_IMAGE_COLOR); 
    if (image == null) 
    { 
     System.out.println("Erro ao carregar imagem!"); 
     return; 
    } 

    double r, g, b; 
    r = g = b = 0.0;  

    CvMat mtx = CvMat.createHeader(image.height(), image.width(), CV_32FC1); 
    cvGetMat(image, mtx, null, 0); 

    System.out.println(mtx.rows() + "x" + mtx.cols()); 

    for (int i = 0; i < mtx.rows(); i++) 
    { 
     for (int j = 0; j < mtx.cols(); j++) 
     { 
      CvScalar rgb = cvGet2D(mtx, i, j); 
      r = rgb.val(0); 
      g = rgb.val(2); 
      b = rgb.val(1); 

      double gray = (r + g + b)/3; 

      CvScalar scalar = new CvScalar(); 
      scalar.setVal(0, gray); 
      scalar.setVal(1, gray); 
      scalar.setVal(2, gray); 
      cvSet2D(mtx, i, j, scalar); 
     } 
    }   

    IplImage result = new IplImage(mtx); 
    cvSaveImage("manual_gray.png", result); 

    cvReleaseImage(image); 

Non sono sicuro che la creazione di un nuovo CvMat sia l'approccio migliore, ma è l'unico modo che conosco per funzionare in javacv.

EDIT:

Purtroppo si utilizza i tipi di dati che non sono da OpenCV, like PImage, ma ho fatto del mio meglio per simulare quello che state facendo.

// Create a black image 
    IplImage imageDst = IplImage.create(imageSrc.width(), imageSrc.height(), IPL_DEPTH_8U, 3); 

    // Create a temporary mat to iterate over it's pixels 
    CvMat imagePixels = CvMat.createHeader(imageDst.height(), imageDst.width(), CV_32FC1); 

    // Copy black image to temporary mat 
    cvGetMat(imageDst, imagePixels, null, 0); 

    int x, y; 
    for(y=0; y<imageSrc.height(); y++) 
     for(x=0; x<imageSrc.width(); x++) 
     { 
      // At this point you tried to do: locPImage = x + y * width; 
      // but I think you might have mistaken for: locPImage = y + x * width; 

      //... 
     } 
     imageDst = new IplImage(imagePixels); 
+0

Grazie mille. Ci proverò. Sono riuscito a leggere il valore usando un approccio simile come ho mostrato. Ci proverò più tardi, ma grazie in anticipo;) –

+0

Non c'è bisogno di ringraziamenti, puoi semplicemente votare la risposta :) – karlphillip

+0

L'ho provato, ma non funziona con me. L'immagine è nullo, non so come:/ –