javaimageopencvhighgui

Highgui class in OpenCV 3.4.0 Java API


I am learning OpenCV using Java and I wanted to create an application that reads an image from file and displays it on the screen. I've seen few threads here on Stackoverflow which say that Highgui class is not present in OpenCV 3.x, but it looks like in my case this class is implemented. For example I can use commands like this:

Highgui.setWindowTitle("EXAMPLE01", "Testing...");
Highgui.waitKeyEx();

Above displays empty window. However I still can't display any image in this window. When I run:

Highgui.imshow("EXAMPLE01", inputImage);

I get an error:

Error:(28, 16) java: cannot find symbol symbol: method imshow(java.lang.String,org.opencv.core.Mat) location: class org.opencv.highgui.Highgui

My questions are:

  1. Is Highgui back in OpenCV Java Api?
  2. How can I display an image using OpenCV Java?

Solution

  • I was facing same issue. Currently there is no imshow() method in new 3.4 (and 3.4.1) Highgui API. I found a little workaround, which is not what we want, but it at least displays OpenCV Mat in easy way. You could try:

    Highgui.selectROI(Imgcodecs.imread("img.jpg"));
    Highgui.waitKeyEx();
    

    The selectROI() method opens new JFrame window with desired image where you could select your region of interest, which is returned after window is closed. The trick is that you don't have to select any ROI and use it only as an image viewer.

    Currently the best way is still making your own conversion methods from Mat to BufferedImage or to Image(JavaFX) objects and then show custom window. I am currently using methods below for my own projects. Just to give you an idea. Hope it helps!

    public static BufferedImage convertMatToBufferedImage(Mat m){
        byte [] buffer = new byte[m.channels()*m.cols()*m.rows()];
        m.get(0, 0, buffer); 
        BufferedImage image = new BufferedImage(m.cols(), m.rows(), BufferedImage.TYPE_BYTE_GRAY);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);     
        return image;
    }
    
    public static Image convertMatToImage(Mat m) {
        if (m == null || m.width() == 0 || m.height() == 0) return null;
        Mat resultMat = m.clone();
        WritableImage image = new WritableImage(m.width(), m.height());
        byte[] data = new byte[m.cols() * m.rows() * 3]; // * 3 because Image needs 3 bytes per pixel even if grayscale
    
        if (resultMat.channels() == 1)
            Imgproc.cvtColor(resultMat, resultMat, Imgproc.COLOR_GRAY2RGB);
        else if (resultMat.channels() == 3)
            Imgproc.cvtColor(resultMat, resultMat, Imgproc.COLOR_BGR2RGB);
    
        resultMat.get(0, 0, data);
        image.getPixelWriter().setPixels(0, 0, m.width(), m.height(), PixelFormat.getByteRgbInstance(), data, 0, m.width() * 3);
        return image;
    }