이미지 여러장 저장하기 - OpenCV(C++)
Updated:
D435를 이용해 이미지를 여러 장 저장하기
Visual Studio 2017을 사용하였습니다.
- Realsense SDK 2.0, OpenCV 사용
Calibration을 하기 위해 많은 이미지가 필요합니다. 물론 한 장의 이미지로도 충분히 구할 수는 있지만 정확도가 매우 낮기 때문에 저의 경우 사진을 여러장 찍었습니다.
D435를 이용하여 촬영을 하였고, Stereo Calibration을 위해 IR camera를 사용해 왼쪽과 오른쪽의 이미지를 얻었습니다. 코드는 다음과 같습니다.
코드는 저번에 구현했던 Disparity Map 추출하는 코드에서 수정하였습니다.
#pragma warning(disable:4996);
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <opencv2/opencv_modules.hpp>
#include <librealsense2/rs.hpp>
#include <iostream>
#include <vector>
using namespace std;
// Defining the dimensions of checkerboard
int CHECKERBOARD[2]{ 6, 9 };
int main()
{
/****************************************************************/
/* IR 이미지 캡쳐하기 */
/* Contruct a pipeline which abstracts the device */
rs2::pipeline pipe;
/* Create a configuration for configuring the pipeline with a non default profile */
rs2::config cfg;
/* Add desired streams to configuration */
cfg.enable_stream(RS2_STREAM_INFRARED, 1, 640, 480, RS2_FORMAT_Y8, 30);
cfg.enable_stream(RS2_STREAM_INFRARED, 2, 640, 480, RS2_FORMAT_Y8, 30);
/* Instruct pipeline to start streaming with the requested configuration */
pipe.start(cfg);
/* Camera warmup - dropping several first frames to let auto-exposure stabilize */
rs2::frameset frames;
char buf[256]; // 이미지 경로를 저장하기 위해 선언
int index = 0; // 이미지 index
bool success = false; // 저장 키 활성화/비활성화
std::vector<cv::Point> ir1_arr; // findChessboardCorners를 위해 선언하였지만
std::vector<cv::Point> ir2_arr; // 값은 사용하지 않는 dummy value
while (1)
{
/* Wait for all configured streams to produce a frame */
frames = pipe.wait_for_frames();
/* Get each frame */
rs2::frame ir_frame1 = frames.get_infrared_frame(1);
rs2::frame ir_frame2 = frames.get_infrared_frame(2);
/* Creating OpenCV Matrix from a color image */
cv::Mat ir1(cv::Size(640, 480), CV_8UC1, (void*)ir_frame1.get_data(), cv::Mat::AUTO_STEP); // 왼쪽
cv::Mat ir2(cv::Size(640, 480), CV_8UC1, (void*)ir_frame2.get_data(), cv::Mat::AUTO_STEP); // 오른쪽
imshow("Display Image1", ir1);
imshow("Display Image2", ir2);
int key = cv::waitKey(10);
if ((key == 82) || (key == 114)) // r 키 또는 R 키 사용
success = true;
// 이미지는 저장했지만 추후 calibration 시에 chessboard를 못 찾을 수 있으므로 찾았을 때만 이미지 저장한다.
// 여기서 OutputArray인 corners는 사용하지 않기 때문에 dummy라고 볼 수 있습니다.
// 추후 Calibration 포스팅에서 사용
// bool findChessboardCorners(InputArray image, Size patternSize, OutputArray corners, int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE )
if (success == true
&& cv::findChessboardCorners(ir1, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), ir1_arr, cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE)
&& cv::findChessboardCorners(ir2, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), ir2_arr, cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE))
{// R키를 눌렀으며 && 우 IR 이미지와 좌 IR 이미지가 모드 chessboard corner를 찾을 때만 저장되도록
sprintf(buf, "D:\\Cali_images\\%d_Left.jpg", index); // 왼쪽 이미지 저장
cv::imwrite(buf, ir1);
sprintf(buf, "D:\\Cali_images\\%d_Right.jpg", index); // 오른쪽 이미지 저장
cv::imwrite(buf, ir2);
index++;
success = false; // R or r 키 비활성화
}
if (key == 27) // esc 누르면 while문 탈출
break;
}
return 0;
}
결과 이미지 캡쳐
-
Left IR Camera Image Sample
-
Right IR Camera Image Sample
Leave a comment