Skip to content

Document capture

The document is detected on the device by IDCardDetectionWrapper and captured automatically once the user holds it correctly in front of the camera. You then send the captured image to Prove ID for verification.

import UIKit
import id_card_detection_ios_wrapper
import id_card_detection_ios_cnn
final class DocumentCaptureViewController: UIViewController {
@IBOutlet weak var containerView: UIView!
var transactionId = ""
private var reader: IDCardDetectionWrapper?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let reader = IDCardDetectionWrapper(frame: containerView.frame)
containerView.addSubview(reader.getView()!)
let conf = IDCardDetectionWrapperConfiguration()
conf.cardTypeList = [.NEW_ID] // .NEW_ID_BACK for the back side
conf.messageToEncrypt = transactionId
conf.encryptDeviceId = true
conf.detectBothOrientation = true
reader.setConfiguration(conf: conf)
reader.setDelegate(delegate: self)
reader.setViewDelegate(delegate: self)
reader.startCapture()
self.reader = reader
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
reader?.stopCapture()
}
}
extension DocumentCaptureViewController: IDCardDetectionWrapperDelegate, IDCardDetectionWrapperViewDelegate {
func cardDetected(image: UIImage, cardType: WrapperCardType) {
reader?.stopCapture()
// Send the image to Prove ID (below)
}
func cardDetectionFailed(wrapperErrorsModel: WrapperErrorsModel) {
// Guide the user: move closer, avoid glare, etc. (see Errors)
}
func onViewDrawn(mainRect: CGRect, photoRect: CGRect?) { }
}

The delegate methods can be called on a background thread; update the UI on DispatchQueue.main.

To also send the full camera frame the document was captured from, set a frame delegate. cardDetected(cardImage:cardType:frame:) is then called with both images; use it instead of cardDetected(image:cardType:).

reader.setFrameDelegate(delegate: self)
extension DocumentCaptureViewController: IDCardDetectionWrapperFrameDelegate {
func cardDetected(cardImage: UIImage, cardType: WrapperCardType, frame: UIImage) {
// Send cardImage and frame
}
}

Convert the captured image to Base64 and send it with the call for the document type:

import ProveIDApiClient
func verifyFront(image: UIImage, frame: UIImage?, controlResults: [ProveIDApiClient.ControlEntryModel]? = nil) {
let body = CheckIDModel(transactionId: transactionId,
img: image.pngData()!.base64EncodedString(),
frame: frame?.pngData()?.base64EncodedString(),
controlResults: controlResults)
IDServiceAPI.checkNewIDCard(body: body) { result in
switch result {
case .success(let response):
let data = response.capturedData // IDInformationModel
let controls = response.controlResults // [ControlEntryModel]
showFrontResult(data, controls)
case .failure(let error):
showError(error)
}
}
}
Document Call
Turkish ID card — front IDServiceAPI.checkNewIDCard(body: CheckIDModel(…))
Turkish ID card, driving licence, old ID — back IDServiceAPI.addSecondary(body: SecondaryIDInformationModel(image:frame:transactionID:))
Old Turkish ID card IDServiceAPI.checkOldIDCard(body: CheckIDModel(…))
Driving licence IDServiceAPI.checkNewDriverCard(body: CheckIDModel(…))
Passport IDServiceAPI.checkPassport(body: CheckIDModel(…))
Blue card IDServiceAPI.checkTurkishBlueCard(body: CheckIDModel(…))
Foreign ID card IDServiceAPI.checkForeignID(body: CheckIDModel(…))

The front calls return a CheckIdReturnModel, the back call a SecondaryResultModel. Both carry capturedData (IDInformationModel) with the data read from the document: id, name, sname, nat, gend, sno, bdat, edat.

With IDCardDetectionWrapperConfiguration:

Setting Description
cardTypeList: [WrapperCardType] Document types to detect
detectBothOrientation: Bool Detects the document in both orientations
isFocusScoreThresholdActive: Bool Waits for a sharp frame instead of capturing immediately (default false)
focusScoreThreshold: Float Score at which a frame is captured immediately (e.g. 0.95)
minFocusScore: Float Lower sharpness threshold (e.g. 0.55)
eligibleFocusScoreCount: Int Consecutive frames that must pass minFocusScore
maxHologramScoreForBlur: Float Avoids hologram glare (e.g. 0.75)
maxGlareScore: Float Avoids glare on the document (e.g. 0.5)
turnIfReverse: Bool Rotates a document held upside down
checkCardType: Bool Rejects documents other than cardTypeList
isMrzActive: Bool MRZ reading
captureOnlyInHint: Bool Captures only when the document is inside the frame hint
captureOnlyInHintMargin: CGFloat Allowed margin around the hint (e.g. 0.1)
messageToEncrypt: String Message embedded in the image; pass the transaction ID
encryptDeviceId: Bool Embeds the device ID in the image

The detection tolerances are global:

CNNUtil.ACCEPTABLE_RIGHT_LEFT_LINE_ERROR_RATIO = 0.075
CNNUtil.ACCEPTABLE_TOP_BOTTOM_LINE_ERROR_RATIO = 0.075
CNNUtil.ACCEPTABLE_WIDTH_HEIGHT_ERROR_RATIO = 0.075

On the front of the Turkish ID card the SDK can check on the device whether a photocopy is shown:

conf.doFraudCheck = true
conf.hologramScoreForFraud = 0.85
conf.checkingFraudTimeInMs = 2000
reader.setFraudDelegate(delegate: self)
extension DocumentCaptureViewController: IDCardDetectionWrapperFraudDelegate {
func fraudChecked(fraudResultModel: WrapperFraudResultModel) {
let captured = fraudResultModel.cardDetectedModel
let passed = fraudResultModel.fraudType == nil
// Pass the outcome to Prove ID with the image
let entry = ProveIDApiClient.ControlEntryModel(entryType: "CLPHOTOCOPYDETECTION",
entryScore: passed ? 1.0 : 0.0,
entryInterpretation: AnyCodable(passed))
verifyFront(image: captured.image, frame: captured.frame, controlResults: [entry])
}
}

fraudChecked is called with the captured document (cardDetectedModel) once the check is done; send the image from there.

For visual settings see Customization.