Python实战项目:Flask人脸识别图书系统(下)

flask人脸识别图书系统(下)


四、flask蓝图(blue_print)改写后端的实现

用蓝图技术来修改这个程序,首先分析一下,目前后端完成了两个功能,上传人脸头像和验证人脸头像,这两个功能可以设计成两个蓝图开发中的两个模块,上传人脸头像这里叫myupload,可以在pycharm建立一个flask蓝图项目mylantu,再建一个python包文件app,将所有的模块应用都集中一个包文件中管理,这样比较有序。接着建立第一个后端功能的python包文件myupload上传头像,在myupload包文件下建立一个views视图文件,将原来实现的upload代码复制到这里来,再加上Blueprint语句初始化这个蓝图应用upload,做upload这个蓝图应用的路由规则,对应的方法中实现原来upload中写入的代码。

代码如下。

from flask import Blueprint,render_template,request
from app import mongo
import base64
import pickle
import face_recognition
from bson.binary import Binary
upload=Blueprint("upload",__name__,template_folder="templates")
@upload.route("/",methods=["GET","POST"])
def upload_face():
    if request.method=="POST":
        imgdata=request.form.get("myimg")
        imgdata=base64.b64decode(imgdata)
        with open("a.png","wb") as f:
            f.write(imgdata)
        faceimg=face_recognition.load_image_file("a.png")
        facedata=face_recognition.face_encodings(faceimg)[0]
        print(facedata)
        binary_data = Binary(pickle.dumps(facedata,protocol=-1),subtype=128)
        mongo.db.myface.insert_one({'face':binary_data})
        return {"result":"OK"}
    return render_template("video.html")

myupload模块的包结构如下。

完成了myupload的功能逻辑模块,继续进行验证人脸头像进行登陆的功能模块开发。在原来建立的包文件夹app下面继续建立mylogin包文件夹,也是在mylogin包文件夹下建立views文件,将原来的checkface()方法中的代码复制到这里,再加上Blueprint语句初始化这个蓝图应用login,做login这个蓝图应用的路由规则,对应的方法中实现原来checkface中写入的代码。

代码如下。

from flask import Blueprint,request,render_template
import base64
import face_recognition
from app import mongo
import pickle
login=Blueprint("login",__name__,template_folder="templates")
@login.route("/",methods=["GET","POST"])
def login_home():
    if request.method == "POST":
        imgdata = request.form.get("myimg")
        imgdata = base64.b64decode(imgdata)
        with open("b.png", "wb") as f:
            f.write(imgdata)
        faceimg = face_recognition.load_image_file("b.png")
        facedata = face_recognition.face_encodings(faceimg)[0]
        faces=mongo.db.myface.find()
        for fa in faces:
            '''
                取出的数据是myface数据库中的每一条记录face的"face"键对应的值
            '''
            facedata_orign=pickle.loads(fa["face"])
            res=face_recognition.compare_faces([facedata],facedata_orign)
            print(res)
            if res[0]:
                return {"result":"this is true face"}
            else:
                return {"result":"not you face"}
    return render_template("check_face.html")

两个后端基本功能完成以后,在建立app包文件的init.py文件中写入flask初始化的相关语句。

from flask import Flask
from flask_pymongo import PyMongo
apps=Flask(__name__,template_folder="templates",static_folder="static")
apps.config["MONGO_DBNAME"]="myface"
apps.config["MONGO_URI"]="mongodb://localhost:27017/myface"
mongo= PyMongo(apps)

完成上面的语句后,还要在当前app应用中注册上面完成的两个后端功能应用。注意,这段注册后端功能的应用代码和导包都要在mongo=PyMongo(apps)后面,不然会报错,原因是这两个模块中的views中都要调用这个mongo变量,如果mongo变量没有产生,就不能被导包和调用。

from app.mylogin.views import login
from app.myupload.views import upload
apps.register_blueprint(login,url_prefix="/login")
apps.register_blueprint(upload,url_prefix="/upload")

最后完成manage.py调用app初始化的应用run()方法即可.

from app import apps
if __name__=="__main__":
    apps.run()

至此,后端结合前端的flask人脸登录图书系统flask蓝图技术实现完成。

五、图书管理系统数据分析

1、根据书名和分类,找出适合表达书籍的主题的词汇

在数据分析中,主题词的提取也是很重要的数据分析的内容,一个主题词往往反应出书名属于哪个领域。

