javaCV+idea+gradle configuration tutorial

preface

This article is completely free!!!
This article is completely free!!!
This article is completely free!!!
Important things are said three times. All articles are paid for in their own research. Even if they are free, they only say general or a little, which is really disgusting.
This article is mainly about the installation and deployment environment, and does not involve specific development. The cases are mainly official and online.
Another: this method does not need to install openCV and other software, and should not be confused with the online joint deployment mode.
At present, I have just started research, and I will modify it from time to time according to my own research.

Required documents and download / reference locations

Currently known jar packages require:

  1. javaCV.jar and its related jar packages:
    a. Download my jar package: Click to jump: This is my own jar. If you want to follow it again, I suggest it
    b. Official free jar package download: Click jump : there are subsequent delivery and download methods, jar package differentiation of corresponding version and case download

jar package download instructions

  1. Download instructions:
    Lower versions can be pulled down, and each version has a corresponding detailed description

  2. Version Description:
    Each version of jar looks the same, but, but!!! It's as like as two peas. It's also a big pit I encountered. The jar just like that on the Internet is not enough. The compilation of the same batch is successful.

  3. Official website case: Click jump
    Later, we will introduce where to look at detailed cases of functions, including code implementation
    The following is a random cut. There are many jump and instructions of other documents in it. It is not very detailed, but it can basically find out a general idea. You can also study it slowly

    Can't understand English, use the translation plug-in, ha ha
    I use Firefox "translation web page", which is easy to use!!!

  4. Precautions for network cases:
    Different javaCV versions have different jar package reference paths, and even different methods and method names. Please be careful

Install and configure the required software

I mainly deal with pictures here, so it's openCV. If you deal with other processing, please configure it according to the actual situation

jar package configuration description

  1. Core jar: javacv jar,javacpp.jar, these two jars must have
  2. Function jar: OpenCV jar,ffmpeg.jar, etc. if you want to use the corresponding function, this kind of non suffix name must also have
  3. Environment jar: ffmpeg-linux-arm64 jar,ffmpeg-windows-x86_64.jar,opencv-linux-arm64.jar and opencv windows x86_ 64. Jar and other jar packages with system environment suffix. These jar packages are corresponding dll and so and other third-party library files. This package additionally introduces jar packages related to environment configuration according to its own running environment
  4. Other jar packages: openblas jar,openblas-windows-x86_64.jar, etc. I'm not very clear about these, but it's necessary according to DeBug, otherwise an error will be reported. According to different functions, it may be necessary to import other jars. For details, you can go to · jar package troubleshooting · check the missing package troubleshooting process

gradle introduction description

Directly introduce all jar packages, and maven is the same. It won't take good remedial courses. There are many online tutorials, so I won't introduce them in detail

Introduction of cases (official case location)

In the downloaded jar package, there is the samples folder. The following are all cases. You can directly drag them out to run the test. During the test, you need to see clearly the calling picture and the location of the modified picture. Many cases are thrown together directly. You can distinguish them manually
Error reporting processing will be introduced in the next item

jar package troubleshooting method

There are various errors reported during runtime, the most important of which is caused by the conflict or lack of jar packages. It is recommended to directly remove all jar packages and only introduce javacv Jar and javacpp Jar, and then run it. Generally, an error will be reported and the error reporting method will be entered (most of them are "TypeNotPresentExceptionProxy"). The entry method of idea: press Shift twice in a row, then enter "TypeNotPresentExceptionProxy", select "Class", click enter, click breakpoint, and then run to check the package path exception, and then import or adjust the jar package
I put the exception of the network case at the end

Case description

