我正在try 使用SWIFT的Vision库从图像中读取文本.我遵循了这个指南--https://developer.apple.com/documentation/vision/recognizing_text_in_images.

就我的代码而言,所讨论的图像是self.Image,这是一个UIImage,而要显示的文本是self.RecognizedText,这是一个字符串.我在将文本识别请求识别的文本分配给完成处理程序RecognizeTextHandler中的self.RecognizedText时遇到问题.请注意,我确实记得在执行请求之前将self.Image转换为CGImage对象.

我在下面附上的代码不是我的完整代码.我已经在为Vision识别的文本赋值self.RecognizedText的位置进行了注释.我省略了用于控制呈现的UI组件的UI组件和某些状态(布尔值).我正在SwiftUI框架中的iOS上进行开发.

struct AnnotatorView: View {
    @State private var image: UIImage?
    @State private var recognizedText: String = "No text recognized."
    
     func recognizeTextHandler(request: VNRequest, error: Error?) -> Void {
        guard let results = request.results as? [VNRecognizedTextObservation] else {return}

        let recognizedStrings: Array<String> = results.compactMap({result in result.topCandidates(1).first!.string})

        // Problematic code.
        self.recognizedText = recognizedStrings.joined()
    }
    
    func performTextRecognition(requestHandler: VNImageRequestHandler, request: VNRecognizeTextRequest) -> String {
        do {
            try requestHandler.perform([request])
            return "Text recognition succeeded."
        } catch {
            return "Could not perform text recognition request because of the following error: \(error)"
        }
    }
    
    var body: some View {
        VStack(spacing: 15){
            
            // Camera opening button.
            
            // Image opening button.
            
            // Fullscreen cover that displays camera and sets self.image to a UIImage object.

            // Fullscreen cover that displays image and recognized text.
            .fullScreenCover(isPresented: self.$isAnnotatedImageDisplayed) {
                VStack {
                  // Fullscreen cover closing button.
                
                    if let cgImage: CGImage = self.image?.cgImage {
                        let requestHandler: VNImageRequestHandler = VNImageRequestHandler(cgImage: cgImage)
                        let recognizeTextRequest = VNRecognizeTextRequest(completionHandler: recognizeTextHandler)     
                        let textRecognitionStatus: String = performTextRecognition(requestHandler: requestHandler, request: recognizeTextRequest)
                    
                      // Display whether recognition request went through, the image taken and text recognized (if any).
                      Text(textRecognitionStatus)
                    
                      // Display image.
                    
                      if (!self.recognizedText.isEmpty) {
                        Text("\(self.recognizedText)")
                    } else {
                        Text("No text recognized because the image is not good enough.")
                    }
                  } else {
                    Text("You haven't taken any pictures yet!")
                    Text("\(self.recognizedText)")
    }}}}}}

struct AnnotatorView_Previews: PreviewProvider {
    static var previews: some View {
        AnnotatorView()
    }
}

我已try 在控制台上进行调试,但我的控制台拒绝记录任何信息.我在互联网上寻找了解决方案,但一无所获.无论如何,我解决这个问题的第一次try 是测试我的文本识别请求是否通过了.我用以下代码将其显示在全屏封面上--文本(ExtRecognitionStatus).但是,当我这样做时,我看到下面的消息-"文本识别成功."-我认为这意味着文本识别请求已经完成,没有任何错误.我曾try 使用数组来存储识别的文本,而不是文本,我认为这可能与Mutations 有关,但没有起到作用.我研究了 struct Mutations 的常见问题,但这些问题中的大多数都与 struct 本身之外的Mutations 有关.我认为这个问题可能与在SwiftUI的声明性框架中添加控制流语句有关,但所有其他文本都可以正确显示.如果我在这里犯了任何与语法相关的简单问题,例如,额外的方括号或缺少方括号,那可能是我在将代码复制到StackOverflow时犯下的错误.

推荐答案

这是一个工作样本,就像我之前说的,这可能是一个时间问题,因为你是在body分工作.

但另一件需要考虑的事情是,VNRecognizeTextRequest需要JPEG,因为它没有Alpha/透明度.

