从iOS相机捕捉图片

时间:2014-11-13 13:46:57

标签: ios iphone swift camera avfoundation

我需要通过相机拍摄图像。但它出现以下错误:'NSInvalidArgumentException',原因:'无法直接实例化AVCaptureDevice。'

遵循以下代码:

    var session: AVCaptureSession!
    var device: AVCaptureDevice!
    var captureVideoPreviewLayer: AVCaptureVideoPreviewLayer!
    var image: UIImage!
    var input: AVCaptureDeviceInput!
    var stillImageOutput: AVCaptureStillImageOutput!
    var viewControllerScheduling: RentalSchedulingViewController!

    override func viewDidLoad() {
        super.viewDidLoad()

        session = AVCaptureSession()
        session.sessionPreset = AVCaptureSessionPresetPhoto;
        captureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
        captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        captureVideoPreviewLayer.frame = self.view.frame
        self.view.layer.addSublayer(captureVideoPreviewLayer)
        var error = NSErrorPointer()
        captureVideoPreviewLayer.session.beginConfiguration()
        input = AVCaptureDeviceInput(device: self.getBackCamera(), error: error)
        session.addInput(input)
        captureVideoPreviewLayer.session.commitConfiguration()
        stillImageOutput = AVCaptureStillImageOutput()
        var outputSettings = NSDictionary(objectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey)
        stillImageOutput.outputSettings = outputSettings
        session.addOutput(stillImageOutput)
        session.startRunning()
    }

取回相机:

    func getBackCamera() -> AVCaptureDevice {
        var devic = AVCaptureDevice()
        let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as NSArray
        for dev in devices {
            devic = dev as AVCaptureDevice
            if devic.position == AVCaptureDevicePosition.Back {
                return devic
            }
        }
        return devic
    }

捕捉图片的事件:

   @IBAction func capture(sender: AnyObject) {
        var videoConnection = AVCaptureConnection()

        for con in stillImageOutput.connections {
            let connection = con as AVCaptureConnection

            for p in connection.inputPorts {
                let port = p as AVCaptureInputPort

                if port.mediaType == AVMediaTypeVideo {
                    videoConnection = connection
                    break;
                }
            }
        }

        stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection) {
            (imageSampleBuffer, error) in
            if imageSampleBuffer != nil {
                let imageData = AVCaptureStillImageOutput .jpegStillImageNSDataRepresentation(imageSampleBuffer)
                self.processImage(UIImage(data: imageData)!)
            }
        }
    }

处理图片:

    func processImage(image: UIImage) {
        UIGraphicsBeginImageContext(CGSizeMake(320, 426));
        image.drawInRect(CGRectMake(0, 0, 320, 426))
        let smallImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();

        let cropRect = CGRectMake(0, 55, 320, 320)
        let imageRef = CGImageCreateWithImageInRect(smallImage.CGImage, cropRect)
        self.image = UIImage(CGImage: imageRef)
    }

错误发生在这里:

input = AVCaptureDeviceInput(device: self.getBackCamera(), error: error)

2 个答案:

答案 0 :(得分:2)

我一直在查找这个问题。您似乎无法实际实例化设备AVCaptureDevice对象。必须通过引用传递它。这就是我克服挑战的方式。 我没有实例化该类,我只是将其作为对AVCaptureDeviceInput对象的引用传递给它。

希望这有帮助!

    var captureDevice : AVCaptureDevice?

    let devices = AVCaptureDevice.devices()

    // Loop through all the capture devices on this phone
    for device in devices {
        // Make sure this particular device supports video
        if (device.hasMediaType(AVMediaTypeVideo)) {
            // Finally check the position and confirm we've got the back camera
            if(device.position == AVCaptureDevicePosition.Back) {
                captureDevice = device as? AVCaptureDevice
            }
        }
    }

}

答案 1 :(得分:0)

也许你在此期间解决了这个问题,但是如果你改变这样的代码它应该有效:

只需移除devic = AVCaptureDevice()

中的getBackCamera()即可

并在类的头部声明如下:var device, devic : AVCaptureDevice!

class ViewController: UIViewController {

var session: AVCaptureSession!
var device, devic : AVCaptureDevice!
var captureVideoPreviewLayer: AVCaptureVideoPreviewLayer!
var image: UIImage!
var input: AVCaptureDeviceInput!
var stillImageOutput: AVCaptureStillImageOutput!
//var viewControllerScheduling: RentalSchedulingViewController!


override func viewDidLoad() {
    super.viewDidLoad()

    session = AVCaptureSession()
    session.sessionPreset = AVCaptureSessionPresetPhoto;
    captureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    captureVideoPreviewLayer.frame = self.view.frame
    self.view.layer.addSublayer(captureVideoPreviewLayer)
    var error = NSErrorPointer()
    captureVideoPreviewLayer.session.beginConfiguration()
    input = AVCaptureDeviceInput(device: self.getBackCamera(), error: error)
    session.addInput(input)
    captureVideoPreviewLayer.session.commitConfiguration()
    stillImageOutput = AVCaptureStillImageOutput()
    var outputSettings = NSDictionary(objectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey)
    stillImageOutput.outputSettings = outputSettings as [NSObject : AnyObject]
    session.addOutput(stillImageOutput)
    session.startRunning()

}

func getBackCamera() -> AVCaptureDevice {
   // devic = AVCaptureDevice()
    let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as NSArray
    for dev in devices {
        devic = dev as! AVCaptureDevice
        if devic.position == AVCaptureDevicePosition.Back {
            return devic
        }
    }
    return devic
}