1 | initial version |
In most of my tests the result was:
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);
}