抱歉停更两周有余,工作时而忙碌,抽出了一些时间陪家人,还建了StereoV3D交流群(博客主页有群二维码哦~),朋友们都非常活跃,简直太棒了!
废话少说,我们继续更新AD-Census的实战教学篇。
上篇框架中,我们梳理了算法框架和代码框架,工程师拿到了设计图纸,得找水泥工砖瓦工砌墙打砖了。
本篇开始就带领大家一起砌墙打砖。
先贴一下AD-Census的效果图:
|
|
|
|
完整代码已开源在我的Github仓库,供大家下载。
仓库地址:https://github.com/ethan-li-coding/AD-Census
我们来看本篇的内容:
文章目录
-
- 主类
- 公有函数
- 私有函数
- 成员变量
主类
我们将ADCensusStereo作为主类名:
class ADCensusStereo {
public:ADCensusStereo();~ADCensusStereo();
}
如果是个空类,那只有构造和析构,当然不能是空类。它必须有成员函数和成员变量。
公有函数
在共有函数列表中,最重要的是设计 Match 成员函数为执行匹配的接口,给调用者调用,传入图像,传出视差图。注意接口的输入是三通道彩色图像哦!
/** * \brief 执行匹配 * \param img_left 输入,左影像数据指针,3通道彩色数据 * \param img_right 输入,右影像数据指针,3通道彩色数据 * \param disp_left 输出,左影像视差图指针,预先分配和影像等尺寸的内存空间 */
bool Match(const uint8* img_left, const uint8* img_right, float32* disp_left);
在公有函数列表中,我们还需要指定一个初始化接口和释放内存接口,初始化的目的是做一些准备工作,比如内存的初始化、状态的初始化等等。预分配往往是提高效率的常规操作,别总是需要的时候才分配,开辟内存的开销不可忽视。
重设接口是重新初始化操作,当你想改变分辨率或者改变算法参数时,可以调用此接口。
/** * \brief 类的初始化,完成一些内存的预分配、参数的预设置等 * \param width 输入,核线像对影像宽 * \param height 输入,核线像对影像高 * \param option 输入,算法参数 */
bool Initialize(const sint32& width, const sint32& height, const ADCensusOption& option);
/** * \brief 重设 * \param width 输入,核线像对影像宽 * \param height 输入,核线像对影像高 * \param option 输入,算法参数 */
bool Reset(const uint32& width, const uint32& height, const ADCensusOption& option);
私有函数
在私有函数列表中,我将AD-Census算法的子步骤分别写成单独的接口,便于清晰地调用,每一个接口代表着一个独立的功能。它们分别是
- 代价计算
- 代价聚合
- 扫描线优化
- 多步骤视差优化
- 视差计算
/** \brief 代价计算 */
void ComputeCost();/** \brief 代价聚合 */
void CostAggregation();/** \brief 扫描线优化 */
void ScanlineOptimize();/** \brief 多步骤视差优化 */
void MultiStepRefine();/** \brief 视差计算(左视图)*/
void ComputeDisparity();/** \brief 视差计算(右视图)*/
void ComputeDisparityRight();
此外,释放接口则把初始化时开辟的内存释放掉,内存泄漏可是严重的问题,不可掉以轻心。鉴于历史原因,我是一个中度指针用户,内存的开辟释放很小心,现在也渐渐意识到容器的便利性,所以后面的编码中我开始注重容器的使用。
/** \brief 内存释放 */
void Release();
成员变量
为了安全,将成员变量全部设置为私有类型,调用者没有必要直接接触。
首先看成员函数的一览:
/** \brief 算法参数 */
ADCensusOption option_;/** \brief 影像宽 */
sint32 width_;
/** \brief 影像高 */
sint32 height_;/** \brief 左影像数据,3通道彩色数据 */
const uint8* img_left_;
/** \brief 右影像数据 ,3通道彩色数据 */
const uint8* img_right_;/** \brief 代价计算器 */
CostComputor cost_computer_;
/** \brief 代价聚合器 */
CrossAggregator aggregator_;
/** \brief 扫描线优化器 */
ScanlineOptimizer scan_line;
/** \brief 多步优化器 */
MultiStepRefiner refiner_;/** \brief 左影像视差图 */
float32* disp_left_;
/** \brief 右影像视差图 */
float32* disp_right_;/** \brief 是否初始化标志 */
bool is_initialized_;
-
ADCensusOption option_
算法参数变量,参数结构体ADCensusOption的定义放在文件adcensus_types.h里。里面是根据ADCensus的原文设置的各类阈值。
/** \brief ADCensus参数结构体 */
struct ADCensusOption {
sint32 min_disparity; // 最小视差sint32 max_disparity; // 最大视差sint32 lambda_ad; // 控制AD代价值的参数sint32 lambda_census; // 控制Census代价值的参数sint32 cross_L1; // 十字交叉窗口的空间域参数:L1sint32 cross_L2; // 十字交叉窗口的空间域参数:L2sint32 cross_t1; // 十字交叉窗口的颜色域参数:t1sint32 cross_t2; // 十字交叉窗口的颜色域参数:t2float32 so_p1; // 扫描线优化参数p1float32 so_p2; // 扫描线优化参数p2sint32 so_tso; // 扫描线优化参数tsosint32 irv_ts; // Iterative Region Voting法参数tsfloat32 irv_th; // Iterative Region Voting法参数thfloat32 lrcheck_thres; // 左右一致性约束阈值bool do_lr_check; // 是否检查左右一致性bool do_filling; // 是否做视差填充bool do_discontinuity_adjustment; // 是否做非连续区调整
};
-
sint32 width_/height_
图像宽高,无需多言。
-
const uint8* img_left_/img_right_
图像数据,注释说明是3通道的彩色数据,表明算法目前是只支持3通道彩色数据的。const标示表示算法执行过程中不会对输入的图像数据做任何的写入修改。
-
CostComputor cost_computer_
代价计算器,我将代价计算部分的所有功能代码都集成到一个代价计算器类CostComputor中,这样组织会比较清晰,理解上也更加容易。CostComputor类的实现放在cost_computor.h/cost_computor.cpp中,后面篇章我们会细说。
-
CrossAggregator aggregator_
代价聚合器,道理同上,我将代价聚合部分的所有功能代码都集成到一个代价聚合器类CrossAggregator中。CrossAggregator类的实现放在cost_aggregator.h/cost_aggregator.cpp中。
-
ScanlineOptimizer scan_line_
扫描线优化器,道理同上。ScanlineOptimizer类的实现放在scanline_optimizer.h/scanline_optimizer.cpp中。
-
MultiStepRefiner refiner_
多步视差优化器,道理同上。MultiStepRefiner类的实现放multistep_refiner.h/multistep_refiner.cpp中。
-
float32* disp_left_/disp_right_
左右图像的视差图,保存算法最终生成的视差图结果。类型是float32,是真实视差值,可直接用于计算深度。
-
bool is_initialized_
是否初始化标志。若成功执行Initialize接口,则此标志为true,反之为false,为false时不会执行匹配。
以上就是本篇主类的所有内容,下篇将给大家带来基于AD-Census 代价计算 的代码介绍。
下载AD-Census完整源码,点击进入: https://github.com/ethan-li-coding/AD-Census
欢迎同学们在Github项目里讨论,如果觉得博主代码质量不错,右上角给颗星!感谢!
博主简介:
Ethan Li 李迎松(知乎:李迎松)
武汉大学 摄影测量与遥感专业博士
主方向立体匹配、三维重建
2019年获测绘科技进步一等奖(省部级)
爱三维,爱分享,爱开源
GitHub: https://github.com/ethan-li-coding (欢迎follow和star)
个人微信:
欢迎交流!
关注博主不迷路,感谢!
博客主页:https://ethanli.blog.csdn.net