Tengo una sesión de AVCaptureSession simple para obtener una alimentación de cámara en mi aplicación y tomar fotos. ¿Cómo puedo implementar la funcionalidad 'pellizcar para ampliar' usando un UIGestureRecognizer
para la cámara?AVCaptureDevice Camera Zoom
Respuesta
La respuesta aceptada es obsoleta y no estoy seguro de que realmente tome la foto de la imagen ampliada. Hay un método para acercar como dice la respuesta de bcattle. El problema de su respuesta es que no toma en cuenta el hecho de que el usuario puede hacer zoom y luego reiniciar desde esa posición de zoom. Su solución creará algún tipo de saltos que no son realmente elegantes.
La manera más fácil y más elegante de hacerlo es usar la velocidad del gesto de pellizco.
-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer {
const CGFloat pinchVelocityDividerFactor = 5.0f;
if (pinchRecognizer.state == UIGestureRecognizerStateChanged) {
NSError *error = nil;
if ([videoDevice lockForConfiguration:&error]) {
CGFloat desiredZoomFactor = device.videoZoomFactor + atan2f(pinchRecognizer.velocity, pinchVelocityDividerFactor);
// Check if desiredZoomFactor fits required range from 1.0 to activeFormat.videoMaxZoomFactor
device.videoZoomFactor = MAX(1.0, MIN(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor));
[videoDevice unlockForConfiguration];
} else {
NSLog(@"error: %@", error);
}
}
}
Me pareció que agregar la función arctan a la velocidad facilitará el zoom en el efecto de alejamiento un poco. No es exactamente perfecto, pero el efecto es lo suficientemente bueno para las necesidades. Probablemente haya otra función para facilitar el alejamiento cuando casi alcanza 1.
NOTA: Además, la escala de un gesto de pellizco va de 0 a infinito con 0 a 1 pellizcando (alejando) y 1 a ser infinito pellizcando (acercar). Para obtener un buen acercamiento del efecto de alejamiento con esto, necesitarías tener una ecuación matemática. La velocidad es en realidad de -infinita a infinita, siendo 0 el punto de partida.
EDIT: Se ha producido un bloqueo fijo en la excepción de rango. Gracias a @garafajon!
Gracias. Use esto para no obtener una excepción de rango: \t \t \t CGFloat desiredZoom = videoDevice.videoZoomFactor + atan (pinchRecognizer.velocity/pinchZoomScaleFactor); \t \t \t videoDevice.videoZoomFactor = MAX (1.0, MIN (desiredZoom, videoDevice.activeFormat.videoMaxZoomFactor)); – garafajon
¡maravilloso! Funciona. – Sourabh
Tenga en cuenta que la velocidad puede devolver nan. Es posible que desee comprobarlo antes de continuar con el cálculo: if (isnan (pinchRecognizer.velocity)) {return; } – Masa
Muchos han intentado hacer esto estableciendo la propiedad de transformación en la capa en CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y);
Ver here para una implementación completa de pellizcar para ampliar.
Gracias por la respuesta. ¿Pero cómo el simple cambio de la escala de la vista previa de video realmente cambia el zoom del hardware de la cámara? –
No es así. Es por eso que incluso la cámara de Apple realmente no "amplía". Son solo CGAffines y algunos cultivos elegantes. – CodaFi
Derecha, la cámara solo usa un "zoom digital". Pero, ¿qué más debo hacer aparte de escalar la vista previa del video para realmente hacer que la imagen que se está escribiendo en el disco "se amplíe"? –
Desde iOS 7 puede establecer el zoom directamente con la propiedad videoZoomFactor
de AVCaptureDevice
.
Ate la propiedad scale
del UIPinchGestureRecognizer
al videoZoomFactor
con una constante de escala. Esto le permitirá variar la sensibilidad al gusto:
-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer {
const CGFloat pinchZoomScaleFactor = 2.0;
if (pinchRecognizer.state == UIGestureRecognizerStateChanged) {
NSError *error = nil;
if ([videoDevice lockForConfiguration:&error]) {
videoDevice.videoZoomFactor = 1.0 + pinchRecognizer.scale * pinchZoomScaleFactor;
[videoDevice unlockForConfiguration];
} else {
NSLog(@"error: %@", error);
}
}
}
Tenga en cuenta que AVCaptureDevice
, a lo largo de todo lo relacionado con AVCaptureSession
, no es seguro para subprocesos. Entonces probablemente no quieras hacer esto desde la cola principal.
Estoy utilizando el SDK de iOS 8.3 y el marco AVFoundation y para mí usando el siguiente método ha funcionado para:
nameOfAVCaptureVideoPreviewLayer.affineTransform = CGAffineTransformMakeScale(scaleX, scaleY)
Para guardar la imagen con la misma escala He utilizado el siguiente método:
nameOfAVCaptureConnection.videoScaleAndCropFactor = factorNumber;
el código de abajo es para conseguir la imagen en la escala
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if(imageDataSampleBuffer != NULL){
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:imageData];
}
}];
en swif t versión, puede acercar/alejar simplemente al pasar el número de escala en videoZoomFactor. El siguiente código en el controlador UIPinchGestureRecognizer resolverá el problema.
do {
try device.lockForConfiguration()
switch gesture.state {
case .began:
self.pivotPinchScale = device.videoZoomFactor
case .changed:
var factor = self.pivotPinchScale * gesture.scale
factor = max(1, min(factor, device.activeFormat.videoMaxZoomFactor))
device.videoZoomFactor = factor
default:
break
}
device.unlockForConfiguration()
} catch {
// handle exception
}
Aquí, pivotPinchScale es una propiedad CGFloat que se declaró en su controlador en alguna parte.
También puede consultar el siguiente proyecto para ver cómo funciona la cámara con UIPinchGestureRecognizer. https://github.com/DragonCherry/CameraPreviewController
Swift 4
Añadir un reconocedor pizca gesto a la vista frontal más y conectarlo a esta acción (pinchToZoom). captureDevice debe ser la instancia que actualmente proporciona entrada a la sesión de captura. pinchToZoom proporciona zoom suave para frente & atrás dispositivos de captura.
@IBAction func pinchToZoom(_ sender: UIPinchGestureRecognizer) {
guard let device = captureDevice else { return }
func minMaxZoom(_ factor: CGFloat) -> CGFloat { return min(max(factor, 1.0), device.activeFormat.videoMaxZoomFactor) }
func update(scale factor: CGFloat) {
do {
try device.lockForConfiguration()
defer { device.unlockForConfiguration() }
device.videoZoomFactor = factor
} catch {
debugPrint(error)
}
}
let newScaleFactor = minMaxZoom(pinch.scale * zoomFactor)
switch sender.state {
case .began: fallthrough
case .changed: update(scale: newScaleFactor)
case .ended:
zoomFactor = minMaxZoom(newScaleFactor)
update(scale: zoomFactor)
default: break
}
}
Será útil declarar zoomFactor en su cámara o vc. Normalmente lo pongo en el mismo singleton que tiene AVCaptureSession. Esto actuará como un valor predeterminado para captureDevice videoZoomFactor.
var zoomFactor: Float = 1.0
- 1. AVCaptureDevice: ¿Flash o linterna?
- 2. Cómo calcular focusPointOfInterest para AVCaptureDevice?
- 3. Android Camera API ISO?
- 4. Broadcasting Android Camera Video
- 5. Android x86 virtualbox + camera
- 6. Android Camera Orientation ISsue
- 7. iPad Camera Connection kit?
- 8. Android Camera setJpegQuality ignorado
- 9. C# Camera Object Tracking
- 10. Android Camera Set Resolución
- 11. iPhone Xcode Camera Integration Tutorials
- 12. OnResume Camera Reinit Black Screen
- 13. Android Camera Intent with Crop
- 14. Android, manupulate camera preview frames
- 15. Determine Person from the Camera
- 16. iPhone 3.1 SDK Camera Access
- 17. use maemo camera por python
- 18. ¿Cómo obtener 720p Android Camera Preview Data?
- 19. Android Camera Preview - Cómo congelar la cámara?
- 20. Android Camera Preview Cambiar entre cámaras
- 21. Cómo mostrar 'Camera Roll' directamente usando ImagePickerController
- 22. Cómo silenciar OpenCV "Camera dropped frame"
- 23. Pinch-zoom con GLSurfaceView
- 24. android pellizcar zoom
- 25. Establecer zoom para Webview
- 26. Desactivar zoom con Openlayers
- 27. Zoom HTML/CSS
- 28. propiedad CSS zoom
- 29. Zoom con lienzo
- 30. HTML5 Canvas: zoom
¿Dónde está agregando el gesto de pellizco? – Dalvik