I’m merely attempting to scan bank card info by way of imaginative and prescient and am having combined outcomes. Non-embossed playing cards (which appear extra frequent these days) have probably the most points. I really feel like it could be having troubles with there being restricted distinction between the letters and backgrounds (silver card, white textual content). Ive tried up to now to attempt altering the picture to grayscale earlier than scanning, in addition to growing distinction and sharpness however that made outcomes worse the place it couldn’t acknowledge any textual content. What am i able to do to enhance my code to yield higher outcomes?
// MARK: Credit score Card Picture Recognition
open func detectRectangle(in picture: CVPixelBuffer) {
let request = VNDetectRectanglesRequest(completionHandler: { (request, error) in
DispatchQueue.principal.async {
guard let outcomes = request.outcomes as? [VNRectangleObservation], let outcome = outcomes.first else { return }
self.doPerspectiveCorrection(outcome, from: picture)
}
})
request.minimumAspectRatio = VNAspectRatio(1.3)
request.maximumAspectRatio = VNAspectRatio(1.3)
request.minimumSize = Float(0.5)
request.maximumObservations = 1
let imageHandler = VNImageRequestHandler(cvPixelBuffer: picture, choices: [:])
attempt? imageHandler.carry out([request])
}
open func doPerspectiveCorrection(_ commentary: VNRectangleObservation, from buffer: CVImageBuffer) {
var ciImage = CIImage(cvImageBuffer: buffer)
ciImage.cropped(to: holedOutRect)
let topLeft = commentary.topLeft.scaled(to: ciImage.extent.measurement)
let topRight = commentary.topRight.scaled(to: ciImage.extent.measurement)
let bottomLeft = commentary.bottomLeft.scaled(to: ciImage.extent.measurement)
let bottomRight = commentary.bottomRight.scaled(to: ciImage.extent.measurement)
ciImage = ciImage.applyingFilter("CIPerspectiveCorrection", parameters: [
"inputTopLeft": CIVector(cgPoint: topLeft),
"inputTopRight": CIVector(cgPoint: topRight),
"inputBottomLeft": CIVector(cgPoint: bottomLeft),
"inputBottomRight": CIVector(cgPoint: bottomRight),
])
let context = CIContext()
let cgImage = context.createCGImage(ciImage, from: ciImage.extent)
let output = UIImage(cgImage: cgImage!)
recognizeTextInImage(output)
}
open func recognizeTextInImage(_ picture: UIImage) {
guard let cgImage = picture.cgImage else { return }
textRecognitionWorkQueue.async {
guard !self.captured else { return }
let requestHandler = VNImageRequestHandler(cgImage: cgImage, choices: [:])
do {
guard let textRecognitionRequest = self.textRecognitionRequest else { return }
attempt requestHandler.carry out([textRecognitionRequest])
} catch {
print(error)
}
}
}
open func setupVision() {
textRecognitionRequest = VNRecognizeTextRequest { (request, error) in
guard !self.captured, let observations = request.outcomes as? [VNRecognizedTextObservation] else { return }
let creditCard = CardModel()
for commentary in observations {
guard let topCandidate = commentary.topCandidates(1).first, topCandidate.confidence > 0.25 else { return }
let topCandidateString = topCandidate.string
if topCandidateString.isName {
creditCard.identify = topCandidateString
}
if topCandidateString.isCardNumber {
creditCard.quantity = topCandidateString.onlyDigits
}
if topCandidateString.isExpirationDate {
creditCard.month = topCandidateString.expirationMonth
creditCard.yr = topCandidateString.expirationYear
}
}
DispatchQueue.principal.async {
guard let _ = creditCard.quantity else { return }
// Bank card quantity have been discovered, cease the digicam seize session
self.hapticScanSuccessResponse()
self.showScannedCardDetails(identify: creditCard.identify, cardNumber: creditCard.quantity, expiryMonth: creditCard.month, expiryYear: creditCard.yr)
DispatchQueue.principal.asyncAfter(deadline: .now() + 1, execute: {
// Ship it again to the calling protocol/delegate
guard !self.captured else { return }
self.captured = true
self.captureSession.stopRunning()
if self.embeddedAsView {
self.delegate?.didFinishScanningCreditCard?(cardModel: creditCard)
self.onDismissal?(creditCard)
} else {
self.dismiss(animated: true) {
self.delegate?.didFinishScanningCreditCard?(cardModel: creditCard)
}
}
})
}
}
textRecognitionRequest?.recognitionLevel = .correct
}
}
// MARK: AVCaptureVideoDataOutputSampleBufferDelegate
extension PaymentScannerViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
// AVCaptureVideoDataOutputSampleBufferDelegate -
open func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}
let ciImage = CIImage(cvPixelBuffer: imageBuffer)
guard let picture = ciImage.convertToUIImage() else { return }
imageCounter += 1
// Reduces the quantity of pictures processed to each twenty fifth picture with the intention to not attain max cpu utilization
guard !captured && imageCounter.isMultiple(of: 25) else { return }
detectRectangle(in: imageBuffer)
}
}