Establecer una distancia focal inicial en iOS
camera focus (3)
Estoy trabajando en una aplicación para iOS donde una de las funciones es escanear códigos QR. Para esto estoy usando la excelente biblioteca, ZBar. El escaneo funciona bien y generalmente es muy rápido. Sin embargo, cuando utiliza códigos QR más pequeños, el escaneo tarda un poco más, principalmente debido al hecho de que el enfoque automático necesita algo de tiempo para ajustarse. Estaba experimentando y noté que el enfoque se podía bloquear usando el siguiente código:
AVCaptureDevice *cameraDevice = readerView.device;
if ([cameraDevice lockForConfiguration:nil]) {
[cameraDevice setFocusMode:AVCaptureFocusModeLocked];
[cameraDevice unlockForConfiguration];
}
Cuando este código se usa después de un escaneo exitoso, los escaneos que vienen son realmente rápidos. Eso me hizo preguntarme, ¿podría de alguna manera bloquear el enfoque antes de escanear un código? La aplicación solo escaneará códigos QR pequeños, por lo que nunca será necesario centrarse en algo lejano. Claro, podría implementar algo como tocar para enfocar, pero preferiblemente me gustaría evitar ese paso adicional. ¿Hay una manera de lograr esto? ¿O tal vez hay otra forma de acelerar las cosas cuando se trata de códigos QR más pequeños?
// Alexander
No, no puedes.
iOS solo realiza el enfoque cuando la cámara está encendida y, en ese punto, la cámara ya está encendida, ¿por qué molestarse? No puedes darle a la cámara una distancia específica para enfocar, ese es su trabajo.
Los usuarios están acostumbrados a que la cámara se tome el tiempo para realizar el ajuste, así que déjala como está. Buen enfoque en los detalles, sin embargo.
El [cameraDevice setFocusMode:AVCaptureFocusModeLocked];
es para implementar un bloqueo de enfoque en una aplicación de tipo fotografía.
¡iOS 8 recientemente agregó esta configuración! Es casi como si leyeran desbordamiento de pila
/*!
@method setFocusModeLockedWithLensPosition:completionHandler:
@abstract
Sets focusMode to AVCaptureFocusModeLocked and locks lensPosition at an explicit value.
@param lensPosition
The lens position, as described in the documentation for the lensPosition property. A value of AVCaptureLensPositionCurrent can be used
to indicate that the caller does not wish to specify a value for lensPosition.
@param handler
A block to be called when lensPosition has been set to the value specified and focusMode is set to AVCaptureFocusModeLocked. If
setFocusModeLockedWithLensPosition:completionHandler: is called multiple times, the completion handlers will be called in FIFO order.
The block receives a timestamp which matches that of the first buffer to which all settings have been applied. Note that the timestamp
is synchronized to the device clock, and thus must be converted to the master clock prior to comparison with the timestamps of buffers
delivered via an AVCaptureVideoDataOutput. The client may pass nil for the handler parameter if knowledge of the operation''s completion
is not required.
@discussion
This is the only way of setting lensPosition.
This method throws an NSRangeException if lensPosition is set to an unsupported level.
This method throws an NSGenericException if called without first obtaining exclusive access to the receiver using lockForConfiguration:.
*/
- (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler NS_AVAILABLE_IOS(8_0);
EDIT: este es un método de AVCaptureDevice
En iOS7 esto es ahora posible!
Apple ha agregado la propiedad autoFocusRangeRestriction a la clase AVCaptureDevice. Esta propiedad es de la enumeración AVCaptureAutoFocusRangeRestriction que tiene tres valores diferentes:
- AVCaptureAutoFocusRangeRestrictionNone: predeterminado, sin restricciones
- AVCaptureAutoFocusRangeRestrictionNear - El tema que importa está cerca de la cámara
- AVCaptureAutoFocusRangeRestrictionFar - El tema que importa está lejos de la cámara
Para verificar si el método está disponible, primero debemos verificar si la propiedad autoFocusRangeRestrictionSupported es verdadera. Y como solo se admite en iOS7 y en adelante, también deberíamos usar respondsToSelector para no tener una excepción en versiones anteriores de iOS.
Por lo tanto, el código resultante debería ser algo como esto:
AVCaptureDevice *cameraDevice = zbarReaderView.device;
if ([cameraDevice respondsToSelector:@selector(isAutoFocusRangeRestrictionSupported)] && cameraDevice.autoFocusRangeRestrictionSupported) {
// If we are on an iOS version that supports AutoFocusRangeRestriction and the device supports it
// Set the focus range to "near"
if ([cameraDevice lockForConfiguration:nil]) {
cameraDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;
[cameraDevice unlockForConfiguration];
}
}
Esto parece acelerar un poco el escaneo de pequeños códigos QR de acuerdo con mis pruebas iniciales :)
Actualización - iOS8
Con iOS8, Apple nos ha dado muchas nuevas API de cámara para jugar. Uno de estos nuevos métodos es este:
- (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler
Este método bloquea el enfoque moviendo la lente a una posición entre 0.0 y 1.0. Jugué con el método, bloqueando la lente en valores cercanos. Sin embargo, en general causó más problemas que resolvió. Tenía que mantener los códigos QR / códigos de barras a una distancia muy específica, lo que podría causar problemas cuando tenía códigos de diferentes tamaños.
Pero. Creo que he encontrado una muy buena alternativa para bloquear el enfoque por completo. Cuando el usuario presiona el botón de escaneo, bloqueo la lente a una distancia cercana, y cuando termina, enciendo la cámara de nuevo en enfoque automático. Esto nos brinda los beneficios de mantener el enfoque automático, pero obliga a la cámara a comenzar a una distancia cercana donde es probable que se encuentre un código QR / código de barras. Esto en combinación con:
cameraDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;
Y:
cameraDevice.focusPointOfInterest = CGPointMake(0.5,0.5);
Resultados en un escáner bastante rápido. También construí un escáner personalizado con las API introducidas en iOS7, en lugar de usar ZBar. Sobre todo porque las ZBar-libs están bastante desactualizadas y como cuando el iPhone 5 introdujo ARMv7s, ahora tenía que volver a compilarlo para ARM64.
// Alexander