我正试图编写一个应用SURF对象检测的代码,所以我取了一个openCV样本(样本3),并开始更新onCameraViewStarted()
和onCameraFrame()
方法,但当我在galaxy S3手机上尝试它时,我一直遇到运行时错误,我找不到任何有助于解决我的问题的东西。以下是我的代码和我更新的内容:
public class Sample3Native extends Activity implements CvCameraViewListener{
private static final String TAG = "OCVSample::Activity";
private Mat mRgba;
private Mat mGrayMat;
private CameraBridgeViewBase mOpenCvCameraView;
Mat descriptors ;
List<Mat> descriptorsList;
FeatureDetector featureDetector;
MatOfKeyPoint keyPoints;
DescriptorExtractor descriptorExtractor;
DescriptorMatcher descriptorMatcher;**
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
// Load native library after(!) OpenCV initialization
System.loadLibrary("native_sample");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public void onCameraViewStarted(int width, int height) {
mRgba = new Mat(height, width, CvType.CV_8UC4);
mGrayMat = new Mat(height, width, CvType.CV_8UC1);
featureDetector=FeatureDetector.create(4); // SURF= 4;
descriptorExtractor=DescriptorExtractor.create(2);//SURF = 2
descriptorMatcher=DescriptorMatcher.create(6); //BRUTEFORCE_SL2 = 6**
}
public Mat onCameraFrame(Mat inputFrame) {
inputFrame.copyTo(mRgba);
//detect_1(0, mRgba.getNativeObjAddr(), keyPoints.getNativeObjAddr());
//Now mRgba contains the current frame ( start manipulation part)
//detecting keypoints
featureDetector.detect(mRgba, keyPoints);
//draw keypoints
// Features2d.drawKeypoints(mRgba, keyPoints, mRgba);
//finding descriptors
descriptorExtractor.compute(mRgba, keyPoints, descriptors);
//Matcher between 2 images or set of images
// Note: training set and query set are handled here! (in matcher)
//descriptorsList = descriptorMatcher.getTrainDescriptors();
//descriptorsList.add(descriptors);
// descriptorMatcher.add(descriptorsList);
//Imgproc.cvtColor(mRgba, mGrayMat, Imgproc.COLOR_RGBA2GRAY);
//FindFeatures(mGrayMat.getNativeObjAddr(), mRgba.getNativeObjAddr());
return mRgba;
}
}
注意:我已经尝试过在onCameraFrame()
方法中注释除featureDetector.detect(mRgba, keyPoints)
之外的所有内容,但在我的手机上仍然出现运行时错误。
如果我没有错的话,OpenCV SURF特征检测器只适用于灰度图像。因此,请尝试在调用onCameraFrame()
方法中的copyTo之后添加此项:
cvtColor(mRgba, mGrayMat, COLOR_RGBA2GRAY);
您确定以正确的方式使用SIFT吗?据我所知,SIFT和SURF不包括在OpenCV Android的分发包中。要使用它们,您需要编译非自由模块并在项目中使用它。因此,您需要做的是创建一个NDK项目,将非自由模块编译为一个独立的库。然后使用这个库来编译您的程序。然后您应该能够构建您的应用程序。您可以参考本教程。
在获得jni库之后,您可以很容易地将其包装为JAVA jni接口。然后你应该能够在你的Android应用程序中使用JAVA界面。
SURF或SIFT仅支持灰度。因此,您必须首先使用以下代码将其转换为灰度:cvt颜色(mRgba、mRgbb、CV_BGR2GRAY);
评论cid和HMK的答案(对不起,我没有"添加评论"的50名,所以我必须创建一个新的答案)。
OpenCV库可以接受彩色图像作为输入。以下是我的SIFT检测和描述提取代码。它运行得很好。这意味着您不需要将图像转换为灰度格式,尽管SIFT算法仅适用于灰度图像。我相信OpenCV检测器已经做了一些预处理。(由于suft检测器和sift以类似的方式工作,我认为SURF也不需要灰度格式输入)
Mat image;
image = imread(argv[1], CV_LOAD_IMAGE_COLOR);
if(! image.data )
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
vector<KeyPoint> keypoints;
Mat descriptors;
// Create a SIFT keypoint detector.
SiftFeatureDetector detector;
detector.detect(image, keypoints);
cout << "Detected " << (int) keypoints.size() << " keypoints" <<endl;
// Compute feature description.
detector.compute(image,keypoints, descriptors);
cout << "Computed feature."<<endl;