ios iphone camera avcapturesession fieldofview

ios - ¿Cómo calcular FOV?



iphone camera (5)

Contexto inicial

Estoy desarrollando una aplicación de realidad aumentada basada en la ubicación y necesito obtener el campo de visión [FOV] (solo actualizo el valor cuando cambia la orientación, por lo que estoy buscando un método que pueda obtener este valor cuando lo llame)

El objetivo es hacer que una "regla de grado" sea relevante para la realidad como la siguiente:

Ya estoy usando AVCaptureSession para mostrar el flujo de la cámara; y un camino acoplado con un CAShapeLayer para dibujar la regla. Esto está funcionando bastante bien, pero ahora tengo que usar el valor de Campo de visión para colocar mi elemento en el lugar correcto (por ejemplo, elija el espacio correcto entre 160 ° y 170 °).

En realidad, estoy codificando estos valores con estas fuentes: https://stackoverflow.com/a/3594424/3198096 (gracias especiales a @ hotpaw2!) Pero no estoy seguro de que sean completamente precisos y esto no está manejando el iPhone 5, etc. . No pude obtener los valores de las fuentes oficiales (¡Apple!), Pero hay un enlace que muestra los valores de todos los iDevice que creo que necesito (4, 4S, 5, 5S): AnandTech | Algunas reflexiones sobre las mejoras de la cámara del iPhone 5s .

Nota : Después de las pruebas personales y algunas otras investigaciones en línea, estoy bastante seguro de que estos valores son inexactos. Además, esto me obliga a usar una biblioteca externa para comprobar qué modelo de iPhone estoy usando para inicializar manualmente mi FOV ... Y tengo que verificar mis valores para todos los dispositivos compatibles.

Preferiría un "código de solución" !

Después de leer este post: iPhone: ¿Información de color de video en tiempo real, distancia focal, apertura? Estoy intentando obtener exif data exif de AVCaptureStillImageOutput como se sugiere. ¡Después de lo que pude leer la distancia focal de los datos exif, y luego calcular el campo de visión horizontal y vertical a través de la fórmula! (O tal vez obtenga directamente el FOV como se muestra aquí: http://www.brianklug.org/2011/11/a-quick-analysis-of-exif-data-from-apples-iphone-4s-camera-samples/ - - nota : después de un cierto número de actualizaciones, parece que no podemos obtener directamente el campo de visión de exif!)

Punto actual

Fuentes de : http://iphonedevsdk.com/forum/iphone-sdk-development/112225-camera-app-working-well-on-3gs-but-not-on-4s.html y los datos EXIF ​​modificados no se guardan correctamente

Aquí está el código que estoy usando:

AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if (camera != nil) { captureSession = [[AVCaptureSession alloc] init]; AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:nil]; [captureSession addInput:newVideoInput]; captureLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession]; captureLayer.frame = overlayCamera.bounds; [captureLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; previewLayerConnection=captureLayer.connection; [self setCameraOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; [overlayCamera.layer addSublayer:captureLayer]; [captureSession startRunning]; AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; [stillImageOutput setOutputSettings:outputSettings]; [captureSession addOutput:stillImageOutput]; AVCaptureConnection *videoConnection = nil; for (AVCaptureConnection *connection in stillImageOutput.connections) { for (AVCaptureInputPort *port in [connection inputPorts]) { if ([[port mediaType] isEqual:AVMediaTypeVideo] ) { videoConnection = connection; break; } } if (videoConnection) { break; } } [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) { NSData *imageNSData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; CGImageSourceRef imgSource = CGImageSourceCreateWithData((__bridge_retained CFDataRef)imageNSData, NULL); NSDictionary *metadata = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imgSource, 0, NULL); NSMutableDictionary *metadataAsMutable = [metadata mutableCopy]; NSMutableDictionary *EXIFDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy]; if(!EXIFDictionary) EXIFDictionary = [[NSMutableDictionary dictionary] init]; [metadataAsMutable setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary]; NSLog(@"%@",EXIFDictionary); }]; }

Aquí está la salida:

{ ApertureValue = "2.52606882168926"; BrightnessValue = "0.5019629837352776"; ColorSpace = 1; ComponentsConfiguration = ( 1, 2, 3, 0 ); ExifVersion = ( 2, 2, 1 ); ExposureMode = 0; ExposureProgram = 2; ExposureTime = "0.008333333333333333"; FNumber = "2.4"; Flash = 16; FlashPixVersion = ( 1, 0 ); FocalLenIn35mmFilm = 40; FocalLength = "4.28"; ISOSpeedRatings = ( 50 ); LensMake = Apple; LensModel = "iPhone 4S back camera 4.28mm f/2.4"; LensSpecification = ( "4.28", "4.28", "2.4", "2.4" ); MeteringMode = 5; PixelXDimension = 1920; PixelYDimension = 1080; SceneCaptureType = 0; SceneType = 1; SensingMethod = 2; ShutterSpeedValue = "6.906947890818858"; SubjectDistance = "69.999"; UserComment = "[S.D.] kCGImagePropertyExifUserComment"; WhiteBalance = 0; }

