반응형
250x250
Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

폴크(FOLC)

머신 비전 알고리즘 - OpenCV - 캘리브레이션 본문

머신 비전/머신 비전 알고리즘 테크닉 CPP

머신 비전 알고리즘 - OpenCV - 캘리브레이션

folcjin 2021. 7. 23. 16:04
728x90
반응형

# 눈으로 보는 실제 공간 3차원 정보(XYZ)를 가상 공간 2차원 정보(XY-이미지)로 표현하는데 필요한 파라미터를 찾는 과정
   # 실제 공간 3차원 정보의 특별한 1Point -> 가상 공간 2차원 정보의 특별한 1Point 로 맵핑된다.
   # 위와 같은 과정중에는 많은 오차들이 존재 ( 사용
렌즈, 렌즈와 센서 사이 거리, 렌즈와 이미지 센서 사이 각 등등...)

# 3차원 정보를 2차원 정보와의 맵핑을 위해 이용되는 파라미터를 크게 2가지로 분리 한다.
   # 카메라 내부 파라미터 : 초점 거리, 주점, 비대칭 계수
      > 상수값 형태로 표현 가능
   # 카메라 외부 파라미터 : 카메라 좌표계, 공간상 좌표계
      > 회전과 평행 이동으로 표현 가능

 

# 이미지 인헨스 - OpenCV 4.5.3 으로 테스트
   # 3차원 정보를 2차원 정보로 투영 시키는 작업
   > srcImage : 입력, dstImage : 결과, dst_size : 결과 크기, offsetX : X 방향 이동, offsetY : Y 방향 이동
   > interpolation : 보간법, borderMode : 이미지끝부분, angle : 기울기(deg), scale : 배율

// 캘리브레이션
int total_image_count = 30;
int chess_board_countX = 9, chess_board_countY = 6;
cv::Size chess_board_size = cv::Size(chess_board_countX, chess_board_countY);

vector<vector<cv::Point3f> > ref_points, tar_points;

for (int i = 0; i < total_image_count; i++)
{
vector<cv::Point3f> ref_board_cross_point_corner;
int x = i % chess_board_countX;
int y = i / chess_board_countX;
ref_board_cross_point_corner.push_back(cv::Point3f(x * 28, y * 28, 0));

vector<cv::Point3f> tar_found_cross_point_corner;
int flags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE;
bool success = cv::findChessboardCorners(srcImage, chess_board_size, tar_found_cross_point_corner, flags);
   if (success)
   {
      int type = cv::TermCriteria::EPS | cv::TermCriteria::MAX_ITER;
      int maxCount = 30;
      double epsilon = 0.001;
      cv::TermCriteria criteria(type, maxCount, epsilon);

      cv::Size winSize = cv::Size(11, 11), zeroZone = cv::Size(-1, -1);
      cv::cornerSubPix(srcImage, tar_found_cross_point_corner, winSize, zeroZone, criteria);
      cv::drawChessboardCorners(srcImage, chess_board_size, tar_found_cross_point_corner, success);
   }

   ref_points.push_back(ref_board_cross_point_corner);
   tar_points.push_back(tar_found_cross_point_corner);
}

cv::Mat camera_instric_matrix, distortion_coeffs, rotation_vecs, translate_vecs;
cv::calibrateCamera(ref_points, tar_points, srcImage.size(), camera_instric_matrix, distortion_coeffs, rotation_vecs, translate_vecs);

cv::Mat map1, map2;
cv::Mat new_camera_matrix = cv::getOptimalNewCameraMatrix(camera_instric_matrix, distortion_coeffs, srcImage.size(), 1.0, srcImage.size(), 0);
cv::initUndistortRectifyMap(camera_instric_matrix, distortion_coeffs, cv::Mat(), new_camera_matrix, srcImage.size(), CV_16SC2, map1, map2);


// 보정수행
if (map1.data && map2.data) 
{
   remap(srcImage, dstImage, map1, map2, cv::INTER_LINEAR);
}

728x90
반응형
사업자 정보 표시
사업자 등록번호 : -- | TEL : --