このコードを使用して、iOSカスタムカメラアプリでTap-to-Focusを実現しましたが、機能していません。これがコードです
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touchPer = touches.anyObject() as UITouch
let screenSize = UIScreen.mainScreen().bounds.size
var focus_x = touchPer.locationInView(self.view).x / screenSize.width
var focus_y = touchPer.locationInView(self.view).y / screenSize.height
if let device = captureDevice {
if(device.lockForConfiguration(nil)) {
device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus
device.focusPointOfInterest = CGPointMake(focus_x, focus_y)
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
device.unlockForConfiguration()
}
}
}
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.AutoFocus
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
なぜこれが機能するのかはわかりませんが、機能しました。
videoView: UIView
がビデオを表示し、cameraDevice: AVCaptureDevice
を使用すると、次のことがうまくいくようです。
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touchPoint = touches.first as! UITouch
var screenSize = videoView.bounds.size
var focusPoint = CGPoint(x: touchPoint.locationInView(videoView).y / screenSize.height, y: 1.0 - touchPoint.locationInView(videoView.x / screenSize.width)
if let device = cameraDevice {
if(device.lockForConfiguration(nil)) {
if device.focusPointOfInterestSupported {
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.AutoFocus
}
if device.exposurePointOfInterestSupported {
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.AutoExpose
}
device.unlockForConfiguration()
}
}
}
x
座標とy
座標を交換し、x
座標を0から1ではなく1から0に再マップする必要があることに注意してください—なぜそうなのかはわかりませんが、正しく機能させる必要があるようです(テストするのも少し難しいですが)。
編集: Appleのドキュメント 座標変換の理由を説明しています。
さらに、デバイスは、関心のあるフォーカスポイントをサポートする場合があります。 focusPointOfInterestSupportedを使用してサポートをテストします。サポートされている場合は、focusPointOfInterestを使用してフォーカルポイントを設定します。 CGPointを渡します。ここで、{0,0}は画像領域の左上を表し、{1,1}は右下を表し、ホームボタンが右側にあります。これは、デバイスがポートレートモードの場合でも適用されます。 。
私の例では、.ContinuousAutoFocus
と.ContinuousAutoExposure
を使用していましたが、ドキュメントには.AutoFocus
が正しい選択であることが示されています。奇妙なことに、ドキュメントには.AutoExpose
についての記載がありませんが、コードで使用しており、正常に動作します。
また、サンプルコードを変更して、.focusPointOfInterestSupported
および.exposurePointOfInterestSupported
テストを含めました。ドキュメントには、特定のフォーカス/露出モードでisFocusModeSupported:
およびisExposureModeSupported:
メソッドを使用してテストするかどうかも記載されています。設定する前に特定のデバイスで使用できますが、デバイスが関心のあるモードをサポートしている場合は、自動モードもサポートしていると思います。私のアプリではすべて正常に機能しているようです。
Swift 3.0ソリューション
コーディの答えをSwift 3で実用的なソリューションに変換しました。
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchPoint = touches.first! as UITouch
let screenSize = cameraView.bounds.size
let focusPoint = CGPoint(x: touchPoint.location(in: cameraView).y / screenSize.height, y: 1.0 - touchPoint.location(in: cameraView).x / screenSize.width)
if let device = captureDevice {
do {
try device.lockForConfiguration()
if device.isFocusPointOfInterestSupported {
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.autoFocus
}
if device.isExposurePointOfInterestSupported {
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.autoExpose
}
device.unlockForConfiguration()
} catch {
// Handle errors here
}
}
}
関心のあるフォーカスポイントを設定するためのより良い方法:
最初に関心のあるポイントを計算します。
let devicePoint: CGPoint = (self.previewView.layer as! AVCaptureVideoPreviewLayer).captureDevicePointOfInterestForPoint(gestureRecognizer.locationInView(gestureRecognizer.view))
その後、関心のあるフォーカスポイントを設定します。
let device: AVCaptureDevice! = self.videoDeviceInput!.device
do {
try device.lockForConfiguration()
if device.focusPointOfInterestSupported && device.isFocusModeSupported(focusMode){
device.focusPointOfInterest = devicePoint
device.focusMode = focusMode
}
device.unlockForConfiguration()
}catch{
print(error)
}
メソッドを正しい順序で呼び出す必要があります。
if(device.lockForConfiguration(nil)) {
device.focusPointOfInterest = CGPointMake(focus_x, focus_y)
device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
device.unlockForConfiguration()
}
フォーカスモードを設定する前に、関心のあるポイントを設定してください。そうしないと、前の関心のあるポイントにフォーカスが移されます。
同じことがexposurePointOfInterest
にも当てはまります。