- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
cv::detail::findMaxSpanningTree 是 OpenCV 中用于图像拼接工作流的一个函数,它帮助构建一个最大生成树(Maximum Spanning Tree),这在图像拼接中用于确定图像之间的最佳连接方式。这个函数特别适用于处理多个图像间的匹配信息,并基于这些信息来构建一个图结构,从而为后续的图像拼接步骤提供基础。
函数原型
void cv::detail::findMaxSpanningTree
(
int num_images,
const std::vector< MatchesInfo > & pairwise_matches,
Graph & span_tree,
std::vector< int > & centers
)
参数
- num_images: 图像的数量。
- pairwise_matches: 包含每对图像之间匹配信息的向量。每个 MatchesInfo 结构体包含了两个图像之间的匹配点、置信度等信息。
- span_tree: 输出参数,表示由函数计算得到的最大生成树。这个图结构描述了如何以最优的方式将所有图像连接起来。
- centers: 输出参数,包含可能作为拼接中心的图像索引列表。在全景拼接中,通常选择一个或几个中心图像来开始拼接过程。
代码示例
#include <opencv2/opencv.hpp>
#include <opencv2/stitching/detail/matchers.hpp>
#include <opencv2/stitching/detail/util.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace cv::detail;
int main() {
// 加载图像(此处仅作示意,实际应用中需要加载真实图像)
std::vector<std::string> img_filenames = {
"/media/dingxin/data/study/OpenCV/sources/images/left01.jpg",
"/media/dingxin/data/study/OpenCV/sources/images/right01.jpg",
"/media/dingxin/data/study/OpenCV/sources/images/right01.jpg"
};
std::vector<cv::Mat> imgs;
for (const auto& filename : img_filenames) {
cv::Mat img = cv::imread(filename);
if (img.empty()) {
std::cerr << "无法加载图像: " << filename << std::endl;
return -1;
}
imgs.push_back(img);
}
// 初始化特征检测器和描述符提取器
Ptr<Feature2D> detector = ORB::create();
BestOf2NearestMatcher matcher(false, 0.3f);
// 计算每张图像的特征点
std::vector<ImageFeatures> features(imgs.size());
for (size_t i = 0; i < imgs.size(); ++i) {
detector->detectAndCompute(imgs[i], Mat(), features[i].keypoints, features[i].descriptors);
}
// 匹配特征点
std::vector<MatchesInfo> pairwise_matches;
matcher(features, pairwise_matches);
// 构建最大生成树
Graph span_tree;
std::vector<int> centers;
findMaxSpanningTree(imgs.size(), pairwise_matches, span_tree, centers);
// 打印中心图像索引
std::cout << "Centers: ";
for (int center : centers) {
std::cout << center << " ";
}
std::cout << std::endl;
// 手动重建最大生成树的边
std::vector<bool> visited(imgs.size(), false);
for (int center : centers) {
std::cout << "Starting from center: " << center << std::endl;
visited[center] = true;
for (size_t i = 0; i < pairwise_matches.size(); ++i) {
const MatchesInfo& match_info = pairwise_matches[i];
if (match_info.confidence > 0 && !visited[match_info.src_img_idx] && !visited[match_info.dst_img_idx]) {
std::cout << "(" << match_info.src_img_idx << ", " << match_info.dst_img_idx << ")" << std::endl;
visited[match_info.src_img_idx] = true;
visited[match_info.dst_img_idx] = true;
}
}
}
return 0;
}
运行结果
Centers: 2
Starting from center: 2
(0, 1)