title: Trying to get OpenCV to work in Java, sample code to stitch 2 photos together
body: <p>I'm trying to use OpenCV in Java.  I want to stitch 2 photos together.  OpenCV is a C++ library and it has a Java wrapper.</p>
  
  <ol>
  <li><p>I downloaded OpenCV Java with the pre-build Windows .dll's from the official site:  <a href="https://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.4.1/opencv-3.4.1-vc14_vc15.exe/download" rel="nofollow noreferrer">https://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.4.1/opencv-3.4.1-vc14_vc15.exe/download</a></p></li>
  <li><p>I'm using IntelliJ 2016.1.4</p></li>
  <li><p>I set up my project and pointed it to the relevant .jar</p></li>
  <li><p>I found code like you see below on the web.  </p></li>
  <li><p>It didn't work out of the box so I fixed a couple of things, e.g.:
      private static final int CV_RANSAC = 8; // This is just a guess!</p></li>
  <li><p>I ran it. It fails with the error:  "error: (-5) Specified descriptor extractor type is not supported"  on the line:              fe = DescriptorExtractor.create(DescriptorExtractor.SURF);  I </p></li>
  <li><p>I tried a bunch of alternative algoriths (ORB, SIFT, BRIEF) and got the same error.</p></li>
  </ol>
  
  <p>I'd like to get this code working.  Ideally I'd get working code which is not using a bunch of deprecated functions...the functions are deprecated but there's no comment saying what I should use instead...that always annoys me.</p>
  
  <p>(More generally I'd like any working Java sample code which can stitch together photos to form a panorama.)</p>
  
  <p>Can anyone help?</p>
  
  <pre><code>import org.opencv.calib3d.Calib3d;
  import org.opencv.core.*;
  import org.opencv.features2d.DescriptorExtractor;
  import org.opencv.features2d.DescriptorMatcher;
  import org.opencv.features2d.FeatureDetector;
  import org.opencv.features2d.Features2d;
  import org.opencv.imgproc.Imgproc;
  
  import java.util.LinkedList;
  import java.util.List;
  
  import static org.opencv.imgcodecs.Imgcodecs.imread;
  import static org.opencv.imgcodecs.Imgcodecs.imwrite;
  
  
  public class ImageStitching {
  
      static Mat image1;
      static Mat image2;
  
      static FeatureDetector fd;
      static DescriptorExtractor fe;
      static DescriptorMatcher fm;
  
  
      // Compulsory
      static{
          try {
              System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
          }
          catch (UnsatisfiedLinkError e) {
              throw new RuntimeException("Couldn't find \"" + Core.NATIVE_LIBRARY_NAME + ".dll .\n"
                      +"You need to add something like this to the run configuration \"VM options\":\n"
                      +"-Djava.library.path=C:\\OpenCvPreBuilt\\opencv\\build\\java\\x64");
          }
      }
  
  
      public static void go()
      {
          //new CvException("hello");
          fd = FeatureDetector.create(FeatureDetector.BRISK);
          fe = DescriptorExtractor.create(DescriptorExtractor.SURF);
          fm = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);
  
          //images
          image1 = imread("A.jpg");
          image2 = imread("B.jpg");
  
          //structures for the keypoints from the 2 images
          MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
          MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
  
          //structures for the computed descriptors
          Mat descriptors1 = new Mat();
          Mat descriptors2 = new Mat();
  
          //structure for the matches
          MatOfDMatch matches = new MatOfDMatch();
  
          //getting the keypoints
          fd.detect(image1, keypoints1);
          fd.detect(image1, keypoints2);
  
          //getting the descriptors from the keypoints
          fe.compute(image1, keypoints1, descriptors1);
          fe.compute(image2,keypoints2,descriptors2);
  
          //getting the matches the 2 sets of descriptors
          fm.match(descriptors2,descriptors1, matches);
  
          //turn the matches to a list
          List&lt;DMatch&gt; matchesList = matches.toList();
  
          Double maxDist = 0.0; //keep track of max distance from the matches
          Double minDist = 100.0; //keep track of min distance from the matches
  
          //calculate max &amp; min distances between keypoints
          for(int i=0; i&lt;keypoints1.rows();i++){
              Double dist = (double) matchesList.get(i).distance;
              if (dist&lt;minDist) minDist = dist;
              if(dist&gt;maxDist) maxDist=dist;
          }
  
          System.out.println("max dist: " + maxDist );
          System.out.println("min dist: " + minDist);
  
          //structure for the good matches
          LinkedList&lt;DMatch&gt; goodMatches = new LinkedList&lt;DMatch&gt;();
  
          //use only the good matches (i.e. whose distance is less than 3*min_dist)
          for(int i=0;i&lt;descriptors1.rows();i++){
              if(matchesList.get(i).distance&lt;3*minDist){
                  goodMatches.addLast(matchesList.get(i));
              }
          }
  
          //structures to hold points of the good matches (coordinates)
          LinkedList&lt;Point&gt; objList = new LinkedList&lt;Point&gt;(); // image1
          LinkedList&lt;Point&gt; sceneList = new LinkedList&lt;Point&gt;(); //image 2
  
          List&lt;KeyPoint&gt; keypoints_objectList = keypoints1.toList();
          List&lt;KeyPoint&gt; keypoints_sceneList = keypoints2.toList();
  
          //putting the points of the good matches into above structures
          for(int i = 0; i&lt;goodMatches.size(); i++){
              objList.addLast(keypoints_objectList.get(goodMatches.get(i).queryIdx).pt);
              sceneList.addLast(keypoints_sceneList.get(goodMatches.get(i).trainIdx).pt);
          }
  
          System.out.println("\nNum. of good matches" +goodMatches.size());
  
          MatOfDMatch gm = new MatOfDMatch();
          gm.fromList(goodMatches);
  
          //converting the points into the appropriate data structure
          MatOfPoint2f obj = new MatOfPoint2f();
          obj.fromList(objList);
  
          MatOfPoint2f scene = new MatOfPoint2f();
          scene.fromList(sceneList);
  
          //finding the homography matrix
          Mat H = Calib3d.findHomography(obj, scene, CV_RANSAC, 3);
  
          //LinkedList&lt;Point&gt; cornerList = new LinkedList&lt;Point&gt;();
          Mat obj_corners = new Mat(4,1,CvType.CV_32FC2);
          Mat scene_corners = new Mat(4,1,CvType.CV_32FC2);
  
          obj_corners.put(0,0, new double[]{0,0});
          obj_corners.put(0,0, new double[]{image1.cols(),0});
          obj_corners.put(0,0,new double[]{image1.cols(),image1.rows()});
          obj_corners.put(0,0,new double[]{0,image1.rows()});
  
          Core.perspectiveTransform(obj_corners, scene_corners, H);
  
          //structure to hold the result of the homography matrix
          Mat result = new Mat();
  
          //size of the new image - i.e. image 1 + image 2
          Size s = new Size(image1.cols()+image2.cols(),image1.rows());
  
          //using the homography matrix to warp the two images
          Imgproc.warpPerspective(image1, result, H, s);
          int i = image1.cols();
          Mat m = new Mat(result,new Rect(i,0,image2.cols(), image2.rows()));
  
          image2.copyTo(m);
  
          Mat img_mat = new Mat();
  
          Features2d.drawMatches(image1, keypoints1, image2, keypoints2, gm, img_mat, new Scalar(254,0,0),new Scalar(254,0,0) , new MatOfByte(), 2);
  
          //creating the output file
          boolean imageStitched = imwrite("imageStitched.jpg",result);
          boolean imageMatched = imwrite("imageMatched.jpg",img_mat);
      }
  
  
      public static void main(String args[])
      {
          go();
      }
  }
  </code></pre>