Ask Your Question

Revision history [back]

In most of my tests the result was:

image description image description

Some code that I tried:

    import static org.bytedeco.javacpp.opencv_stitching.Stitcher;
    Mat pano = new Mat();
    Stitcher stitcher = Stitcher.createDefault(try_use_gpu);
    System.out.println("estimateTransform: " + stitcher.estimateTransform(imgs));
    int status = stitcher.stitch(imgs, pano);

and

    static public Mat stitch(Mat imgLeft, Mat imgRight) {
    Calendar timelog;

    Mat gray_imageLeft = new Mat();
    Mat gray_imageRight = new Mat();

    Imgproc.cvtColor(imgLeft, gray_imageLeft, Imgproc.COLOR_RGB2GRAY);
    Imgproc.cvtColor(imgRight, gray_imageRight, Imgproc.COLOR_RGB2GRAY);

    Imgproc.threshold(gray_imageLeft, gray_imageLeft, 60.0, 255.0, Imgproc.THRESH_BINARY);
    Imgproc.threshold(gray_imageRight, gray_imageRight, 60.0, 255.0, Imgproc.THRESH_BINARY);

    //Imgcodecs.imwrite("image_gray.png", gray_imageLeft);

    MatOfKeyPoint keyPointsLeft = new MatOfKeyPoint();
    MatOfKeyPoint keyPointsRight = new MatOfKeyPoint();
    Mat descriptorsLeft = new Mat();
    Mat descriptorsRight = new Mat();

    //ORB detector = ORB.create();
    AKAZE detector = AKAZE.create();

    int size = gray_imageRight.cols() / 2;

    timelog = Calendar.getInstance();
    detector.detect(gray_imageLeft, keyPointsLeft);
    ArrayList<KeyPoint> keyList = new ArrayList<>(keyPointsLeft.toList());
    keyList.removeIf(keyPoint -> keyPoint.pt.x < gray_imageLeft.cols() - size);
    keyPointsLeft.fromList(keyList);
    detector.compute(gray_imageLeft, keyPointsLeft, descriptorsLeft);
    log(timelog, "Detect imagem 1");

    timelog = Calendar.getInstance();
    detector.detect(gray_imageRight, keyPointsRight);
    keyList = new ArrayList<>(keyPointsRight.toList());
    keyList.removeIf(keyPoint -> keyPoint.pt.x > size);
    keyPointsRight.fromList(keyList);
    detector.compute(gray_imageRight, keyPointsRight, descriptorsRight);
    log(timelog, "Detect imagem 2");

    MatOfDMatch matches = new MatOfDMatch();

    BFMatcher matcher = BFMatcher.create();
    timelog = Calendar.getInstance();
    matcher.match(descriptorsLeft, descriptorsRight, matches);
    log(timelog, "Matching");

    timelog = Calendar.getInstance();
    List<DMatch> goods = matches.toList();
    goods.sort((o1, o2) -> Float.compare(o1.distance, o2.distance));
    goods = goods.subList(0, 500);
    log(timelog, "Sorting");

    System.out.println("keyPointsLeft: " + keyPointsLeft.elemSize() + "; matches: " + matches.size().height * matches.size().width + "; goods: " + goods.size());

    MatOfDMatch new_matches = new MatOfDMatch();
    new_matches.fromList(goods);

    timelog = Calendar.getInstance();
    Mat img_temp = new Mat(imgRight.rows(), imgRight.cols() + imgLeft.cols(), CvType.CV_32FC2);
    Features2d.drawMatches(imgLeft, keyPointsLeft, imgRight, keyPointsRight, new_matches, img_temp);
    Imgcodecs.imwrite("image_match.png", img_temp);
    log(timelog, "Drawing match");

    LinkedList<Point> imgPoints1List = new LinkedList<Point>();
    LinkedList<Point> imgPoints2List = new LinkedList<Point>();
    List<KeyPoint> keypointsRightList = keyPointsRight.toList();
    List<KeyPoint> keypointsLeftList = keyPointsLeft.toList();

    timelog = Calendar.getInstance();
    int i = 0;
    while (i < goods.size()) {
        DMatch good_matche = goods.get(i);
        imgPoints1List.addLast(keypointsRightList.get(good_matche.trainIdx).pt);
        imgPoints2List.addLast(keypointsLeftList.get(good_matche.queryIdx).pt);
        i++;
    }
    log(timelog, "Loading points");

    timelog = Calendar.getInstance();
    MatOfPoint2f obj = new MatOfPoint2f();
    obj.fromList(imgPoints1List);
    MatOfPoint2f scene = new MatOfPoint2f();
    scene.fromList(imgPoints2List);
    log(timelog, "Loading points (2)");

    timelog = Calendar.getInstance();
    Mat homography = Calib3d.findHomography(obj, scene, Calib3d.RANSAC, 3);
    Size newSize = new Size(imgRight.cols() + imgLeft.cols(), imgRight.rows());
    Mat img_matches = new Mat(newSize, CvType.CV_32FC2);
    log(timelog, "Homography");

    timelog = Calendar.getInstance();
    Imgproc.warpPerspective(imgRight, img_matches, homography, newSize);
    log(timelog, "WarpPerspective");

    timelog = Calendar.getInstance();
    Mat m = new Mat(img_matches, new Rect(0, 0, imgLeft.cols(), imgLeft.rows()));
    imgLeft.copyTo(m);
    log(timelog, "Copying");

    int offset = img_matches.cols()-1;
    int center1 = (img_matches.rows() / 2) + img_matches.rows() / 4;
    int center2 = img_matches.rows() / 2 - img_matches.rows() / 4;
    while (offset > 0) {
        if (img_matches.get(center1, offset)[0] > 0 && img_matches.get(center2, offset)[0] > 0) {
            break;
        }
        offset--;
    }

    return img_matches.submat(0, img_matches.rows(), 0, offset-10);
}

public static void main(String[] args) {
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    Calendar inicio = Calendar.getInstance();

    Mat img1 = Imgcodecs.imread("C:\\Users\\marcelo.SIMULA\\OneDrive\\Documentos\\Projetos\\WaveCounter\\opencv_seq1.png");
    Mat img2 = Imgcodecs.imread("C:\\Users\\marcelo.SIMULA\\OneDrive\\Documentos\\Projetos\\WaveCounter\\opencv_seq2.png");

    Mat img_matches = stitch(img1, img2);

    img2 = Imgcodecs.imread("C:\\Users\\marcelo.SIMULA\\OneDrive\\Documentos\\Projetos\\WaveCounter\\opencv_seq3.png");
    img_matches = stitch(img_matches, img2);

    img2 = Imgcodecs.imread("C:\\Users\\marcelo.SIMULA\\OneDrive\\Documentos\\Projetos\\WaveCounter\\opencv_seq4.png");
    img_matches = stitch(img_matches, img2);

    log(inicio, "---------FIM----------");

    Imgcodecs.imwrite("image_result.png", img_matches);
}