open - ios AVFoundation toca para enfocar
open camera swift 4 (2)
Intento crear una aplicación de cámara que, más o menos, actúe como la aplicación de cámara predeterminada. Lo que no funciona para mí en este momento, es tocar para enfocar. Quiero que la cámara enfoque y haga lo que haga en mi punto tocado, tal como lo hace la aplicación real de la cámara.
Aquí está mi viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// Session
_session = [[AVCaptureSession alloc] init];
_session.sessionPreset = AVCaptureSessionPresetPhoto;
// Input
_videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
_videoInput = [AVCaptureDeviceInput deviceInputWithDevice:_videoDevice error:nil];
// Output
_frameOutput = [[AVCaptureVideoDataOutput alloc] init];
_frameOutput.videoSettings = [NSDictionary dictionaryWithObject:AVVideoCodecJPEG forKey:AVVideoCodecKey];
[_frameOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[_session addInput:_videoInput];
[_session addOutput:_frameOutput];
[_session startRunning];
};
Y aquí está el método que debería hacer que mi cámara enfocara todo al hacer clic.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
UITouch *touch = obj;
CGPoint touchPoint = [touch locationInView:touch.view];
focusLayer.frame = CGRectMake((touchPoint.x-25), (touchPoint.y-25), 50, 50);
if ([_videoDevice isFocusPointOfInterestSupported]) {
NSError *error;
if ([_videoDevice lockForConfiguration:&error]) {
[_videoDevice setFocusPointOfInterest:touchPoint];
[_videoDevice setExposurePointOfInterest:touchPoint];
[_videoDevice setFocusMode:AVCaptureFocusModeAutoFocus];
if ([_videoDevice isExposureModeSupported:AVCaptureExposureModeAutoExpose]){
[_videoDevice setExposureMode:AVCaptureExposureModeAutoExpose];
}
[_videoDevice unlockForConfiguration];
}
}
// NSLog(@"x = %f, y = %f", touchPoint.x, touchPoint.y);
}];
}
Nada realmente sucede una vez que hago clic en la pantalla.
Tienes que ajustar el touchPoint a un rango de [0,1] usando algo como el siguiente código:
CGRect screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
screenHeight = screenRect.size.height;
double focus_x = thisFocusPoint.center.x/screenWidth;
double focus_y = thisFocusPoint.center.y/screenHeight;
[[self captureManager].videoDevice lockForConfiguration:&error];
[[self captureManager].videoDevice setFocusPointOfInterest:CGPointMake(focus_x,focus_y)];
[[self captureManager].videoDevice unlockForConfiguration];
La documentación sobre esto se puede encontrar en Apple - Pautas de programación AV Foundation - ver la sección Captura de medios, donde encontrará información sobre los modos de enfoque :
Si es compatible, establezca el punto focal utilizando focusPointOfInterest. Usted pasa un CGPoint donde {0,0} representa la parte superior izquierda del área de la imagen, y {1,1} representa la parte inferior derecha en el modo horizontal con el botón de inicio a la derecha, esto se aplica incluso si el dispositivo está en modo vertical .
UITapGestureRecognizer *shortTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapToFocus:)];
shortTap.numberOfTapsRequired=1;
shortTap.numberOfTouchesRequired=1;
[viewCanvasRecording addGestureRecognizer:shortTap];
y luego esto:
- (void)handleTapToFocus:(UITapGestureRecognizer *)tapGesture
{
AVCaptureDevice *acd=!currentFrontCamera ? captureBackInput.device : captureFrontInput.device;
if (tapGesture.state == UIGestureRecognizerStateEnded)
{
CGPoint thisFocusPoint = [tapGesture locationInView:viewCanvasRecording];
double focus_x = thisFocusPoint.x/viewCanvasRecording.frame.size.width;
double focus_y = thisFocusPoint.y/viewCanvasRecording.frame.size.height;
if ([acd isFocusModeSupported:AVCaptureFocusModeAutoFocus] && [acd isFocusPointOfInterestSupported])
{
if ([acd lockForConfiguration:nil])
{
[acd setFocusMode:AVCaptureFocusModeAutoFocus];
[acd setFocusPointOfInterest:CGPointMake(focus_x, focus_y)];
/*
if ([acd isExposureModeSupported:AVCaptureExposureModeAutoExpose] && [acd isExposurePointOfInterestSupported])
{
[acd setExposureMode:AVCaptureExposureModeAutoExpose];
[acd setExposurePointOfInterest:CGPointMake(focus_x, focus_y)];
}*/
[acd unlockForConfiguration];
}
}
}
}
Una versión Swift:
@IBAction func tapToFocus(_ sender: UITapGestureRecognizer) {
if (sender.state == .ended) {
let thisFocusPoint = sender.location(in: previewView)
print("touch to focus ", thisFocusPoint)
let focus_x = thisFocusPoint.x / previewView.frame.size.width
let focus_y = thisFocusPoint.y / previewView.frame.size.height
if (captureDevice!.isFocusModeSupported(.autoFocus) && captureDevice!.isFocusPointOfInterestSupported) {
do {
try captureDevice?.lockForConfiguration()
captureDevice?.focusMode = .autoFocus
captureDevice?.focusPointOfInterest = CGPoint(x: focus_x, y: focus_y)
if (captureDevice!.isExposureModeSupported(.autoExpose) && captureDevice!.isExposurePointOfInterestSupported) {
captureDevice?.exposureMode = .autoExpose;
captureDevice?.exposurePointOfInterest = CGPoint(x: focus_x, y: focus_y);
}
captureDevice?.unlockForConfiguration()
} catch {
print(error)
}
}
}
}