Comment puis-je utiliser le metadataOutputRectOfInterestForRect méthode et rectOfInterest propriété pour numériser un domaine précis? (QR Code)
Je suis la construction d'un QR code à scanner avec Swift et tout fonctionne à cet égard. Le problème que j'ai c'est que je suis en train de faire une petite partie de l'ensemble du visible AVCaptureVideoPreviewLayer
être en mesure de scanner les QR codes. J'ai découvert que dans le but de spécifier quelle zone de l'écran sera en mesure de lire/capture QR codes que je dois utiliser une propriété de AVCaptureMetadataOutput
appelé rectOfInterest
. Le problème, c'est quand j'ai attribué cela à un CGRect, je ne pouvais pas scanner quoi que ce soit. Après avoir fait plusieurs recherches sur internet j'ai trouvé quelques suggérant que j'aurais besoin d'utiliser une méthode appelée metadataOutputRectOfInterestForRect
pour convertir un CGRect dans un format correct que la propriété rectOfInterest
peuvent réellement utiliser. CEPENDANT, le gros problème que j'ai maintenant c'est que quand j'utilise cette méthode metadataoutputRectOfInterestForRect
j'obtiens un message d'erreur qui indique CGAffineTransformInvert: singular matrix
. Quelqu'un peut me dire pourquoi j'obtiens cette erreur? Je crois que je suis en utilisant cette méthode correctement selon le site Apple developer documentation et je crois que j'ai besoin pour utiliser cette fonction pour toutes les informations que j'ai trouvé en ligne pour accomplir mon objectif. Je vais inclure des liens vers la documentation que j'ai trouvé jusqu'à présent ainsi qu'un exemple de code de la fonction que j'utilise pour scanner les QR codes
EXEMPLE DE CODE
func startScan() {
//Get an instance of the AVCaptureDevice class to initialize a device object and provide the video
//as the media type parameter.
let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
//Get an instance of the AVCaptureDeviceInput class using the previous device object.
var error:NSError?
let input: AnyObject! = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &error)
if (error != nil) {
//If any error occurs, simply log the description of it and don't continue any more.
println("\(error?.localizedDescription)")
return
}
//Initialize the captureSession object.
captureSession = AVCaptureSession()
//Set the input device on the capture session.
captureSession?.addInput(input as! AVCaptureInput)
//Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession?.addOutput(captureMetadataOutput)
//calculate a centered square rectangle with red border
let size = 300
let screenWidth = self.view.frame.size.width
let xPos = (CGFloat(screenWidth) / CGFloat(2)) - (CGFloat(size) / CGFloat(2))
let scanRect = CGRect(x: Int(xPos), y: 150, width: size, height: size)
//create UIView that will server as a red square to indicate where to place QRCode for scanning
scanAreaView = UIView()
scanAreaView?.layer.borderColor = UIColor.redColor().CGColor
scanAreaView?.layer.borderWidth = 4
scanAreaView?.frame = scanRect
view.addSubview(scanAreaView!)
//Set delegate and use the default dispatch queue to execute the call back
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
captureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
//Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
captureMetadataOutput.rectOfInterest = videoPreviewLayer!.metadataOutputRectOfInterestForRect(scanRect)
view.layer.addSublayer(videoPreviewLayer)
//Start video capture.
captureSession?.startRunning()
//Initialize QR Code Frame to highlight the QR code
qrCodeFrameView = UIView()
qrCodeFrameView?.layer.borderColor = UIColor.greenColor().CGColor
qrCodeFrameView?.layer.borderWidth = 2
view.addSubview(qrCodeFrameView!)
view.bringSubviewToFront(qrCodeFrameView!)
//Add a button that will be used to close out of the scan view
videoBtn.setTitle("Close", forState: .Normal)
videoBtn.setTitleColor(UIColor.blackColor(), forState: .Normal)
videoBtn.backgroundColor = UIColor.grayColor()
videoBtn.layer.cornerRadius = 5.0;
videoBtn.frame = CGRectMake(10, 30, 70, 45)
videoBtn.addTarget(self, action: "pressClose:", forControlEvents: .TouchUpInside)
view.addSubview(videoBtn)
view.bringSubviewToFront(scanAreaView!)
}
Veuillez noter que la ligne de l'intérêt de la cause de l'erreur est:
captureMetadataOutput.rectOfInterest = videoPreviewLayer!.metadataOutputRectOfInterestForRect(scanRect)
D'autres choses que j'ai essayé ne sont que de passage dans un CGRect directement comme paramètre et qui a provoqué la même erreur. J'ai également passé dans scanAreaView!.bounds
comme un paramètre que c'est vraiment la taille exacte/domaine, je suis à la recherche d', et qui provoque également la même erreur exact. J'ai vu ce fait dans d'autres, des exemples de code en ligne et ils ne semblent pas avoir les erreurs que j'ai. Voici quelques exemples:
AVCaptureSession de codes à barres de numérisation
La documentation d'Apple
metadataOutputRectOfInterestForRect
Image de scanAreaView je suis à l'aide de la région désignée je suis en train de faire la seule analysables de la zone de l'aperçu vidéo de la couche:
- Ce peut être utilisée si vous utilisez AVCapturePhotoCaptureDelegate de func photoOutput(_ de sortie: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, d'erreur: Erreur?) au lieu de cela ?
Vous devez vous connecter pour publier un commentaire.
Je n'étais pas vraiment en mesure de clarifier la question avec metadataOutputRectOfInterestForRect, cependant, vous pouvez régler directement la propriété ainsi. Vous avez besoin d'avoir la résolution en largeur et la hauteur de votre vidéo, que vous pouvez spécifier à l'avance. J'ai rapidement utilisé le 640*480 réglage. Comme indiqué dans la documentation, ces valeurs doivent être
Voir https://developer.apple.com/documentation/avfoundation/avcaptureoutput/1616304-metadataoutputrectofinterestforr
Ci-dessous le code que j'ai essayé
Je l'ai juste testé sur un appareil iOS et il semble fonctionner.
Modifier
Au moins j'ai résolu le metadataOutputRectOfInterestForRect problème. Je crois que vous avez à faire cela, après que l'appareil a été correctement mis en place et est en cours d'exécution, comme l'appareil photo, la résolution n'est pas encore disponible.
Tout d'abord, ajoutez une notification observateur de la méthode au sein de l'viewDidLoad()
Puis ajoutez la méthode suivante
Ici vous pouvez réinitialiser la rectOfInterest de la propriété. Puis, dans votre code, vous pouvez afficher le AVMetadataObject dans le didOutputMetadataObjects fonction
J'ai essayé, et le rectangle est toujours à l'intérieur de la zone spécifiée.
Dans iOS 9.3.2 j'ai pu faire
metadataoutputRectOfInterestForRect
travail de l'appeler juste aprèsstartRunning
méthode deAVCaptureSession
:Swift 4:
J'ai réussi à créer un effet de disposer d'une région d'intérêt. J'ai essayé toutes les solutions proposées, mais la région a été un CGPoint.zéro ou a taille inappropriée (après la conversion d'images à un 0-1 coordonner). C'est en fait un hack pour ceux qui ne peuvent pas obtenir la
regionOfInterest
de travailler et de ne pas optimiser la détection.Dans:
J'ai le code suivant:
///Après
///Ajouter ce
De lire un QRCode/code à Barres d'un petit rect(région spécifique) d'une pleine vue de la caméra.
Remarque:
captureMetadataOutput
--> AVCaptureMetadataOutput_videoPreviewLayer
--> AVCaptureVideoPreviewLayerscanRect
--> Rect où vous souhaitez que le QRCode pour être lu.J'ai écrit ce qui suit:
Et cela a fonctionné pour moi, mais je ne sais toujours pas pourquoi.