Android中的OpenCV图像比较和相似性

我是OpenCV学习者。 我正在尝试图像比较。 我已经使用OpenCV 2.4.13.3我有这两个图像1.jpgcam1.jpg

在这里输入图像说明 在这里输入图像说明

当我在openCV中使用下面的命令

 File sdCard = Environment.getExternalStorageDirectory(); String path1, path2; path1 = sdCard.getAbsolutePath() + "/1.jpg"; path2 = sdCard.getAbsolutePath() + "/cam1.jpg"; FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB); DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRIEF); DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); Mat img1 = Highgui.imread(path1); Mat img2 = Highgui.imread(path2); Mat descriptors1 = new Mat(); MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); detector.detect(img1, keypoints1); extractor.compute(img1, keypoints1, descriptors1); //second image // Mat img2 = Imgcodecs.imread(path2); Mat descriptors2 = new Mat(); MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); detector.detect(img2, keypoints2); extractor.compute(img2, keypoints2, descriptors2); //matcher image descriptors MatOfDMatch matches = new MatOfDMatch(); matcher.match(descriptors1,descriptors2,matches); // Filter matches by distance MatOfDMatch filtered = filterMatchesByDistance(matches); int total = (int) matches.size().height; int Match= (int) filtered.size().height; Log.d("LOG", "total:" + total + " Match:"+Match); 

方法filterMatchesByDistance

  static MatOfDMatch filterMatchesByDistance(MatOfDMatch matches){ List<DMatch> matches_original = matches.toList(); List<DMatch> matches_filtered = new ArrayList<DMatch>(); int DIST_LIMIT = 30; // Check all the matches distance and if it passes add to list of filtered matches Log.d("DISTFILTER", "ORG SIZE:" + matches_original.size() + ""); for (int i = 0; i < matches_original.size(); i++) { DMatch d = matches_original.get(i); if (Math.abs(d.distance) <= DIST_LIMIT) { matches_filtered.add(d); } } Log.d("DISTFILTER", "FIL SIZE:" + matches_filtered.size() + ""); MatOfDMatch mat = new MatOfDMatch(); mat.fromList(matches_filtered); return mat; } 

日志

 total:122 Match:30 

从日志匹配中我们可以看到30。
但是,我们可以看到两个图像具有相同的视觉元素(in)。
如何使用openCV获得match = 90?
如果有人可以帮助使用代码片段,这将是非常好的。
如果使用opencv这是不可能的,那么我们可以find的其他select是什么?

Solutions Collecting From Web of "Android中的OpenCV图像比较和相似性"

但是,我们可以看到两个图像具有相同的视觉元素(in)。

所以,我们应该比较不是整个图像,而是“相同的视觉元素”。 如果您不比较“模板”和“相机”图像本身,而是以相同方式处理(例如,转换为二进制黑色/白色)“模板”和“相机”图像,则可以提高Match值。 例如,尝试在两个(“模板”和“照相机”)图像上find蓝色(模板标志的背景)正方形,并比较该正方形(感兴趣区域)。 代码可能是这样的:

 Bitmap bmImageTemplate = <get your template image Bitmap>; Bitmap bmTemplate = findLogo(bmImageTemplate); // process template image Bitmap bmImage = <get your camera image Bitmap>; Bitmap bmLogo = findLogo(bmImage); // process camera image same way compareBitmaps(bmTemplate, bmLogo); 

哪里

 private Bitmap findLogo(Bitmap sourceBitmap) { Bitmap roiBitmap = null; Mat sourceMat = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3); Utils.bitmapToMat(sourceBitmap, sourceMat); Mat roiTmp = sourceMat.clone(); final Mat hsvMat = new Mat(); sourceMat.copyTo(hsvMat); // convert mat to HSV format for Core.inRange() Imgproc.cvtColor(hsvMat, hsvMat, Imgproc.COLOR_RGB2HSV); Scalar lowerb = new Scalar(85, 50, 40); // lower color border for BLUE Scalar upperb = new Scalar(135, 255, 255); // upper color border for BLUE Core.inRange(hsvMat, lowerb, upperb, roiTmp); // select only blue pixels // find contours List<MatOfPoint> contours = new ArrayList<>(); List<Rect> squares = new ArrayList<>(); Imgproc.findContours(roiTmp, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); // find appropriate bounding rectangles for (MatOfPoint contour : contours) { MatOfPoint2f areaPoints = new MatOfPoint2f(contour.toArray()); RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints); double rectangleArea = boundingRect.size.area(); // test min ROI area in pixels if (rectangleArea > 400) { Point rotated_rect_points[] = new Point[4]; boundingRect.points(rotated_rect_points); Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points)); double aspectRatio = rect.width > rect.height ? (double) rect.height / (double) rect.width : (double) rect.width / (double) rect.height; if (aspectRatio >= 0.9) { squares.add(rect); } } } Mat logoMat = extractSquareMat(roiTmp, getBiggestSquare(squares)); roiBitmap = Bitmap.createBitmap(logoMat.cols(), logoMat.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(logoMat, roiBitmap); return roiBitmap; } 

方法extractSquareMat() )从整个图像中提取感兴趣的区域(标识)

 public static Mat extractSquareMat(Mat sourceMat, Rect rect) { Mat squareMat = null; int padding = 50; if (rect != null) { Rect truncatedRect = new Rect((int) rect.tl().x + padding, (int) rect.tl().y + padding, rect.width - 2 * padding, rect.height - 2 * padding); squareMat = new Mat(sourceMat, truncatedRect); } return squareMat ; } 