对于一些专业的词汇,用jieba分词进行分词化时,也需要加载用户自定义的分词文件,具体代码如下。

jieba.load_userdict("library_new_words.txt")

对于书籍主题词的提取,可以读取图书目录,对图书来讲,主要是分类号,不同的分类号表示了不同的书籍类型,可以对分类号进行前去空格处理,也对分类号对应的书名做前后去空格处理,接着可以提取图书分类号中的主码,主码可以表征当前图书分类的所属类别,具体图书分类的主码可以参见《中国图书馆图书分类法》简表,这张简表也是一般大型图书馆对图书分类的参考,也是对图书管理行业的专业的知识体现。

对数据进行了格式上面的处理及重要信息的提取后,就可以按照数据分析的思路:去重、去空、去异常等操作。这里的数据可以去掉空值行,去掉重复的数据,对于重复的数据只保留第一个,对于文学作品来说,主题词一般和题目息息相关,这里可以不考虑文学作品的主题词提取。根据《中国图书馆图书分类法》简表可以知道,文学对应的分类主码是I,相当于在图书分类号中把首字母为“I”的图书信息过滤掉。最后再将图书目录信息表的数据重置相关的索引号。代码如下。

book = pd.DataFrame(pd.read_excel(dataPath+'\\图书目录.xlsx'))
book=book.loc[:,['书名','图书分类号']] #

book['图书分类号']=book['图书分类号'].str.strip()  #去掉图书分类号前后的空格
book['书名']=book['书名'].str.strip()  #去掉书名前后的空格
book['图书分类号']=book['图书分类号'].str.extract('([A-Z]+)', expand=False) #提取图书分类主码
book=book[book['书名'].notnull() & book['图书分类号'].notnull()] #去掉空值行
book=book.drop_duplicates(['图书分类号','书名']) #去掉重复的,保留第1个
book=book.loc[~ book['图书分类号'].str.startswith('I')] #去掉文学作品,文学作品不参加主题词筛选
book=book.reset_index(drop=True) #重置索引

因为最终要达到的目的一个主题词反映的书名属于哪一个领域。可以用图书分类号的主码和书名的分化结合起来,jieba分词提取主题词函数jieba.analyse.extract_tags()后变成了横向的维度,表明了这种分类的书有哪些主题词,也就是这些主题词能表示哪一种分类的书。对于横向维度的数据有很多的值是None,因为是以最长的主题词来进行横向式的扩展的。通过stack()堆叠技术可以将横向的数据维度进行纵向化,并且将数据维度中是None值的清除掉,紧接着把索引值重置,语义化一下将此列名列更改为“词条”。

将上面的逻辑语句分步执地如下:

1、把数据集中先把书名这一列删除。

book.drop('书名', axis=1)

2、从书名中提取关键词。

jieba.analyse.extract_tags(x) for x in book['书名']

3、将书名中的“关键词”列表转换成DataFrame和图书分类号形成数据表。

