类 DescriptorExtractor 在适用于 Android 的 opencv 4.1.0 中不可用
Posted
技术标签:
【中文标题】类 DescriptorExtractor 在适用于 Android 的 opencv 4.1.0 中不可用【英文标题】:Class DescriptorExtractor not available in opencv 4.1.0 for Android 【发布时间】:2019-09-12 14:32:20 【问题描述】:我是 openCV 的新手,我正在处理一些旨在使用 openCV 3 的文档,我正在编写一个使用 org.opencv.features2d.DescriptorExtractor
类的过滤器,但是,该类在 openCV 4.1.0 中不可用。
我需要使用 openCV 4.1.0 中的现有类来实现相同的目标,因为我无法使用 DescriptorExtractor
。
该应用程序可以识别某些任意的矩形图像,例如绘画,并确定它们在 2D 投影中的姿势。当跟踪图像出现在摄像头供稿中时,该应用会在其周围绘制轮廓。
这是使用缺失类的代码部分:
public final class ImageDetectionFilter
// Not relevant section...
// A descriptor extractor, which creates descriptors of features.
private final DescriptorExtractor mDescriptorExtractor =
DescriptorExtractor.create(DescriptorExtractor.ORB);
public ImageDetectionFilter(final Context context,
final int referenceImageResourceID) throws IOException
// Not relevant section...
// Detect the reference features and compute their descriptors.
mFeatureDetector.detect(referenceImageGray, mReferenceKeypoints);
mDescriptorExtractor.compute(referenceImageGray, mReferenceKeypoints, mReferenceDescriptors);
@Override
public void apply(final Mat src, final Mat dst)
// ...
// Detect the scene features, compute their descriptors,
// and match the scene descriptors to reference descriptors.
mFeatureDetector.detect(mGraySrc, mSceneKeypoints);
mDescriptorExtractor.compute(mGraySrc, mSceneKeypoints, mSceneDescriptors);
mDescriptorMatcher.match(mSceneDescriptors, mReferenceDescriptors, mMatches);
//...
这是完整的课程,以防万一:
package com.sample.opencv.filters;
import android.content.Context;
import org.opencv.android.Utils;
import org.opencv.calib3d.Calib3d;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
import org.opencv.core.Mat;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.features2d.DescriptorExtractor;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.ORB;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public final class ImageDetectionFilter implements Filter
// The reference image (this detector's target).
private final Mat mReferenceImage;
// Features of the reference image.
private final MatOfKeyPoint mReferenceKeypoints =
new MatOfKeyPoint();
// Descriptors of the reference image's features.
private final Mat mReferenceDescriptors = new Mat();
// The corner coordinates of the reference image, in pixels.
// CvType defines the color depth, number of channels, and
// channel layout in the image. Here, each point is represented
// by two 32-bit floats.
private final Mat mReferenceCorners =
new Mat(4, 1, CvType.CV_32FC2);
// Features of the scene (the current frame).
private final MatOfKeyPoint mSceneKeypoints =
new MatOfKeyPoint();
// Descriptors of the scene's features.
private final Mat mSceneDescriptors = new Mat();
// Tentative corner coordinates detected in the scene, in
// pixels.
private final Mat mCandidateSceneCorners =
new Mat(4, 1, CvType.CV_32FC2);
// Good corner coordinates detected in the scene, in pixels.
private final Mat mSceneCorners = new Mat(4, 1, CvType.CV_32FC2);
// The good detected corner coordinates, in pixels, as integers.
private final MatOfPoint mIntSceneCorners = new MatOfPoint();
// A grayscale version of the scene.
private final Mat mGraySrc = new Mat();
// Tentative matches of scene features and reference features.
private final MatOfDMatch mMatches = new MatOfDMatch();
// A feature detector, which finds features in images.
private final ORB mFeatureDetector =
ORB.create();
// A descriptor extractor, which creates descriptors of
// features.
private final DescriptorExtractor mDescriptorExtractor =
DescriptorExtractor.create(DescriptorExtractor.ORB);
// A descriptor matcher, which matches features based on their descriptors.
private final DescriptorMatcher mDescriptorMatcher =
DescriptorMatcher.create(
DescriptorMatcher.BRUTEFORCE_HAMMINGLUT);
// The color of the outline drawn around the detected image.
private final Scalar mLineColor = new Scalar(0, 255, 0);
public ImageDetectionFilter(final Context context,
final int referenceImageResourceID) throws IOException
// Load the reference image from the app's resources.
// It is loaded in BGR (blue, green, red) format.
mReferenceImage = Utils.loadResource(context,
referenceImageResourceID,
Imgcodecs.IMREAD_COLOR);
// Create grayscale and RGBA versions of the reference image.
final Mat referenceImageGray = new Mat();
Imgproc.cvtColor(mReferenceImage, referenceImageGray,
Imgproc.COLOR_BGR2GRAY);
Imgproc.cvtColor(mReferenceImage, mReferenceImage,
Imgproc.COLOR_BGR2RGBA);
// Store the reference image's corner coordinates, in pixels.
mReferenceCorners.put(0, 0,
new double[]0.0, 0.0);
mReferenceCorners.put(1, 0,
new double[]referenceImageGray.cols(), 0.0);
mReferenceCorners.put(2, 0,
new double[]referenceImageGray.cols(),
referenceImageGray.rows());
mReferenceCorners.put(3, 0,
new double[]0.0, referenceImageGray.rows());
// Detect the reference features and compute their descriptors.
mFeatureDetector.detect(referenceImageGray,
mReferenceKeypoints);
mDescriptorExtractor.compute(referenceImageGray,
mReferenceKeypoints, mReferenceDescriptors);
@Override
public void apply(final Mat src, final Mat dst)
// Convert the scene to grayscale.
Imgproc.cvtColor(src, mGraySrc, Imgproc.COLOR_RGBA2GRAY);
// Detect the scene features, compute their descriptors,
// and match the scene descriptors to reference descriptors.
mFeatureDetector.detect(mGraySrc, mSceneKeypoints);
mDescriptorExtractor.compute(mGraySrc, mSceneKeypoints,
mSceneDescriptors);
mDescriptorMatcher.match(mSceneDescriptors,
mReferenceDescriptors, mMatches);
// Attempt to find the target image's corners in the scene.
findSceneCorners();
// If the corners have been found, draw an outline around the
// target image.
// Else, draw a thumbnail of the target image.
draw(src, dst);
private void findSceneCorners()
final List<DMatch> matchesList = mMatches.toList();
if (matchesList.size() < 4)
// There are too few matches to find the homography.
return;
final List<KeyPoint> referenceKeypointsList =
mReferenceKeypoints.toList();
final List<KeyPoint> sceneKeypointsList =
mSceneKeypoints.toList();
// Calculate the max and min distances between keypoints.
double maxDist = 0.0;
double minDist = Double.MAX_VALUE;
for (final DMatch match : matchesList)
final double dist = match.distance;
if (dist < minDist)
minDist = dist;
if (dist > maxDist)
maxDist = dist;
// The thresholds for minDist are chosen subjectively
// based on testing. The unit is not related to pixel
// distances; it is related to the number of failed tests
// for similarity between the matched descriptors.
if (minDist > 50.0)
// The target is completely lost.
// Discard any previously found corners.
mSceneCorners.create(0, 0, mSceneCorners.type());
return;
else if (minDist > 25.0)
// The target is lost but maybe it is still close.
// Keep any previously found corners.
return;
// Identify "good" keypoints based on match distance.
final ArrayList<Point> goodReferencePointsList =
new ArrayList<Point>();
final ArrayList<Point> goodScenePointsList =
new ArrayList<Point>();
final double maxGoodMatchDist = 1.75 * minDist;
for (final DMatch match : matchesList)
if (match.distance < maxGoodMatchDist)
goodReferencePointsList.add(
referenceKeypointsList.get(match.trainIdx).pt);
goodScenePointsList.add(
sceneKeypointsList.get(match.queryIdx).pt);
if (goodReferencePointsList.size() < 4 ||
goodScenePointsList.size() < 4)
// There are too few good points to find the homography.
return;
// There are enough good points to find the homography.
// (Otherwise, the method would have already returned.)
// Convert the matched points to MatOfPoint2f format, as
// required by the Calib3d.findHomography function.
final MatOfPoint2f goodReferencePoints = new MatOfPoint2f();
goodReferencePoints.fromList(goodReferencePointsList);
final MatOfPoint2f goodScenePoints = new MatOfPoint2f();
goodScenePoints.fromList(goodScenePointsList);
// Find the homography.
final Mat homography = Calib3d.findHomography(
goodReferencePoints, goodScenePoints);
// Use the homography to project the reference corner
// coordinates into scene coordinates.
Core.perspectiveTransform(mReferenceCorners,
mCandidateSceneCorners, homography);
// Convert the scene corners to integer format, as required
// by the Imgproc.isContourConvex function.
mCandidateSceneCorners.convertTo(mIntSceneCorners,
CvType.CV_32S);
// Check whether the corners form a convex polygon. If not,
// (that is, if the corners form a concave polygon), the
// detection result is invalid because no real perspective can
// make the corners of a rectangular image look like a concave
// polygon!
if (Imgproc.isContourConvex(mIntSceneCorners))
// The corners form a convex polygon, so record them as
// valid scene corners.
mCandidateSceneCorners.copyTo(mSceneCorners);
protected void draw(final Mat src, final Mat dst)
if (dst != src)
src.copyTo(dst);
if (mSceneCorners.height() < 4)
// The target has not been found.
// Draw a thumbnail of the target in the upper-left
// corner so that the user knows what it is.
// Compute the thumbnail's larger dimension as half the
// video frame's smaller dimension.
int height = mReferenceImage.height();
int width = mReferenceImage.width();
final int maxDimension = Math.min(dst.width(),
dst.height()) / 2;
final double aspectRatio = width / (double) height;
if (height > width)
height = maxDimension;
width = (int) (height * aspectRatio);
else
width = maxDimension;
height = (int) (width / aspectRatio);
// Select the region of interest (ROI) where the thumbnail
// will be drawn.
final Mat dstROI = dst.submat(0, height, 0, width);
// Copy a resized reference image into the ROI.
Imgproc.resize(mReferenceImage, dstROI, dstROI.size(),
0.0, 0.0, Imgproc.INTER_AREA);
return;
// Outline the found target in green.
Imgproc.line(dst, new Point(mSceneCorners.get(0, 0)),
new Point(mSceneCorners.get(1, 0)), mLineColor, 4);
Imgproc.line(dst, new Point(mSceneCorners.get(1, 0)),
new Point(mSceneCorners.get(2, 0)), mLineColor, 4);
Imgproc.line(dst, new Point(mSceneCorners.get(2, 0)),
new Point(mSceneCorners.get(3, 0)), mLineColor, 4);
Imgproc.line(dst, new Point(mSceneCorners.get(3, 0)),
new Point(mSceneCorners.get(0, 0)), mLineColor, 4);
【问题讨论】:
【参考方案1】:降级到较低版本的opencv,3.4.9对我有用!
【讨论】:
以上是关于类 DescriptorExtractor 在适用于 Android 的 opencv 4.1.0 中不可用的主要内容,如果未能解决你的问题,请参考以下文章