- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
cv::detail::MultiBandBlender 是 OpenCV 中用于图像拼接(stitching)模块的一个类,主要用于将多张重叠的图像无缝地融合成一张全景图。它实现了多频带融合算法,通过分解图像的频率成分来实现平滑的过渡效果。
主要功能与概念
-
多频带融合(Multi-Band Blending)
该算法将图像分解为多个频率带(使用高斯金字塔和拉普拉斯金字塔)。
对每个频率带分别进行融合,然后重新组合成最终图像。
这种方法可以有效减少拼接区域的可见接缝,并处理亮度差异。
-
融合流程
准备输入图像及其掩码。
将图像和掩码送入融合器。
执行融合并生成最终结果。
常用成员函数
- 构造函数
cpp
cv::detail::MultiBandBlender(bool try_gpu = false);
- 参数:
try_gpu: 如果为 true,尝试使用 GPU 加速(如果可用)。默认值为 false。
- 准备函数
cpp
void prepare(cv::Rect dst_roi);
- 用途: 初始化融合器,设置目标图像的感兴趣区域(ROI)。
- 参数:
dst_roi: 目标图像中需要融合的区域。
- 添加图像
cpp
void feed(const cv::Mat& img, const cv::Mat& mask, cv::Point tl);
- 用途: 向融合器中添加图像及其掩码。
- 参数:
img: 输入图像。
mask: 图像的有效区域掩码。
tl: 图像在最终全景图中的左上角位置。
- 执行融合
cpp
void blend(cv::Mat& dst, cv::Mat& dst_mask);
- 用途: 执行实际的融合操作,并输出结果。
- 参数:
dst: 输出的融合图像。
dst_mask: 输出的融合掩码。
代码示例
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/stitching/detail/blenders.hpp>
int main()
{
// 创建 MultiBandBlender 对象
cv::Ptr< cv::detail::MultiBandBlender > blender = cv::makePtr< cv::detail::MultiBandBlender >();
// 加载图像
cv::Mat img1 = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/stich1.png" );
cv::Mat img2 = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/stich2.png" );
if ( img1.empty() || img2.empty() )
{
std::cerr << "Error: Failed to load images!" << std::endl;
return -1;
}
// 调试:单独显示原始图像
cv::imshow( "Image1", img1 );
cv::imshow( "Image2", img2 );
// 确保为三通道
if ( img1.channels() != 3 )
{
cv::cvtColor( img1, img1, cv::COLOR_GRAY2BGR );
}
if ( img2.channels() != 3 )
{
cv::cvtColor( img2, img2, cv::COLOR_GRAY2BGR );
}
// 创建掩码
cv::Mat mask1 = cv::Mat::ones( img1.size(), CV_8UC1 ) * 255;
cv::Mat mask2 = cv::Mat::ones( img2.size(), CV_8UC1 ) * 255;
// 设置ROI(假设两图水平拼接)
int roi_width = img1.cols + img2.cols;
int roi_height = std::max( img1.rows, img2.rows );
cv::Rect roi( 0, 0, roi_width, roi_height );
blender->prepare( roi );
// 输入图像到融合器
blender->feed( img1, mask1, cv::Point( 0, 0 ) ); // 左图
blender->feed( img2, mask2, cv::Point( img1.cols, 0 ) ); // 右图
// 融合
cv::Mat result, result_mask;
blender->blend( result, result_mask );
// 处理结果
if ( result.empty() )
{
std::cerr << "Error: Blending failed!" << std::endl;
return -1;
}
if ( result.depth() == CV_32F )
{
result.convertTo( result, CV_8UC3, 255.0 ); // 转为8位三通道
}
// 显示和保存
cv::imwrite( "panorama2.jpg", result );
cv::Mat result_8u;
result.convertTo( result_8u, CV_8U ); // 转换为 8 位无符号整型:ml-citation{ref="3,8" data="citationList"}
cv::imshow( "全景图", result_8u );
cv::waitKey( 0 ); // 必须调用!
return 0;
}
运行结果