• 红外相机和RGB相机标定:实现两种模态数据融合


    1. 前期准备

    1. RGB相机:森云智能SG2-IMX390,1个
    2. 红外相机:艾睿光电IR-Pilot 640X-32G,1个
    3. 红外标定板:https://item.taobao.com/item.htm?_u=jp3fdd12b99&id=644506141871&spm=a1z09.2.0.0.5f822e8dKrxxYI

    2.操作步骤

    2.1 采集标定数据

    两种模态相机均未进行内参标定,如果发现原始图片畸变较大,可以先进行内参标定。数据采集代码如下,加热红外标定板后断电,移动标定板到合适的位置,按下s键,同时保存IR图和RG图

    1. #!/usr/bin/env python3
    2. import cv2 , time
    3. import numpy as np
    4. ir_dev = "/dev/video6"
    5. rgb_dev = "/dev/video0"
    6. # define a video capture object
    7. ir_vid = cv2.VideoCapture(ir_dev)
    8. rgb_vid = cv2.VideoCapture(rgb_dev)
    9. count = 0
    10. while(True):
    11. # Capture the video frame by frame
    12. st_time = time.time()
    13. ret, ir_frame = ir_vid.read()
    14. # print(f"{time.time() - st_time}")
    15. ret, rgb_frame = rgb_vid.read()
    16. print(f"{time.time() - st_time}")
    17. # Display the resulting frame
    18. height, width = ir_frame.shape[:2]
    19. #(512,1280)
    20. index = [2*i+1 for i in range(width//2)]
    21. vis_ir_frame = ir_frame[:,index,:]
    22. vis_rgb_frame = cv2.resize(rgb_frame, (640,512))
    23. cv2.imshow('IR frame', vis_ir_frame)
    24. cv2.imshow('RGB frame', vis_rgb_frame)
    25. key = cv2.waitKey(1) & 0xFF
    26. if key == ord('q'):
    27. break
    28. if key == ord('s'):
    29. cv2.imwrite(f"IR_{count}.png", vis_ir_frame)
    30. cv2.imwrite(f"RGB_{count}.png", vis_rgb_frame)
    31. count += 1
    32. # After the loop release the cap object
    33. ir_vid.release()
    34. rgb_vid.release()
    35. # Destroy all the windows
    36. cv2.destroyAllWindows()

    2.2 进行标定

    核心操作是调用opencv函数cv2.findHomography计算两个相机之间的单应性矩阵,代码如下

    1. #!/usr/bin/python
    2. # -*- coding: UTF-8 -*-
    3. import cv2
    4. import numpy as np
    5. def find_chessboard(filename, pattern=(9,8), wind_name="rgb"):
    6. # read input image
    7. img = cv2.imread(filename)
    8. # cv2.imshow("raw", img)
    9. # img = cv2.undistort(img, camera_matrix, distortion_coefficients)
    10. # convert the input image to a grayscale
    11. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    12. # Find the chess board corners
    13. ret, corners = cv2.findChessboardCorners(gray, pattern, None)
    14. # if chessboard corners are detected
    15. if ret == True:
    16. # Draw and display the corners
    17. img = cv2.drawChessboardCorners(img, pattern, corners, ret)
    18. #Draw number,打印角点编号,便于确定对应点
    19. corners = np.ceil(corners[:,0,:])
    20. for i, pt in enumerate(corners):
    21. cv2.putText(img, str(i), (int(pt[0]),int(pt[1])), cv2.FONT_HERSHEY_COMPLEX, 0.3, (0,255,0), 1)
    22. cv2.imshow(wind_name,img)
    23. return corners
    24. return None
    25. if __name__ == '__main__' :
    26. idx = 2 #0~71
    27. rgb_img = cv2.imread(f"RGB_{idx}.png")
    28. t_img = cv2.imread(f"IR_{idx}.png")
    29. #chessboard grid nums in rgb ,注意观察,同一块标定板在RGB相机和红外相机中的格子说可能不一样
    30. rgb_width, rgb_height = 9, 8
    31. rgb_corners = find_chessboard(f"RGB_{idx}.png", (rgb_width, rgb_height), "rgb")
    32. #chessboard grid nums in thermal
    33. thermal_width, thermal_height = 11, 8
    34. t_corners = find_chessboard(f"IR_{idx}.png", (thermal_width, thermal_height), "thermal")
    35. if rgb_corners is not None and t_corners is not None:
    36. # test the id correspondence between rgb and thermal corners
    37. rgb_idx = 27 #可视化一个点,确认取对应点的过程是否正确
    38. row, col = rgb_idx//rgb_width, rgb_idx%rgb_width
    39. t_idx = row*thermal_width + col + 1
    40. pt = rgb_corners[rgb_idx]
    41. cv2.putText(rgb_img, str(rgb_idx), (int(pt[0]),int(pt[1])), cv2.FONT_HERSHEY_COMPLEX, 0.3, (0,255,0), 1)
    42. pt = t_corners[t_idx]
    43. cv2.putText(t_img, str(t_idx), (int(pt[0]),int(pt[1])), cv2.FONT_HERSHEY_COMPLEX, 0.3, (0,255,0), 1)
    44. cv2.imshow(f"Point {rgb_idx} on rgb", rgb_img)
    45. cv2.imshow(f"Point {t_idx} on thermal", t_img)
    46. # Calculate Homography
    47. src_pts = []
    48. for rgb_idx in range(len(rgb_corners)):
    49. row, col = rgb_idx//9, rgb_idx%9
    50. t_idx = row*11+col+1
    51. src_pts.append(t_corners[t_idx])
    52. h, status = cv2.findHomography(np.array(src_pts)[:,None,:], rgb_corners[:,None,:])
    53. np.savetxt("calib.param", h)
    54. # Warp source image to destination based on homography
    55. t_warp = cv2.warpPerspective(t_img, h, (640,512), borderValue=(255,255,255))
    56. #colorize
    57. t_warp = cv2.applyColorMap(t_warp, cv2.COLORMAP_JET)
    58. #mix rgb and thermal
    59. alpha = 0.5
    60. merge = cv2.addWeighted(rgb_img, alpha, t_warp, 1-alpha, gamma=0)
    61. cv2.imshow("warp", merge)
    62. cv2.waitKey(0)
    63. cv2.destroyAllWindows()

    运行结果如下,观察红外和RGB图中角点的对应关系,编号已经可视化出来了

    同时,也单独画出了1个对应后的点,如下图,可检查映射关系是否找对

    最后,融合结果如下图所示:

  • 相关阅读:
    【Leetcode60天带刷】day01——704.二分查找、27.移除元素
    Android:创建jniLibs的步骤
    Leetcode 中等:95. 不同的二叉搜索树II
    信息系统项目管理师必背核心考点(六十一)项目组合概念
    【目标检测】【边界框回归】Bounding-Box regression
    AI实战营第二期 第五节 《目标检测与MMDetection》——笔记6
    PDAC复盘法是什么?怎么用?
    用友BIP 安装配置专业脚手架开发工具(图文)
    【大厂面试必备系列】滑动窗口协议
    SpringBoot【 Thymeleaf、SpringBoot热部署、SpringBoot整合MyBatis、 SpringBoot参数校验】(四)-全面详解(学习总结---从入门到深化)
  • 原文地址:https://blog.csdn.net/mjlsuccess/article/details/136842527