본문 바로가기
프로그래밍/OpenCV.

[OpenCV] 07.. OpenCV 빠른 매칭과 변환 행렬 추정(feat.JAVA)

by _Chavi 2020. 11. 2.

JAVA와 OpenCV를 이용하여 지난번에 추출한 SIFT Key Point를 가지고 빠른 매칭과 변환 행렬 추정을 진행하겠습니다.

 

빠른 매칭
public static void showLennaMatch() {
	try {
		String locGrayLennaOri = "경로생략/LennaGray.png";
		String locGrayLennaTun = "경로생략/LennaGrayTurn.png";
		Mat imageLennaOri = Imgcodecs.imread(locGrayLennaOri);
		Mat imageLennaTun = Imgcodecs.imread(locGrayLennaTun);
		
		MatOfKeyPoint keyPointOfLennaOri = new MatOfKeyPoint(), keyPointOfLennaTun = new MatOfKeyPoint();
		SIFT.create().detect(imageLennaOri, keyPointOfLennaOri);
		SIFT.create().detect(imageLennaTun, keyPointOfLennaTun);
		
		Mat keyPointLennaOri = new Mat(), keyPointLennaTun = new Mat();
		Features2d.drawKeypoints(imageLennaOri, keyPointOfLennaOri, keyPointLennaOri);
		Features2d.drawKeypoints(imageLennaTun, keyPointOfLennaTun, keyPointLennaTun);
		
		Mat descriptorsOri = new Mat(), descriptorsTun = new Mat();
		SIFT.create().compute(imageLennaOri, keyPointOfLennaOri, descriptorsOri);
		SIFT.create().compute(imageLennaTun, keyPointOfLennaTun, descriptorsTun);
		
		// Match
		DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
		MatOfDMatch matches = new MatOfDMatch();
		matcher.match(descriptorsOri, descriptorsTun, matches);
		
		double maxd = 0.0; double mind = 100.0;
		for (int index = 0; index < descriptorsOri.rows(); index++) {
			double dist = matches.toArray()[index].distance;
			if (dist<mind) mind=dist;
			if (dist>maxd) maxd=dist;
		}
		
		List<DMatch> aryGoodMatches= new ArrayList<DMatch>();
		MatOfDMatch goodMatches = new MatOfDMatch();
		for (int index = 0; index < descriptorsOri.rows(); index++) {
			if (matches.toArray()[index].distance <= Math.max(2*mind, 0.02)) aryGoodMatches.add(matches.toArray()[index]);
		}
		goodMatches.fromList(aryGoodMatches);
		
		Mat imageLennaMatch = new Mat();
		MatOfByte matchesMask = new MatOfByte();
		Features2d.drawMatches(imageLennaOri, keyPointOfLennaOri, imageLennaTun, keyPointOfLennaTun,
				goodMatches, imageLennaMatch, Scalar.all(-1), Scalar.all(-1), matchesMask, Features2d.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS);
		
		// Show
		HighGui.imshow("Match", imageLennaMatch);
		
		HighGui.waitKey();
		System.exit(0);
		
	} catch (Exception e) {
		e.printStackTrace();
	}
}

실행결과

 