compareBitmaps()只是包装你的代码:

 private void compareBitmaps(Bitmap bitmap1, Bitmap bitmap2) { Mat mat1 = new Mat(bitmap1.getWidth(), bitmap1.getHeight(), CvType.CV_8UC3); Utils.bitmapToMat(bitmap1, mat1); Mat mat2 = new Mat(bitmap2.getWidth(), bitmap2.getHeight(), CvType.CV_8UC3); Utils.bitmapToMat(bitmap2, mat2); compareMats(mat1, mat2); } 

你的代码作为方法:

 private void compareMats(Mat img1, Mat img2) { FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB); DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRIEF); DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); Mat descriptors1 = new Mat(); MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); detector.detect(img1, keypoints1); extractor.compute(img1, keypoints1, descriptors1); //second image // Mat img2 = Imgcodecs.imread(path2); Mat descriptors2 = new Mat(); MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); detector.detect(img2, keypoints2); extractor.compute(img2, keypoints2, descriptors2); //matcher image descriptors MatOfDMatch matches = new MatOfDMatch(); matcher.match(descriptors1,descriptors2,matches); // Filter matches by distance MatOfDMatch filtered = filterMatchesByDistance(matches); int total = (int) matches.size().height; int Match= (int) filtered.size().height; Log.d("LOG", "total:" + total + " Match:" + Match); } static MatOfDMatch filterMatchesByDistance(MatOfDMatch matches){ List<DMatch> matches_original = matches.toList(); List<DMatch> matches_filtered = new ArrayList<DMatch>(); int DIST_LIMIT = 30; // Check all the matches distance and if it passes add to list of filtered matches Log.d("DISTFILTER", "ORG SIZE:" + matches_original.size() + ""); for (int i = 0; i < matches_original.size(); i++) { DMatch d = matches_original.get(i); if (Math.abs(d.distance) <= DIST_LIMIT) { matches_filtered.add(d); } } Log.d("DISTFILTER", "FIL SIZE:" + matches_filtered.size() + ""); MatOfDMatch mat = new MatOfDMatch(); mat.fromList(matches_filtered); return mat; } 

结果从您的问题结果保存resize(缩放为50%)的图像是:

 D/DISTFILTER: ORG SIZE:237 D/DISTFILTER: FIL SIZE:230 D/LOG: total:237 Match:230 

NB! 这是一个快速和肮脏的例子,只是为了给出模板的演示方​​法。