【发布时间】:2014-08-21 09:25:09
【问题描述】:
我正在开发一个 android 应用程序,其主要目的是检测场景中的询问对象。为此,我使用 OpenCV 的 SURF 算法。我对检测没有“好运”,因为我不知道什么时候“找到”了一个物体。
我用我的设备相机获取一个帧,然后按照以下步骤获取对象的关键点和描述符:
Java 代码
public void onSnapClick(View v) {
Imgproc.GaussianBlur(frameGray, frameGray, new Size(3, 3), 2);
Imgproc.Canny(frameGray, frameGray, 40, 120);
Imgproc.resize(frameGray, frameGray, new Size(320, 240));
FindFeatures(frameGray.getNativeObjAddr()); //JNI call
//Some code to store data in DB...
}
JNI 调用
double hessianThreshold=600;
int nOctaves=4;
int nOctaveLayers=2;
bool extended=true;
bool upright=false;
JNIEXPORT void JNICALL Java_es_ugr_reconocimiento_Juego_FindFeatures(JNIEnv* env, jobject, jlong addrGray) {
Mat& frameGray= *(Mat*) addrGray;
vector<KeyPoint> keyPoints;
Mat descriptores;
SurfFeatureDetector detector_Surf(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);
SurfDescriptorExtractor extractor_Surf;
detector_Surf.detect(frameGray, keyPoints);
if (keyPoints.size() > 0)
extractor_Surf.compute(frameGray, keyPoints, descriptores);
}
现在我选择要查找的对象,然后按照以下步骤进行操作:
Java 代码
public void onSearchClick(View v) {
Imgproc.GaussianBlur(frameGray, frameGray, new Size(3, 3), 2);
Imgproc.Canny(frameGray, frameGray, 40, 120);
Imgproc.resize(frameGray, frameGray, new Size(320, 240));
nObject = FindObjects(frameGray.getNativeObjAddr()); //JNI call
if (nObject = searchObject)
//draw frame with a rectangle around the found object in the scenario....
}
JNI 调用
double hessianThreshold=600;
int nOctaves=4;
int nOctaveLayers=2;
bool extended=true;
bool upright=false;
JNIEXPORT jint JNICALL Java_es_ugr_reconocimiento_Juego_FindObjects(JNIEnv* env, jobject, jlong addrGray) {
Mat& frameGray = *(Mat*) addrGray;
vector<KeyPoint> keyPoints_esc;
Mat descriptores_esc;
SurfFeatureDetector detector_Surf(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);
SurfDescriptorExtractor extractor_Surf;
detector_Surf.detect(frameGray , keyPoints_esc);
if (keyPoints_esc.size() == 0) return -1;
extractor_Surf.compute(frameGray , keyPoints_esc, descriptores_esc);
if (descriptores_esc.rows() == 0) return -1;
for(int i=0;i<lstObjects.size();i++){
Mat descriptores_obj = lstDescriptors.at(i);
vector<KeyPoint> keyPoints_obj = lstKeyPoints.at(i);
FlannBasedMatcher matcher;
vector<vector<DMatch> > matches;
matcher.knnMatch(descriptores_obj, descriptores_esc, matches, 2);
// ----------------------------------------------------------------------
// Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
// or a small arbitary value ( 0.02 ) in the event that min_dist is very
// small)
// PS.- radiusMatch can also be used here.
// ----------------------------------------------------------------------
vector<DMatch> good_matches;
//THIS LOOP IS SENSITIVE TO SEGFAULTS
for (int i = 0; i < min(descriptores_obj.rows - 1, (int) matches.size());i++){
if ( (matches[i][0].distance < 0.6 * (matches[i][1].distance)) &&
((int) matches[i].size() <= 2 && (int) matches[i].size() > 0) ) {
good_matches.push_back(matches[i][0]);
}
}
if (good_matches.size() >= nThreshold) {
vector < Point2f > obj;
vector < Point2f > scene;
for (int i = 0; i < good_matches.size(); i++) {
//-- Get the keypoints from the good matches
obj.push_back(keyPoints_obj[good_matches[i].queryIdx].pt);
scene.push_back(keyPoints_esc[good_matches[i].trainIdx].pt);
}
Mat H = findHomography(obj, scene, CV_RANSAC);
vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0, 0);
obj_corners[1] = cvPoint(240, 0);
obj_corners[2] = cvPoint(240, 320);
obj_corners[3] = cvPoint(0, 320);
vector<Point2f> scene_corners(4);
perspectiveTransform(obj_corners, scene_corners, H);
line(frameGray, scene_corners[0], scene_corners[1], Scalar(255, 0, 0), 4);
line(frameGray, scene_corners[1], scene_corners[2], Scalar(255, 0, 0), 4);
line(frameGray, scene_corners[2], scene_corners[3], Scalar(255, 0, 0), 4);
line(frameGray, scene_corners[3], scene_corners[0], Scalar(255, 0, 0), 4);
for (unsigned int i = 0; i < scene.size(); i++) {
const Point2f& kp = scene[i];
circle(frameGray, Point(kp.x, kp.y), 10, Scalar(255, 255, 255, 255));
}
return i; //position of the matched object
}
}
}
我不知道在这个比较中哪个阈值可能是最好的
if (good_matches.size() >= nThreshold) // do findHomography...
我一直在搜索,几乎我发现的每个代码都包含数字 4 作为 nThreshold,但对我来说它效果不佳。我的代码几乎每次都“找到”一个对象。
还有其他更好的方法吗?就像使用不同的匹配器或其他阈值,或者试图弄清楚进行单应性是否会创建类似于矩形的东西(我之所以这么说是因为有时它“找到”了一些东西,但绘制了四条线而不是构建一个矩形)。
【问题讨论】:
-
您可能需要 2 个条件。至少 4 个点做单应性,以及一个好的匹配的阈值(可能像 60% 的匹配是好的)
-
@migue02 我的解决方案对您有帮助吗?
-
@migue02 你能解决这个问题吗?
标签: java android c++ opencv surf