OpenCv Image-conversie

When trying to do the watershed method i got this error:Unsupported format or combination of formats (Only 32-bit, 1-channel output images are supported) in cvWatershed

Ik denk dat dit komt omdat mijn markers 3 kanalen en een diepte van 8 heeft. Ik denk dat ik deze 3-kanaals 8-diepteafbeelding moet converteren naar een 32-bits 1-kanaals afbeelding. Mijn vraag is dat ik gelijk heb? en hoe doe ik deze conversie?

EDIT: bijgewerkte code met oplossingen

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package kitouch;

import org.OpenNI.*;
import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.*;
import com.googlecode.javacv.cpp.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_calib3d.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import java.nio.ShortBuffer;
import java.awt.*;
import java.awt.image.*;

/**
 *
 * @author olivierjanssens
 */
public class watherShedExample {


  //CanvasFrame frame5 = new CanvasFrame("Some T");
    public static void main(String s[])
    {
    CanvasFrame frame1 = new CanvasFrame("Foreground");
    CanvasFrame frame2 = new CanvasFrame("Dilated");
    CanvasFrame frame3 = new CanvasFrame("Background");
    CanvasFrame frame4 = new CanvasFrame("Markers");
    CanvasFrame frame5 = new CanvasFrame("Watershed");
       //Read input image
    IplImage image = cvLoadImage("/Users/olivierjanssens/Downloads/images/group.jpg");
    IplImage test = cvLoadImage("/Users/olivierjanssens/Downloads/images/binary.bmp");

    IplImage binary = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
     cvCvtColor(test, binary, CV_BGR2GRAY);

   //Eliminate noise and smaller objects, repeat erosion 6 times
    IplImage fg = cvCreateImage(cvGetSize(binary), binary.depth(), binary.nChannels() /* channels */);
    cvErode(binary, fg, null /* 3x3 square */ , 6 /* iterations */);
    frame1.showImage(fg);


   //Identify image pixels pixels objects
    IplImage bg = cvCreateImage(cvGetSize(binary), binary.depth(), binary.nChannels() /* channels */);
    cvDilate(binary, bg, null /* 3x3 square */ , 6 /* iterations */);
    frame2.showImage(bg);

    cvThreshold(bg, bg, 1 /* threshold */ , 128 /* max value */ , CV_THRESH_BINARY_INV);
    frame3.showImage(bg);

   //Create marker image
    IplImage markers = cvCreateImage(cvGetSize(binary), IPL_DEPTH_8U, binary.nChannels() /* channels */);
    cvAdd(fg, bg, markers, null);
    frame4.showImage(markers);
/*
     * TEST SOLUTION 1
    IplImage gray = cvCreateImage(cvGetSize(markers), IPL_DEPTH_8U, 1); 
    cvCvtColor(markers, gray, CV_BGR2GRAY);

    IplImage img32bit1chan = cvCreateImage(cvGetSize(gray), IPL_DEPTH_32F, 1);

    double ve;
    for (int i = 0; i < gray.width(); i++)//markers width
    {
       for (int j = 0; j < gray.height(); j++)//markers height
       {
           ve = cvGetReal2D((IplImage)gray, j, i); 
           cvSetReal2D((IplImage)img32bit1chan , i, j, ve);
       }
    }
*/

    //SOLUTION 2 
    IplImage markers32f = cvCreateImage(cvGetSize(binary), IPL_DEPTH_32F, binary.nChannels());
    cvConvertScale(markers, markers32f, 1, 0);//converts from IPL_DEPTH_8U to IPL_DEPTH_32F


    cvWatershed(image, markers32f);

    frame5.showImage(image);

    }
}
2
Hoeveel kanalen afbeelding en binaire heeft?
toegevoegd de auteur karlphillip, de bron

2 antwoord

Ik ben niet bekend met de Java API, maar hier gaat het om hoe u het kunt doen:

IplImage image = cvLoadImage("/Users/olivierjanssens/Downloads/images/group.jpg");

// this will force the image to be read as grayscale (i.e. single channel)
// sometimes saving a "binary" bitmap will result in a 3 channel image
IplImage binary = cvLoadImage("/Users/olivierjanssens/Downloads/images/binary.bmp", 0);

...

IplImage markers = cvCreateImage(cvGetSize(binary), IPL_DEPTH_8U, binary.nChannels() /* channels */);
cvAdd(fg, bg, markers, null);
frame4.showImage(markers);

IplImage markers32f = cvCreateImage(cvGetSize(binary), IPL_DEPTH_32F, binary.nChannels());
cvConvertScale(markers, markers32f, 1, 0);//converts from IPL_DEPTH_8U to IPL_DEPTH_32F

cvWatershed(image, markers32f);

Kijk of dat voor jou werkt.

