开发者学堂课程【视觉 AI 应用开发教程: 身份证识别系统销量(二)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/289/detail/3412
身份证识别系统销量(二)
(ICollectionUtils.isEmpty &g
model.addAttribute
model.addAttribute(
model.addAttribute(s: "backResultH backResults sults.size
return"index";
@PostMapping("/upload")
public String uploadFile(@RequestParam MultipartFileface, @RequestParam("back")MultipartFile back, RedirectAttributes attributes if(face.isEmpty()
back.isEmpty())
attributes.addFlashAttribute( attributeNam I select a file to upload.");
returnPredirect:/i
String errorMessagee null;
try (
Path dir = Paths.get(uploadDirectory)
if(IFiles.exists(dir))
Files.createDirectories(dir);
11 (lface.isEmpty()(
saveFile(face):
Map<String, String> res ocrservice.RecognizeIdCard( filePath: uploadDirectory + filename, side: "face"
filenam
faceResults.add(res)i
if (Iback.isEmpty())(
Stringfilename saveFile(back);
Map<String,String: ocrService.RecognizeIdCard( filePath: uploadDirectory + filename, side: "back");
backImages.add("/images/n filename
backResults.add(res);
)catch (TeaException 《
printStackTrace();
JSON.toJSONString(e.getData
printStackTrace
errorHessage getMessag
上图为上传文件的控制方法,有几个参数,一个是接受的 face,类型为 multifile。首先查看图片是否为空,如果为空,直接把它重定向到 index,相当于是重新下到首页,然后它会讨论这个 index 这个模板,相当于优惠进到首页。此外会增加一个 message,提醒用户必须要上传一个文件。
1.主要逻辑:
(tace.1sEmpty() back.1sEmpty())
attributes.addFlashAttribute( attributeName
return attributeValue: "Please select a file to upload.");
"redirect:/2;
String errorMessage = null;
try
Path dir = Paths.get(uploadDirectory)
if (IFiles.exists(dir))(
Files.createDirectories(dir)|I
if (lface.isEmpty()) (
String filename saveFile(face):
MapcString, String>res side: "face
faceImages.add("/images/"+ fileyocarermeruploadDirectory + filename,
filename
) faceResutts.add(res)
if (Iback.isEmpty())
String filename saveFile(back);
res
Map<String,String>
/images/"+caokereuploadDirectory + filename, side: "back") backImages.add(
1 backResults.add(res)
)catch
(TeaException e)
e.printStackTrace();
errorMessage -
)catch JSON.toJSONString(e.getData())i
(Exception e)(
e.printStackTrace():
errorMessage e.getMessage
if
(StringUtils.isNotBlank(errorMessage)
) attributes.addFlashAttribute( errorMessage);
return"redirect:/";
首先查看上传目录是否存在,如果存在,则递归创建目录。接下来,如果人像图片不为空,则下载到本地,保存图像逻辑。首先通过提供的公用方法,去把文件的后缀名解出来,
为其生成一个随机的文件名,并且加上后缀。这个的作用是为了防止上传的图片是重复的文件名,会把旧的文件名覆盖掉,然后把这个文件保存到本地,并且返回文件名。
拿到文件名的时候,相当于已经保存成功,这个时候去调用 OCR service 的身份证识别的方法,把这个文件的完整路径告知,并且告知这是人下面的照片,这个时候会拿到返回的一个识别结果,把这个已经上传的图片,加载到这个缓存池里面。然后把识别结果也加入到缓存池里面。这里为什么加了 images 呢?
因为保存目录里有 images,因为 spring boot 默认的访问地址是在 static 下。
上图中,是国徽面的处理方式,基本上是完全一致的,不过是参数以及保存的地方有差异,下面有异常处理,如果有 sdk 抛出的一些异常,有异常信息,需要先将其输出。然后把这个异常信息补捉,给他 message。这个 message 里面其实是同样的作用。提醒用户这一次处理出错了以及具体的原因是什么。然后再重定向到首页。此时回到了这个逻辑里面,然后会把 face 和 face 以及相关的一些上传图片的信息以及结果都会渲染到这个页面上。
以上,即为控制器的大致逻辑。
2.OCR service 的实现逻辑
(face.isEmpty()| back.1sEmpty())
attributes.addFlashAttribute(attributeName.attributeValue: "Please select a file to upload."); return"redirect:/";
StringerrorMessage = null;
try
Path dir = Paths.get(uploadDirectory);
if (IFiles.exists(dir)) (
Files.createDirectories(dir);
if (Iface.isEmpty())
String filenam saveFile(face);
Map<String.String
resocrService.Reco(ie1Card(
filePath: upload Directory+filename,
side:"face") faceImages.add("/images/" filename
faceResults.add(res)
4f(lback.isEmpty()) (
String filename saveFile(back);
Map<String,
String>res=ocrService.RecognizeIdCard( filePath:uploadDirectory+filename,side:"back" backimagessaddina/n filename
backResults.add(res)
catch (TeaException e) [
e.printstackiraceo:
errorMessage = JSON.toJSONString(e.getData());
catch (Exception e)
e.printStaockTraceo
errorMessage = e.getMessage
1f(StringUtils.isNotBlank(errorMessage))
attributes.addFlashAttribute( attributeName errorMessage)
return"redirect:/"
可以看到 OCR service 里面有几个变量,首先一个呢是 OCR client,就是调用 OCR OCR 能力的时候,需要调用参数,然后是 access kid 和 access secret,相当于是在开通视觉智能开放平台的这些的一些视觉能力的时候,会用到阿里云账户的一个这个 ak 和就是 k secret,需要把它配置到配置文件里面。
eauthor joffre
edate 2020/4/6
@Service
public class OcrService
privateClient ocrClient;
private RuntimeOptions runtime
eValue("$(viapi.accessKeyId)"
StringaccesskeyId:
evatue(styiapi.accesskeySecret
privateString accessKeySecret;
@PostConstruct
PAvat voidinit()throwsException
Config config Config();
config.tvpe faccess
config.regionId fcn-shanghai":
config.accessKeyId accessKeyId:
config.accessKeySecret accesskeySecret;
config.endpoint "ocr.cn-shanghai.aljyuncs.com
ocrClient- newClient(config)
runtime new RuntimeOptions();
)
public Map<String, String> RecognizeIdCard(StringfilePath, String side) throws Exception 《
RecognizeIdentityCardAdvanceRequest
request
RecognizeIdentityCardAdvanceRequest();
request.imageURLobject=Files.newInputStreom(Paths.get(filePath));
request.side-side;
RecognizeIdentityCardResponse
response
ocrClient.recognizeIdentity
CardAdvance(request, runtime);
("face".equals(side))(
turnJSON.parseObject(JSON.toJSONString(response.data.frontResult),new
TypeReference<Map<String,
String>>()(O);
turnJSON.parseObject(JSON.toJSONString(response.data.backResult), newTypeReference<Map<String, String>>() O);
它有一个初始化的方法,是用 spring boot 提供的这个标注来实现初始化,初始化的时候,需要初始化若干个信息。然后通过这个信息来初始化一个 OCR client,初始化一个 longtime 状态,其实是空的一个对象,就是需要把另外一个空对象调用出来,需要在下面进行调用。
aService
public classOcrService
privat Client ocrClient:
RuntimeOptions runtime
@Value("$(viapi.accessKeyId)"
StringaccessKeyId;
@Value("$(yiani.accessKeySecret)"
private StringaccessKeySecret;
@PostConstruct
privatevoid init()throwsException
Configconfig ConfigO;
config.type
config.regionId "cn-shanghai"
confe-accescKevId accesekevtd
config.accessKeySecret accessKeySecret;
config.endpoint "ocr.cn-shanghai.alixunsa.com"
ocrClient. newClient(config);
runtime new RuntimeOptions()
public Map<String, String>RecognizeIdCard(String filePath, String side) throws Exception
RecognizeIdentityCardAdvanceRequest
requestnew
RecognizeIdentityCardAdvanceRequest();
request.imageURLObject=Files.newInputStreom(Paths.get(filePath));
request.side
RecognizeIdentityCardResponse
response=ocrClient.recognizeIdentityCardAdvance(request, runtime
face".equals(side))(
curn50N.parseObject(3soN.toJsONString(response.data.frontResult),newTypeReference<Map<String,String>>()(O);]
Ls
curnJSON.parseObject(JSON.toJSONString(response.data,backResult), newTypeReference<Map<String,String>>() O);
首先是调用 controller 层调用的 ID card 的一个方法,它有两个参数,pass 是本地的文件路径,是标识了正反面,身份证正反面的信息。另一个 request,点进去查看代码。
可以看到 request 下面还有很多的 OCR 的能力。其实只用到了身份证识别这一个功能。
<input typemHFile" names"backHide'i-back? accept=".jpg,·png, .jpeg" onchange="s('#location1').ya(支(
kdiv
button type="submit" class="btn btn-primary">开始识别</button>
</div)
div
style="margin-top:30px;"
cdiv
mg stylem"width:100%; ac ge face mage ne nuttj" class "img-fluid" Lt-"
</div>
ediv class="col-sm
/div>mg style="width:100%; backimage nutt mg-fluid"
Ldiv
div styles?
div col-md-12 mx-auto"2
<p th:ife"s(faceResultne nutt)"y<span>姓名:</span><span th:texta"s(faceResult.nam t></span></p >
<p span?性别:(/span><span >x/span></p
onalityjt></span>k/p>
th:ife"s(faceResult span>出生日期:</span><spanth:texto"
nul1)"><span>身份证号码:
</span>span (faceResult.IDNumber]"></span><
/div:
th:ifel backResult nutl)"><span>签发机关:</span><span th:texta's(backResult.issuet></span></p
th:ifa"stbackResult nuttj"><span>有效日期:
span><spanth:text="(backResult.startDate
pan>-<spanth:text="s(backR
div
c/div:
body
前端代码用到了 face result name,face result gender 和face result nationality。