最近接到一个调用接口识别身份证的web项目,简单看了下阿里云身份证识别的接口,接口实例使用的是python2,我仔细研究了下,把python2改为python3,并且结合最新的Django实现用户上传身份证正反面,在web中返回识别结果

1、源码下载

本程序为www.ivdone.top原创内容,版权归www.ivdone.top所有,请不要用作商业用途,仅供个人学习使用,如有问题,请在评论区,留下你咨询的问题和联系方式,以便后续联系和问题解决,谢谢你的支持

下载地址:点我下载

2、使用说明

将压缩包解压,进入解压目录,修改api.py文件中的appcode变量,写入你申请阿里云给你的appcode

cd ./recognition/recognition/
# 然后编辑文件
vi api.py
# 找到 有appcode那一行 ,写入阿里云给你自己的appcode
appcode = 'xxxx'

运行代码(本程序已经打包好的,解压就能运行,但是前提你能运行Django程序,本程序使用的Django版本是3.0.5),一定要确保你的机器能运行Django程序,如果你的Linux没有安装Django环境,请移步我的博客教程:Linux下如何使用Django创建一个helloworld的web程序

# 端口你可以随意定义,但是要注意在linux防火墙中开放该端口,不然会被切掉
python manage.py  runserver 0.0.0.0:8001

3、测试

在你的浏览器中打开我们刚刚运行的ip和端口:http://x.x.x.x/8001/index/

你会看到下面的界面:

上传身份证的正反面,识别结果如下:

4、核心代码

view.py文件

# coding:utf-8
import os
from django.http import HttpResponse, HttpResponseRedirect
from django.conf import settings
from django.contrib import messages
from django.shortcuts import render
from PIL import Image
from .api import recognition

# 信息显示类, 所有的信息在这里解码,并保存,然后把这个变量渲染到html中显示
class Info(object):

    def __init__(self):
        pass

    def write(self, is_back, result):
        if is_back:
            self.start_date = result['start_date']
            self.end_date = result['end_date']
            self.issue = result['issue']
        else:
            self.name = result['name']
            self.nationality = result['nationality']
            self.num = result['num']
            self.sex = result['sex']
            self.birth = result['birth']
            self.address = result['address']
            self.face_rect_angle = result['face_rect']['angle']
            self.face_rect_center = (result['face_rect']['center']['x'], result['face_rect']['center']['x']).__str__()
            self.face_rect_size = (result['face_rect']['size']['height'], result['face_rect']['size']['width']).__str__()
            self.card_region = str([(result['card_region'][i]['x'], result['card_region'][i]['y']).__str__()  for i in range(4)])
            self.face_rect_vertices =self.card_region = str([(result['face_rect_vertices'][i]['x'], result['face_rect_vertices'][i]['y']).__str__()  for i in range(4)])


def index(request):
    return render(request, 'index.html', {})

def upload(request):
    if request.method == 'POST' and request.POST:
        file = request.FILES.get('image_file', None)
        file_b = request.FILES.get('image_file_b', None)
        img_dir = os.path.join(settings.BASE_DIR, 'media', 'tju')
        if not os.path.isdir(img_dir):
            os.makedirs(img_dir)
        info = Info()
        # 用于控制识别信息显示
        stat_c = None
        stat_b = None   
        if file is None and file_b is None:
            messages.error(request, '提交表单为空,请重新提交')
            HttpResponseRedirect(redirect_to='/index')
        # 正面身份证 文件
        if file :
            image = Image.open(file)
            filename = os.path.join(img_dir, 'idcard' + os.path.splitext(file.name)[-1])
            if os.path.isfile(filename):
                os.remove(filename)
            with open(filename, 'wb') as f:
                for chunk in file.chunks():
                    f.write(chunk)
            result = recognition(filename=filename, is_back=False)
            info.write(is_back=False, result=result)
            # 正面身份证显示 状态改为真
            stat_c = True
        # 反面身份证 文件
        if file_b:
            filename_b = os.path.join(img_dir, 'idcard_b' + os.path.splitext(file_b.name)[-1])
            if os.path.isfile(filename_b):
                os.remove(filename_b)
            with open(filename_b, 'wb') as f:
                for chunk in file_b.chunks():
                    f.write(chunk)
            # 调用识别的接口
            result = recognition(filename=filename_b, is_back=True)
            info.write(is_back=True, result=result)
            # 反面身份证显示 状态改为真
            stat_b = True
    return render(request, 'index.html', {
        "result_c" : stat_c,
         "result_b" : stat_b,
        "info" : info
    })

api.py文件

import sys,os
import base64
import time
import json

import traceback
import urllib
import base64


def get_img_base64(img_file):
    with open(img_file, 'rb') as infile:
        s = infile.read()
    return str(base64.b64encode(s), 'utf-8') 


def predict(url, appcode, img_base64, kv_config, old_format):
        if not old_format:
            param = {}
            param['image'] = img_base64

            if kv_config is not None:
                param['configure'] = json.dumps(kv_config)
            #body = json.dumps(param, cls=Encode, indent=4)
            body = json.dumps(param).encode(encoding='UTF8')
        else:
            param = {}
            pic = {}
            pic['dataType'] = 50
            pic['dataValue'] = img_base64
            param['image'] = pic

            if kv_config is not None:
                conf = {}
                conf['dataType'] = 50
                conf['dataValue'] = json.dumps(kv_config) 
                param['configure'] = conf


            inputs = { "inputs" : [param]}
            body = json.dumps(inputs)

        headers = {'Authorization' : 'APPCODE %s' % appcode}
        request = urllib.request.Request(url=url, headers=headers, data=body)
        try:
            response = urllib.request.urlopen(url=request, timeout=10)
            return response.code, response.headers, response.read()
        except urllib.request.HTTPError as e:
            return e.code, e.headers, e.read()


def recognition(filename, is_back):
    """
    filename : 你的身份证文件
    is_back : True->反面  False->正面
    """
    # 这里更改为自己在阿里云的申请的appcode
    appcode = '你的appcode'
    url = 'http://dm-51.data.aliyun.com/rest/160601/ocr/ocr_idcard.json'
    #如果输入带有inputs, 设置为True,否则设为False
    is_old_format = False
    # 代表识别正面
    if not is_back:
        config = {'side':'face'}
    else:
        config = {'side':'back'}
    #如果没有configure字段,config设为None
    #config = None

    img_base64data = get_img_base64(filename)
    stat, header, content = predict( url, appcode, img_base64data, config, is_old_format)

    if stat != 200:
        print("Http status code:{}".format(stat))
        print('Error msg in header: {}'.format(header['x-ca-error-message']))
        print('Error msg in body: {}'.format(content))
        raise RuntimeError("发送请求失败")

    else:
        if is_old_format:
            result_str = json.loads(content)['outputs'][0]['outputValue']['dataValue']
        else:
            result_str = json.loads(content)
    return result_str
0
Posted in 研究, 科技, 算法设计与分析

Leave a Comment:

电子邮件地址不会被公开。