Here I use "Square.java" as an example (I won't continue to explain the problem of package Guide)

  • Process picture path
  • Handling specific functions
    – scan and draw squares
  • I'm afraid some students still can't find it. I put the code directly here
package com.xiaoma.test.samples;

import java.awt.event.KeyEvent;

import org.bytedeco.javacpp.*;
import org.bytedeco.javacv.*;

import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;

/**
 * I was unable to find the OpenCV squares.c translated into JavaCV, so this
 * is a line-by-line translation of the C source.
 * The squares.c source used, found here:
 *      https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/c/squares.c?rev=1429
 *
 * This is a demo class for finding squares/rectangles in an image, using JavaCV.
 *
 * All individual imports are kept as is; if you are like me,
 * you probably dislike the catch all .* import when trying to understand stuff.
 *
 * The major headache of the C code was figuring out the
 * "drawLines" method, and what parameters "cvPolyLine" is supposed to use.
 *
 * @author geir.ruud@digitalinferno.com
 */
public class Square {

    int thresh = 50;
    IplImage img = null;
    IplImage img0 = null;
    CvMemStorage storage = null;
    String wndname = "Square Detection Demo";

    // Java spesific
    CanvasFrame canvas = null;
    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();

    // helper function:
    // finds a cosine of angle between vectors
    // from pt0->pt1 and from pt0->pt2
    double angle(CvPoint pt1, CvPoint pt2, CvPoint pt0) {
        double dx1 = pt1.x() - pt0.x();
        double dy1 = pt1.y() - pt0.y();
        double dx2 = pt2.x() - pt0.x();
        double dy2 = pt2.y() - pt0.y();

        return (dx1*dx2 + dy1*dy2) / Math.sqrt((dx1*dx1 + dy1*dy1) * (dx2*dx2 + dy2*dy2) + 1e-10);
    }

    // returns sequence of squares detected on the image.
    // the sequence is stored in the specified memory storage
    CvSeq findSquares4(IplImage img, CvMemStorage storage) {
        // Java translation: moved into loop
        // CvSeq contours = new CvSeq();
        int i, c, l, N = 11;
        CvSize sz = cvSize(img.width() & -2, img.height() & -2);
        IplImage timg = cvCloneImage(img); // make a copy of input image
        IplImage gray = cvCreateImage(sz, 8, 1);
        IplImage pyr = cvCreateImage(cvSize(sz.width()/2, sz.height()/2), 8, 3);
        IplImage tgray = null;
        // Java translation: moved into loop
        // CvSeq result = null;
        // double s = 0.0, t = 0.0;

        // create empty sequence that will contain points -
        // 4 points per square (the square's vertices)
        CvSeq squares = cvCreateSeq(0, Loader.sizeof(CvSeq.class), Loader.sizeof(CvPoint.class), storage);

        // select the maximum ROI in the image
        // with the width and height divisible by 2
        cvSetImageROI(timg, cvRect(0, 0, sz.width(), sz.height()));

        // down-scale and upscale the image to filter out the noise
        cvPyrDown(timg, pyr, 7);
        cvPyrUp(pyr, timg, 7);
        tgray = cvCreateImage(sz, 8, 1);

        // find squares in every color plane of the image
        for (c = 0; c < 3; c++) {
            // extract the c-th color plane
            cvSetImageCOI(timg, c+1);
            cvCopy(timg, tgray);

            // try several threshold levels
            for (l = 0; l < N; l++) {
                // hack: use Canny instead of zero threshold level.
                // Canny helps to catch squares with gradient shading
                if (l == 0) {
                    // apply Canny. Take the upper threshold from slider
                    // and set the lower to 0 (which forces edges merging)
                    cvCanny(tgray, gray, 0, thresh, 5);
                    // dilate canny output to remove potential
                    // holes between edge segments
                    cvDilate(gray, gray, null, 1);
                } else {
                    // apply threshold if l!=0:
                    //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                    cvThreshold(tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY);
                }

                // find contours and store them all as a list
                // Java translation: moved into the loop
                CvSeq contours = new CvSeq();
                cvFindContours(gray, storage, contours, Loader.sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

                // test each contour
                while (contours != null && !contours.isNull()) {
                    // approximate contour with accuracy proportional
                    // to the contour perimeter
                    // Java translation: moved into the loop
                    CvSeq result = cvApproxPoly(contours, Loader.sizeof(CvContour.class), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0);
                    // square contours should have 4 vertices after approximation
                    // relatively large area (to filter out noisy contours)
                    // and be convex.
                    // Note: absolute value of an area is used because
                    // area may be positive or negative - in accordance with the
                    // contour orientation
                    if(result.total() == 4 && Math.abs(cvContourArea(result, CV_WHOLE_SEQ, 0)) > 1000 && cvCheckContourConvexity(result) != 0) {

                        // Java translation: moved into loop
                        double s = 0.0, t = 0.0;

                        for( i = 0; i < 5; i++ ) {
                            // find minimum angle between joint
                            // edges (maximum of cosine)
                            if( i >= 2 ) {
                                //      Java translation:
                                //          Comment from the HoughLines.java sample code:
                                //          "    Based on JavaCPP, the equivalent of the C code:
                                //                  CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
                                //                  CvPoint first=line[0];
                                //                  CvPoint second=line[1];
                                //          is:
                                //                  Pointer line = cvGetSeqElem(lines, i);
                                //                  CvPoint first = new CvPoint(line).position(0);
                                //                  CvPoint second = new CvPoint(line).position(1);
                                //          "
                                //          ... so after some trial and error this seem to work
//                                t = fabs(angle(
//                                        (CvPoint*)cvGetSeqElem( result, i ),
//                                        (CvPoint*)cvGetSeqElem( result, i-2 ),
//                                        (CvPoint*)cvGetSeqElem( result, i-1 )));
                                t = Math.abs(angle(new CvPoint(cvGetSeqElem(result, i)),
                                        new CvPoint(cvGetSeqElem(result, i-2)),
                                        new CvPoint(cvGetSeqElem(result, i-1))));
                                s = s > t ? s : t;
                            }
                        }

                        // if cosines of all angles are small
                        // (all angles are ~90 degree) then write quandrange
                        // vertices to resultant sequence
                        if (s < 0.3)
                            for( i = 0; i < 4; i++ ) {
                                cvSeqPush(squares, cvGetSeqElem(result, i));
                            }
                    }

                    // take the next contour
                    contours = contours.h_next();
                }
            }
        }

        // release all the temporary images
        cvReleaseImage(gray);
        cvReleaseImage(pyr);
        cvReleaseImage(tgray);
        cvReleaseImage(timg);

        return squares;
    }

    // the function draws all the squares in the image
    void drawSquares(IplImage img, CvSeq squares) {

        //      Java translation: Here the code is somewhat different from the C version.
        //      I was unable to get straight forward CvPoint[] arrays
        //      working with "reader" and the "CV_READ_SEQ_ELEM".

//        CvSeqReader reader = new CvSeqReader();

        IplImage cpy = cvCloneImage(img);
        int i = 0;

        // Used by attempt 3
        // Create a "super"-slice, consisting of the entire sequence of squares
        CvSlice slice = new CvSlice(squares);

        // initialize reader of the sequence
//        cvStartReadSeq(squares, reader, 0);

         // read 4 sequence elements at a time (all vertices of a square)
         for(i = 0; i < squares.total(); i += 4) {

//              // Attempt 1:
//              // This does not work, uses the "reader"
//              CvPoint pt[] = new CvPoint[]{new CvPoint(1), new CvPoint(1), new CvPoint(1), new CvPoint(1)};
//              PointerPointer rect = new PointerPointer(pt);
//              int count[] = new int[]{4};
//
//              CV_READ_SEQ_ELEM(pt[0], reader);
//              CV_READ_SEQ_ELEM(pt[1], reader);
//              CV_READ_SEQ_ELEM(pt[2], reader);
//              CV_READ_SEQ_ELEM(pt[3], reader);

//              // Attempt 2:
//              // This works, somewhat similar to the C code, somewhat messy, does not use the "reader"
//              CvPoint pt[] = new CvPoint[]{
//                      new CvPoint(cvGetSeqElem(squares, i)),
//                      new CvPoint(cvGetSeqElem(squares, i + 1)),
//                      new CvPoint(cvGetSeqElem(squares, i + 2)),
//                      new CvPoint(cvGetSeqElem(squares, i + 3))};
//              PointerPointer rect = new PointerPointer(pt);
//              int count[] = new int[]{4};

              // Attempt 3:
              // This works, may be the "cleanest" solution, does not use the "reader"
             CvPoint rect = new CvPoint(4);
             IntPointer count = new IntPointer(1).put(4);
             // get the 4 corner slice from the "super"-slice
             cvCvtSeqToArray(squares, rect, slice.start_index(i).end_index(i + 4));

//             // Attempt 4:
//             // This works, and look the most like the original C code, uses the "reader"
//             CvPoint rect = new CvPoint(4);
//             int count[] = new int[]{4};
//
//             // read 4 vertices
//             CV_READ_SEQ_ELEM(rect.position(0), reader);
//             CV_READ_SEQ_ELEM(rect.position(1), reader);
//             CV_READ_SEQ_ELEM(rect.position(2), reader);
//             CV_READ_SEQ_ELEM(rect.position(3), reader);

             // draw the square as a closed polyline
             // Java translation: gotcha (re-)setting the opening "position" of the CvPoint sequence thing
             cvPolyLine(cpy, rect.position(0), count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0);
         }

        // show the resultant image
        // cvShowImage(wndname, cpy);
        canvas.showImage(converter.convert(cpy));
        cvReleaseImage(cpy);
    }

    String names[] = new String[]{ "pic1.png", "pic2.png", "pic3.png",
                      "pic4.png", "pic5.png", "pic6.png" };

    public static void main(String args[]) throws Exception {
        new Square().main();
    }

    public void main() throws InterruptedException {
        // Java translation: c not used
        int i; // , c;
        // create memory storage that will contain all the dynamic data
        storage = cvCreateMemStorage(0);

        for(i = 0; i < names.length; i++) {
            // load i-th image

            // Java translation
            String filePathAndName = Square.class.getClassLoader().getResource(names[i]).getPath();
            filePathAndName = filePathAndName == null || filePathAndName.isEmpty() ? names[i] : filePathAndName;
            // img0 = cvLoadImage(names[i], 1);
            img0 = cvLoadImage(filePathAndName, 1);
            if (img0 == null) {
                System.err.println("Couldn't load " + names[i]);
                continue;
            }
            img = cvCloneImage(img0);

            // create window and a trackbar (slider) with parent "image" and set callback
            // (the slider regulates upper threshold, passed to Canny edge detector)
            // Java translation
            canvas = new CanvasFrame(wndname, 1);
            canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
            // cvNamedWindow( wndname, 1 );

            // find and draw the squares
            drawSquares(img, findSquares4(img, storage));

            // wait for key.
            // Also the function cvWaitKey takes care of event processing
            // Java translation
            KeyEvent key = canvas.waitKey(0);
            // c = cvWaitKey(0);

            // release both images
            cvReleaseImage(img);
            cvReleaseImage(img0);
            // clear memory storage - reset free space position
            cvClearMemStorage(storage);

            if (key.getKeyCode() == 27) {
                break;
            }
        }
        // cvDestroyWindow( wndname );
        if (canvas != null) {
            canvas.dispose();
        }
    }

}


Realization effect

Various other functions

Here refer to the statistics of other articles. There are many online. Just refer to the specific methods

Troubleshooting instructions for network cases

In fact, most online cases report errors, which are caused by inconsistent jar packages or abnormal method calls

  • Mat, mat and IplImage are confused
    – there are two kinds of Mat references. If the two references are inconsistent, all the later methods are different. It is easy to understand that although they are written in the same way, they are two sets of things

  • IplImage and Mat are also different
    – in some cases, both IplImage and Mat can directly use the image address to obtain files, just like the IplImage used in this article. At the same time, they can sometimes pass parameter values as an object
    – but they are not one object. Try not to use them at the same time. Of course, it may be a miracle to change them when testing or debugging code

  • Troubleshooting method
    – just turn to the original code here. Please detour for specific leaders. Just for those who can't teach below
    – for example, if you want to import Imgproc, but according to the package imported on the Internet, it shows that it does not exist. What should you do?

    There are generally two situations:
    1. The way of referencing packages has been changed or omitted
    Similar to opencv in this case_ Imgproc and opencv_ The core cannot find the package
    In fact, the processing method is very simple. Just delete it, just like the following

2. Position changed:
Enter a common type: for example, Mat, then press Ctrl + Click to enter the code, and click the upper left cornerFind the location of the code page. The directory on the left is the package it calls, and then look for it according to the previous path clues

That's it

This is the end. I hope you can solve the problem smoothly after reading my article, and then wish you a happy new year in advance!!!

Keywords: Java Gradle intellij-idea javacv

Added by ramma03 on Fri, 28 Jan 2022 19:18:14 +0200