Установите фокус камеры на точку касания с помощью Swift
API для быстрого использования камеры кажется совсем другим, и мне трудно сфокусировать камеру на какой-либо точке. Когда пользователь касается экрана, я хочу, чтобы камера сфокусировалась на этой точке.
Это мой код:
func focusCamera(point:CGPoint)
{
var screenRect:CGRect = bounds
var focusX = Float(point.x/screenRect.width)
var focusY = Float(point.y/screenRect.height)
_currentDevice.lockForConfiguration(nil)
_currentDevice.setFocusModeLockedWithLensPosition(focusX)
{
time in
self._currentDevice.unlockForConfiguration()
}
_currentDevice.setFocusModeLockedWithLensPosition(focusY)
{
time in
self._currentDevice.unlockForConfiguration()
}
}
Но это не похоже на работу.
Любые предложения приветствуются!
7 ответов
Оказывается, это очень просто:
_currentDevice.lockForConfiguration(nil)
_currentDevice.focusPointOfInterest = tap.locationInView(self)
_currentDevice.unlockForConfiguration()
Обновленный ответ от @ryantxr для Swift 3:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let screenSize = videoView.bounds.size
if let touchPoint = touches.first {
let x = touchPoint.location(in: videoView).y / screenSize.height
let y = 1.0 - touchPoint.location(in: videoView).x / screenSize.width
let focusPoint = CGPoint(x: x, y: y)
if let device = captureDevice {
do {
try device.lockForConfiguration()
device.focusPointOfInterest = focusPoint
//device.focusMode = .continuousAutoFocus
device.focusMode = .autoFocus
//device.focusMode = .locked
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.continuousAutoExposure
device.unlockForConfiguration()
}
catch {
// just ignore
}
}
}
}
Лучшее решение, так как оно работает правильно для всех videoGravity
режимы, также когда соотношение сторон слоя предварительного просмотра отличается от соотношения устройства:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touchPoint = touches.first else { return }
// precondition: the videoView contains the previewLayer, and the frames of the two are being kept equal
let touchPointInPreviewLayer = touchPoint.location(in: videoView)
let focusPoint = previewLayer.captureDevicePointOfInterest(for: touchPointInPreviewLayer)
// etc
}
Обновленный ответ от @Code для Swift 2.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let screenSize = videoView.bounds.size
if let touchPoint = touches.first {
let x = touchPoint.locationInView(videoView).y / screenSize.height
let y = 1.0 - touchPoint.locationInView(videoView).x / screenSize.width
let focusPoint = CGPoint(x: x, y: y)
if let device = captureDevice {
do {
try device.lockForConfiguration()
device.focusPointOfInterest = focusPoint
//device.focusMode = .ContinuousAutoFocus
device.focusMode = .AutoFocus
//device.focusMode = .Locked
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
device.unlockForConfiguration()
}
catch {
// just ignore
}
}
}
}
Я использовал AVFoundation
библиотека и обертка, что диспетчер камеры. Я делюсь с примером кода. Вы можете адаптировать свой проект. Кстати, вы не можете сфокусировать камеру с помощью фронтальной камеры. Это не поддерживает это. Вы можете регулировать экспозицию только для фронтальной камеры. С помощью редкой камеры вы можете сделать это.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let screenSize = cameraView.bounds.size
let frameSize:CGSize = view.frame.size
if let touchPoint = touches.first {
var location:CGPoint = touchPoint.locationInView(cameraView)
if cameraManager.cameraDevice == .Front {
print("Front camera is used")
location.x = frameSize.width - location.x;
}
else {
print("Back camera is used")
}
let x = location.x / frameSize.width
let y = 1.0 - (location.x / frameSize.width)
let focusPoint = CGPoint(x: x, y: y)
print("POINT : X: \(x), Y: \(y)")
let captureDevice = (AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice]).filter{$0.position == .Back}.first
if let device = captureDevice {
do {
try device.lockForConfiguration()
let support:Bool = device.focusPointOfInterestSupported
if support {
print("focusPointOfInterestSupported: \(support)")
device.focusPointOfInterest = focusPoint
// device.focusMode = .ContinuousAutoFocus
device.focusMode = .AutoFocus
// device.focusMode = .Locked
device.unlockForConfiguration()
print("Focus point was set successfully")
}
else{
print("focusPointOfInterestSupported is not supported: \(support)")
}
}
catch {
// just ignore
print("Focus point error")
}
}
}
}
Swift 2.0
if let device = captureDevice {
do {
try device.lockForConfiguration()
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
} catch let error as NSError {
print(error.localizedDescription)
}
}
Этот вопрос, возможно, является дубликатом касания iOS для фокусировки, где я разместил это (надеюсь, явное) решение, которое сработало для меня:
С 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)) {
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.ContinuousAutoExposure
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
device.unlockForConfiguration()
}
}
}
Обратите внимание, что я должен был поменять x
а также y
координаты и переназначить x
Координаты от 1 до 0 вместо 0 до 1 - не уверен, почему так должно быть, но кажется, что необходимо заставить его работать правильно (хотя это тоже немного сложно проверить).