import SwiftUI
import Vision
import VisionKit
struct TextRecognitionView: View {
    let model: TextRecognitionModel = .init()
    @State private var image: UIImage?
    @State private var recognizedText: String? = nil
    var body: some View {
        VStack(spacing: 15){
            VStack {
                switch image { //Unwrap the Image
                case .none:
                    Text("You haven't taken any pictures yet!")
                case .some(let image):
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFit()
                    switch recognizedText { //Unwrap the text
                    case .none:
                        ProgressView() //Show this while recognizing
                    case .some(let text):
                        Text(text) //Show text
                    }
                }
                
                Button("set random text image") {
                    self.image = Text("Random text \((0...100).randomElement()!)")
                        .frame(width: 100, height: 100)
                        .snapshot().validJPEG() // Vision requires JPEG image likely because of transparency/alpha
                    self.recognizedText = nil //Clear the text
                    Task {
                        do {
                            self.recognizedText = try await model.performRequest(image: image!)
                        } catch {
                            self.recognizedText = error.localizedDescription //Show an error to the user
                            print(error)
                        }
                    }
                }
            }
        }
    }
}

struct TextRecognitionModel {
    /// async await version of a VNRecognizeTextRequest + VNImageRequestHandler
    func performRequest(image: UIImage) async throws -> String {
        guard let cgImage: CGImage = image.cgImage  else {
            throw RequestErrors.unableToRetrieveImage
        }
        let requestHandler: VNImageRequestHandler = VNImageRequestHandler(cgImage: cgImage)
        
        return try await withCheckedThrowingContinuation({ continuation in
            let request = VNRecognizeTextRequest(completionHandler: { request, error in
                if let error {
                    continuation.resume(throwing: error)
                } else {
                    let results = request.results as? [VNRecognizedTextObservation] ?? []
                    let recognizedStrings: Array<String> = results.compactMap({result in result.topCandidates(1).first!.string})
                    
                    continuation.resume(returning: recognizedStrings.joined())
                }
            })
            do {
                try requestHandler.perform([request])
            } catch {
                continuation.resume(throwing: error)
            }
        })
    }
}

enum RequestErrors: LocalizedError {
    case unableToRetrieveImage
}

struct TextRecognitionView_Previews: PreviewProvider {
    static var previews: some View {
        TextRecognitionView()
    }
}

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view
        
        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear
        
        let renderer = UIGraphicsImageRenderer(size: targetSize)
        
        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

extension UIImage {
    func validJPEG() -> UIImage {
        guard let data = self.jpegData(compressionQuality: 1) else {
            return .init()
        }
        
        guard let jpegImage = UIImage(data: data) else {
            return .init()
        }
        return jpegImage
    }
}

Ios相关问答推荐

在SWIFT中将圆角+透明背景从导入视频(.mp4)添加到导出视频(.mov)

SwiftUI@Observable不跟踪父类属性中的更改以更新视图

如何访问iOS模拟器中的zoom 设置?(在搜索中列出,但不可见)

如何在KMM项目中处理PHPickerViewController的回调?

在flatter_riverpod中,如果没有ref对象,我们如何访问提供程序?

无法关闭包含字体 Select 器的工作表

使用 Objective-C 创建 iOS 框架

使用异步重载实现Swift协议一致性

如何从 Locale Swift 获取货币符号

.onAppear() 函数不适用于 NavigationLink

NSFetchedResultsController 由字符串的第一个字母创建的部分

Xcode 缺少支持文件 iOS 12.2 (16E227)

Xcode 故事板:内部错误.请提交错误

iOS 中的 Crashlytics 不会继续通过 Fabric 应用程序中的构建您的项目

Xcode 11 向后兼容性:UIWindowScene 仅在 iOS 13 或更高版本中可用

是否可以使用 sharedHTTPCookieStorage 为 UIWebView 手动设置 cookie?

测试目标 X 遇到错误(提前意外退出,操作从未完成 bootstrap - 不会try 重新启动

iOS在应用程序中下载并保存图像

在 Objective-C 中将所有文本转换为小写

值/对象的 NSDictionary 键?