book.drop('书名', axis=1).join(pd.DataFrame(jieba.analyse.extract_tags(x) for x in book['书名'])

4、stack()方法将横向的DataFrame数据表堆叠起来。

book.drop('书名', axis=1).join(pd.DataFrame(jieba.analyse.extract_tags(x) for x in book['书名']).stack()

5、将堆叠后的竖向DataFrame数据表重置索引。

book.drop('书名', axis=1).join(pd.DataFrame(jieba.analyse.extract_tags(x) for x in book['书名']).stack().reset_index(level=1, drop=True)

6、最后将此列更名为“词条”。

book.drop('书名', axis=1).join(pd.DataFrame(jieba.analyse.extract_tags(x) for x in book['书名']).stack().reset_index(level=1, drop=True).rename('词条'))

表达书籍的主题词汇这个问题实际上可以理解成tf-idf统计词频逆词频的问题,这里就需要进行各种量值的统计。现对各种统计量的变量值含义进行统计。

(1)dw_count:为词条在图书分类中出现的次数。

(2)dw_total为图书分类中所有的词条数目。相同图书分类具有相同的值。相同词条重复个数。

(3)d_total为图书分类总数。只有一个值,不计重复个数。

(4)d_count为包含词条的图书分类数。相同词条具有相同的值。

(5)w_total:词条在图书分类中出现的总次数,重复计数。

(6)cumsum: 相同词条的记录,按词条在分类中出现次数降序排列时,词条出现次数dw_count的累加和。

(7)rank:相同词条的记录,按词条在分类中出现次数降序排列时的顺序号,出现频次最多的分类的rank值为1。

(8)tf:词频,词条在图书分类中出现的次数占该分类中所有词条的比例。

(9)cumtf: 词频的累加值,同一词条最后行的累加值总是为1。

(10)tfidf:tf和idf的乘积值。

程序逻辑中先假定词条在图书分类中初始化的初值为1。代码如下。

words['dw_count']=1

将前面分步讨论的词条提取步骤的结果按第一索引值"图书分类号"和第二索引值“词条”进行分组聚合,然后对分组出的结果进行求和。然后进行重置索引号,这样就实现了对应图书分类号中的词条数量统计。代码如下。

words=words.groupby(['图书分类号','词条']).sum()
words.reset_index(inplace=True)

图书每个分类号下面的所有词条数,可以按“图书分类号”统计,求出sum总和,更新到dw_total字段中。

words['dw_total']=words.groupby('图书分类号')['dw_count'].transform('sum')

图书分类总数就是对书籍列表的describe()方法统计后的每一个不同的“图书分类号”。可以用unique()方法展示图书分类号所有可能的取值。

d_total=book.describe()['图书分类号']['unique']

包含该词条的图书分类数,可以按“词条”进行分组,求出其count值,然后更新到d_count中。

words['d_count']=words.groupby('词条')['dw_count'].transform('count')

词条在图书分类中出现的总次数,可以按“词条”分组,求出其sum值,然后更新到w_total中。

words['w_total']=words.groupby('词条')['dw_count'].transform('sum')

紧接着按第一索引值"词条"和第二索引值"dwcount",也就是对词条分组的条件下,再按词条图书分类中的次数来分组。cumsum()函数的方法是相同词条的记录,按词条在分类中出现次数降序排列时,词条出现次数dwcount的累加和。

words=words.sort_values(['词条','dw_count'],ascending=[True, False])
words['cumsum']=words.groupby('词条')['dw_count'].cumsum()

用rank()函数的作用是相同词条的记录,按词条在分类中出现次数降序排列时的顺序号,出现频次最多。

words['rank']=words.groupby('词条')['cumsum'].rank()

根据tf(词频)的计算公式,如下。

由上面的公式,前面某个词在文章中出现的次数使用dwcount的变量来保存的,文章的总词数是由wtotal的变量来保存的。这样tf(词频)的计算代码如下。

words['tf']=words['dw_count']/words['w_total']

根据idf(逆词频)的计算公式,如下。

由上面的公式,前面语料库的文档总数使用dtotal变量来保存,包含该词的文档数由dcount变量来保存。这样idf(逆词频)的计算代码如下。

words["idf"]=(1+d_total/words['d_count']).transform(math.log)

tf和idf的计算就是把tf和idf的值进行相乘即可。代码如下。

words['tfidf'] = words['tf']*(1+d_total/words['d_count']).transform(math.log)

这样可以输出词条文件。

words.to_excel(dataPath+'\\words.xlsx',index=None)

接下来,可以按照一定的规则去筛选出主题词,比如规定包含该词的文档数大于等于3定为主题词,小于3等于2的话如果文章的总词数达到15以上,或者小于3等于1的话如果文章总词数达到6以上,都可以定为主题词。

topicWords=words.loc[((words['d_count']>=3) & (words['rank']==3) & (words['cumtf']>0.85) & (words['cumsum']>20)) \
              | ((words['d_count']==2) & (words['w_total']>15)) \
              | ((words['d_count']==1) & (words['w_total']>6))]

这样导出文档,就是图书馆收藏书目的主题词列表。

topicWords.to_excel(dataPath+'\\TopicWords_detail.xls',index=None)
topicWords = topicWords.loc[:,['词条']]
topicWords.to_excel(dataPath+'\\TopicWords.xls',index=None)

代码的github地址:https://github.com/wawacode/flask_over_face_recognition

项目对应的视频地址:

flask人脸登录图书系统4-facerecognition模块实现化妆功能
https://www.bilibili.com/video/BV19i4y1K7bz/
flask人脸登录图书系统5-图书爬虫技术分享
https://www.bilibili.com/video/BV1fr4y1P7fq/
flask人脸登录图书系统6-图书管理数据分析
https://www.bilibili.com/video/BV1Ez4y127RX/

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值