Skip to content

Instantly share code, notes, and snippets.

View craigmarvelley's full-sized avatar

Craig Marvelley craigmarvelley

View GitHub Profile
// Pseudocode for checking if there is a large gap between the
// current and next candidate's bounding box.
var isNextItemOnNewParagraph: Bool {
let avgHeight = (currentObservationCandidateHeight + currentObservationCandidateHeight / 2)
let currentItemHeight = currentObservationCandidateHeight
let nextItemHeight = currentObservationCandidateHeight
let isSeparationLargerThanCurrentItemHeight = avgHeight >= currentItemHeight
let isSeparationLargerThanNextItemHeight = avgHeight >= nextItemHeight
extension Array where Element == OCRCandidate {
func sortCandidates() -> [OCRCandidate] {
self.sorted { (currentCandidate, nextCandidate) -> Bool in
let currentCandidateBottomY = currentCandidate.boundingPoints.avgBottomY
let nextCandidateBottomY = nextCandidate.boundingPoints.avgBottomY
if currentCandidateBottomY < nextCandidateBottomY {
// Rounding item for discrepancies with Y positions.
let difference = (currentCandidateBottomY - nextCandidateBottomY).roundTo2dp
private func ocrRequestHandler(request: VNRequest, error: Error?) {
guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
var ocrCandidates: [OCRCandidate] = []
for observation in observations {
guard let topCandidate = observation.topCandidates(1).first else { return }
// Vision algorithms use a coordinate system with lower left origin.
// Converting to upper left so the y values are increasing as the bounding box for observation
// goes down the list as to how humans read english text.
class DocumentOCRRequestProxy: OCRRequestProxy {
private lazy var ocrRequest: VNRecognizeTextRequest = VNRecognizeTextRequest(completionHandler: ocrRequestHandler)
private let requestHandler: VNImageRequestHandler
private weak var ocrRequestDelegate: OCRRequestDelegate?
private let cgImage: CGImage
init(cgImage: CGImage) {
self.cgImage = cgImage
// presenting VNDocumentCameraViewController
let scanVC = VNDocumentCameraViewController()
scanVC.delegate = self
present(scanVC, animated: true)
// VNDocumentCameraViewControllerDelegate conformance
extension DocumentsScannerViewController: VNDocumentCameraViewControllerDelegate {
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
[{"id":1,"name":"3 Hwr Doeth","description":"A mysterious hip hop crew from the Caernarfon area, big on lo-fi beats, weird pseudonyms and swearing, 3 Hwr Doeth bring the weirdness and Welsh language rap grubbiness in the best way since cult icons Tystion. Their debut, self-titled album, released on the great Pasta Hull label, is a rowdy 16-tracker, taking in much guest appearances and dissolute living, and which, in Smocio, Hustlo, Dwyn O Tesco, contains both epic title and life motto, whatever lingo you speak.","description_cy":"Hip hop collective o Gaernarfon yw 3 Hwr Doeth, yn arbrofi gyda synau gwahanol ag yn uno eu dylanwadau eclectig i greu rap Cymraeg sy\u2019n ymgorffori elfennau o funk, jazz a blues.","facebook":"https:\/\/www.facebook.com\/3hwrdoeth\/","soundcloud":"https:\/\/soundcloud.com\/3-hwr-doeth","twitter":"https:\/\/twitter.com\/achwmet","website":null,"image_url":"http:\/\/swnfest.com\/wp-content\/uploads\/2019\/04\/3-HWR-DOETH-2.jpg"},{"id":2,"name":"Alffa","description":"In these mid-apo
[{"id":1,"name":"Jacob's (Off Track Cafe)","address":"W Canal Wharf","city":"Cardiff","postcode":"CF10 5DB","telephone_number":"029 2039 0939","website":"https:\/\/jacobsmarket.co.uk","latitude":51.47546,"longitude":-3.17614,"capacity_status":0},{"id":2,"name":"Jacob's 2","address":"W Canal Wharf","city":"Cardiff","postcode":"CF10 5DB","telephone_number":"029 2039 0939","website":"https:\/\/jacobsmarket.co.uk","latitude":51.47546,"longitude":-3.17614,"capacity_status":0},{"id":3,"name":"Clwb Ifor Bach (Top)","address":"11 Womanby St","city":"Cardiff","postcode":"CF10 1BR","telephone_number":"029 2023 2199","website":"https:\/\/clwb.net","latitude":51.53443,"longitude":-3.21426,"capacity_status":0},{"id":4,"name":"Clwb Ifor Bach (Lawr)","address":"11 Womanby St","city":"Cardiff","postcode":"CF10 1BR","telephone_number":"029 2023 2199","website":"https:\/\/clwb.net","latitude":51.53443,"longitude":-3.21426,"capacity_status":0},{"id":5,"name":"Kongs","address":"114-116 St Mary Street","city":"Cardiff","postcode"
[{"artist_id":21,"venue_id":11,"id":1,"title":null,"start_time":"2019-10-18T19:30:00+0100","finish_time":"2019-10-18T20:15:00+0100","stage":null},{"artist_id":92,"venue_id":11,"id":2,"title":null,"start_time":"2019-10-18T20:45:00+0100","finish_time":"2019-10-18T21:30:00+0100","stage":null},{"artist_id":55,"venue_id":11,"id":3,"title":null,"start_time":"2019-10-18T22:00:00+0100","finish_time":"2019-10-18T23:15:00+0100","stage":null},{"artist_id":78,"venue_id":3,"id":4,"title":null,"start_time":"2019-10-18T19:00:00+0100","finish_time":"2019-10-18T19:30:00+0100","stage":null},{"artist_id":30,"venue_id":3,"id":5,"title":null,"start_time":"2019-10-18T20:00:00+0100","finish_time":"2019-10-18T20:30:00+0100","stage":null},{"artist_id":72,"venue_id":3,"id":6,"title":null,"start_time":"2019-10-18T21:00:00+0100","finish_time":"2019-10-18T21:30:00+0100","stage":null},{"artist_id":73,"venue_id":3,"id":7,"title":null,"start_time":"2019-10-18T22:00:00+0100","finish_time":"2019-10-18T22:45:00+0100","stage":null},{"artist_id"
- (NSMutableDictionary *)throttleActionHash
{
NSMutableDictionary *throttleData = objc_getAssociatedObject(self, THROTTLE_ACTION_HASH_PROPERTY_KEY);
if (!throttleData) {
throttleData = [[NSMutableDictionary alloc] init];
objc_setAssociatedObject(self, THROTTLE_ACTION_HASH_PROPERTY_KEY, throttleData, OBJC_ASSOCIATION_RETAIN);
}
return throttleData;
// Assume we have an NSPersistentStoreCoordinator which has been initialised with our entity model, and
// an NSURL which points to our store's location on disk
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeUrl options:options error:&error];
NSManagedObjectModel *destinationModel = coordinator.managedObjectModel;
BOOL storeIsCompatible = [destinationModel isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata];