IOS自带的OCR识别功能
一、识别身份证
@interface IDCardScanViewController () <AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic, strong) AVCaptureSession *captureSession;
@end
@implementation IDCardScanViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建视频预览层
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.frame = self.scanView.bounds;
[self.scanView.layer addSublayer:previewLayer];
// 创建数据输出
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[self.captureSession addOutput:output];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
// 设置扫描支持的码类型
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeIDCard]) {
output.metadataObjectTypes = @[AVMetadataObjectTypeIDCard];
}
// 启动扫描
[self.captureSession startRunning];
}
- (AVCaptureSession *)captureSession {
if (!_captureSession) {
_captureSession = [[AVCaptureSession alloc] init];
// 配置摄像头输入
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
[_captureSession addInput:input];
}
return _captureSession;
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
for (AVMetadataObject *metadata in metadataObjects) {
if ([metadata isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
AVMetadataMachineReadableCodeObject *code = (AVMetadataMachineReadableCodeObject *)metadata;
if ([code.type isEqualToString:AVMetadataObjectTypeIDCard]) {
NSString *result = code.stringValue;
// 对扫描结果进行处理
NSLog(@"扫描结果:%@", result);
}
}
}
}
下面的方法需要iOS13以上才能支持
#import <Vision/Vision.h>
#import <VisionKit/VisionKit.h>
@interface ViewController () <VNDocumentCameraViewControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 在需要的地方调用此方法启动身份证扫描
[self startDocumentCapture];
}
- (void)startDocumentCapture {
VNDocumentCameraViewController *documentCameraViewController = [[VNDocumentCameraViewController alloc] init];
documentCameraViewController.delegate = self;
[self presentViewController:documentCameraViewController animated:YES completion:nil];
}
#pragma mark - VNDocumentCameraViewControllerDelegate
- (void)documentCameraViewController:(VNDocumentCameraViewController *)controller didFinishWithScan:(VNDocumentCameraScan *)scan {
// 遍历扫描结果
for (NSUInteger pageIndex = 0; pageIndex < scan.pageCount; pageIndex++) {
VNPage *page = [scan pageAtIndex:pageIndex];
// 检查扫描结果是否为身份证
if ([self isIdentityCard:page]) {
// 获取身份证号码和姓名
NSString *number = [self identityCardNumberFromPage:page];
NSString *name = [self identityCardNameFromPage:page];
NSLog(@"身份证号码:%@", number);
NSLog(@"姓名:%@", name);
// 在这里进行身份证识别后的处理
}
}
// 关闭扫描视图控制器
[controller dismissViewControllerAnimated:YES completion:nil];
}
- (void)documentCameraViewControllerDidCancel:(VNDocumentCameraViewController *)controller {
// 用户取消了扫描,关闭扫描视图控制器
[controller dismissViewControllerAnimated:YES completion:nil];
}
- (void)documentCameraViewController:(VNDocumentCameraViewController *)controller didFailWithError:(NSError *)error {
// 扫描失败,处理错误信息
NSLog(@"扫描身份证发生错误:%@", error);
[controller dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Helper Methods
- (BOOL)isIdentityCard:(VNPage *)page {
// 获取页面文本内容
NSString *text = page.recognizedText.string;
// 判断是否包含“公民身份号码”和“姓名”关键字
if ([text containsString:@"公民身份号码"] && [text containsString:@"姓名"]) {
return YES;
}
return NO;
}
- (NSString *)identityCardNumberFromPage:(VNPage *)page {
// 获取页面文本内容
NSString *text = page.recognizedText.string;
// 查找身份证号码
NSRange range = [text rangeOfString:@"公民身份号码"];
if (range.location != NSNotFound) {
NSString *number = [text substringFromIndex:range.location + range.length];
number = [number stringByReplacingOccurrencesOfString:@" " withString:@""];
return number;
}
return nil;
}
- (NSString *)identityCardNameFromPage:(VNPage *)page {
// 获取页面文本内容
NSString *text = page.recognizedText.string;
// 查找姓名
NSRange range = [text rangeOfString:@"姓名"];
if (range.location != NSNotFound) {
NSString *name = [text substringFromIndex:range.location + range.length];
name = [name stringByReplacingOccurrencesOfString:@" " withString:@""];
return name;
}
return nil;
}
@end
二、识别图片上的文字
#import <Vision/Vision.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:@"test_image.jpg"];
[self recognizeTextInImage:image];
}
- (void)recognizeTextInImage:(UIImage *)image {
// 创建VNImageRequestHandler对象
VNImageRequestHandler *requestHandler = [[VNImageRequestHandler alloc] initWithCGImage:image.CGImage options:@{}];
// 创建VNRecognizeTextRequest对象
VNRecognizeTextRequest *textRequest = [[VNRecognizeTextRequest alloc] initWithCompletionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error) {
// 处理识别结果
if (error == nil) {
NSArray *results = request.results;
NSMutableString *recognizedText = [NSMutableString string];
for (VNRecognizedTextObservation *observation in results) {
for (VNRecognizedText *text in observation.topCandidates(1)) {
[recognizedText appendString:text.string];
[recognizedText appendString:@"\n"];
}
}
NSLog(@"识别结果:%@", recognizedText);
// 在这里进行识别后的处理
} else {
NSLog(@"识别出错:%@", error);
}
}];
// 设置识别方式和语种
textRequest.recognitionLevel = VNRequestTextRecognitionLevelAccurate;
textRequest.usesLanguageCorrection = YES;
// 发送识别请求
NSError *requestError = nil;
[requestHandler performRequests:@[textRequest] error:&requestError];
if (requestError != nil) {
NSLog(@"发送识别请求出错:%@", requestError);
}
}
@end
相关文章:
IOS自带的OCR识别功能
一、识别身份证 interface IDCardScanViewController () <AVCaptureMetadataOutputObjectsDelegate> property (nonatomic, strong) AVCaptureSession *captureSession; end implementation IDCardScanViewController - (void)viewDidLoad { [super viewDidLoad…...

1300*C. Product of Three Numbers(质数数学)
Problem - 1294C - Codeforces 解析: 首先这个数肯定不是质数,然后找到第一个因子p,对于n/p再判断质数,然后找到另外两个因子即可。 注意三个因子不能相同。 #include<bits/stdc.h> using namespace std; #define int long…...

【网络】五中IO模型介绍 + 多路转接中select和poll服务器的简单编写
高级IO 前言正式开始前面的IO函数简单过一遍什么叫做低效的IO钓鱼的例子同步IO和异步IO五种IO模型阻塞IO非阻塞IO信号驱动多路转接异步IO 小结 代码演示非阻塞IO多路转接select介绍简易select服务器timeout 为 nullptrtimeout 为 {0, 0}timeout 为 {5, 0}调用accept select编写…...

Camtasia2024破解版电脑屏幕录制剪辑软件
屏幕录制剪辑 TechSmith Camtasia for Mac v2021是 TechSmith 公司所开发出一款专业屏幕录像和编辑, Camtasia Studio2024版是由TechSmith公司官方进行汉化推出的最新版本,除2023版以下版本均没有官方汉化。 同时TechSmith公司打击第三方贩卖Camtasia Studio汉化的…...

c语言进阶部分详解(《高质量C-C++编程》经典例题讲解及柔性数组)
上篇文章我介绍了介绍动态内存管理 的相关内容:c语言进阶部分详解(详细解析动态内存管理)-CSDN博客 各种源码大家可以去我的github主页进行查找:唔姆/比特学习过程2 (gitee.com) 今天便接“上回书所言”,来介绍《高质…...
Unreal PythonScriptPlugin
Unreal PythonScriptPlugin 文章目录 Unreal PythonScriptPluginPython vs UnLua官方文档PyStubDoString 示例代码,引擎里有很多插件已经用 py 写编辑器脚本了 unreal.get_editor_subsystem(unreal.LevelEditorSubsystem).load_level("/Game/maps/UVlayoutTes…...

什么是数据可视化,为什么数据可视化很重要?
数据可视化是数据的图形表示,可以帮助人们更轻松地理解和解释复杂的信息。它涉及创建数据的视觉表示,例如图表、图形、地图和其他视觉元素,以传达数据中的见解、模式和趋势。数据可视化是将原始数据转化为可操作知识的关键工具。 以下是数据…...
chatgpt相关问题解答
1. openAI的chatgpt的收费方式有哪几种? 根据OpenAI官方的信息,ChatGPT的收费方式包括两种: 1.订阅计划(Subscription Plan):OpenAI提供了ChatGPT Plus订阅计划,每月收费20美元。订阅计划的用…...

nssm将exe应用封装成windows服务
一、简介 NSSM(Non-Sucking Service Manager)是一个用于在Windows操作系统上管理和运行应用程序作为服务的工具。它提供了一种简单的方法来将任意可执行文件转换为Windows服务,并提供了一些额外的功能和配置选项。 优点: 简单易…...

golang实现极简todolist
ToDoList 最近跟着qimi老师做了一个ToDoList,我做的GitHub地址贴在这里,但由于前端出了点问题,所以都是用postman进行测试 原项目地址 部分功能展示 删除代办 查找代办 下面给出思路 思路 其实这是一个很简单的增删改查的实现ÿ…...

C# Onnx Dense Face 3D人脸重建,人脸Mesh
效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms;namespace Onnx_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent();}string fileFilter "*.…...

Java 8 新特性 Stream 的使用场景(不定期更新)
方便在写代码的过程中直接使用,好记性不如好文章,直接 CV 改了直接用。提高 办(摸)公(鱼)效(时)率(间), 不然就直接问 GPT 也不是说不行。 只符合…...

公开IP属地信息如何保护用户的隐私?
公开IP属地信息通常涉及与用户或组织的隐私有关,因此在公开此类信息时需要非常小心,以避免侵犯他人的隐私权。以下是触碰底线的几种情况以及如何保护网络安全和用户隐私: 个人隐私保护: 公开IP属地信息可能泄露用户的物理位置&…...

大桌子初步使用
大桌子安装成功后进入应用市场首推安装首页和网盘 一键安装的时候如果出现这样的错误,只要你能保证服务器是正常联网的就再试一次,十有八九就是网络不稳定 安装成功后,要到已安装里去启用一下 然后回到这个页面 http://服务器ip/dzzoffice/h…...
初步了解ORM框架之一Mybatis
ORM(对象关系映射)框架是现代软件开发中不可或缺的一部分。它们简化了将对象模型映射到关系数据库的过程,提供了更加便捷和高效的数据库操作方式,常见有:Hibernate、JPA(Java Persistence API)、…...

2023 electron最新最简版windows、mac打包、自动升级详解
这里我将讲解一下从0搭建一个electron最简版架子,以及如何实现打包自动化更新 之前我有写过两篇文章关于electron框架概述以及 常用api的使用,感兴趣的同学可以看看 Electron桌面应用开发 Electron桌面应用开发2 搭建electron 官方文档:ht…...

Ubuntu18.04安装pcl-1.12.1,make时报错:/usr/bin/ld: cannot find -lvtkIOMPIImage
解决方案: 在vtk安装包中,重新打开cmake-gui,然后勾选上VTK_Group_MPI和VTK_Group_Imaging。 cd VTK-8.2.0 cd build cmake-gui然后重新编译生成。 make -j8 # 或者j4,量力而行。 sudo make install 就可以解决了。 然后重新回到pcl安装…...
表单验证不通过的一个点form中未定义这个字段
这个坑就是犯了好几次了,一直记不住,尤其是加了字段后的时候,总是忘记,然后导致验证不通过。 以前我认为,只要表单绑定的内容中的属性有这个值就在ruler里面就可以验证他,,以至于我总是不在dat…...

最新、最全、最详细的 K8S 学习笔记总结
Kubernetes就是一个编排容器的工具,一个可以管理应用全生命周期的工具,从创建应用,应用的部署,应用提供服务,扩容缩容应用,应用更新,都非常的方便,而且可以做到故障自愈。 K8S的前景…...

Emacs之高亮显示超过80个字符部分(一百三十)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
STL 2迭代器
文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器? 1.迭代器…...