Photometric Stereo 3D
1 개요
한 물체를 같은 위치에서 찍은 여러 이미지와 각 이미지에서 광원의 위치를 사용하여 Albedo, Curvature, Height Map을 구하는 알고리즘입니다.
2 알고리즘 상세 설명
Photometric Stereo는 카메라의 위치와 물체의 위치를 고정하고 광원의 위치를 바꿔가며 구한 이미지를 사용하여 3D 모델을 구하는 알고리즘입니다.
- 알고리즘의 실행을 위해서 광원의 위치를 바꾼 이미지가 총 3개 이상이 필요합니다. 광원의 위치를 바꾼 이미지의 수가 많을수록 결과 모델의 정확도가 올라갑니다.
- 이미지는 찍는 과정에서 카메라의 위치와 모델의 위치가 같아야 됩니다. 모든 이미지에서의 모델의 위치가 동일해야 합니다. 이미지 간의 모델의 위치가 다른 경우 결과에 오류가 발생할 확률이 상당히 높습니다.
- 해당 알고리즘은 모델의 표면이 램버시안 반사율을 가진다고 가정합니다. 모델의 반사율이 더 높거나 낮은 경우 결과에 오류가 발생할 수 있습니다.
Photometric Stereo의 광원 위치 입력하는 방식에 여러 방식이 있습니다.
- Slant, Tilt: 광원의 위치를 2개의 각도로 받습니다. 각도를 표현하는 방식으로 Degree와 Radian이 있습니다. 광원의 거리가 1이라고 고정하고 연산을 합니다.
- X, Y, Z: 광원의 위치를 3개의 좌표를 받습니다. 모든 광원의 거리가 1이라고 예상하는 각도와는 다르게 각각 광원의 거리를 다르게 설정할 수 있습니다.
Position(XYZ) Diagram | Slant Diagram | Tilt Diagram |
---|---|---|
![]() |
![]() |
![]() |
Photometric Stereo는 총 3개의 출력을 가집니다.
- Albedo
- 모델의 표면 색을 표현하는 이미지 입니다. 그림자 등의 불필요한 데이터를 제거한 이미지가 나옵니다. 결과 3D 모델의 Texture에 사용됩니다.
- Curvature Image
- 모델의 높이의 2차 미분을 표현합니다. 모델 내에 급격한 높이의 변화가 확인 가능합니다. 모델 내에 균열 등의 결함을 확인하기 위하여 사용됩니다.
- Height Map:
- 각 픽셀의 값이 높이가 되는 실제 모델을 출력합니다. 해당 값을 사용하여 3D 모델의 생성이 가능합니다.
Photometric Stereo는 Calibration을 사용하여 광원의 위치 설정이 가능합니다.
- 구의 이미지와 입력에 사용될 모델의 이미지가 같은 광원의 위치를 가진 상태여야 됩니다. 잘못된 이미지 순서나 두 이미지 간에 다른 광원의 위치를 사용한 경우 실행에 잘못된 광원의 위치를 입력하여 오류가 발생할 확률이 높습니다.
- Calibration을 하기 위하여 구 이미지의 수와 모델의 이미지의 수가 같아야 됩니다.
- 구의 이미지가 모델의 이미지 보다 많은 경우 동작에는 오류가 없으나 모델 이미지를 추가하여 더 정확한 결과를 얻을 수 있습니다.
- 구의 이미지가 모델의 이미지 보다 적은 경우 알고리즘이 동작하지 않습니다.
- 구의 위치는, 입력 모델 이미지와 같이, 모든 이미지 내에 같은 위치에 고정되어 있어야 합니다.
Source Image | Calibration Image | Destination Image |
---|---|---|
![]() |
![]() |
![]() |
모든 Slant, Tilt / X, Y, Z 값을 직접 코드에 적어 넣는 방식보다는 CSV 파일을 CMatrix에 로드하여 이를 Photometric Stereo의 입력으로 간단한 사용이 가능합니다.
Calibration 이후 광원의 위치 재사용을 위하여 CMatrix으로 광원의 위치를 받고 CSV로 저장하여 사용이 가능합니다.
3 예제 코드
다음 코드와 구의 이미지를 사용하여 광원의 위치 설정이 가능합니다.
// 객체 생성
CPhotometricStereo3D photometricStereo;
// 구 ROI
CFLCircle<double> flfCalibROI;
// 구 이미지
CFLImage fliCalibImage;
// Calibration 이미지 설정
photometricStereo.SetCalibrationImage(fliCalibImage);
// 구 ROI 설정
photometricStereo.SetCalibrationCircleROI(flfCalibROI);
// Calibration 실행
photometricStereo.Calibrate();
다음 코드를 사용하여 CSV를 CMatrix에 로드하여 이를 Photometric Stereo의 입력으로 사용이 가능합니다. Calibrate 함수 사용 이후 Source 이미지를 설정하고 바로 Execute가 사용 가능합니다.
// 객체 생성
CPhotometricStereo3D photometricStereo3D;
// 광원의 위치
CMatrix<double> cMatPos;
// CSV 파일 위치
CFLString<wchar_t> flStrFilePath;
// CSV 로드
cMatPos.LoadCSV(flStrFilePath);
// CSV가 광원의 위치를 X, Y, Z로 저장하면
photometricStereo3D.SetLightPositions(cMatPos);
// CSV가 광원의 위치를 Slant와 Tilt로 Degree 방식으로 저장하면
photometricStereo3D.SetLightAngleDegrees(cMatPos);
// CSV가 광원의 위치를 Slant와 Tilt로 Radian 방식으로 저장하면
photometricStereo3D.SetLightAngleRadians(cMatPos);
4 추가 함수 설명
Calibration을 위한 데이터 설정 및 실행
// 객체 생성
CPhotometricStereo3D photometricStereo3D;
// Calibration 모드의 설정을 위해서는 SetLightAngleDegrees, SetLightAngleRadians, SetLightPositions으로 설정이 가능합니다.
CMatrix<double> cMatTemp;
// Degree 각도 모드로 Calibration 모드 설정
photometricStereo3D.SetLightAngleDegrees(cMatTemp);
// Radians 각도 모드로 Calibration 모드 설정
photometricStereo3D.SetLightAngleRadians(cMatTemp);
// 위치 모드로 Calibration 모드 설정
photometricStereo3D.SetLightPositions(cMatTemp);
// 설정된 Calibration 모드를 가져옵니다.
CPhotometricStereo3D::ECalibrationMode eGetCalibrationMode = photometricStereo3D.GetCalibrationMode();
CPhotometricStereo3D::ECalibrationMode
은 CPhotometricStereo3D의 알고리즘 Calibration 방식을 저장하는데 사용됩니다.
함수 GetCalibrationMode
를 사용하면 반환되는 값이 알고리즘에 설정된 Calibration 방식입니다.
// 객체 생성
CPhotometricStereo3D photometricStereo3D;
// 이미지로 Calibration 이미지 설정
CFLImage fliSetCalibImage;
photometricStereo3D.SetCalibrationImage(fliSetCalibImage);
// 이미지 포인터로 Calibration 이미지 설정
CFLImage* pFliSetCalibImage = &fliSetCalibImage;
photometricStereo3D.SetCalibrationImage(pFliSetCalibImage);
// 설정된 Calibration 이미지 불러오기
CFLImage fliGetCalibImage;
fliGetCalibImage = photometricStereo3D.GetCalibrationImage();
// 구의 위치를 표시하는 ROI를 설정합니다.
CFLCircle<double> flfSetCircleROI;
photometricStereo3D.SetCalibrationCircleROI(flfSetCircleROI);
// 구의 위치를 표시하는 포인터 ROI를 설정합니다.
CFLFigure* pFlfSetCircleROI = &flfSetCircleROI;
photometricStereo3D.SetCalibrationCircleROI(pFlfSetCircleROI);
// 설정된 구의 위치를 표시하는 ROI를 가져옵니다.
CFLCircle<double> flfGetCircleROI;
photometricStereo3D.GetCalibrationCircleROI(flfGetCircleROI);
// 설정된 구의 위치를 표시하는 포인터 ROI를 가져옵니다.
CFLFigure* pFlfGetCircleROI = &flfGetCircleROI;
photometricStereo3D.GetCalibrationCircleROI(pFlfGetCircleROI);
// 입력된 이미지와 ROI를 사용하여 Calibration을 진행합니다.
photometricStereo3D.Calibrate();
함수 SetCalibrationImage
는 이미지와 이미지 포인터를 입력으로 받습니다.
함수 GetCalibrationImage
는 설정한 Calibration 이미지를 포인터로 가져옵니다.
함수 SetCalibrationCircleROI
는 구 ROI를 설정합니다.
함수 GetCalibrationCircleROI
는 설정된 구 ROI를 가져옵니다.
함수 Calibrate
를 사용하면 위에 SetCalibrationImage
를 사용하여 설정한 거울 구의 이미지들과 SetCalibrationCircleROI
로 설정한 구의 위치를 사용하여 빛의 위치를 구하는 Calibration을 실행합니다. 두 입력 변수에 오차가 있으면 오류가 발생할 가능성이 큽니다.
SetCalibrationCircleROI
에서 Circle이 아닌 다른 모양의 ROI를 입력하는 경우 오류를 반환합니다.
설정된 Calibration 이미지가 3개 미만의 Page가 있는 경우 오류를 반환합니다.
SetCalibrationImage
에 사용된 이미지 들는 입력되는 모델 이미지 들과 촬영 시 광원의 위치가 같아야 합니다. 두 이미지의 Page가 섞인 경우 결과에 오류가 발생합니다.
Reconstruction Parameter 설정 및 가져오기
// 객체 생성
CPhotometricStereo3D photometricStereo3D;
// 광원의 위치를 Radian으로 입력
CMultiVar<double> cMulVarDSetAngleRadianSlant;
CMultiVar<double> cMulVarDSetAngleRadianTilt;
photometricStereo3D.SetLightAngleRadians(cMulVarDSetAngleRadianSlant, cMulVarDSetAngleRadianTilt);
// 설정된 광원의 위치를 Radian으로 받아옵니다.
CMultiVar<double> cMulVarDGetAngleRadianSlant;
CMultiVar<double> cMulVarDGetAngleRadianTilt;
photometricStereo3D.GetLightAngleRadians(cMulVarDGetAngleRadianSlant, cMulVarDGetAngleRadianTilt);
// 광원의 위치를 Degree로 입력
CMultiVar<double> cMulVarDSetAngleDegreeSlant;
CMultiVar<double> cMulVarDSetAngleDegreeTilt;
photometricStereo3D.SetLightAngleDegrees(cMulVarDSetAngleDegreeSlant, cMulVarDSetAngleDegreeTilt);
// 설정된 광원의 위치를 Degree로 받아옵니다.
CMultiVar<double> cMulVarDGetAngleDegreeSlant;
CMultiVar<double> cMulVarDGetAngleDegreeTilt;
photometricStereo3D.GetLightAngleDegrees(cMulVarDGetAngleDegreeSlant, cMulVarDGetAngleDegreeTilt);
// 광원의 위치를 Position으로 입력
CMultiVar<double> cMulVarSetPositionX;
CMultiVar<double> cMulVarSetPositionY;
CMultiVar<double> cMulVarSetPositionZ;
photometricStereo3D.SetLightPositions(cMulVarSetPositionX, cMulVarSetPositionY, cMulVarSetPositionZ);
// 설정된 광원의 위치를 Position으로 받아옵니다.
CMultiVar<double> cMulVarGetPositionX;
CMultiVar<double> cMulVarGetPositionY;
CMultiVar<double> cMulVarGetPositionZ;
photometricStereo3D.GetLightPositions(cMulVarGetPositionX, cMulVarGetPositionY, cMulVarGetPositionZ);
함수 SetLightAngleRadians
는 광원의 위치를 Radian Slant와 Tilt로 설정합니다.
함수 GetLightAngleRadians
는 설정된 광원의 위치를 Radian Slant와 Tilt로 받아옵니다.
함수 SetLightAngleDegrees
는 광원의 위치를 Degree Slant와 Tilt로 설정합니다.
함수 GetLightAngleDegrees
는 설정된 광원의 위치를 Degree Slant와 Tilt로 받아옵니다.
함수 SetLightPositions
는 광원의 위치를 Position으로 설정합니다.
함수 GetLightPositions
는 설정된 광원의 위치를 Position으로 가져옵니다.
위 Set 함수를 사용하면 설정한 데이터의 방식으로 Calibrate 방식이 설정됩니다. SetLightAngleRadians
으로 설정을 진행한 경우 Calibration이 ECalibrationMode_Angle_Radians
으로 설정됩니다.
위 Get 함수를 설정되지 않은 Calibrate 방식으로 불러오면 오류를 반환합니다. Calibration 방식이 ECalibrationMode_Angle_Radians
으로 설정된 경우 GetLightAngleRadians
으로 광원의 위치를 받을 수 있고 GetLightAngleDegrees
으로는 오류를 반환합니다.
// 객체 생성
CPhotometricStereo3D photometricStereo3D;
// 광원의 위치를 Radian으로 입력
CMatrix<double> cMatSetAngleRadian;
photometricStereo3D.SetLightAngleRadians(cMatSetAngleRadian);
// 설정된 광원의 위치를 Radian으로 받아옵니다.
CMatrix<double> cMatGetAngleRadian;
photometricStereo3D.GetLightAngleRadians(cMatGetAngleRadian);
// 광원의 위치를 Degree로 입력
CMatrix<double> cMatSetAngleDegree;
photometricStereo3D.SetLightAngleDegrees(cMatSetAngleDegree);
// 설정된 광원의 위치를 Degree로 받아옵니다.
CMatrix<double> cMatGetAngleDegree;
photometricStereo3D.GetLightAngleDegrees(cMatGetAngleDegree);
// 광원의 위치를 Position으로 입력
CMatrix<double> cMatSetPosition;
photometricStereo3D.SetLightPositions(cMatSetPosition);
// 설정된 광원의 위치를 Position으로 받아옵니다.
CMatrix<double> cMatGetPosition;
photometricStereo3D.GetLightPositions(cMatGetPosition);
함수들은 위 결과와 같은 출력/입력을 받습니다.
Matrix의 경우 함수를 사용하여 CSV로 저장 및 불러오기가 가능합니다.
// 객체 생성
CPhotometricStereo3D photometricStereo3D;
// Photometric Stereo Reconstruction 모드 설정
CPhotometricStereo3D::EReconstructionMode eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_Poisson_FP32;
// 3D 모델 재구성 방식을 RFT Floating 32로 설정합니다.
eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_RFT_FP32;
// 3D 모델 재구성 방식을 RFT Floating 64로 설정합니다.
eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_RFT_FP64;
// 3D 모델 재구성 방식을 FFT Floating 32로 설정합니다.
eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_FFT_FP32;
// 3D 모델 재구성 방식을 FFT Floating 64로 설정합니다.
eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_FFT_FP64;
// 3D 모델 재구성 방식을 Poisson Floating 32로 설정합니다.
eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_Poisson_FP32;
// 3D 모델 재구성 방식을 Poisson Floating 64로 설정합니다.
eReconstructionMode = CPhotometricStereo3D::EReconstructionMode_Poisson_FP64;
// Reconstruction 모드를 설정합니다.
CPhotometricStereo3D::EReconstructionMode eSetReconstructionMode = eReconstructionMode;
photometricStereo3D.SetReconstructionMode(eSetReconstructionMode);
// 설정된 Reconstruction 모드를 가져옵니다.
CPhotometricStereo3D::EReconstructionMode eGetReconstructionMode = photometricStereo3D.GetReconstructionMode();
CPhotometricStereo3D::EReconstructionMode
은 CPhotometricStereo3D의 알고리즘 Reconstruction 방식을 저장하는 데 사용됩니다.
함수 SetReconstructionMode
를 사용하면 Reconstruction 방식의 설정이 가능합니다.
함수 GetReconstructionMode
를 사용하면 반환되는 값이 알고리즘에 설정된 Reconstruction 방식입니다.