上一個教程: 高動態範圍成像
下一個教程: 如何使用背景減除方法
| |
| 原始作者 | Jiri Horner |
| 相容性 | OpenCV >= 3.2 |
目標
在本教程中,您將學習如何
- 使用OpenCV提供的高階影像拼接API進行影像拼接
- 學習如何使用預配置的Stitcher配置,利用不同的相機模型拼接影像。
程式碼
C++
本教程的程式碼如下所示。您可以從這裡下載。
注意:C++版本包含額外的選項,例如影像分割(–d3)和更詳細的錯誤處理,這些在Python示例中不存在。
#include <iostream>
bool divide_images = false;
vector<Mat> imgs;
string result_name = "result.jpg";
void printUsage(char** argv);
int parseCmdArgs(int argc, char** argv);
int main(
int argc,
char* argv[])
{
int retval = parseCmdArgs(argc, argv);
if (retval) return EXIT_FAILURE;
if (status != Stitcher::OK)
{
cout << "無法拼接影像,錯誤程式碼 = " << int(status) << endl;
return EXIT_FAILURE;
}
imwrite(result_name, pano);
cout << "拼接成功\n" << result_name << " 已儲存!";
return EXIT_SUCCESS;
}
void printUsage(char** argv)
{
cout <<
"影像拼接器。\n\n" << "用法:\n" << argv[0] <<" [標誌] img1 img2 [...imgN]\n\n"
"標誌:\n"
" --d3\n"
" 內部建立每個影像的三個塊以提高拼接成功率\n"
" --mode (panorama|scans)\n"
" 確定拼接器的配置。預設為 'panorama',\n"
" 適用於建立全景照片的模式。選項 'scans' 適用於\n"
" 拼接在仿射變換下的材料,例如掃描件。\n"
" --output <result_img>\n"
" 預設值為“result.jpg”。\n\n"
"示例用法:\n" << argv[0] << " --d3 --mode scans img1.jpg img2.jpg\n";
}
int parseCmdArgs(int argc, char** argv)
{
if (argc == 1)
{
printUsage(argv);
return EXIT_FAILURE;
}
for (int i = 1; i < argc; ++i)
{
if (string(argv[i]) == "--help" || string(argv[i]) == "/?")
{
printUsage(argv);
return EXIT_FAILURE;
}
else if (string(argv[i]) == "--d3")
{
divide_images = true;
}
else if (string(argv[i]) == "--output")
{
result_name = argv[i + 1];
i++;
}
else if (string(argv[i]) == "--mode")
{
if (string(argv[i + 1]) == "panorama")
mode = Stitcher::PANORAMA;
else if (string(argv[i + 1]) == "scans")
mode = Stitcher::SCANS;
else
{
cout << "錯誤的 --mode 標誌值\n";
return EXIT_FAILURE;
}
i++;
}
else
{
Mat img =
imread(samples::findFile(argv[i]));
{
cout << "無法讀取影像 '" << argv[i] << "'\n";
return EXIT_FAILURE;
}
if (divide_images)
{
imgs.push_back(img(rect).clone());
imgs.push_back(img(rect).clone());
imgs.push_back(img(rect).clone());
}
else
imgs.push_back(img);
}
}
return EXIT_SUCCESS;
}
cv::getTickFrequency
double getTickFrequency()
int rows
當矩陣維度超過2時,返回行數和列數,或 (-1, -1)
定義 mat.hpp:2165
2D 矩形的模板類。
定義 types.hpp:444
std::shared_ptr< _Tp > Ptr
Definition cvstd_wrapper.hpp:23
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
從檔案載入影像。
int main(int argc, char *argv[])
定義 highgui_qt.cpp:3
Python
本教程的程式碼如下所示。您可以從這裡下載。
注意:C++版本包含額外的選項,例如影像分割(–d3)和更詳細的錯誤處理,這些在Python示例中不存在。
'''
拼接示例
================
展示如何簡單地使用Python中的Stitcher API來拼接全景圖
或掃描件。
'''
from __future__ import print_function
import numpy as np
import cv2 as cv
import argparse
import sys
modes = (cv.Stitcher_PANORAMA, cv.Stitcher_SCANS)
parser = argparse.ArgumentParser(prog='stitching.py', description='拼接示例。')
parser.add_argument('--mode',
type = int, choices = modes, default = cv.Stitcher_PANORAMA,
help = '確定拼接器的配置。預設為 `PANORAMA` (%d),'
'適用於建立全景照片的模式。選項 `SCANS` (%d) 適用於 '
'拼接在仿射變換下的材料,例如掃描件。' % modes)
parser.add_argument('--output', default = 'result.jpg',
help = '輸出影像。預設為 `result.jpg`。')
parser.add_argument('img', nargs='+', help = '輸入影像')
__doc__ += '\n' + parser.format_help()
args = parser.parse_args()
imgs = []
for img_name in args.img
if img is None
print("無法讀取影像 " + img_name)
sys.exit(-1)
imgs.append(img)
status, pano = stitcher.stitch(imgs)
if status != cv.Stitcher_OK
print("無法拼接影像,錯誤程式碼 = %d" % status)
sys.exit(-1)
print("拼接成功。%s 已儲存!" % args.output)
print('完成')
if __name__ == '__main__'
print(__doc__)
static Ptr< Stitcher > create(Mode mode=Stitcher::PANORAMA)
建立一個以拼接模式之一配置的 Stitcher。
cv::String findFile(const cv::String &relative_path, bool required=true, bool silentMode=false)
嘗試查詢請求的資料檔案。
void destroyAllWindows()
銷燬所有HighGUI視窗。
CV_EXPORTS_W bool imwrite(const String &filename, InputArray img, const std::vector< int > ¶ms=std::vector< int >())
將影像儲存到指定檔案。
解釋
最重要的程式碼部分是
C++
if (status != Stitcher::OK)
{
cout << "無法拼接影像,錯誤程式碼 = " << int(status) << endl;
return EXIT_FAILURE;
}
Python
status, pano = stitcher.stitch(imgs)
if status != cv.Stitcher_OK
print("無法拼接影像,錯誤程式碼 = %d" % status)
sys.exit(-1)
建立了一個新的拼接器例項,然後cv::Stitcher::stitch 將完成所有繁重的工作。
cv::Stitcher::create 可以建立預配置的拼接器(引數為 mode)。詳細資訊請參見cv::Stitcher::Mode。這些配置將設定多個拼接器屬性,使其在預定義的場景之一中執行。在您使用預配置建立拼接器後,可以透過設定任何拼接器屬性來調整拼接。
如果您有CUDA裝置,cv::Stitcher 可以配置為將某些操作解除安裝到GPU。如果您喜歡此配置,請將 try_use_gpu 設定為 true。無論此標誌如何,OpenCL加速都將根據全域性OpenCV設定透明地使用。
拼接可能會因多種原因失敗,您應始終檢查一切是否正常,並且結果全景圖是否儲存在 pano 中。有關可能的錯誤程式碼,請參閱cv::Stitcher::Status 文件。
相機模型
拼接管線中目前實現了2種相機模型。
單應性模型適用於建立相機拍攝的全景照片,而基於仿射的模型可用於拼接掃描件和由專用裝置捕獲的物件。
- 注意
- cv::Stitcher 的某些詳細設定可能沒有意義。特別是,您不應將實現仿射模型的類與實現單應性模型的類混用,因為它們處理不同的變換。
試用
如果您啟用了構建示例,可以在 build/bin/cpp-example-stitching 下找到可執行檔案。此示例是一個控制檯應用程式,不帶引數執行可檢視幫助。opencv_extra 提供了一些示例資料用於測試所有可用配置。
嘗試全景模式執行
./cpp-example-stitching --mode panorama <path to opencv_extra>/testdata/stitching/boat*
嘗試掃描模式執行(來自家用掃描器的資料集)
./cpp-example-stitching --mode scans <path to opencv_extra>/testdata/stitching/newspaper*
或(來自專業書籍掃描器的資料集)
./cpp-example-stitching --mode scans <path to opencv_extra>/testdata/stitching/budapest*
- 注意
- 上述示例假定為POSIX平臺,在Windows上,您必須顯式提供所有檔名(例如
boat1.jpg boat2.jpg...),因為Windows命令列不支援 * 擴充套件。
詳細拼接(Python OpenCV >4.0.1)
如果您想研究拼接管線的內部工作原理或嘗試詳細配置,可以使用C++或Python提供的 stitching_detailed 原始碼
stitching_detailed
C++
Python
stitching_detailed 程式使用命令列獲取拼接引數。存在許多引數。以上示例展示了一些可能的命令列引數
boat5.jpg boat2.jpg boat3.jpg boat4.jpg boat1.jpg boat6.jpg –work_megapix 0.6 –features orb –matcher homography –estimator homography –match_conf 0.3 –conf_thresh 0.3 –ba ray –ba_refine_mask xxxxx –save_graph test.txt –wave_correct no –warp fisheye –blend multiband –expos_comp no –seam gc_colorgrad
成對影像使用單應性匹配器 –matcher homography 進行匹配,並使用估計器 –estimator homography 進行變換估計。
特徵匹配步驟的置信度為0.3:–match_conf 0.3。如果您在匹配影像時遇到困難,可以降低此值。
兩幅影像來自同一全景圖的置信度閾值為0.3:–conf_thresh 0.3。如果您在匹配影像時遇到困難,可以降低此值。
光束法平差(Bundle adjustment)的代價函式是 ray –ba ray
光束法平差的細化掩碼為 xxxxx (–ba_refine_mask xxxxx),其中 'x' 表示細化相應引數,'_' 表示不細化。細化一個,格式如下:fx,skew,ppx,aspect,ppy
將DOT語言表示的匹配圖儲存到 test.txt (–save_graph test.txt):標籤說明:Nm 為匹配數,Ni 為內點數,C 為置信度
執行波浪效應校正為 no (–wave_correct no)
扭曲表面型別為 fisheye (–warp fisheye)
混合方法為 multiband (–blend multiband)
曝光補償方法不使用 (–expos_comp no)
接縫估計器是基於最小圖割的接縫 (–seam gc_colorgrad)
您也可以在命令列中使用這些引數
boat5.jpg boat2.jpg boat3.jpg boat4.jpg boat1.jpg boat6.jpg –work_megapix 0.6 –features orb –matcher homography –estimator homography –match_conf 0.3 –conf_thresh 0.3 –ba ray –ba_refine_mask xxxxx –wave_correct horiz –warp compressedPlaneA2B1 –blend multiband –expos_comp channels_blocks –seam gc_colorgrad
您將獲得
對於使用掃描器或無人機捕獲的影像(仿射運動),您可以在命令列中使用這些引數
newspaper1.jpg newspaper2.jpg –work_megapix 0.6 –features surf –matcher affine –estimator affine –match_conf 0.3 –conf_thresh 0.3 –ba affine –ba_refine_mask xxxxx –wave_correct no –warp affine
您可以在 https://github.com/opencv/opencv_extra/tree/4.x/testdata/stitching 找到所有影像