1
toegevoegd
Ik kreeg deze fout bij het converteren:: OpenCV Fout: Assertion failed (src.size == dst.size && src.channels() == dst.channels ()) in cvConvertScale, file /Users/olivierjanssens/source/OpenCV-2.3 .1/modules/core/src/& zwnj; convert.cpp, regel 1193 Uitzondering in thread "main" java.lang.RuntimeException: /Users/olivierjanssens/source/OpenCV-2.3.1/modules/core/src/&zwnj ; Convert.cpp: 1193: error: (-215) src.size == dst.size && src.channels() == dst.channels() in functie cvConvertScale op com.googlecode.javacv.cpp.opencv_core.cvConvertScale (Native methode) op kitouch.watherShedExample.main (watherShedExample.java:65)
toegevoegd de auteur Ojtwist, de bron
Wanneer ik de markers32f bekijk, heeft deze 32 bit en 1 kanaal. De afbeelding heeft 8 bits en 3 kanalen. Als ik de documentatie bekijk, is dit correct: seas.upenn.edu /~bensapp/opencvdocs/ref/opencvref_cv.htm . Maar ik krijg nog steeds de eerder genoemde foutmelding: S. Ik heb mijn code in de vraag bijgewerkt.
toegevoegd de auteur Ojtwist, de bron
Ik heb het opnieuw geprobeerd met de conversie naar grijswaarden. Dus dat deed ik: IplImage test = cvLoadImage ("/ Users/olivierjanssens/Downloads/images/binary. & Zwnj; bmp"); IplImage binary = cvCreateImage (cvGetSize (afbeelding), IPL_DEPTH_8U, 1); cvCvtColor (test, binair, CV_BGR2GRAY); aan het begin. Maar toch blijft de fout: 'Alleen 32-bits, 1-kanaals uitvoerafbeeldingen worden ondersteund) in de fout' cvWatershed '
toegevoegd de auteur Ojtwist, de bron
Binary heeft 3 kanalen en 8 bits, dus blijkbaar niet
toegevoegd de auteur Ojtwist, de bron
ja dat probeerde ik toen ik die fout kreeg
toegevoegd de auteur Ojtwist, de bron
@karlphillip Dat is wat ik ook vermoed :)
toegevoegd de auteur mevatron, de bron
En, u leest de binaire afbeelding in grijswaarden?
toegevoegd de auteur mevatron, de bron
Probeer alle binary.nChannels() te vervangen door 1 . Dit zorgt ervoor dat het aantal kanalen hetzelfde is.
toegevoegd de auteur mevatron, de bron
Dat betekent dat de grootte of het aantal kanalen verschillen tussen markers en markers32f . Wat zijn de formaten en het aantal kanalen van deze twee afbeeldingen op de regel cvConvertScale ?
toegevoegd de auteur mevatron, de bron
Hij is waarschijnlijk niet.
toegevoegd de auteur karlphillip, de bron

Een handmatige conversie ziet er ongeveer als volgt uit (heb de code niet getest):

IplImage gray = cvCreateImage(cvGetSize(markers), IPL_DEPTH_8U, 1); 
cvCvtColor(markers, gray, CV_BGR2GRAY);

IplImage img32bit1chan = cvCreateImage(cvGetSize(gray), IPL_DEPTH_32S, 1);

// convert 8-bit 1-channel image to 32-bit 1-channel
cvConvertScale(gray, img32bit1chan , 1/255.);

cvWatershed(image, img32bit1chan);
1
toegevoegd
Geen fouten meer. maar ik heb dit veranderd: cvConvertScale (grijs, img32bit1chan, 1/255,0); Ik verwachtte echter een andere output ... mijn beeld werd alleen maar helderder. Dat is alles
toegevoegd de auteur Ojtwist, de bron
Ik heb je bijgewerkte code geprobeerd, maar kreeg nog steeds een foutmelding: Uitzondering in thread "main" java.lang.RuntimeException: /Users/olivierjanssens/source/OpenCV-2.3.1/modules/core/src/‌ array.cpp: 1797: fout: (-211) index is buiten bereik in functie cvPtr2D op com.googlecode.javacv.cpp.opencv_core.cvSetReal2D (Native Method) op kitouch.watherShedExample.main (watherShedExample.java:75). Ik dacht dat dit zou werken tbh: p
toegevoegd de auteur Ojtwist, de bron
Oké, ik deed precies wat je zei (in de vraag voor je bevestiging bewerkt). Hoewel het de markeringen zijn die 32 bit 1 chan moeten zijn ... dus ik begrijp niet waarom ik dit met beeld doe: S.
toegevoegd de auteur Ojtwist, de bron
Ik heb geprobeerd het gekleurde beeld in grijs te converteren. Maar de mat32bit1chan heeft diepte 5 en ik kan de nkanalen niet zien. Ik heb de code toegevoegd die je aan de vraag hebt voorgesteld. Misschien kun je er een fout in zien? (Btw het is de marker die 32bit 1chan moet zijn, hoewel het ook een 8 bit 3 chan-afbeelding is, dus er verandert niets.)
toegevoegd de auteur Ojtwist, de bron
Hallo, er is een probleem. cvGetReal2D ondersteunt alleen enkelkanaals arrays. En de afbeelding heeft 3 kanalen.
toegevoegd de auteur Ojtwist, de bron
Bijgewerkte code, kijk eens of dit nu zinvol is.
toegevoegd de auteur karlphillip, de bron
Laatste update. Vertel me als dat werkt.
toegevoegd de auteur karlphillip, de bron
Nou, de fout die in je vraag staat, is opgelost. Nu heb je nog een probleem om mee om te gaan, veel succes.
toegevoegd de auteur karlphillip, de bron