私は多かれ少なかれデフォルトのカメラアプリのように振る舞うカメラアプリを作成しようとしています。現時点ではうまくいかないのは、タップしてフォーカスすることです。カメラに焦点を合わせて、実際のカメラアプリと同じように、タッチした場所で何でもできるようにしたいと思います。
これが私の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];
};
そして、これが私のカメラフォーカスをワンクリックにする方法です。
-(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);
}];
}
画面をクリックしても何も起こりません。
次のコードのようなものを使用して、touchPointを[0,1]の範囲に調整する必要があります。
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];
これに関するドキュメントは Apple-AV Foundationプログラミングガイドライン-セクションMedia Captureを参照してください。 フォーカスモードに関する情報を見つける :
サポートされている場合は、focusPointOfInterestを使用してフォーカルポイントを設定します。 CGPointを渡します。{0,0}は画像領域の左上を表し、{1,1}は右がホームボタンの横長モードの右下を表します。これは、デバイスが縦長モードであっても適用されます。
UITapGestureRecognizer *shortTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapToFocus:)];
shortTap.numberOfTapsRequired=1;
shortTap.numberOfTouchesRequired=1;
[viewCanvasRecording addGestureRecognizer:shortTap];
そしてこれ:
- (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];
}
}
}
}
A 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)
}
}
}
}
これが、AVカメラプレビューのジェスチャーの処理方法です。最初にUITapGestureRecognizerをセットアップしてから、captureDevicePointOfInterestForPointを使用してポイントを取得します。
- (void)setupGestures
{
UITapGestureRecognizer *tapToFocusRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleTapToFocusAndExposureRecognizer:)];
[self addGestureRecognizer:tapToFocusRecognizer];
}
- (void)handleTapToFocusAndExposureRecognizer:(UITapGestureRecognizer*)tabRecognizer {
CGPoint touchPoint = [tabRecognizer locationInView:self];
CGPoint point = [self.previewLayer captureDevicePointOfInterestForPoint:touchPoint];
AVCaptureDevice *device = [self.videoCaptureDeviceInput device];
NSError *error = nil;
if (tabRecognizer.state == UIGestureRecognizerStateEnded) {
if (![device lockForConfiguration:&error]) {
if (error) {
RCTLogError(@"%s: %@", __func__, error);
}
return;
}
[device setFocusPointOfInterest:CGPointMake(point.x, point.y)];
[device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[device setExposurePointOfInterest:CGPointMake(point.x, point.y)];
[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
[device unlockForConfiguration];
}
}
AVCaptureVideoPreviewLayerを使用してタッチポイントを取得しています。ただし、AVCaptureVideoPreviewLayerの代わりにGLKViewを使用してプレビューをレンダリングする場合、ポイントを直接取得することはできませんが、前の回答のようにポイントを取得する必要があります。
IOS開発用の新しいコーダー。これがお役に立てば幸いです。