Camera Intrinsics
Zivid 카메라 모델은 잘 알려진 일부 핀홀 카메라 모델(예: OpenCV 카메라 모델)보다 더 많은 Intrinsics 파라미터를 사용하여 더 복잡합니다. 또한 카메라는 롤링 보정(rolling calibration)을 사용합니다. 즉, 조리개, 온도 및 색상 채널의 기능으로 포인트 클라우드가 생성됩니다.
Zivid 카메라 모델은 독점적이므로 SDK에서 내부 카메라 Intrinsics을 사용할 수 없습니다. 그러나 많은 머신 비전 알고리즘이 이에 의존하기 때문에 OpenCV 및 Halcon 모델의 근사치를 제공합니다.
조심
일반적으로 우리는 카메라 Intrinsics를 사용하지 않는 경향이 있습니다. 한 가지 이유는 근사치에서 귀중한 정보가 손실되기 때문입니다. 또 다른 이유는 종종 동일한 결과를 얻는 더 나은 방법이 있다는 것입니다. 주제가 복잡하기 때문에 사용 사례에 대해 논의하려면 따로 문의를 해주시면 감사하겠습니다. Intrinsics는 복잡합니다. 가능한 한 포인트 클라우드를 사용하십시오!
OpenCV camera intrinsics
Zivid SDK는 OpenCV 카메라 Intrinsics 기능을 얻을 수 있는 몇 가지 옵션을 제공합니다.
intrinsics(camera)
카메라에 대한
Zivid::Settings::Sampling::Pixel
기본값에 해당하는 Intrinsics 함수를 반환합니다.intrinsics(camera, settings)
settings
에 사용된Zivid::Settings::Sampling::Pixel
값에 해당하는 Intrinsics 함수를 반환합니다.intrinsics(camera, settings_2d)
settings_2d
사용하여 캡처에 해당하는 Intrinsics 함수를 반환합니다.estimateIntrinsics(frame)
frame
캡처하는 데 사용된Zivid::Settings::Sampling::Pixel
값에 해당하는 Intrinsics 함수를 반환합니다.
단일 조리개 및 단일 온도에 대해 하드 코딩된 카메라 Intrinsics가 제공됩니다. 이 온도와 간극은 일반적인 조건으로 간주되는 것과 일치합니다.
Camera Model |
Lens Temperature (°C) |
Aperture |
---|---|---|
Zivid 2+ |
35 |
2.68 |
Zivid 2 |
35 |
2.30 |
하드 코딩된 카메라 Intrinsics를 가져오려면 먼저 카메라에 연결해야 합니다.
std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();
Console.WriteLine("Connecting to camera");
var camera = zivid.ConnectCamera();
print("Connecting to camera")
camera = app.connect_camera()
그런 다음 기본 OpenCV 카메라 Intrinsics 함수를 가져올 수 있습니다(이 함수는 즉시 반환됨).
std::cout << "Getting camera intrinsics" << std::endl;
const auto intrinsics = Zivid::Experimental::Calibration::intrinsics(camera);
Console.WriteLine("Getting camera intrinsics");
var intrinsics = Zivid.NET.Experimental.Calibration.Calibrator.Intrinsics(camera);
print("Getting camera intrinsics")
intrinsics = zivid.experimental.calibration.intrinsics(camera)
또는 settings
에 사용된 Zivid::Settings::Sampling::Pixel
값에 해당하는 OpenCV 카메라 Intrinsics 함수를 가져올 수 있습니다.
const auto settingsSubsampled =
Zivid::Settings{ Zivid::Settings::Engine::phase,
Zivid::Settings::Acquisitions{ Zivid::Settings::Acquisition{} },
Zivid::Settings::Sampling::Pixel::blueSubsample2x2 };
const auto fixedIntrinsicsForSubsampledSettings =
Zivid::Experimental::Calibration::intrinsics(camera, settingsSubsampled);
var settingsSubsampled = new Zivid.NET.Settings();
settingsSubsampled.Acquisitions.Add(new Zivid.NET.Settings.Acquisition { });
settingsSubsampled.Sampling.Pixel = Zivid.NET.Settings.SamplingGroup.PixelOption.BlueSubsample2x2;
var fixedIntrinsicsForSubsampledSettings = Zivid.NET.Experimental.Calibration.Calibrator.Intrinsics(camera, settingsSubsampled);
settings_subsampled = zivid.Settings(
acquisitions=[zivid.Settings.Acquisition()],
sampling=zivid.Settings.Sampling(pixel=zivid.Settings.Sampling.Pixel.blueSubsample2x2),
)
fixed_intrinsics_for_subsampled_settings = zivid.experimental.calibration.intrinsics(camera, settings_subsampled)
또는 2D 설정과 유사한 설정:
const auto settings2D = Zivid::Settings2D{ Zivid::Settings2D::Acquisitions{ Zivid::Settings2D::Acquisition{} }};
const auto fixedIntrinsicsForSettings2D = Zivid::Experimental::Calibration::intrinsics(camera, settings2D);
var settings2D = new Zivid.NET.Settings2D
{
Acquisitions = { new Zivid.NET.Settings2D.Acquisition { } }
};
var fixedIntrinsicsForSettings2D = Zivid.NET.Experimental.Calibration.Intrinsics(camera, settings2D);
settings_2d = zivid.Settings2D()
fixed_intrinsics_for_settings_2d = calibration.intrinsics(camera, settings_2d)
조심
하드 코딩된 OpenCV Intrinsics 함수는 고정되어 있으며 포인트 클라우드의 보정과 달리 환경에 적응하지 않습니다. 따라서 다른 온도에서 다른 조리개로 촬영한 캡처와 완벽하게 일치하지 않습니다.
생산 환경의 주변 온도는 다를 수 있으며 카메라 온도도 이에 따라 달라집니다. 열 안정화는 내부 온도를 조절하여 도움을 줍니다. 그럼에도 불구하고 카메라가 안정화 기간 이후보다 워밍업할 시간이 없는 경우 배치 시작 시 렌즈 온도가 상당히 낮아질 수 있습니다. 온도 차이로 인해 하드 코딩된 고유 함수는 포인트 클라우드 데이터와 덜 일치합니다.
조리개와 관련하여 획득할 때마다 다른 조리개를 사용하는 HDR 모드를 사용하여 포인트 클라우드를 캡처하면 상황이 더욱 복잡해집니다. 그러한 경우에 대한 내재성을 결정하는 것이 사소한 일이 아니기 때문입니다.
이러한 복잡성 때문에 우리는 OpenCV 카메라 내장 함수(포인트 클라우드에서 추정된 카메라 내장 함수)를 얻는 대체 방법을 제공합니다.
이러한 카메라 Intrinsics은 포인트 클라우드에서 추정됩니다. 보정을 사용하여 포인트 클라우드가 온도와 구경의 함수로 생성됩니다. 따라서 추정된 고유값은 온도와 구경을 간접적으로 활용합니다.
예상 OpenCV Intrinsics를 얻으려면 먼저 카메라에 연결해야 합니다.
std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();
Console.WriteLine("Connecting to camera");
var camera = zivid.ConnectCamera();
print("Connecting to camera")
camera = app.connect_camera()
그런 다음 프레임을 캡처해야 합니다.
const auto frame = camera.capture(settings);
var frame = camera.Capture(settings);
with camera.capture(settings=settings) as frame:
그런 다음 프레임에서 Intrinsics를 추정할 수 있습니다(관련된 계산이 있기 때문에 이 함수는 즉시 반환되지 않음).
const auto estimated_intrinsics = Zivid::Experimental::Calibration::estimateIntrinsics(frame);
var estimatedIntrinsics = Zivid.NET.Experimental.Calibration.Calibrator.EstimateIntrinsics(frame);
estimated_intrinsics = zivid.experimental.calibration.estimate_intrinsics(frame)
Zivid::Settings::Sampling::Pixel
을 예를 들어 Zivid::Settings::Sampling::Pixel::blueSubsample2x2
로 설정하면 동일한 기능으로 정확한(서브 샘플링된) Intrinsics을 얻습니다:
const auto settingsSubsampled =
Zivid::Settings{ Zivid::Settings::Engine::phase,
Zivid::Settings::Acquisitions{ Zivid::Settings::Acquisition{} },
Zivid::Settings::Sampling::Pixel::blueSubsample2x2 };
const auto frame = camera.capture(settingsSubsampled);
const auto estimatedIntrinsicsForSubsampledSettings =
Zivid::Experimental::Calibration::estimateIntrinsics(frame);
var settingsSubsampled = new Zivid.NET.Settings();
settingsSubsampled.Acquisitions.Add(new Zivid.NET.Settings.Acquisition { });
settingsSubsampled.Sampling.Pixel = Zivid.NET.Settings.SamplingGroup.PixelOption.BlueSubsample2x2;
var frameSubsampled = camera.Capture(settingsSubsampled);
var estimatedIntrinsicsForSubsampledSettings = Zivid.NET.Experimental.Calibration.Calibrator.EstimateIntrinsics(frameSubsampled);
settings_subsampled = zivid.Settings(
acquisitions=[zivid.Settings.Acquisition()],
sampling=zivid.Settings.Sampling(pixel=zivid.Settings.Sampling.Pixel.blueSubsample2x2),
)
frame = camera.capture(settings_subsampled)
estimated_intrinsics_for_subsampled_settings = zivid.experimental.calibration.estimate_intrinsics(frame)
Saving camera intrinsics
OpenCV 카메라 Intrinsics를 YML 파일에 저장할 수 있습니다.
const std::string outputFile = "Intrinsics.yml";
std::cout << "Saving camera intrinsics to file: " << outputFile << std::endl;
intrinsics.save(outputFile);
var intrinsicsFile = "Intrinsics.yml";
Console.WriteLine("Saving camera intrinsics to file: " + intrinsicsFile);
intrinsics.Save(intrinsicsFile);
output_file = "Intrinsics.yml"
print(f"Saving camera intrinsics to file: {output_file}")
intrinsics.save(output_file)
Halcon camera intrinsics
Halcon은 Zivid 및 OpenCV 카메라 모델과 다른 카메라 모델을 사용합니다. Halcon Intrinsics를 가져오는 두 가지 옵션이 있으며 둘 다 OpenCV 모델의 근사값을 기반으로 합니다.
조심
Halcon Intrinsics(카메라 내부 매개변수)를 사용해야 하는 경우 아래에 설명된 접근 방식 중 하나를 사용하여 가져옵니다. Halcon Intrinsics을 얻기 위해 Halcon에서 2D 카메라를 보정하지 마십시오. 그것은 우리 카메라와 잘 작동하지 않습니다.
요구 사항:
Python 설치 및 Python 스크립트 실행
Zivid-Python 설치됨
카메라용 Halcon Intrinsics를 얻는 가장 간단한 방법은 convert_intrinsics_opencv_to_halcon.py 코드 샘플을 실행하는 것입니다. example when reading from camera 를 중심으로 샘플 설명을 읽어보십시오.
참고
이 방법은 하드 코딩된 카메라 Intrinsics를 가져오는 것으로 제한됩니다.
요구 사항:
Python 설치 및 Python 스크립트 실행
C++ 또는 C# 코드 샘플 빌드
카메라용 Halcon Intrinsics를 가져오는 다른 방법은 YML 파일에서 OpenCV 카메라 Intrinsics를 로드하고 Halcon 형식으로 변환하는 것입니다.
OpenCV 카메라 Intrinsics을 가져오고 파일에 저장하려면 다음 샘플 중 하나를 실행합니다.
OpenCV 카메라 Intrinsics를 가져와 파일에 저장하려면 GetCameraIntrinsics.cpp 실행합니다. Configure C++ Samples With CMake and Build Them in Visual Studio in Windows 을 참고하십시오.
OpenCV 카메라 Intrinsics를 가져와서 파일에 저장하려면 GetCameraIntrinsics.cs 실행합니다. C# 샘플 Build C# Samples using Visual Studio 을 참고하십시오.
OpenCV 카메라 Intrinsics를 가져와서 파일에 저장하려면 get_camera_intrinsics.py 실행합니다.
그런 다음 convert_intrinsics_opencv_to_halcon.py 코드 샘플을 실행합니다. Example when reading from camera 를 중심으로 샘플 설명을 읽어보십시오.
참고
이 방법을 사용하면 하드코딩된 카메라 Intrinsics와 포인트 클라우드에서 추정된 카메라 Intrinsics를 모두 가져올 수 있습니다. 그러나 후자의 경우 Intrinsics이 필요한 각 캡처에 대해 파일에서 저장 및 로드한다고 가정합니다.
Which camera intrinsics should I use?
Hard-coded camera intrinsics
다음을 가정하는 경우에만 하드 코딩된 카메라 Intrinsics를 사용하는 것이 좋습니다.
다음 중 하나에서 컬러 이미지를 얻습니다.
2D 캡처
단일 획득 3D 캡처
UseFirstAcquisition
으로 Color Mode 가 설정된 다중 획득 HDR 3D 캡처.
관련 획득(위의 세 가지 옵션 중 하나)에 대해 하드 코딩된 Intrinsics를 제공하는 조리개 값을 사용합니다(table 참조).
실내 온도에 가까운 온도용.
2D 데이터만 사용하는 애플리케이션의 경우(예: 직선을 감지하기 위해 이미지 왜곡 제거).
포인트 클라우드에서 추정된 카메라 Intrinsics
다음을 가정하여 추정 Intrinsics를 사용하는 것이 좋습니다.
Automatic
또는ToneMapping
으로 Color Mode 가 설정된 다중 획득 HDR 3D 캡처에서 컬러 이미지를 얻습니다. 이는 포인트 클라우드가 하드 코딩된 Intrinsics에 해당하는 온도와 다른 조리개 및 온도에서 획득한 결과일 가능성이 높기 때문입니다.OpenCV Intrinsics를 사용하는 경우 다른 사용 사례가 필요합니다. 예를 들면 다음과 같습니다.
projectPoints()를 사용하여 3D 데이터를 2D 이미지로 투영합니다.
solvePnP()를 사용하여 2D 이미지에서 3D 포즈를 추정합니다.
참고
추정된 카메라 Intrinsics 함수는 하드 코딩된 카메라 Intrinsics 함수를 권장하는 모든 경우에도 잘 작동합니다. 따라서 단순함을 위해 항상 estimateIntrinsics
함수를 사용할 수 있습니다. 그러나 포인트 클라우드에서 Intrinsics을 추정하는 데는 시간이 걸리는 반면 카메라에서 하드 코딩된 Intrinsics을 가져오는 것은 즉각적입니다.
또한 추정 Intrinsics 함수는 3D 캡처 설정을 사용합니다. 이는 Intrinsics내장 함수가 3D 해상도에 해당함을 의미합니다. 해상도가 3D와 다른 별도의 2D 캡처를 수행하면 잘못된 Intrinsics을 얻게 됩니다. 이 경우 하드 코딩된 방법을 사용하십시오.
2D and 3D capture with different resolution
2D 이미지의 해상도에 따라 다른 Intrinsics을 함수가 필요합니다. Monochrome Capture 수행하면 2D와 3D에서 서로 다른 해상도를 얻을 수 있습니다. 3D 캡처에서 2D 데이터를 가져오면 estimateIntrinsics
로 원하는 Intrinsics을을 반환합니다. 별도의 2D 캡처에서 2D 데이터를 가져오면 intrinsics(camera, settings_2d)
호출할 수 있습니다. 여기서 settings_2d
는 2D 캡처에 사용되는 설정입니다.
참고
estimateIntrinsics
는 최고의 Intrinsics을 제공합니다. 따라서 별도의 2D를 캡처하는 경우에도 이러한 Intrinsics 기능을 사용하는 것이 좋습니다. 그러나 2D 해상도가 다른 경우 이에 따라 Intrinsics을 함수를 수정해야 합니다. 이 경우 customersuccess@zivid.com 로 문의해 주세요. .
2D의 해상도와 일치하도록 Intrinsics 함수를 만드는 대신 3D 해상도와 일치하도록 2D 이미지를 다운샘플링하거나 서브샘플링할 수 있습니다.
Hand-Eye Calibration
일반적으로 권장하는 Hand-Eye Calibration은 Zivid 카메라에 가장 적합하므로 Zivid의 Hand-Eye Calibration 을 추천드립니다. 우리의 Hand-Eye Calibration 방법에는 카메라 Intrinsics가 필요하지 않습니다. 그러나 많은 다른 방법이 있습니다. 다른 방법 중 하나를 사용하는 경우 포인트 클라우드에서 추정된 카메라 Intrinsics에을 사용하는 것이 좋습니다. choosing the correct Hand-Eye calibration method 을 확인해보십시오.
Projecting 3D points to a 2D image plane
Warning! Zivid 포인트 클라우드를 2D 이미지 평면에 투영할 때 추정된 Intrinsics를 사용하면 하드 코딩된 Intrinsics를 사용하는 것보다 재투영 오류가 더 적습니다. 그러나 수정 필터 Gaussian Smoothing 사용한다는 점을 명심하십시오. 그리고 Contrast Distortion Filter 는 더 높은 재투영 오류를 발생시킬 수 있습니다. 보정 필터 없이 캡처된 포인트 클라우드에서 추정된 Intrinsics를 사용하는 경우 1픽셀 미만의 재투영 오류가 예상됩니다. 수정 필터를 사용할 때 재투영 오류는 크게 수정된 지점에 대해 더 커집니다. 그러나 대부분의 포인트에 대해 1픽셀 미만의 재투영 오류가 있어야 합니다.
참고
Downsampled or Subsampled 2D
2D 데이터를 서브샘플링하면 Monochrome Capture 에서 2D와 3D 간의 직접적인 1:1 매핑을 얻을 수 있습니다.
이제 전체 해상도 2D 이미지를 다운샘플링하는 것을 고려하십시오. 다운샘플링된 픽셀을 생성하는 데 사용되는 픽셀을 이해하는 것이 중요합니다. 원하는 픽셀 주위에 대칭으로 픽셀을 사용하는 경우 평균화된 픽셀은 3D 데이터에 해당하는 픽셀 위치에 도달해야 합니다. 이는 SDK가 제공하는 Intrinsics 함수와 가장 잘 일치합니다.
For more information see 전체 해상도 2D 이미지와 서브샘플링된 포인트 클라우드 간의 매핑.
Estimating 3D pose from a 2D image
예를 들어 OpenCV에서 solvePnP()를 사용하여 2D 이미지에서 객체의 3D 포즈를 추정한다고 가정해 보겠습니다. 하드 코딩된 카메라 Intrinsics와 비교하여 포인트 클라우드에서 추정된 Intrinsics가 더 나은 결과를 제공합니다. 그러나 2D 이미지에서 포즈를 추정하는 것은 포인트 클라우드에서 더 정확하게 포즈를 추정하는 것이 가능하므로 권장하지 않습니다.
2D image processing algorithms
어플리케이션에 2D 데이터만 사용하는 경우 하드 코딩된 Intrinsics 및 포인트 클라우드에서 추정된 Intrinsics 데이터가 제대로 작동합니다. 예를 들어 2D 이미지의 왜곡을 제거하여 렌즈 왜곡을 보정하여 직선을 감지할 수 있습니다.
Version History
SDK |
Changes |
---|---|
2.10.0 |
Monochrome Capture 사용하기 전에 Intrinsics 기능을 수정해야 합니다. |