Skip to main content

get_live_text.swift

1#!/usr/bin/env swift
2// Get OCR'd text from an image using Live Text in macOS.
3//
4// If you're using Preview, you can use Live Text to copy and paste text
5// that's in an image. This script allows you to access that text
6// programatically, which is useful if you want to do bulk analysis of
7// the text in your images.
8//
9// You can search text in the Photos app, but this is useful if you:
10//
11// - want to search images that aren't in your Photos library
12// - want to do analysis which isn't just searching
13//
14// This is based on https://developer.apple.com/documentation/vision/recognizing_text_in_images
15//
16// Tested on macOS Monterey.
17//
18// You may need to run `chmod +x get_live_text` first and install the Xcode
19// command-line tools.
20//
21// == Usage ==
22//
23// Pass the path to your image as a single command-line argument. Any text
24// in the image will be returned as a JSON list:
25//
26// $ get_live_text railway-sign.jpg
27// ["Passengers must","not pass this point","or cross the line"]
28//
29// If the image doesn't contain any text, it returns an empty list:
30//
31// $ get_live_text dancers.jpg
32// []
33//
35import Vision
37let SCRIPT_VERSION = "1.0.0"
39// Process the results of the text-recognition request.
40//
41// This is based on the code in Apple's documentation, and prints the
42// recognized text as a list of JSON strings.
43//
44// See https://developer.apple.com/documentation/vision/recognizing_text_in_images#3601255
45func recognizeTextHandler(request: VNRequest, error: Error?) {
46 guard
47 let observations =
48 request.results as? [VNRecognizedTextObservation]
49 else {
50 return
51 }
52 let recognizedStrings = observations.compactMap { observation in
53 // Return the string of the top VNRecognizedText instance.
54 return observation.topCandidates(1).first?.string
55 }
57 print(recognizedStrings.joined(separator: " "))
60// Given the path to an image, print a JSON array of text it contains.
61func printTextInImage(imagePath: String) {
62 if !FileManager.default.fileExists(atPath: imagePath) {
63 fputs("Cannot find file at path: \(imagePath)\n", stderr)
64 exit(1)
65 }
67 let requestHandler = VNImageRequestHandler(
68 url: URL(fileURLWithPath: imagePath),
69 options: [:]
70 )
72 let request = VNRecognizeTextRequest(completionHandler: recognizeTextHandler)
74 do {
75 // Perform the text-recognition request.
76 try requestHandler.perform([request])
77 } catch {
78 fputs("Unable to recognise text: \(error).\n", stderr)
79 exit(1)
80 }
83let arguments = CommandLine.arguments
85if arguments.count == 2 && arguments[1] == "--version" {
86 let filename = (arguments[0] as NSString).lastPathComponent
87 print("\(filename) \(SCRIPT_VERSION)")
88 exit(0)
91if arguments.count != 2 {
92 fputs("Usage: \(arguments[0]) <PATH>\n", stderr)
93 exit(1)
96printTextInImage(imagePath: arguments[1])