我正在尝试从视频中检测车辆,我将在实时应用程序中进行检测,但是暂时并为了更好地理解,我正在视频中进行检测,代码如下:void surf_detection(Mat img_1,Mat img_2); /** @function main */int main( int argc, char** argv ){ int i; int key; CvCapture* capture = cvCaptureFromAVI("try2.avi");// Read the video file if (!capture){ std::cout <<" Error in capture video file"; return -1; } Mat img_template = imread("images.jpg"); // read template imageint numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);IplImage* img = 0;for(i=0;i<numFrames;i++){ cvGrabFrame(capture); // capture a frame img=cvRetrieveFrame(capture); // retrieve the captured frame surf_detection (img_template,img); cvShowImage("mainWin", img); key=cvWaitKey(20);} return 0; }void surf_detection(Mat img_1,Mat img_2){if( !img_1.data || !img_2.data ){ std::cout<< " --(!) Error reading images " << std::endl;}//-- Step 1: Detect the keypoints using SURF Detectorint minHessian = 400;SurfFeatureDetector detector( minHessian );std::vector<KeyPoint> keypoints_1, keypoints_2;std::vector< DMatch > good_matches;do{detector.detect( img_1, keypoints_1 );detector.detect( img_2, keypoints_2 );//-- Draw keypointsMat img_keypoints_1; Mat img_keypoints_2;drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );//-- Step 2: Calculate descriptors (feature vectors)SurfDescriptorExtractor extractor;Mat descriptors_1, descriptors_2;extractor.compute( img_1, keypoints_1, descriptors_1 );extractor.compute( img_2, keypoints_2, descriptors_2 );//-- Step 3: Matching descriptor vectors using FLANN matcherFlannBasedMatcher matcher;std::vector< DMatch > matches;matcher.match( descriptors_1, descriptors_2, matches );double max_dist = 0;double min_dist = 100;//-- Quick calculation of max and min distances between keypointsfor( int i = 0; i < descriptors_1.rows; i++ ){ double dist = matches[i].distance;if( dist < min_dist ) min_dist = dist;if( dist > max_dist ) max_dist = dist;}//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )for( int i = 0; i < descriptors_1.rows; i++ ){ if( matches[i].distance < 2*min_dist ) { good_matches.push_back( matches[i]); }}}while(good_matches.size()<100);//-- Draw only "good" matchesMat img_matches;drawMatches( img_1, keypoints_1, img_2, keypoints_2,good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );//-- Localize the objectstd::vector<Point2f> obj;std::vector<Point2f> scene;for( int i = 0; i < good_matches.size(); i++ ){//-- Get the keypoints from the good matchesobj.push_back( keypoints_1[ good_matches[i].queryIdx ].pt );scene.push_back( keypoints_2[ good_matches[i].trainIdx ].pt );}Mat H = findHomography( obj, scene, CV_RANSAC );//-- Get the corners from the image_1 ( the object to be "detected" )std::vector<Point2f> obj_corners(4);obj_corners[0] = Point2f(0,0);obj_corners[1] = Point2f( img_1.cols, 0 );obj_corners[2] = Point2f( img_1.cols, img_1.rows );obj_corners[3] = Point2f( 0, img_1.rows );std::vector<Point2f> scene_corners(4);perspectiveTransform( obj_corners, scene_corners, H);//-- Draw lines between the corners (the mapped object in the scene - image_2 )line( img_matches, scene_corners[0] , scene_corners[1] , Scalar(0, 255, 0), 4 );line( img_matches, scene_corners[1], scene_corners[2], Scalar( 0, 255, 0), 4 );line( img_matches, scene_corners[2] , scene_corners[3], Scalar( 0, 255, 0), 4 );line( img_matches, scene_corners[3] , scene_corners[0], Scalar( 0, 255, 0), 4 );imshow( "Good Matches & Object detection", img_matches );}我得到以下输出和std::cout H值:但是我的问题是为什么它在检测到的对象上没有绘制矩形:我是在简单的视频和图像上执行此操作的,但是当我在静态相机上执行此操作时,如果没有该矩形可能会很困难 (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 首先,在您显示的图像中,根本没有绘制矩形。例如,您可以在图像中间绘制一个矩形吗?然后,看下面的代码:int x1 , x2 , y1 , y2 ;x1 = scene_corners[0].x + Point2f( img_1.cols, 0).x ;y1 = scene_corners[0].y + Point2f( img_1.cols, 0).y ;x2 = scene_corners[0].x + Point2f( img_1.cols, 0).x + in_box.width ;y2 = scene_corners[0].y + Point2f( img_1.cols, 0).y + in_box.height ;我不明白为什么要在每个角上添加in_box.width和in_box.height(它们在哪里定义?)。您应该改为使用scene_corners[2]。但是注释行应在某处打印一个矩形。由于您要求提供更多详细信息,因此让我们看看代码中会发生什么。首先,您如何获得perspectiveTransform()?您可以使用detector.detect检测特征点。它使您对这两个图像都感兴趣。 您使用extractor.compute描述这些功能。它为您提供了一种比较兴趣点的方法。比较两个功能的描述符可以回答以下问题:这些点有多相似?* 您实际上将第一张图像上的每个功能与第二张图像(某种)中的所有功能进行比较,并保持每个功能的最佳匹配。至此,您知道了看起来最相似的功能对。 您只保留good_matches。因为可能会发生一个功能,而另一张图像中最相似的一个实际上却完全不同(因为您没有更好的选择,所以它仍然是最相似的)。这是删除错误匹配项的第一个过滤器。 您会找到与找到的匹配项相对应的单应性变换。这意味着您尝试找到应如何在第二张图像中投影第一张图像中的点。然后,您将获得单应矩阵,从而可以将第一张图像的任意点投影在第二张图像中的对应位置上。 其次,您如何处理?现在变得有趣了。 您有一个单应矩阵,可以将第一张图像的任意点投影到第二张图像中的对应位置上。因此,您可以决定在对象周围绘制一个矩形(即obj_corners),并将其投影在第二个图像上(perspectiveTransform( obj_corners, scene_corners, H);)。结果在scene_corners中。现在,您想使用scene_corners绘制一个矩形。但是还有一点:drawMatches()显然在img_matches中将您的两个图像彼此相邻。但是投影(单应矩阵)是分别在图像上计算的!这意味着每个scene_corner必须相应地进行翻译。由于场景图像是在对象图像的右侧绘制的,因此必须将对象图像的宽度添加到每个scene_corner中,以便将它们转换到右侧。这就是为什么您将0添加到y1和y2的原因,因为您不必垂直转换它们。但是对于x1和x2,您必须添加img_1.cols。//-- Draw lines between the corners (the mapped object in the scene - image_2 )line( img_matches, scene_corners[0] + Point2f( img_1.cols, 0), scene_corners[1] + Point2f( img_1.cols, 0), Scalar(0, 255, 0), 4 );line( img_matches, scene_corners[1] + Point2f( img_1.cols, 0), scene_corners[2] + Point2f( img_1.cols, 0), Scalar( 0, 255, 0), 4 );line( img_matches, scene_corners[2] + Point2f( img_1.cols, 0), scene_corners[3] + Point2f( img_1.cols, 0), Scalar( 0, 255, 0), 4 );line( img_matches, scene_corners[3] + Point2f( img_1.cols, 0), scene_corners[0] + Point2f( img_1.cols, 0), Scalar( 0, 255, 0), 4 );因此,我建议您取消注释这些线,并查看是否绘制了矩形。如果不是,请尝试对值(例如Point2f(0, 0)和Point2f(100, 100))进行硬编码,直到成功绘制矩形。也许您的问题来自一起使用cvPoint和Point2f。也尝试使用Scalar(0, 255, 0, 255) ...希望能帮助到你。*必须理解,两个点可能看起来完全相同,但实际上并不对应于同一点。考虑一个真正重复的图案,例如建筑物窗户的角。所有窗口看起来都是相同的,因此即使这显然是错误的匹配,两个不同窗口的拐角也可能看起来非常相似。 (adsbygoogle = window.adsbygoogle || []).push({});
07-28 03:12