テスト ケースの 1 つで動作する Android 用の OpenCV を使用して Image Alignment を実装しようとしましたが、別のテスト ケースでは動作しませんでした。
テスト ケース #1 - 私のコードが機能した場合:
たとえばScene ImageとObject Imageのような 2 つの画像が与えられた場合、
出力オブジェクトの画像をシーンの画像に揃えたい。最終出力を確認してください。
テスト ケース #2 - 私のコードが機能しなかった場合:
この機能マッチング結果と、これを warpPerspective への出力として取得しました。
私の質問は、2 番目のテスト ケースで画像を整列できない理由を教えてください。
Mat mObjectMat = new Mat();
Mat mSceneMat = new Mat();
Mat img3 = mSceneMat.clone();
//Bitmap to Mat
Utils.bitmapToMat(inputImage2, mObjectMat);
Utils.bitmapToMat(inputImage1, mSceneMat);
//rgb to gray
Imgproc.cvtColor(mObjectMat, mObjectMat, Imgproc.COLOR_RGBA2GRAY);
Imgproc.cvtColor(mSceneMat, mSceneMat, Imgproc.COLOR_RGBA2GRAY);
//find interest points/keypoints in an image
MatOfKeyPoint keypoints_object = new MatOfKeyPoint();
MatOfKeyPoint keypoints_scene = new MatOfKeyPoint();
FeatureDetector fd = FeatureDetector.create(FeatureDetector.ORB);
fd.detect(mObjectMat, keypoints_object);
fd.detect(mSceneMat, keypoints_scene);
//extract descriptor
Mat descriptors_object = new Mat();
Mat descriptors_scene = new Mat();
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
extractor.compute(mObjectMat, keypoints_object, descriptors_object);
extractor.compute(mSceneMat, keypoints_scene, descriptors_scene);
//match keypoint descriptors
MatOfDMatch matches = new MatOfDMatch();
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
matcher.match( descriptors_object, descriptors_scene, matches);
List<DMatch> matchesList = matches.toList();
//Calculate max and min distances between keypoints
matchesList = matches.toList();
Double maxDistance = 0.0;
Double minDistance = 100.0;
for( int i = 0; i < descriptors_object.rows(); i++ )
{
Double dist = (double) matchesList.get(i).distance;
if( dist < minDistance ) minDistance = dist;
if( dist > maxDistance ) maxDistance = dist;
}
//display
Toast.makeText(getApplicationContext(), "[ Max dist : " + maxDistance + " ] [ Min dist : " + minDistance + " ]", Toast.LENGTH_LONG).show();
//find good matches
LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
MatOfDMatch gm = new MatOfDMatch();
//Draw only good matches
for(int i = 0; i < descriptors_object.rows(); i++){
if(matchesList.get(i).distance < 3*minDistance){
good_matches.addLast(matchesList.get(i));
}
}
gm.fromList(good_matches);
//display matches on imageView
Mat opt = new Mat();
Scalar RED = new Scalar(255,0,0);
Scalar GREEN = new Scalar(0,255,0);
MatOfByte drawnMatches = new MatOfByte();
Features2d.drawMatches(mObjectMat,keypoints_object,mSceneMat,keypoints_scene,gm,opt,GREEN, RED, drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);
List<KeyPoint> keypoints_objectList = keypoints_object.toList();
List<KeyPoint> keypoints_sceneList = keypoints_scene.toList();
LinkedList<Point> objList = new LinkedList<Point>();
LinkedList<Point> sceneList = new LinkedList<Point>();
MatOfPoint2f obj = new MatOfPoint2f();
MatOfPoint2f scene = new MatOfPoint2f();
//Localize the object & find the keypoints from the good matches
//separate corresponding points for both images
for(int i = 0; i<good_matches.size(); i++){
objList.addLast(keypoints_objectList.get(good_matches.get(i).queryIdx).pt);
sceneList.addLast(keypoints_sceneList.get(good_matches.get(i).trainIdx).pt);
}
obj.fromList(objList);
scene.fromList(sceneList);
//Find homography - perspective transformation between two planes
Mat H = Calib3d.findHomography(obj, scene, Calib3d.RANSAC);
//perform perspective warp
Mat imgWarped = new Mat();
Imgproc.warpPerspective(mObjectMat, imgWarped, H, mSceneMat.size());
//warp and scene images
Mat finalImage = new Mat();
Core.add(mSceneMat, imgWarped,finalImage);
//add image to imageView
Bitmap imageMatched = Bitmap.createBitmap(finalImage.cols(), finalImage.rows(), Bitmap.Config.RGB_565);//need to save bitmap
Utils.matToBitmap(finalImage, imageMatched);
imageView1.setImageBitmap(imageMatched);