落地 基于特征的对象检测
首先要通过暴力匹配对比出图像和目标图像的相同点
using namespace std;
int main(int argc, char** argv) {
// Mat image = imread("D:/images/butterfly.jpg");
Mat book = imread("C:/newword/image/29.jpg");
Mat book_on_desk = imread("C:/newword/image/30.jpg");
imshow("book", book);
auto orb = ORB::create(500);
vector<KeyPoint> kypts_book;
vector<KeyPoint> kypts_book_on_desk;
Mat desc_book, desc_book_on_desk;
orb->detectAndCompute(book, Mat(), kypts_book, desc_book);
orb->detectAndCompute(book_on_desk, Mat(), kypts_book_on_desk, desc_book_on_desk);
Mat result;
auto bf_matcher = BFMatcher::create(NORM_HAMMING, false);
vector<DMatch> matches;
bf_matcher->match(desc_book, desc_book_on_desk, matches);
float good_rate = 0.15f;//用于筛选相同点位
int num_good_matches = matches.size() * good_rate;
std::cout << num_good_matches << std::endl;
std::sort(matches.begin(), matches.end());//从高到低排序
matches.erase(matches.begin() + num_good_matches, matches.end());//筛选目标点位
drawMatches(book, kypts_book, book_on_desk, kypts_book_on_desk, matches, result);//绘制
imshow("暴力匹配23", result);
接下来处理锁定目标图片
vector<Point2f> obj_pts;
vector<Point2f> scene_pts;
for (size_t t = 0; t < matches.size(); t++) {
obj_pts.push_back(kypts_book[matches[t].queryIdx].pt);
scene_pts.push_back(kypts_book_on_desk[matches[t].trainIdx].pt);
}//
用作对比
在OpenCV的特征匹配相关操作中,queryIdx 和 trainIdx 用于区分不同图像中的特征点索引,.pt 用于获取对应特征点的坐标,它们的区别如下:
• queryIdx 及 queryIdx].pt:queryIdx 是指在查询图像(query image)的特征点集合中的索引。比如在进行图像匹配时,将一幅图像设为查询图像,要在另一幅图像中找与它匹配的部分,queryIdx 就用来索引查询图像中的特征点,queryIdx].pt 就是通过该索引获取到的查询图像中特征点的坐标。
• trainIdx 及 trainIdx].pt:trainIdx 是在训练图像(train image)的特征点集合中的索引。在图像匹配任务里,训练图像是用来与查询图像进行匹配对比的图像,trainIdx 用于索引训练图像中的特征点,trainIdx].pt 就是获取到的训练图像中对应特征点的坐标。
例如在代码 obj_pts.push_back(kypts_book[matches[t].queryIdx].pt); 与 scene_pts.push_back(kypts_book_on_desk[matches[t].trainIdx].pt); 中,queryIdx 用于从 kypts_book(可视为查询图像的特征点集)中取点,trainIdx 用于从 kypts_book_on_desk(可视为训练图像的特征点集)中取点,分别获取在不同图像中相互匹配的特征点坐标。
Mat h = findHomography(obj_pts, scene_pts, RANSAC);//
功能
findHomography函数用于计算两个平面之间的单应性矩阵。简单来说,就是在已知两组对应点的情况下,找到一个能够将一组点通过透视变换映射到另一组点的变换矩阵,这个矩阵就被称为单应性矩阵。它在图像配准、图像拼接、相机标定等计算机视觉任务中有着广泛的应用。
● obj_pts:这是源图像(这里指 book 图像)中匹配点的坐标集合,作为单应性矩阵计算的输入点集之一。这些点将通过计算得到的单应性矩阵映射到目标图像中的对应位置。
● scene_pts:目标图像(book_on_desk 图像)中与 obj_pts 对应的匹配点坐标集合。它与 obj_pts 共同决定了单应性矩阵的计算,使得通过该矩阵能够将 obj_pts 中的点尽可能准确地映射到 scene_pts 中的位置。
● RANSAC:这是指定的计算单应性矩阵的方法,即随机抽样一致性(Random Sample Consensus)算法。由于在实际的特征匹配中,可能存在误匹配点(外点),RANSAC 算法能够通过多次随机抽样,从包含外点的数据中估计出最优的单应性矩阵。它会尝试不同的点对组合来计算单应性矩阵,并根据重投影误差来判断哪些点是内点(正确匹配的点)。经过多次迭代,选择内点数量最多的那个单应性矩阵作为最终结果,从而提高了单应性矩阵计算的准确性和鲁棒性。
vector<Point2f> srcPts;
srcPts.push_back(Point2f(0, 0));
srcPts.push_back(Point2f(book.cols, 0));
srcPts.push_back(Point2f(book.cols, book.rows));
srcPts.push_back(Point2f(0, book.rows));
std::vector<Point2f> dstPts(4);
perspectiveTransform(srcPts, dstPts, h);
perspectiveTransform 通常是计算机视觉库(如OpenCV)中的一个函数,用于执行透视变换操作,以下是关于它的详述:
函数功能
perspectiveTransform 主要用于对一组点或图像进行透视变换。它根据给定的透视变换矩阵,将源坐标系统中的点映射到目标坐标系统中,实现图像的视角变换、校正等操作,常用于图像校正、图像拼接、目标识别等计算机视觉任务。
在perspectiveTransform函数中,dst是结合src和m来输出的。具体来说:
● src是输入的源数据,它可以是一组点的坐标集合,也可以是一幅图像等数据,代表了要进行透视变换的原始对象。
● m是3×3的透视变换矩阵,它定义了从源坐标系统到目标坐标系统的映射关系,决定了透视变换的具体方式和效果,比如旋转、缩放、平移、扭曲等操作的组合。
● dst作为函数的输出参数,根据src提供的原始数据,按照m所定义的变换规则,存储经过透视变换后的结果。函数通过将src中的每个元素(如点的坐标)与变换矩阵m进行相应的数学运算,来计算出在目标空间中的新位置,并将结果存储到dst中。
for (int i = 0; i < 4; i++) {
line(book_on_desk, dstPts[i], dstPts[(i + 1) % 4], Scalar(0, 0, 255), 2, 8, 0);
}
imshow("暴力匹配", result);
namedWindow("对象检测", WINDOW_FREERATIO);
imshow("对象检测", book_on_desk);
imwrite("C:/newword/31.jpg", book_on_desk);
waitKey(0);
return 0;
}