변환 행렬 추정
public static void showLennaTransform() {
	try {
		String locGrayLennaOri = "경로생략/LennaGray.png";
		String locGrayLennaTun = "경로생략/LennaGrayTurn_1.png";
		Mat imageLennaOri = Imgcodecs.imread(locGrayLennaOri);
		Mat imageLennaTun = Imgcodecs.imread(locGrayLennaTun);
		
		MatOfKeyPoint keyPointOfLennaOri = new MatOfKeyPoint(), keyPointOfLennaTun = new MatOfKeyPoint();
		SIFT.create().detect(imageLennaOri, keyPointOfLennaOri);
		SIFT.create().detect(imageLennaTun, keyPointOfLennaTun);
		
		Mat keyPointLennaOri = new Mat(), keyPointLennaTun = new Mat();
		Features2d.drawKeypoints(imageLennaOri, keyPointOfLennaOri, keyPointLennaOri);
		Features2d.drawKeypoints(imageLennaTun, keyPointOfLennaTun, keyPointLennaTun);
		
		Mat descriptorsOri = new Mat(), descriptorsTun = new Mat();
		SIFT.create().compute(imageLennaOri, keyPointOfLennaOri, descriptorsOri);
		SIFT.create().compute(imageLennaTun, keyPointOfLennaTun, descriptorsTun);
		
		// Start Match
		DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
		MatOfDMatch matches = new MatOfDMatch();
		matcher.match(descriptorsOri, descriptorsTun, matches);
		
		double maxd = 0.0; double mind = 100.0;
		for (int index = 0; index < descriptorsOri.rows(); index++) {
			double dist = matches.toArray()[index].distance;
			if (dist<mind) mind=dist;
			if (dist>maxd) maxd=dist;
		}
		
		List<DMatch> aryGoodMatches = new ArrayList<DMatch>();
		MatOfDMatch goodMatches = new MatOfDMatch();
		for (int index = 0; index < descriptorsOri.rows(); index++) {
			if (matches.toArray()[index].distance <= Math.max(2*mind, 0.02)) aryGoodMatches.add(matches.toArray()[index]);
		}
		goodMatches.fromList(aryGoodMatches);
		
		Mat imageLennaMatch = new Mat();
		MatOfByte matchesMask = new MatOfByte();
		Features2d.drawMatches(imageLennaOri, keyPointOfLennaOri, imageLennaTun, keyPointOfLennaTun,
				goodMatches, imageLennaMatch, Scalar.all(-1), Scalar.all(-1), matchesMask, Features2d.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS);
		// End Match
		
		// Start Transform
		List<Point> aryModel_pt = new ArrayList<Point>(), aryScene_pt = new ArrayList<Point>();
		MatOfPoint2f model_pt = new MatOfPoint2f(), scene_pt = new MatOfPoint2f();
		for (int index = 0; index < aryGoodMatches.size(); index++) {
			aryModel_pt.add(keyPointOfLennaOri.toArray()[aryGoodMatches.get(index).queryIdx].pt);
			aryScene_pt.add(keyPointOfLennaTun.toArray()[aryGoodMatches.get(index).trainIdx].pt);
		}
		model_pt.fromList(aryModel_pt);
		scene_pt.fromList(aryScene_pt);
		
		Mat H = Calib3d.findHomography(model_pt, scene_pt, Calib3d.RANSAC);
		
		MatOfPoint2f model_corner = new MatOfPoint2f();
		List<Point> aryModel_corner = new ArrayList<Point>();
		aryModel_corner.add(new Point(0, 0));
		aryModel_corner.add(new Point(imageLennaTun.cols(), 0));
		aryModel_corner.add(new Point(imageLennaTun.cols(), imageLennaTun.rows()));
		aryModel_corner.add(new Point(0, imageLennaTun.rows()));
		model_corner.fromList(aryModel_corner);
		
		MatOfPoint2f scene_corner = new MatOfPoint2f();
		Core.perspectiveTransform(model_corner, scene_corner, H);
		
		Point p = new Point(imageLennaOri.cols(),0);
		scene_corner.toArray()[0].x =+ p.x;
		scene_corner.toArray()[0].y =+ p.y;
		scene_corner.toArray()[1].x =+ p.x;
		scene_corner.toArray()[1].y =+ p.y;
		scene_corner.toArray()[2].x =+ p.x;
		scene_corner.toArray()[2].y =+ p.y;
		scene_corner.toArray()[3].x =+ p.x;
		scene_corner.toArray()[3].y =+ p.y;
		Imgproc.line(imageLennaMatch, scene_corner.toArray()[0], scene_corner.toArray()[1], new Scalar(0, 0, 255), 3);
		Imgproc.line(imageLennaMatch, scene_corner.toArray()[1], scene_corner.toArray()[2], new Scalar(0, 0, 255), 3);
		Imgproc.line(imageLennaMatch, scene_corner.toArray()[2], scene_corner.toArray()[3], new Scalar(0, 0, 255), 3);
		Imgproc.line(imageLennaMatch, scene_corner.toArray()[3], scene_corner.toArray()[0], new Scalar(0, 0, 255), 3);
		// End Transform
		
		// Show
		HighGui.imshow("Transform", imageLennaMatch);
		
		HighGui.waitKey();
		System.exit(0);
		
	} catch (Exception e) {
		e.printStackTrace();
	}
}

실행결과

 

댓글