[Github Result]
[Reference Site]
- OpenCV Description
- Image Stitching
- Image Stitching with Masking
[OpecCV Description]
- 간단하게 설명하면 stitching을 위해서 기초적으로 feature extraction과 feature matching을 통해서 이미지간의 homography를 추정하게 되는데 이때, 추출되는 이미지 feature가 이미지 간의 overlap 되지 않은 부분에 focus 되면 stitching의 성능을 저하시킬 수 있기 때문에 masking(RoI)을 적용하여 overlap 되는 부분에 focus를 시킴으로서 성능을 높혀주기 위함이다.
- OpenCV 3.2.0 기준으로 masking(RoI) setting 하는 부분까지 설명된 코드는 다음과 같다.
- Stitch Function Arguments:
- InputArrayOfArrays images = std::vector images
- std::vector<std::vector<cv::Rect>> &rois
- 여기서 std::vector 안에 std::vector가 붙은 이유는 하나의 이미지 안에도 여러 가지 interesting region들이 존재할 수 있기 때문이다.
- 그래서 각 이미지 마다 std::vector로 관심 있는 영역을 Setting 해주고 stitching 하는 총 이미지 개수만큼 rois 에 차례대로 push_back 해주면 된다.
- OutputArray pano = cv::Mat
- Stitch Function Arguments:
Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois, OutputArray pano)
{
Status status = estimateTransform(images, rois);
if (status != OK)
return status;
return composePanorama(pano);
}
[Code]
- 다음과 같은 opencv library들을 포함: imgcodecs, highgui, stitching
#include <iostream>
#include <fstream>
// stitching related
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/stitching.hpp"
int main()
{
// Define mode for stitching as panorama
cv::Stitcher::Mode mode = cv::Stitcher::PANORAMA;
// Road images
cv::Mat left = cv::imread("/home/sj/iros2022/image/left.jpg", 1);
cv::Mat front = cv::imread("/home/sj/iros2022/image/front.jpg", 1);
cv::Mat right = cv::imread("/home/sj/iros2022/image/right.jpg", 1);
// Check image read correctly
if(left.cols != 0)
std::cout << "Correctly read left image !!" << std::endl;
if(front.cols != 0)
std::cout << "Correctly read front image !!" << std::endl;
if(right.cols != 0)
std::cout << "Correctly read right image !!" << std::endl;
// Combine three images in one vector
std::vector<cv::Mat> imgs;
imgs.push_back(left);
imgs.push_back(front);
imgs.push_back(right);
// Initialization output image
cv::Mat panorama;
// Add Masking
std::vector<std::vector<cv::Rect>> masks;
std::vector<cv::Rect> mask1;
std::vector<cv::Rect> mask2;
std::vector<cv::Rect> mask3;
// Define cv::Rect what part we focus on !!
cv::Rect left_rect(int(left.cols/2), 0, int(left.cols/2) , left.rows);
cv::Rect front_rect(0, 0, front.cols, front.rows);
cv::Rect right_rect(0, 0, int(right.cols/2), right.rows);
// Set the desired RoI for each image
mask1.push_back(left_rect);
mask2.push_back(front_rect);
mask3.push_back(right_rect);
masks.push_back(mask1);
masks.push_back(mask2);
masks.push_back(mask3);
// Make panorama image using cv::Stitcher adding masks
cv::Ptr<cv::Stitcher> stitcher = cv::Stitcher::create(mode, false);
cv::Stitcher::Status status = stitcher->stitch(imgs, masks, panorama);
// Write and show result image
cv::imwrite("/home/sj/iros2022/image/result.jpg", panorama);
cv::imshow("Result", panorama);
// Wait image not auto cancel
cv::waitKey(0);
return 0;
}
[Compile]
- C++을 사용하였고 3개의 라이브러리를 포함하고 있으므로 stitching 이라는 이름을 가진 exeutive file을 만들어줌
g++ stitching.cpp -L/usr/local/include/opencv2 -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_core -lopencv_stitching -o stitching
-
- g++: c++ & gcc: c
- stitching.cpp: 현재 저장되어 있는 코드의 이름
- -L: 포함된 라이브러리가 있는 경로
- -lopencv_~: 코드에 포함된 라이브러리들
- -o: 실행파일에 대한 정보를 입력할 flag
- stitching: 실행파일의 이름
[Run]
- 해당 파일에 다음과 같이 작성해주면 컴파일한 코드를 빌드 및 실행
# Example of current path: ~/src/Stitching
./stitching
[Output]
- Masking Setting
Left Masking | Front Masking | Right Masking |
- Output image
- 각 3개의 이미지들에 masking 을 적용한 것을 visualization
-
- 기존에 실험했던 이미지를 가지고 masking 적용 전후 비교
Masking 적용 전 |
Masking 적용 후 |