Creo que tengo todo lo que necesito para calcular FOV. ¿Pero son los valores correctos? Porque después de leer un montón de sitios web diferentes con diferentes valores de distancia focal , ¡estoy un poco confundido! ¡También mi PixelDimensions parece estar equivocada!

A través de http://en.wikipedia.org/wiki/Angle_of_view esta es la fórmula que planeé usar:

FOV = (IN_DEGREES( 2*atan( (d) / (2 * f) ) )); // d = sensor dimensions (mm) // f = focal length (mm)

Mi pregunta

¿Mi método y mi fórmula se ven bien y, en caso afirmativo, qué valores transfiero a la función?

Precisiones

  • FOV es lo que creo que debo usar, si tiene alguna sugerencia de cómo el gobernante puede igualar la realidad; ¡Aceptaría la respuesta!
  • El zoom está desactivado en el controlador de vista de realidad aumentada, por lo que mi campo de visión se corrige cuando se inicializa la cámara, ¡y no puede cambiar hasta que el usuario gire el teléfono!

También perdón por mis errores de inglés, soy francés ...



De la ecuación de FOV, necesita longitud focal y dimensiones del sensor. Los datos exif tienen una distancia focal pero no las dimensiones del sensor. He encontrado un solo proveedor de cámaras (Canon) que proporciona las dimensiones del sensor en los metadatos, y eso está en sus archivos en bruto CRW. Por lo tanto, tendrá que consultar las dimensiones de los sensores en función de la cámara o el teléfono inteligente. El siguiente enlace de Wikipedia enumera las dimensiones del sensor para numerosas cámaras y algunos iPhones más nuevos. La lista está cerca del final del artículo de Wiki. http://en.wikipedia.org/wiki/Image_sensor_format

Otra fuente para este tipo de información puede ser varios blogs de fotografía. Espero que esto ayude.

Si se utiliza el zoom digital, multiplique la distancia focal por el valor del zoom. Los datos Exif contienen el factor de zoom.

Los blogs de fotografía y los sitios web como http://www.kenrockwell.com tienen mucha información sobre las dimensiones del sensor de la cámara.

Una corrección: en realidad, hay etiquetas Exif para la resolución del plano focal X y la resolución del plano focal Y (en píxeles) y las unidades de resolución del plano focal. De esas etiquetas y las dimensiones de la imagen, puede calcular el tamaño del sensor. Pero no todas las cámaras proporcionan esas etiquetas Exif. Por ejemplo, el iPhone 4 no proporciona esas etiquetas.


El diámetro del campo de visión es el diámetro del círculo de luz que puedes ver cuando miras al microscopio.

Si alrededor de diez celdas redondas en una fila podrían ajustarse a lo largo del diámetro del campo de visión y si conoce el diámetro en milímetros, entonces puede dividir el diámetro total por el número de celdas que se ajustaría para encontrar el tamaño de cada celda.

El diámetro total dividido por el número de celdas que cabrían es igual al tamaño (diámetro) de cada celda

Ejemplo

Si el diámetro del campo de visión es de 1.5 mm y caben diez celdas si estuvieran dispuestas en una línea, entonces cada celda es:

1.5mm / 10 = 0.15mm

0.15 milimetros

RECUERDE que cada vez que cambias la ampliación, cambias el diámetro del círculo de luz que puedes ver. Así que cada aumento tendrá su propio diámetro.

Si coloca una regla debajo de un microscopio, cuanto más amplíe la imagen, menor será el número de líneas en la regla que podrá ver.


En iOS 7 y superiores puedes hacer algo en este sentido:

float FOV = camera.activeFormat.videoFieldOfView;

donde la camera es su AVCaptureDevice . Dependiendo de la configuración predeterminada que elija para la sesión de video, esto puede cambiar incluso en el mismo dispositivo . Es el campo de visión horizontal (en grados), por lo que deberá calcular el campo de visión vertical a partir de las dimensiones de la pantalla.

Aquí está el material de referencia de Apple .


Para responder tu pregunta:

¿Mi método y mi fórmula se ven bien ...?

Tal vez, pero también parecen demasiado complejos.

... y si es así, ¿qué valores le paso a la función?

No lo sé, pero si el objetivo es calcular HFOV y VFOV, aquí hay un ejemplo de código que encuentra programáticamente el Ángulo de visión horizontal, que es el único ángulo de visión al que se puede acceder actualmente en Swift, y luego calcula el Ángulo de visión vertical Basado en la relación de aspecto del iPhone 6, 16: 9.

let devices = AVCaptureDevice.devices() var captureDevice : AVCaptureDevice? for device in devices { if (device.hasMediaType(AVMediaTypeVideo)) { if(device.position == AVCaptureDevicePosition.Back) { captureDevice = device as? AVCaptureDevice } } } if let retrievedDevice = captureDevice { var HFOV : Float = retrievedDevice.activeFormat.videoFieldOfView var VFOV : Float = ((HFOV)/16.0)*9.0 }

¡También recuerda importar AVFoundation si quieres que esto funcione!