├── .gitignore ├── LICENSE ├── README.md ├── docs_image ├── estimation_and_compose.png ├── get_camera_params.png ├── parameter_module_setup.png ├── resize.png ├── simply_call_stitch.png └── stitch_output.png ├── estimation_and_compose ├── estimation_and_compose.cpp └── estimation_and_compose.md ├── get_camera_params ├── get_camera_params.cpp └── get_camera_params.md ├── parameter_module_setup ├── parameter_module_setup.cpp └── parameter_module_setup.md ├── sample_image ├── test_image1.jpg ├── test_image2.jpg └── test_image3.jpg └── simply_call_stitch ├── simply_call_stitch.cpp └── simply_call_stitch.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/c++,cmake,opencv 3 | 4 | ### C++ ### 5 | # Prerequisites 6 | *.d 7 | 8 | # Compiled Object files 9 | *.slo 10 | *.lo 11 | *.o 12 | *.obj 13 | 14 | # Precompiled Headers 15 | *.gch 16 | *.pch 17 | 18 | # Compiled Dynamic libraries 19 | *.so 20 | *.dylib 21 | *.dll 22 | 23 | # Fortran module files 24 | *.mod 25 | *.smod 26 | 27 | # Compiled Static libraries 28 | *.lai 29 | *.la 30 | *.a 31 | *.lib 32 | 33 | # Executables 34 | *.exe 35 | *.out 36 | *.app 37 | 38 | ### CMake ### 39 | CMakeCache.txt 40 | CMakeFiles 41 | CMakeScripts 42 | Testing 43 | Makefile 44 | cmake_install.cmake 45 | install_manifest.txt 46 | compile_commands.json 47 | CTestTestfile.cmake 48 | CMakeLists.txt 49 | 50 | ### OpenCV ### 51 | #OpenCV for Mac and Linux 52 | #build and release folders 53 | */CMakeFiles 54 | */CMakeCache.txt 55 | */Makefile 56 | */cmake_install.cmake 57 | .DS_Store 58 | 59 | 60 | # End of https://www.gitignore.io/api/c++,cmake,opencv 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 ChoYG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stitching tutorial with OpenCV 2 | A repository for organizing examples and documents using OpenCV's image stitch API 3 | 4 | For understanding, testing OpenCV's stitcher. 5 | 6 | * [Simply call stitch](/simply_call_stitch/simply_call_stitch.md) 7 | Simple/short stitch example 8 | * [Estimation and compose](/estimation_and_compose/estimation_and_compose.md) 9 | Stitch example for understanding estimate camera parameter and compose panorama 10 | * [Get camera parameters](/get_camera_params/get_camera_params.md) 11 | Show how OpenCV's Stitcher API implement camera's parameter and how to get matrix of it 12 | * [Setup Parameter and module of OpenCV's stitcher](/parameter_module_setup/parameter_module_setup.md) 13 | Let's set up parameters and modules of Stitcher API 14 | 15 | This examples work with 3 images and output is one panorama image. 16 | You can also another images that taken with your camera 17 | 18 | ![output image](/docs_image/stitch_output.png) 19 | -------------------------------------------------------------------------------- /docs_image/estimation_and_compose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/docs_image/estimation_and_compose.png -------------------------------------------------------------------------------- /docs_image/get_camera_params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/docs_image/get_camera_params.png -------------------------------------------------------------------------------- /docs_image/parameter_module_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/docs_image/parameter_module_setup.png -------------------------------------------------------------------------------- /docs_image/resize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/docs_image/resize.png -------------------------------------------------------------------------------- /docs_image/simply_call_stitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/docs_image/simply_call_stitch.png -------------------------------------------------------------------------------- /docs_image/stitch_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/docs_image/stitch_output.png -------------------------------------------------------------------------------- /estimation_and_compose/estimation_and_compose.cpp: -------------------------------------------------------------------------------- 1 | #include "opencv2/imgcodecs.hpp" 2 | #include "opencv2/highgui.hpp" 3 | #include "opencv2/stitching.hpp" 4 | 5 | #include 6 | 7 | #define DEBUG_PRINT 8 | 9 | #ifdef DEBUG_PRINT 10 | #define DEBUG_PRINT_ERR(x) (std::cerr << x << std::endl) 11 | #define DEBUG_PRINT_OUT(x) (std::cout << x << std::endl) 12 | #else 13 | #define DEBUG_PRINT_ERR(x) 14 | #define DEBUG_PRINT_OUT(x) 15 | #endif 16 | 17 | using namespace std; 18 | using namespace cv; 19 | 20 | bool try_gpu = false; 21 | float imshow_scale_factor = 0.2f; 22 | 23 | int main() 24 | { 25 | Mat im1 = imread("../sample_image/test_image1.jpg"); 26 | Mat im2 = imread("../sample_image/test_image2.jpg"); 27 | Mat im3 = imread("../sample_image/test_image3.jpg"); 28 | 29 | vector imgs; 30 | imgs.push_back(im1); 31 | imgs.push_back(im2); 32 | imgs.push_back(im3); 33 | 34 | Mat output; 35 | Ptr stitcher = Stitcher::create(Stitcher::PANORAMA, try_gpu); 36 | 37 | Stitcher::Status status = stitcher->estimateTransform(imgs); 38 | 39 | if (status != Stitcher::OK) 40 | { 41 | DEBUG_PRINT_ERR("Fail stitching: "); 42 | switch(status) 43 | { 44 | case Stitcher::ERR_NEED_MORE_IMGS : 45 | DEBUG_PRINT_ERR("Need more images"); 46 | break; 47 | case Stitcher::ERR_HOMOGRAPHY_EST_FAIL : 48 | DEBUG_PRINT_ERR("Homography estimation failed"); 49 | break; 50 | case Stitcher::ERR_CAMERA_PARAMS_ADJUST_FAIL : 51 | DEBUG_PRINT_ERR("Camera parameter adjustment failed"); 52 | break; 53 | default : 54 | DEBUG_PRINT_ERR("Unknown Error"); 55 | } 56 | return -1; 57 | } 58 | 59 | stitcher->composePanorama(output); 60 | 61 | DEBUG_PRINT_OUT("resize output panorama image and show it"); 62 | Mat tmp; 63 | resize(output, tmp, Size(), imshow_scale_factor, imshow_scale_factor); 64 | imshow("Panorama image", tmp); 65 | waitKey(0); 66 | 67 | return 0; 68 | } -------------------------------------------------------------------------------- /estimation_and_compose/estimation_and_compose.md: -------------------------------------------------------------------------------- 1 | # Estimation and compose 2 | 3 | Before see this document and example, Please see 4 | [Simply call stitch](../simply_call_stitch/simply_call_stitch.md) 5 | 6 | ## What is difference? 7 | 8 | In previouse example simply_call_stitch. just call stitch method of Stitcher 9 | 10 | ```cpp 11 | Stitcher::Status status = stitcher->stitch(imgs, output); 12 | ``` 13 | 14 | Actually, there are many way to call stitcher's API to stitch. 15 | One way is call estimateTransform and composePanorama. 16 | 17 | ```cpp 18 | Stitcher::Status status = stitcher->estimateTransform(imgs); 19 | ///checking error 20 | stitcher->composePanorama(output); 21 | ``` 22 | 23 | So, this steps are just divided from stitch step. 24 | 25 | ![structure](../docs_image/estimation_and_compose.png) 26 | 27 | ### estimateTransform 28 | 29 | estimateTransform contains 30 | * Feature finding 31 | * Matching features 32 | * Homography or Affine based camera parameter estimation 33 | * Bundle adjustment 34 | 35 | ### composePanorama 36 | 37 | composePanorama contains 38 | * Warping images 39 | * Exposure compensation 40 | * Finding Seam 41 | * Blending 42 | 43 | ### Why use estimateTransform and composePanorama, not stitch method 44 | 45 | To sum up 46 | * __estimateTransform__ 47 | Find camera's parameter(intrinsic, rotation, translation,,,etc) 48 | * __composePanorama__ 49 | Combine images according to camera parameters 50 | 51 | If you want to get camera parameter calcualted from stitcher API, do like this 52 | 1. Do estimateTransform 53 | 2. Get camera parameter 54 | 3. Do composePanorama to get result image 55 | 56 | Also, OpenCV's Stitcher API provide getter of camera parameter. 57 | Let's see in the next document 58 | -------------------------------------------------------------------------------- /get_camera_params/get_camera_params.cpp: -------------------------------------------------------------------------------- 1 | #include "opencv2/imgcodecs.hpp" 2 | #include "opencv2/highgui.hpp" 3 | #include "opencv2/stitching.hpp" 4 | 5 | #include 6 | 7 | #define DEBUG_PRINT 8 | 9 | #ifdef DEBUG_PRINT 10 | #define DEBUG_PRINT_ERR(x) (std::cerr << x << std::endl) 11 | #define DEBUG_PRINT_OUT(x) (std::cout << x << std::endl) 12 | #else 13 | #define DEBUG_PRINT_ERR(x) 14 | #define DEBUG_PRINT_OUT(x) 15 | #endif 16 | 17 | using namespace std; 18 | using namespace cv; 19 | 20 | bool try_gpu = false; 21 | float imshow_scale_factor = 0.2f; 22 | 23 | int main() 24 | { 25 | Mat im1 = imread("../sample_image/test_image1.jpg"); 26 | Mat im2 = imread("../sample_image/test_image2.jpg"); 27 | Mat im3 = imread("../sample_image/test_image3.jpg"); 28 | 29 | vector imgs; 30 | imgs.push_back(im1); 31 | imgs.push_back(im2); 32 | imgs.push_back(im3); 33 | 34 | Mat output; 35 | Ptr stitcher = Stitcher::create(Stitcher::PANORAMA, try_gpu); 36 | 37 | Stitcher::Status status = stitcher->estimateTransform(imgs); 38 | 39 | if (status != Stitcher::OK) 40 | { 41 | DEBUG_PRINT_ERR("Fail stitching: "); 42 | switch(status) 43 | { 44 | case Stitcher::ERR_NEED_MORE_IMGS : 45 | DEBUG_PRINT_ERR("Need more images"); 46 | break; 47 | case Stitcher::ERR_HOMOGRAPHY_EST_FAIL : 48 | DEBUG_PRINT_ERR("Homography estimation failed"); 49 | break; 50 | case Stitcher::ERR_CAMERA_PARAMS_ADJUST_FAIL : 51 | DEBUG_PRINT_ERR("Camera parameter adjustment failed"); 52 | break; 53 | default : 54 | DEBUG_PRINT_ERR("Unknown Error"); 55 | } 56 | return -1; 57 | } 58 | 59 | vector cameras = stitcher->cameras(); 60 | 61 | for(int i = 0; i < imgs.size(); i++) 62 | { 63 | DEBUG_PRINT_OUT("----Image index " << i << " camera parameters----"); 64 | DEBUG_PRINT_OUT("Camera intrinsic matrix"); 65 | DEBUG_PRINT_OUT(cameras[i].K()); 66 | 67 | DEBUG_PRINT_OUT("Focal length : " << cameras[i].focal); 68 | 69 | DEBUG_PRINT_OUT("Aspect ratio : " << cameras[i].aspect); 70 | 71 | DEBUG_PRINT_OUT("Principle Point X : " << cameras[i].ppx); 72 | 73 | DEBUG_PRINT_OUT("Principle Point Y : " << cameras[i].ppy); 74 | 75 | DEBUG_PRINT_OUT("Rotation matrix"); 76 | DEBUG_PRINT_OUT(cameras[i].R); 77 | 78 | DEBUG_PRINT_OUT("Translation matrix"); 79 | DEBUG_PRINT_OUT(cameras[i].t); 80 | DEBUG_PRINT_OUT(" "); 81 | } 82 | 83 | return 0; 84 | } -------------------------------------------------------------------------------- /get_camera_params/get_camera_params.md: -------------------------------------------------------------------------------- 1 | # Get camera parameters 2 | 3 | Before see this docs, check below docs 4 | 5 | __Detailed Description__ part of 6 | [OpenCV's official docs](https://docs.opencv.org/3.4.2/d9/d0c/group__calib3d.html) 7 | 8 | Previous docs 9 | [Simply call stitch](../simply_call_stitch/simply_call_stitch.md) 10 | [Estimation and compose](../estimation_and_compose/estimation_and_compose.md) 11 | 12 | ## What is difference? 13 | 14 | In previous example, 15 | * calculate camera parameters with estimateTransform 16 | * compose images to panorama image with camera parameter 17 | 18 | ```cpp 19 | Stitcher::Status status = stitcher->estimateTransform(imgs); 20 | ///checking error 21 | stitcher->composePanorama(output); 22 | ``` 23 | 24 | In this example, Let's check how they store camera parameters in structure 25 | 26 | ```cpp 27 | Stitcher::Status status = stitcher->estimateTransform(imgs); 28 | 29 | ///checking error 30 | 31 | vector cameras = stitcher->cameras(); 32 | 33 | for(int i = 0; i < imgs.size(); i++) 34 | { 35 | DEBUG_PRINT_OUT("----Image index " << i << " camera parameters----"); 36 | DEBUG_PRINT_OUT("Camera intrinsic matrix"); 37 | DEBUG_PRINT_OUT(cameras[i].K()); 38 | 39 | DEBUG_PRINT_OUT("Focal length : " << cameras[i].focal); 40 | 41 | DEBUG_PRINT_OUT("Aspect ratio : " << cameras[i].aspect); 42 | 43 | DEBUG_PRINT_OUT("Principle Point X : " << cameras[i].ppx); 44 | 45 | DEBUG_PRINT_OUT("Principle Point Y : " << cameras[i].ppy); 46 | 47 | DEBUG_PRINT_OUT("Rotation matrix"); 48 | DEBUG_PRINT_OUT(cameras[i].R); 49 | 50 | DEBUG_PRINT_OUT("Translation matrix"); 51 | DEBUG_PRINT_OUT(cameras[i].t); 52 | DEBUG_PRINT_OUT(" "); 53 | } 54 | ``` 55 | 56 | ![structure](../docs_image/get_camera_params.png) 57 | 58 | ## What is CameraParams? 59 | Call cameras getter from Stitcher API, You can get camera parameters 60 | ```cpp 61 | vector cameras = stitcher->cameras(); 62 | ``` 63 | 64 | Definition of this structure is in OpenCV's stitcher moduls's detail 65 | "include/opencv2/stitching/detail/camera.hpp" 66 | 67 | ```cpp 68 | struct CV_EXPORTS CameraParams 69 | { 70 | CameraParams(); 71 | CameraParams(const CameraParams& other); 72 | const CameraParams& operator =(const CameraParams& other); 73 | Mat K() const; 74 | 75 | double focal; // Focal length 76 | double aspect; // Aspect ratio 77 | double ppx; // Principal point X 78 | double ppy; // Principal point Y 79 | Mat R; // Rotation 80 | Mat t; // Translation 81 | }; 82 | ``` 83 | * __K matrix__ 84 | camera's intrinsic matrix, include Focal length and Principle point 85 | * __focal__ 86 | Focal length 87 | * __aspect__ 88 | Scale factor 89 | * __ppx and ppy__ 90 | Principle point 91 | * __R matrix__ 92 | Rotation matrix 93 | * __t matrix__ 94 | Translation matrix 95 | 96 | With these informations, You can do another work that camera parmameter related. 97 | 98 | ## Result print out 99 | 100 | With this repo's sample images 101 | 102 | ``` 103 | ----Image index 0 camera parameters---- 104 | Camera intrinsic matrix 105 | [709.650348798485, 0, 447; 106 | 0, 709.650348798485, 335.5; 107 | 0, 0, 1] 108 | Focal length : 709.65 109 | Aspect ratio : 1 110 | Principle Point X : 447 111 | Principle Point Y : 335.5 112 | Rotation matrix 113 | [0.93108684, 0.035384167, -0.36307758; 114 | 0.0001988858, 0.99523526, 0.097501867; 115 | 0.36479765, -0.090854913, 0.92664331] 116 | Translation matrix 117 | [0; 118 | 0; 119 | 0] 120 | 121 | ----Image index 1 camera parameters---- 122 | Camera intrinsic matrix 123 | [719.9602633448541, 0, 447; 124 | 0, 719.9602633448541, 335.5; 125 | 0, 0, 1] 126 | Focal length : 719.96 127 | Aspect ratio : 1 128 | Principle Point X : 447 129 | Principle Point Y : 335.5 130 | Rotation matrix 131 | [0.99949676, 0.0036283, -0.031512056; 132 | -0.00032901776, 0.99456888, 0.10407893; 133 | 0.031718541, -0.10401618, 0.99406964] 134 | Translation matrix 135 | [0; 136 | 0; 137 | 0] 138 | 139 | ----Image index 2 camera parameters---- 140 | Camera intrinsic matrix 141 | [743.4787164662755, 0, 447; 142 | 0, 743.4787164662755, 335.5; 143 | 0, 0, 1] 144 | Focal length : 743.479 145 | Aspect ratio : 1 146 | Principle Point X : 447 147 | Principle Point Y : 335.5 148 | Rotation matrix 149 | [0.91788989, -0.042156182, 0.39458963; 150 | 0.00015651435, 0.99437976, 0.10587097; 151 | -0.39683512, -0.09711612, 0.91273779] 152 | Translation matrix 153 | [0; 154 | 0; 155 | 0] 156 | 157 | ``` 158 | -------------------------------------------------------------------------------- /parameter_module_setup/parameter_module_setup.cpp: -------------------------------------------------------------------------------- 1 | #include "opencv2/imgcodecs.hpp" 2 | #include "opencv2/highgui.hpp" 3 | #include "opencv2/stitching.hpp" 4 | 5 | #include 6 | 7 | #define DEBUG_PRINT 8 | 9 | #ifdef DEBUG_PRINT 10 | #define DEBUG_PRINT_ERR(x) (std::cerr << x << std::endl) 11 | #define DEBUG_PRINT_OUT(x) (std::cout << x << std::endl) 12 | #else 13 | #define DEBUG_PRINT_ERR(x) 14 | #define DEBUG_PRINT_OUT(x) 15 | #endif 16 | 17 | using namespace std; 18 | using namespace cv; 19 | 20 | bool try_gpu = false; 21 | float imshow_scale_factor = 0.2f; 22 | 23 | int main() 24 | { 25 | Mat im1 = imread("../sample_image/test_image1.jpg"); 26 | Mat im2 = imread("../sample_image/test_image2.jpg"); 27 | Mat im3 = imread("../sample_image/test_image3.jpg"); 28 | 29 | vector imgs; 30 | imgs.push_back(im1); 31 | imgs.push_back(im2); 32 | imgs.push_back(im3); 33 | 34 | Mat output; 35 | Ptr stitcher = Stitcher::create(Stitcher::PANORAMA, try_gpu); 36 | 37 | stitcher->setRegistrationResol(0.5); 38 | stitcher->setSeamEstimationResol(0.1); 39 | stitcher->setCompositingResol(Stitcher::ORIG_RESOL); 40 | stitcher->setPanoConfidenceThresh(1.0); 41 | stitcher->setWaveCorrection(true); 42 | stitcher->setWaveCorrectKind(detail::WAVE_CORRECT_HORIZ); 43 | 44 | stitcher->setFeaturesFinder(makePtr()); 45 | stitcher->setFeaturesMatcher(makePtr(try_gpu)); 46 | stitcher->setBundleAdjuster(makePtr()); 47 | stitcher->setWarper(makePtr()); 48 | stitcher->setExposureCompensator(makePtr()); 49 | stitcher->setSeamFinder(makePtr()); 50 | stitcher->setBlender(makePtr()); 51 | 52 | Stitcher::Status status = stitcher->stitch(imgs, output); 53 | 54 | if (status != Stitcher::OK) 55 | { 56 | DEBUG_PRINT_ERR("Fail stitching: "); 57 | switch(status) 58 | { 59 | case Stitcher::ERR_NEED_MORE_IMGS : 60 | DEBUG_PRINT_ERR("Need more images"); 61 | break; 62 | case Stitcher::ERR_HOMOGRAPHY_EST_FAIL : 63 | DEBUG_PRINT_ERR("Homography estimation failed"); 64 | break; 65 | case Stitcher::ERR_CAMERA_PARAMS_ADJUST_FAIL : 66 | DEBUG_PRINT_ERR("Camera parameter adjustment failed"); 67 | break; 68 | default : 69 | DEBUG_PRINT_ERR("Unknown Error"); 70 | } 71 | } 72 | else 73 | { 74 | DEBUG_PRINT_OUT("resize output panorama image and show it"); 75 | Mat tmp; 76 | resize(output, tmp, Size(), imshow_scale_factor, imshow_scale_factor); 77 | imshow("Panorama image", tmp); 78 | waitKey(0); 79 | } 80 | 81 | return 0; 82 | } -------------------------------------------------------------------------------- /parameter_module_setup/parameter_module_setup.md: -------------------------------------------------------------------------------- 1 | # Setup Parameter and module of OpenCV's stitcher 2 | 3 | Before read this docs, this docs from another guys can help you 4 | [Basic Stitching Pipeline](https://sites.google.com/site/ritpanoramaapp/project-stage-iii) 5 | 6 | and, Please see previous docs 7 | [Simply call stitch](../simply_call_stitch/simply_call_stitch.md) 8 | [Estimation and compose](../estimation_and_compose/estimation_and_compose.md) 9 | [Get camera parameters](../get_camera_params/get_camera_params.md) 10 | 11 | ## What is difference? 12 | 13 | The purpose of this docs is for setting up custom stitcher 14 | So, in this example, We try to apply setup method of stitcher 15 | 16 | ![structure](../docs_image/parameter_module_setup.png) 17 | 18 | ## How to setup 19 | 20 | ```cpp 21 | Mat output; 22 | Ptr stitcher = Stitcher::create(Stitcher::PANORAMA, try_gpu); 23 | 24 | stitcher->setRegistrationResol(0.5); 25 | stitcher->setSeamEstimationResol(0.1); 26 | stitcher->setCompositingResol(Stitcher::ORIG_RESOL); 27 | stitcher->setPanoConfidenceThresh(1.0); 28 | stitcher->setWaveCorrection(true); 29 | stitcher->setWaveCorrectKind(detail::WAVE_CORRECT_HORIZ); 30 | 31 | stitcher->setFeaturesFinder(makePtr()); 32 | stitcher->setFeaturesMatcher(makePtr(try_gpu)); 33 | stitcher->setBundleAdjuster(makePtr()); 34 | stitcher->setWarper(makePtr()); 35 | stitcher->setExposureCompensator(makePtr()); 36 | stitcher->setSeamFinder(makePtr()); 37 | stitcher->setBlender(makePtr()); 38 | 39 | Stitcher::Status status = stitcher->stitch(imgs, output); 40 | ``` 41 | 42 | Stitcher API's parameter and module setup methods start with 'set' 43 | 44 | ### Parameter setup 45 | * __setRegistrationResol__ 46 | For speed up, resize images. argument is ratio of resized image 47 | ex) 0.5 means image will resized to half of area of original size 48 | * __setSeamEstimationResol__ 49 | For speed up, resize images for Seam finder. argument is ratio of resized image 50 | ex) 0.1 means image will resized to 10 percent of area of original size 51 | * __setCompositingResol__ 52 | For speed up, resize images when compose panorama. argument is ratio of resized image 53 | ex) ORIG_RESOL means images will not be resized 54 | * __setPanoConfidenceThresh__ 55 | Threshold for bundle adjustment module 56 | * __setWaveCorrection__ 57 | Do wave correction or not, for preventing wavy effect of panorama image 58 | * __setWaveCorrectKind__ 59 | Type of wave correction 60 | 61 | ### Module setup 62 | * __setFeaturesFinder__ 63 | Set module to find feature point and calculate descriptor of feature 64 | * __setFeaturesMatcher__ 65 | Set module to match found features 66 | * __setBundleAdjuster__ 67 | Set module to bundle adjustment 68 | * __setWarper__ 69 | Set module to warp images according to found camera parameter 70 | * __setExposureCompensator__ 71 | Set module to compensate exposure 72 | * __setSeamFinder__ 73 | Set module to find seam from warped images 74 | * __setBlender__ 75 | Set module to blend warped and seam found images 76 | 77 | # Why resize image? 78 | 79 | Some modules like Seam finder and Exposure compensator takes too much time if work with original image 80 | So, They resize images for that modules 81 | 82 | ![resize](../docs_image/resize.png) 83 | -------------------------------------------------------------------------------- /sample_image/test_image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/sample_image/test_image1.jpg -------------------------------------------------------------------------------- /sample_image/test_image2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/sample_image/test_image2.jpg -------------------------------------------------------------------------------- /sample_image/test_image3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whdlgp/Stitching-tutorial-with-OpenCV/d9150dac1db22c9a57612c596fcc3a10a726c423/sample_image/test_image3.jpg -------------------------------------------------------------------------------- /simply_call_stitch/simply_call_stitch.cpp: -------------------------------------------------------------------------------- 1 | #include "opencv2/imgcodecs.hpp" 2 | #include "opencv2/highgui.hpp" 3 | #include "opencv2/stitching.hpp" 4 | 5 | #include 6 | 7 | #define DEBUG_PRINT 8 | 9 | #ifdef DEBUG_PRINT 10 | #define DEBUG_PRINT_ERR(x) (std::cerr << x << std::endl) 11 | #define DEBUG_PRINT_OUT(x) (std::cout << x << std::endl) 12 | #else 13 | #define DEBUG_PRINT_ERR(x) 14 | #define DEBUG_PRINT_OUT(x) 15 | #endif 16 | 17 | using namespace std; 18 | using namespace cv; 19 | 20 | bool try_gpu = false; 21 | float imshow_scale_factor = 0.2f; 22 | 23 | int main() 24 | { 25 | Mat im1 = imread("../sample_image/test_image1.jpg"); 26 | Mat im2 = imread("../sample_image/test_image2.jpg"); 27 | Mat im3 = imread("../sample_image/test_image3.jpg"); 28 | 29 | vector imgs; 30 | imgs.push_back(im1); 31 | imgs.push_back(im2); 32 | imgs.push_back(im3); 33 | 34 | Mat output; 35 | Ptr stitcher = Stitcher::create(Stitcher::PANORAMA, try_gpu); 36 | Stitcher::Status status = stitcher->stitch(imgs, output); 37 | 38 | if (status != Stitcher::OK) 39 | { 40 | DEBUG_PRINT_ERR("Fail stitching: "); 41 | switch(status) 42 | { 43 | case Stitcher::ERR_NEED_MORE_IMGS : 44 | DEBUG_PRINT_ERR("Need more images"); 45 | break; 46 | case Stitcher::ERR_HOMOGRAPHY_EST_FAIL : 47 | DEBUG_PRINT_ERR("Homography estimation failed"); 48 | break; 49 | case Stitcher::ERR_CAMERA_PARAMS_ADJUST_FAIL : 50 | DEBUG_PRINT_ERR("Camera parameter adjustment failed"); 51 | break; 52 | default : 53 | DEBUG_PRINT_ERR("Unknown Error"); 54 | } 55 | } 56 | else 57 | { 58 | DEBUG_PRINT_OUT("resize output panorama image and show it"); 59 | Mat tmp; 60 | resize(output, tmp, Size(), imshow_scale_factor, imshow_scale_factor); 61 | imshow("Panorama image", tmp); 62 | waitKey(0); 63 | } 64 | 65 | return 0; 66 | } -------------------------------------------------------------------------------- /simply_call_stitch/simply_call_stitch.md: -------------------------------------------------------------------------------- 1 | # Simply call stitch 2 | 3 | This example shows easiest way of OpenCV's stitcher 4 | Just call stitch method 5 | 6 | ![structure](../docs_image/simply_call_stitch.png) 7 | 8 | ## Include, definition 9 | 10 | ```cpp 11 | #include "opencv2/imgcodecs.hpp" 12 | #include "opencv2/highgui.hpp" 13 | #include "opencv2/stitching.hpp" 14 | 15 | #include 16 | ``` 17 | 18 | * imgcodecs module is for reading and decoding images 19 | * highgui module is for showing output images with imshow 20 | * stitching module is API for image stitching, contains part of stitching. 21 | 22 | ```cpp 23 | #ifdef DEBUG_PRINT 24 | #define DEBUG_PRINT_ERR(x) (std::cerr << x << std::endl) 25 | #define DEBUG_PRINT_OUT(x) (std::cout << x << std::endl) 26 | #else 27 | #define DEBUG_PRINT_ERR(x) 28 | #define DEBUG_PRINT_OUT(x) 29 | #endif 30 | 31 | using namespace std; 32 | using namespace cv; 33 | 34 | bool try_gpu = false; 35 | float imshow_scale_factor = 0.2f; 36 | ``` 37 | 38 | * DEBUG_PRINT is print wraper for debug 39 | * This example use C++'s STL and OpenCV, for convenience, list namespaces in advance. 40 | * OpenCV has useful option for applying GPU acceleration with CUDA, try_use is for it 41 | * If your sample images is too big, just set imshow_scale_factor to resize output image 42 | 43 | ## In main 44 | 45 | ### Read/Prepare images to stitch 46 | ```cpp 47 | Mat im1 = imread("../sample_image/test_image1.jpg"); 48 | Mat im2 = imread("../sample_image/test_image2.jpg"); 49 | Mat im3 = imread("../sample_image/test_image3.jpg"); 50 | 51 | vector imgs; 52 | imgs.push_back(im1); 53 | imgs.push_back(im2); 54 | imgs.push_back(im3); 55 | ``` 56 | 57 | * First read images with imread 58 | * OpenCV's stitcher API need std::vector of cv::Mat, prepare it 59 | 60 | ### Create instance for Stitcher, call stitch method 61 | 62 | ```cpp 63 | Mat output; 64 | Ptr stitcher = Stitcher::create(Stitcher::PANORAMA, try_gpu); 65 | Stitcher::Status status = stitcher->stitch(imgs, output); 66 | ``` 67 | 68 | * Prepare output Mat 69 | * Create Stitcher as panorama image, set GPU acceleration option 70 | * call stitch method to stitch 71 | 72 | ### Checking error, show output image 73 | 74 | ```cpp 75 | if (status != Stitcher::OK) 76 | { 77 | DEBUG_PRINT_ERR("Fail stitching: "); 78 | switch(status) 79 | { 80 | case Stitcher::ERR_NEED_MORE_IMGS : 81 | DEBUG_PRINT_ERR("Need more images"); 82 | break; 83 | case Stitcher::ERR_HOMOGRAPHY_EST_FAIL : 84 | DEBUG_PRINT_ERR("Homography estimation failed"); 85 | break; 86 | case Stitcher::ERR_CAMERA_PARAMS_ADJUST_FAIL : 87 | DEBUG_PRINT_ERR("Camera parameter adjustment failed"); 88 | break; 89 | default : 90 | DEBUG_PRINT_ERR("Unknown Error"); 91 | } 92 | } 93 | else 94 | { 95 | DEBUG_PRINT_OUT("resize output panorama image and show it"); 96 | Mat tmp; 97 | resize(output, tmp, Size(), imshow_scale_factor, imshow_scale_factor); 98 | imshow("Panorama image", tmp); 99 | waitKey(0); 100 | } 101 | ``` 102 | 103 | * Check status of Stitcher. If error, print out meaning of error 104 | * If there are no error, show output images. If image is too big, resize it according to imshow_scale_factor 105 | 106 | ## Result 107 | 108 | If stitcher API work well, you can see stitched image like below 109 | 110 | ![stitch_output](../docs_image/stitch_output.png) 111 | --------------------------------------------------------------------------------