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工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
