← back to Dw Photo Capture
bin/ocr.swift
35 lines
import Foundation
import Vision
import AppKit
let args = CommandLine.arguments
guard args.count > 1, let img = NSImage(contentsOfFile: args[1]),
let cg = img.cgImage(forProposedRect: nil, context: nil, hints: nil) else { print(""); exit(1) }
// One image pass, two requests: printed-text OCR + barcode/QR detection.
let textReq = VNRecognizeTextRequest()
textReq.recognitionLevel = .accurate
textReq.usesLanguageCorrection = false
let barReq = VNDetectBarcodesRequest() // many sample labels carry a barcode = exact SKU
let h = VNImageRequestHandler(cgImage: cg, options: [:])
try? h.perform([textReq, barReq])
var lines: [String] = []
// Barcodes FIRST and tagged "BC" — the server treats a payload as ground truth (it locks
// immediately, ahead of any OCR'd code). symbology is appended for context.
for obs in (barReq.results ?? []) {
if let payload = obs.payloadStringValue, !payload.isEmpty {
let sym = obs.symbology.rawValue.replacingOccurrences(of: "VNBarcodeSymbology", with: "")
lines.append("BC\t\(payload)\t\(sym)")
}
}
// Text lines as "<heightThousandths>\t<text>" — boundingBox.height is normalized, so bigger
// printed text = taller box; the server ranks "largest letters first".
for obs in (textReq.results ?? []) {
if let t = obs.topCandidates(1).first?.string {
let hgt = Int((obs.boundingBox.height * 1000).rounded())
lines.append("\(hgt)\t\(t)")
}
}
print(lines.joined(separator: "\n"))