在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()
}
}
但它似乎无法奏效。
欢迎任何建议!
答案 0 :(得分:12)
更新了@ryantxr for 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
}
}
}
}
答案 1 :(得分:3)
更好的解决方案,因为它适用于所有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
}
答案 2 :(得分:2)
更新了@Code for 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
}
}
}
}
答案 3 :(得分:1)
原来很简单:
_currentDevice.lockForConfiguration(nil)
_currentDevice.focusPointOfInterest = tap.locationInView(self)
_currentDevice.unlockForConfiguration()
答案 4 :(得分:1)
这个问题可能与iOS tap to focus重复,我发布了这个(希望是明确的)解决方案,对我有用:
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到1 - 不知道为什么会出现这种情况但似乎有必要让它正常工作(虽然测试它也有点棘手)。
答案 5 :(得分:1)
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)
}
}
答案 6 :(得分:1)
我使用了AVFoundation
库和Camera Manager的包装器。
我正在分享代码示例。您可以调整您的项目。
顺便说一句,你不能使用前置摄像头对焦相机。它不支持它。您只能调整前置摄像头的曝光。通过稀有相机,你可以做到。
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")
}
}
}
}