1 /* 2 * test-image-stitching.cpp - test image stitching 3 * 4 * Copyright (c) 2016 Intel Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Yinhang Liu <yinhangx.liu (at) intel.com> 19 * Author: Wind Yuan <feng.yuan (at) intel.com> 20 */ 21 22 #include "test_common.h" 23 #include "test_inline.h" 24 #include <unistd.h> 25 #include <getopt.h> 26 #include <image_file_handle.h> 27 #include <calibration_parser.h> 28 #include <ocl/cl_device.h> 29 #include <ocl/cl_context.h> 30 #include <ocl/cl_fisheye_handler.h> 31 #include <ocl/cl_image_360_stitch.h> 32 #include <ocl/cl_utils.h> 33 #if HAVE_OPENCV 34 #include <ocl/cv_base_class.h> 35 #endif 36 37 #define XCAM_TEST_STITCH_DEBUG 0 38 #define XCAM_ALIGNED_WIDTH 16 39 40 #define CHECK_ACCESS(fliename) \ 41 if (access (fliename, F_OK) != 0) { \ 42 XCAM_LOG_ERROR ("%s not found", fliename); \ 43 return false; \ 44 } 45 46 using namespace XCam; 47 48 #if XCAM_TEST_STITCH_DEBUG 49 static void dbg_write_image ( 50 SmartPtr<CLContext> context, SmartPtr<CLImage360Stitch> image_360, 51 SmartPtr<VideoBuffer> input_bufs[], SmartPtr<VideoBuffer> output_buf, 52 SmartPtr<VideoBuffer> top_view_buf, SmartPtr<VideoBuffer> rectified_view_buf, 53 bool all_in_one, int fisheye_num, int input_count); 54 #endif 55 56 static bool 57 parse_calibration_params ( 58 IntrinsicParameter intrinsic_param[], 59 ExtrinsicParameter extrinsic_param[], 60 int fisheye_num) 61 { 62 CalibrationParser calib_parser; 63 64 char intrinsic_path[1024], extrinsic_path[1024]; 65 for(int index = 0; index < fisheye_num; index++) { 66 switch (index) { 67 case 0: 68 strncpy (intrinsic_path, "./calib_params/intrinsic_camera_front.txt", 1023); 69 strncpy (extrinsic_path, "./calib_params/extrinsic_camera_front.txt", 1023); 70 break; 71 case 1: 72 strncpy (intrinsic_path, "./calib_params/intrinsic_camera_right.txt", 1023); 73 strncpy (extrinsic_path, "./calib_params/extrinsic_camera_right.txt", 1023); 74 break; 75 case 2: 76 strncpy (intrinsic_path, "./calib_params/intrinsic_camera_rear.txt", 1023); 77 strncpy (extrinsic_path, "./calib_params/extrinsic_camera_rear.txt", 1023); 78 break; 79 case 3: 80 strncpy (intrinsic_path, "./calib_params/intrinsic_camera_left.txt", 1023); 81 strncpy (extrinsic_path, "./calib_params/extrinsic_camera_left.txt", 1023); 82 break; 83 default: 84 XCAM_LOG_ERROR ("bowl view only support 4-camera mode"); 85 return false; 86 } 87 88 CHECK_ACCESS (intrinsic_path); 89 CHECK_ACCESS (extrinsic_path); 90 91 if (!xcam_ret_is_ok ( 92 calib_parser.parse_intrinsic_file (intrinsic_path, intrinsic_param[index]))) { 93 XCAM_LOG_ERROR ("parse fisheye:%d intrinsic file:%s failed.", index, intrinsic_path); 94 return false; 95 } 96 if (!xcam_ret_is_ok ( 97 calib_parser.parse_extrinsic_file (extrinsic_path, extrinsic_param[index]))) { 98 XCAM_LOG_ERROR ("parse fisheye:%d extrinsic file:%s failed.", index, extrinsic_path); 99 return false; 100 } 101 102 extrinsic_param[index].trans_x += TEST_CAMERA_POSITION_OFFSET_X; 103 } 104 105 return true; 106 } 107 108 XCamReturn 109 read_file_to_video_buffer ( 110 ImageFileHandle &file, 111 uint32_t width, 112 uint32_t height, 113 uint32_t row_pitch, 114 SmartPtr<VideoBuffer> &buf) 115 { 116 size_t size = row_pitch * height / 2 * 3; 117 uint8_t *nv12_mem = (uint8_t *) xcam_malloc0 (sizeof (uint8_t) * size); 118 XCAM_ASSERT (nv12_mem); 119 120 XCamReturn ret = file.read_file (nv12_mem, size); 121 if (ret != XCAM_RETURN_NO_ERROR) { 122 xcam_free (nv12_mem); 123 return ret; 124 } 125 126 uint32_t offset_uv = row_pitch * height; 127 convert_nv12_mem_to_video_buffer (nv12_mem, width, height, row_pitch, offset_uv, buf); 128 XCAM_ASSERT (buf.ptr ()); 129 130 xcam_free (nv12_mem); 131 return XCAM_RETURN_NO_ERROR; 132 } 133 134 void usage(const char* arg0) 135 { 136 printf ("Usage:\n" 137 "%s --input file --output file\n" 138 "\t--input input image(NV12)\n" 139 "\t--output output image(NV12)\n" 140 "\t--input-w optional, input width, default: 1920\n" 141 "\t--input-h optional, input height, default: 1080\n" 142 "\t--output-w optional, output width, default: 1920\n" 143 "\t--output-h optional, output width, default: 960\n" 144 "\t--res-mode optional, image resolution mode, select from [1080p/1080p4/4k], default: 1080p\n" 145 "\t--surround-mode optional, stitching surround mode, select from [sphere, bowl], default: sphere\n" 146 "\t--scale-mode optional, image scaling mode, select from [local/global], default: local\n" 147 "\t--enable-seam optional, enable seam finder in blending area, default: no\n" 148 "\t--enable-fisheyemap optional, enable fisheye map, default: no\n" 149 "\t--enable-lsc optional, enable lens shading correction, default: no\n" 150 #if HAVE_OPENCV 151 "\t--fm-ocl optional, enable ocl for feature match, select from [true/false], default: false\n" 152 #endif 153 "\t--fisheye-num optional, the number of fisheye lens, default: 2\n" 154 "\t--all-in-one optional, all fisheye in one image, select from [true/false], default: true\n" 155 "\t--save optional, save file or not, select from [true/false], default: true\n" 156 "\t--framerate optional, framerate of saved video, default: 30.0\n" 157 "\t--loop optional, how many loops need to run for performance test, default: 1\n" 158 "\t--help usage\n", 159 arg0); 160 } 161 162 int main (int argc, char *argv[]) 163 { 164 XCamReturn ret = XCAM_RETURN_NO_ERROR; 165 SmartPtr<CLContext> context; 166 SmartPtr<BufferPool> buf_pool[XCAM_STITCH_FISHEYE_MAX_NUM]; 167 ImageFileHandle file_in[XCAM_STITCH_FISHEYE_MAX_NUM]; 168 ImageFileHandle file_out; 169 SmartPtr<VideoBuffer> input_buf, output_buf, top_view_buf, rectified_view_buf; 170 VideoBufferInfo input_buf_info, output_buf_info, top_view_buf_info, rectified_view_buf_info; 171 SmartPtr<CLImage360Stitch> image_360; 172 173 uint32_t input_format = V4L2_PIX_FMT_NV12; 174 uint32_t input_width = 1920; 175 uint32_t input_height = 1080; 176 uint32_t output_height = 960; 177 uint32_t output_width = output_height * 2; 178 179 uint32_t top_view_width = 1920; 180 uint32_t top_view_height = 1080; 181 182 uint32_t rectified_view_width = 1920; 183 uint32_t rectified_view_height = 1080; 184 185 int loop = 1; 186 bool enable_seam = false; 187 bool enable_fisheye_map = false; 188 bool enable_lsc = false; 189 CLBlenderScaleMode scale_mode = CLBlenderScaleLocal; 190 StitchResMode res_mode = StitchRes1080P; 191 SurroundMode surround_mode = BowlView; 192 193 IntrinsicParameter intrinsic_param[XCAM_STITCH_FISHEYE_MAX_NUM]; 194 ExtrinsicParameter extrinsic_param[XCAM_STITCH_FISHEYE_MAX_NUM]; 195 196 #if HAVE_OPENCV 197 bool fm_ocl = false; 198 #endif 199 int fisheye_num = 2; 200 bool all_in_one = true; 201 bool need_save_output = true; 202 double framerate = 30.0; 203 204 const char *file_in_name[XCAM_STITCH_FISHEYE_MAX_NUM] = {NULL}; 205 const char *file_out_name = NULL; 206 const char *top_view_filename = "top_view.mp4"; 207 const char *rectified_view_filename = "rectified_view.mp4"; 208 209 int input_count = 0; 210 211 const struct option long_opts[] = { 212 {"input", required_argument, NULL, 'i'}, 213 {"output", required_argument, NULL, 'o'}, 214 {"input-w", required_argument, NULL, 'w'}, 215 {"input-h", required_argument, NULL, 'h'}, 216 {"output-w", required_argument, NULL, 'W'}, 217 {"output-h", required_argument, NULL, 'H'}, 218 {"res-mode", required_argument, NULL, 'R'}, 219 {"surround-mode", required_argument, NULL, 'r'}, 220 {"scale-mode", required_argument, NULL, 'c'}, 221 {"enable-seam", no_argument, NULL, 'S'}, 222 {"enable-fisheyemap", no_argument, NULL, 'F'}, 223 {"enable-lsc", no_argument, NULL, 'L'}, 224 #if HAVE_OPENCV 225 {"fm-ocl", required_argument, NULL, 'O'}, 226 #endif 227 {"fisheye-num", required_argument, NULL, 'N'}, 228 {"all-in-one", required_argument, NULL, 'A'}, 229 {"save", required_argument, NULL, 's'}, 230 {"framerate", required_argument, NULL, 'f'}, 231 {"loop", required_argument, NULL, 'l'}, 232 {"help", no_argument, NULL, 'e'}, 233 {NULL, 0, NULL, 0}, 234 }; 235 236 int opt = -1; 237 while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { 238 switch (opt) { 239 case 'i': 240 XCAM_ASSERT (optarg); 241 file_in_name[input_count] = optarg; 242 input_count++; 243 break; 244 case 'o': 245 XCAM_ASSERT (optarg); 246 file_out_name = optarg; 247 break; 248 case 'w': 249 input_width = atoi(optarg); 250 break; 251 case 'h': 252 input_height = atoi(optarg); 253 break; 254 case 'W': 255 output_width = atoi(optarg); 256 break; 257 case 'H': 258 output_height = atoi(optarg); 259 break; 260 case 'R': 261 if (!strcasecmp (optarg, "1080p")) 262 res_mode = StitchRes1080P; 263 else if (!strcasecmp (optarg, "1080p4")) 264 res_mode = StitchRes1080P4; 265 else if (!strcasecmp (optarg, "4k")) 266 res_mode = StitchRes4K; 267 else { 268 XCAM_LOG_ERROR ("incorrect resolution mode"); 269 return -1; 270 } 271 break; 272 case 'r': 273 if (!strcasecmp (optarg, "sphere")) 274 surround_mode = SphereView; 275 else if(!strcasecmp (optarg, "bowl")) 276 surround_mode = BowlView; 277 else { 278 XCAM_LOG_ERROR ("incorrect surround mode"); 279 return -1; 280 } 281 break; 282 case 'c': 283 if (!strcasecmp (optarg, "local")) 284 scale_mode = CLBlenderScaleLocal; 285 else if (!strcasecmp (optarg, "global")) 286 scale_mode = CLBlenderScaleGlobal; 287 else { 288 XCAM_LOG_ERROR ("incorrect scaling mode"); 289 return -1; 290 } 291 break; 292 case 'S': 293 enable_seam = true; 294 break; 295 case 'F': 296 enable_fisheye_map = true; 297 break; 298 case 'L': 299 enable_lsc = true; 300 break; 301 #if HAVE_OPENCV 302 case 'O': 303 fm_ocl = (strcasecmp (optarg, "true") == 0 ? true : false); 304 break; 305 #endif 306 case 'N': 307 fisheye_num = atoi(optarg); 308 if (fisheye_num > XCAM_STITCH_FISHEYE_MAX_NUM) { 309 XCAM_LOG_ERROR ("fisheye number should not be greater than %d\n", XCAM_STITCH_FISHEYE_MAX_NUM); 310 return -1; 311 } 312 break; 313 case 'A': 314 all_in_one = (strcasecmp (optarg, "false") == 0 ? false : true); 315 break; 316 case 's': 317 need_save_output = (strcasecmp (optarg, "false") == 0 ? false : true); 318 break; 319 case 'f': 320 framerate = atof(optarg); 321 break; 322 case 'l': 323 loop = atoi(optarg); 324 break; 325 case 'e': 326 usage (argv[0]); 327 return -1; 328 default: 329 XCAM_LOG_ERROR ("getopt_long return unknown value:%c", opt); 330 usage (argv[0]); 331 return -1; 332 } 333 } 334 335 if (optind < argc || argc < 2) { 336 XCAM_LOG_ERROR ("unknown option %s", argv[optind]); 337 usage (argv[0]); 338 return -1; 339 } 340 341 if (!all_in_one && input_count != fisheye_num) { 342 XCAM_LOG_ERROR ("multiple-input mode: conflicting input number(%d) and fisheye number(%d)", 343 input_count, fisheye_num); 344 return -1; 345 } 346 347 for (int i = 0; i < input_count; i++) { 348 if (!file_in_name[i]) { 349 XCAM_LOG_ERROR ("input[%d] path is NULL", i); 350 return -1; 351 } 352 } 353 354 if (!file_out_name) { 355 XCAM_LOG_ERROR ("output path is NULL"); 356 return -1; 357 } 358 359 output_width = XCAM_ALIGN_UP (output_width, XCAM_ALIGNED_WIDTH); 360 output_height = XCAM_ALIGN_UP (output_height, XCAM_ALIGNED_WIDTH); 361 // if (output_width != output_height * 2) { 362 // XCAM_LOG_ERROR ("incorrect output size width:%d height:%d", output_width, output_height); 363 // return -1; 364 // } 365 366 #if !HAVE_OPENCV 367 if (need_save_output) { 368 XCAM_LOG_WARNING ("non-OpenCV mode, can't save video"); 369 need_save_output = false; 370 } 371 #endif 372 373 printf ("Description------------------------\n"); 374 if (all_in_one) 375 printf ("input file:\t\t%s\n", file_in_name[0]); 376 else { 377 for (int i = 0; i < input_count; i++) 378 printf ("input file %d:\t\t%s\n", i, file_in_name[i]); 379 } 380 printf ("output file:\t\t%s\n", file_out_name); 381 printf ("input width:\t\t%d\n", input_width); 382 printf ("input height:\t\t%d\n", input_height); 383 printf ("output width:\t\t%d\n", output_width); 384 printf ("output height:\t\t%d\n", output_height); 385 printf ("resolution mode:\t%s\n", 386 res_mode == StitchRes1080P ? "1080P" : (res_mode == StitchRes1080P4 ? "1080P4" : "4K")); 387 printf ("surround mode: \t\t%s\n", 388 surround_mode == SphereView ? "sphere view" : "bowl view"); 389 printf ("scale mode:\t\t%s\n", scale_mode == CLBlenderScaleLocal ? "local" : "global"); 390 printf ("seam mask:\t\t%s\n", enable_seam ? "true" : "false"); 391 printf ("fisheye map:\t\t%s\n", enable_fisheye_map ? "true" : "false"); 392 printf ("shading correction:\t%s\n", enable_lsc ? "true" : "false"); 393 #if HAVE_OPENCV 394 printf ("feature match ocl:\t%s\n", fm_ocl ? "true" : "false"); 395 #endif 396 printf ("fisheye number:\t\t%d\n", fisheye_num); 397 printf ("all in one:\t\t%s\n", all_in_one ? "true" : "false"); 398 printf ("save file:\t\t%s\n", need_save_output ? "true" : "false"); 399 printf ("framerate:\t\t%.3lf\n", framerate); 400 printf ("loop count:\t\t%d\n", loop); 401 printf ("-----------------------------------\n"); 402 403 context = CLDevice::instance ()->get_context (); 404 image_360 = 405 create_image_360_stitch ( 406 context, enable_seam, scale_mode, enable_fisheye_map, enable_lsc, surround_mode, 407 res_mode, fisheye_num, all_in_one).dynamic_cast_ptr<CLImage360Stitch> (); 408 XCAM_ASSERT (image_360.ptr ()); 409 image_360->set_output_size (output_width, output_height); 410 #if HAVE_OPENCV 411 image_360->set_feature_match_ocl (fm_ocl); 412 #endif 413 image_360->set_pool_type (CLImageHandler::CLVideoPoolType); 414 415 if (surround_mode == BowlView) { 416 parse_calibration_params (intrinsic_param, extrinsic_param, fisheye_num); 417 418 for (int i = 0; i < fisheye_num; i++) { 419 image_360->set_fisheye_intrinsic (intrinsic_param[i], i); 420 image_360->set_fisheye_extrinsic (extrinsic_param[i], i); 421 } 422 } 423 424 input_buf_info.init (input_format, input_width, input_height); 425 output_buf_info.init (input_format, output_width, output_height); 426 top_view_buf_info.init (input_format, top_view_width, top_view_height); 427 rectified_view_buf_info.init (input_format, rectified_view_width, rectified_view_height); 428 for (int i = 0; i < input_count; i++) { 429 buf_pool[i] = new CLVideoBufferPool (); 430 XCAM_ASSERT (buf_pool[i].ptr ()); 431 buf_pool[i]->set_video_info (input_buf_info); 432 if (!buf_pool[i]->reserve (6)) { 433 XCAM_LOG_ERROR ("init buffer pool failed"); 434 return -1; 435 } 436 } 437 438 SmartPtr<BufferPool> top_view_pool = new CLVideoBufferPool (); 439 XCAM_ASSERT (top_view_pool.ptr ()); 440 top_view_pool->set_video_info (top_view_buf_info); 441 if (!top_view_pool->reserve (6)) { 442 XCAM_LOG_ERROR ("top-view-buffer pool reserve failed"); 443 return -1; 444 } 445 top_view_buf = top_view_pool->get_buffer (top_view_pool); 446 447 SmartPtr<BufferPool> rectified_view_pool = new CLVideoBufferPool (); 448 XCAM_ASSERT (rectified_view_pool.ptr ()); 449 rectified_view_pool->set_video_info (rectified_view_buf_info); 450 if (!rectified_view_pool->reserve (6)) { 451 XCAM_LOG_ERROR ("top-view-buffer pool reserve failed"); 452 return -1; 453 } 454 rectified_view_buf = rectified_view_pool->get_buffer (rectified_view_pool); 455 456 for (int i = 0; i < input_count; i++) { 457 ret = file_in[i].open (file_in_name[i], "rb"); 458 CHECK (ret, "open %s failed", file_in_name[i]); 459 } 460 461 #if HAVE_OPENCV 462 cv::VideoWriter writer; 463 cv::VideoWriter top_view_writer; 464 cv::VideoWriter rectified_view_writer; 465 if (need_save_output) { 466 cv::Size dst_size = cv::Size (output_width, output_height); 467 if (!writer.open (file_out_name, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { 468 XCAM_LOG_ERROR ("open file %s failed", file_out_name); 469 return -1; 470 } 471 472 dst_size = cv::Size (top_view_width, top_view_height); 473 if (!top_view_writer.open (top_view_filename, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { 474 XCAM_LOG_ERROR ("open file %s failed", top_view_filename); 475 return -1; 476 } 477 478 dst_size = cv::Size (rectified_view_width, rectified_view_height); 479 if (!rectified_view_writer.open (rectified_view_filename, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { 480 XCAM_LOG_ERROR ("open file %s failed", rectified_view_filename); 481 return -1; 482 } 483 } 484 #endif 485 486 SmartPtr<VideoBuffer> pre_buf, cur_buf; 487 #if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG) 488 SmartPtr<VideoBuffer> input_bufs[XCAM_STITCH_FISHEYE_MAX_NUM]; 489 #endif 490 int frame_id = 0; 491 std::vector<PointFloat2> top_view_map_table; 492 std::vector<PointFloat2> rectified_view_map_table; 493 float rectified_start_angle = -45.0f, rectified_end_angle = 45.0f; 494 495 while (loop--) { 496 for (int i = 0; i < input_count; i++) { 497 ret = file_in[i].rewind (); 498 CHECK (ret, "image_360 stitch rewind file(%s) failed", file_in_name[i]); 499 } 500 501 do { 502 for (int i = 0; i < input_count; i++) { 503 cur_buf = buf_pool[i]->get_buffer (buf_pool[i]); 504 XCAM_ASSERT (cur_buf.ptr ()); 505 ret = file_in[i].read_buf (cur_buf); 506 // ret = read_file_to_video_buffer (file_in[i], input_width, input_height, input_width, cur_buf); 507 if (ret == XCAM_RETURN_BYPASS) 508 break; 509 if (ret == XCAM_RETURN_ERROR_FILE) { 510 XCAM_LOG_ERROR ("read buffer from %s failed", file_in_name[i]); 511 return -1; 512 } 513 514 if (i == 0) 515 input_buf = cur_buf; 516 else 517 pre_buf->attach_buffer (cur_buf); 518 519 pre_buf = cur_buf; 520 #if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG) 521 input_bufs[i] = cur_buf; 522 #endif 523 } 524 if (ret == XCAM_RETURN_BYPASS) 525 break; 526 527 ret = image_360->execute (input_buf, output_buf); 528 CHECK (ret, "image_360 stitch execute failed"); 529 530 #if HAVE_OPENCV 531 if (need_save_output) { 532 cv::Mat out_mat; 533 convert_to_mat (output_buf, out_mat); 534 writer.write (out_mat); 535 536 BowlDataConfig config = image_360->get_fisheye_bowl_config (); 537 cv::Mat top_view_mat; 538 sample_generate_top_view (output_buf, top_view_buf, config, top_view_map_table); 539 convert_to_mat (top_view_buf, top_view_mat); 540 top_view_writer.write (top_view_mat); 541 542 cv::Mat rectified_view_mat; 543 sample_generate_rectified_view (output_buf, rectified_view_buf, config, rectified_start_angle, 544 rectified_end_angle, rectified_view_map_table); 545 convert_to_mat (rectified_view_buf, rectified_view_mat); 546 rectified_view_writer.write (rectified_view_mat); 547 548 #if XCAM_TEST_STITCH_DEBUG 549 dbg_write_image (context, image_360, input_bufs, output_buf, top_view_buf, rectified_view_buf, 550 all_in_one, fisheye_num, input_count); 551 #endif 552 } else 553 #endif 554 ensure_gpu_buffer_done (output_buf); 555 556 frame_id++; 557 FPS_CALCULATION (image_stitching, XCAM_OBJ_DUR_FRAME_NUM); 558 } while (true); 559 } 560 561 return 0; 562 } 563 564 #if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG) 565 static void dbg_write_image ( 566 SmartPtr<CLContext> context, SmartPtr<CLImage360Stitch> image_360, 567 SmartPtr<VideoBuffer> input_bufs[], SmartPtr<VideoBuffer> output_buf, 568 SmartPtr<VideoBuffer> top_view_buf, SmartPtr<VideoBuffer> rectified_view_buf, 569 bool all_in_one, int fisheye_num, int input_count) 570 { 571 cv::Mat mat; 572 static int frame_count = 0; 573 char file_name [1024]; 574 StitchInfo stitch_info = image_360->get_stitch_info (); 575 576 std::snprintf (file_name, 1023, "orig_fisheye_%d.jpg", frame_count); 577 for (int i = 0; i < input_count; i++) { 578 if (!all_in_one) 579 std::snprintf (file_name, 1023, "orig_fisheye_%d_%d.jpg", frame_count, i); 580 581 convert_to_mat (input_bufs[i], mat); 582 int fisheye_per_frame = all_in_one ? fisheye_num : 1; 583 for (int i = 0; i < fisheye_per_frame; i++) { 584 cv::circle (mat, cv::Point(stitch_info.fisheye_info[i].center_x, stitch_info.fisheye_info[i].center_y), 585 stitch_info.fisheye_info[i].radius, cv::Scalar(0, 0, 255), 2); 586 } 587 cv::imwrite (file_name, mat); 588 } 589 590 char frame_str[1024]; 591 std::snprintf (frame_str, 1023, "%d", frame_count); 592 593 convert_to_mat (output_buf, mat); 594 cv::putText (mat, frame_str, cv::Point(120, 120), cv::FONT_HERSHEY_COMPLEX, 2.0, 595 cv::Scalar(0, 0, 255), 2, 8, false); 596 std::snprintf (file_name, 1023, "stitched_img_%d.jpg", frame_count); 597 cv::imwrite (file_name, mat); 598 599 convert_to_mat (top_view_buf, mat); 600 cv::putText (mat, frame_str, cv::Point(120, 120), cv::FONT_HERSHEY_COMPLEX, 2.0, 601 cv::Scalar(0, 0, 255), 2, 8, false); 602 std::snprintf (file_name, 1023, "top_view_img_%d.jpg", frame_count); 603 cv::imwrite (file_name, mat); 604 605 convert_to_mat (rectified_view_buf, mat); 606 cv::putText (mat, frame_str, cv::Point(120, 120), cv::FONT_HERSHEY_COMPLEX, 2.0, 607 cv::Scalar(0, 0, 255), 2, 8, false); 608 std::snprintf (file_name, 1023, "rectified_view_img_%d.jpg", frame_count); 609 cv::imwrite (file_name, mat); 610 611 frame_count++; 612 } 613 #endif 614 615