В качестве примера этот код:
let calibrationPayload = CMGetAttachment(sampleBuffer, key: kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, attachmentModeOut: nil)
if let data = calibrationPayload as? Data {
let matrix: matrix_float3x3 = data.withUnsafeBytes { $0.pointee }
print(matrix)
}
работа на задней камере iPhone 13 Pro дает мне:
simd_float3x3([[4220.394, 0.0, 0.0], [0.0, 4220.394, 0.0], [941.9231, 533.648, 1.0]])
// Corresponding matrix (which makes sense for an 1920x1080 camera):
// [4220.394, 0.0, 941.9231]
// [ 0.0, 4220.394, 533.648]
// [ 0.0, 0.0, 1.0]
Однако теперь мне бы хотелось также получить искажения, связанные с этим объективом. Для этого я изменил свое приложение так, чтобы оно запрашивало устройство типа .builtInDualCamera, и включил поток данных глубины, поскольку только буферы AVDepthData содержат некоторые сопутствующие данные об искажениях (в их свойстве cameraCalibrationData).
В вызове делегата захвата глубины я регистрирую центр искажений, справочную таблицу, а также встроенные функции камеры:
guard let calibrationData = depthData.cameraCalibrationData else {
return
}
print("Intrinsics = \(calibrationData.intrinsicMatrix)")
let distoCenter = calibrationData.lensDistortionCenter
print("Distortion center: \(distoCenter)")
// More code to log the LUT data too
Однако в этом случае встроенные функции сильно различаются и фактически не имеют смысла для камеры 1920x1080 (кажется, между двумя внутренними матрицами существует масштабный коэффициент 2,20):
Intrinsics = simd_float3x3([[9284.896, 0.0, 0.0], [0.0, 9284.896, 0.0], [2072.8423, 1174.5812, 1.0]])
// Corresponding matrix:
// [9284.896, 0.0, 2072.8423]
// [0.0, 9284.896,1174.5812]
// [0.0, 0.0, 1.0]
Distortion center: (2072.839599609375, 1174.5499267578125)
- Может кто-нибудь объяснить мне, откуда взялось это соотношение 2,20?
- Можно ли предварительно вычислить его на основе какие-то запросы к сеансу захвата, или его нужно оценивать по фокусным расстояниям в матрицах встроенных характеристик?
- Для правильного применения LUT для исправления изображения требуется вычисление расстояний от центра искажения, Я полагаю, здесь необходимо принять во внимание дополнительное масштабирование?
// Determine the maximum radius.
float delta_ocx_max = MAX( opticalCenter.x, imageSize.width - opticalCenter.x );
float delta_ocy_max = MAX( opticalCenter.y, imageSize.height - opticalCenter.y );
float r_max = sqrtf( delta_ocx_max * delta_ocx_max + delta_ocy_max * delta_ocy_max );
// Determine the vector from the optical center to the given point.
float v_point_x = point.x - opticalCenter.x;
float v_point_y = point.y - opticalCenter.y;
// Determine the radius of the given point.
float r_point = sqrtf( v_point_x * v_point_x + v_point_y * v_point_y );
// Look up the relative radial magnification to apply in the provided lookup table
float magnification;
const float *lookupTableValues = lookupTable.bytes;
NSUInteger lookupTableCount = lookupTable.length / sizeof(float);
if ( r_point < r_max ) {
...
}
Подробнее здесь: https://stackoverflow.com/questions/769 ... t-video-st
Мобильная версия