《百度AI人脸识别与检测》专栏为项目专栏,从零到一,从无到有开发一个学生人脸识别签到系统;主要用到的技术有百度开放平台中的人脸检测、人脸识别、Python图形界面开发PyQt5、线程的管理、以及通过python调用百度接口实现人脸检测、百度开放平台中人脸检测技术文档的理解等,由浅入深、由局部到整体的一个项目学习过程,如果你想对人脸识别感兴趣,对python的图形界面设计感兴趣,可以订阅本专栏,因为对你可能有帮助哦!

前文参考:

百度AI人脸识别与检测一:学生人脸识别签到系统简介及百度AI开放平台账号注册和人脸实例应用创建
百度AI人脸识别与检测二:学生人脸识别打卡签到系统主界面功能需求和设计以及通过Python实现界面运行
百度AI人脸识别与检测三:学生人脸识别打卡签到系统通过OpenCV实现电脑摄像头数据在Label控件上的实时显示
百度AI人脸识别与检测四:学生人脸识别打卡签到系统之百度AI人脸检测及相应程序异常处理

最近博客发布于6个月之前,这半年时间,学长也接收到很多小伙伴对《百度AI人脸识别与检测》专栏的催更,但也只做了简单的回应。在这脱更的半年时间中,学长完成了自己的毕业设计、毕业论文,同时拿到了自己工作单位的offer,成为了一名简简单单的程序员;拿到了自己的驾驶证,成为了新手司机中的一份子;拿到了属于自己大学四年的毕业证和学位证,成为了广大校友中的一名新人。从学校到职场,从学生到校友,是林君学长这脱更6个月的变化。自己的大学四年,感谢每一位教育过自己的老师,同时也感谢物联一班的每一位同学、朋友。但总之,学长再次开始了属于自己的创作之旅。祝愿我们每一位小伙伴都能在学习中进步和成长,不只是简单的应付作业哦!


百度AI人脸识别与检测五:学生人脸识别打卡签到系统之百度AI人脸识别

  • 一、百度AI人脸识别API接口
    • 1、创建用户脸部信息组
    • 2、创建用户脸部信息
    • 3、人脸搜索API请求文档说明
    • 4、人脸搜索API返回参数说明
  • 二、完成系统人脸识别功能模块
    • 1、定义人脸识别数据接收和发送信号
    • 2、编写人脸搜索访问方法
    • 3、调用函数,进行人脸识别
    • 4、主线程人脸识别数据接收显示
    • 5、人脸识别运行结果测试

上次博客我们介绍了百度AI的人脸检测,并通过界面实现了基本的人脸检测,本次博客林君学长将带大家了解、并实现基于百度AI的人脸识别。人脸识别和人脸检测有本质上的区别,人脸检测只是将图像或者视频中的人脸进行一个简单的检测,包括面部表情、颜值分数、是否佩戴眼镜等等;而人脸识别是指将图像或者视频的人脸进行检测,然后进行识别,不仅检测到这个人,还要识别出这个人是谁,叫什么名字,对应的了解到这个人的一系列信息。因此,人脸识别是在人脸检测到的基础上,通过对应的特征对比,来判断数据库中的人脸特征是否有与检测的到的人脸特征一致,如果一致,找到此人;如果不一致,查无此人!


一、百度AI人脸识别API接口

百度AI人脸识别API接口是本地代码与百度云服务器进行连接的访问规则,本次博客需要对百度人脸识别进行访问,因此需要查看对应的API接口规则,根据规则编写访问接口的Python代码。而对于对应接口地址,在上次博客中已经介绍如何查看,本次博客需要用到的人脸识别主要用的是其中的人脸搜索接口。

1、创建用户脸部信息组

最新的百度AI开放平台好像要进行实名认证,然后才能领取免费的人脸识别模块,打开人脸识别模块的功能,所以小伙伴记得去实名认证,然后免费领取一下

既然是人脸搜索,对应的应该有一个用户的脸部信息库,但由于初次运用,需要我们手动录取信息,在之后的项目中,可以通过软件自动添加人脸信息或者更新人脸信息,便不再需要在百度AI平台上进行手动添加。由于初次进行识别,我们需要穿件用户组合人脸信息,具体步骤如下所示:
(1)、打开控制台,找到人脸识别版块后选择管理应用,上次博客我们创建了应用实例。

(2)、在学生人脸打开签到系统实例中,点击查看人脸库。

(3)、点击新建组,ID我们取为class1,寓意为第一个班级,然后点击确定。

通过以上步骤,我们的班级就创建好了!接下来,我们为班级中添加学生吧!

2、创建用户脸部信息

班级创建完成,但是目前班级中没有成员,需要我们手动添加学生的脸部信息
(1)点击刚刚创建好的class1的用户组,进入到用户组里面添加用户。

(2)、点击新建用户。填入用户的名字(拼音或者英文名字,暂不支持中文),然后选择一张该用户(学生)的照片上传到用户组中,如下所示:


(3)、多次循环操作,便为班级添加好了学生,学长只添加了自己的,因此列表只有一项。


这样,我们班级一的人脸数据库便创建成功,下面便可以通过API接口进行对应代码的编写了!

3、人脸搜索API请求文档说明

在编写相关人脸识别的代码之前,我们首先需要了解如何访问百度AI开放平台中人脸识别模块中的人脸搜索功能。官方给了对于的API文档说明,链接如下:
人脸搜索API官方请求文档说明
在API文档中,我们首先得找请求说明,该部分有请求代码格式,以及请求参数说明,具体如下步骤。
(1)、请求格式标准代码Python

# encoding:utf-8
import requests
'''
人脸搜索
'''
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"
params = "{\"image\":\"027d8308a2ec665acb1bdf63e513bcb9\",\"image_type\":\"FACE_TOKEN\",\"group_id_list\":\"group_repeat,group_233\",\"quality_control\":\"LOW\",\"liveness_control\":\"NORMAL\"}"
access_token = '[调用鉴权接口获取的token]'
request_url = request_url + "?access_token=" + access_token
headers = {'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:print (response.json())

(2)请求参数说明

  • image:需要进行人脸识别的图像。
  • image_type:图像的格式,这里的格式我们上次博客设置的base64,因此本次的格式依旧如此。
  • FACE_TOKEN:调用鉴权接口获取的token,通过AK和SK获取的token
  • group_id_list:需要在那个用户组列表中进行人脸识别对比

重要的是以上四个,后面的参数请通过API官方文档自行了解,下面给出后面参数的解释截图:

4、人脸搜索API返回参数说明

有访问参数,在访问成功后,进行人脸识别,我们需要的便是识别之后的信息,因此读懂API的返回参数是项目中非常重要的技能。百度AI人脸识别项目中,需要根据返回参数进行对应的信息接收、处理和显示。人脸搜索API文档中,请参考返回说明章节。
(1)、返回参数介绍

  • face_token:人脸标志 ,String类型

  • user_list:返回用户信息 ,字典类型

    • group_id:所属的用户组(在那个班级) ,String类型
    • user_id:用户名称,String类型
    • user_info:注册用户时携带的user_info,String类型
    • score:用户的匹配得分,当分数大于80的时候,默认人脸识别成功,float类型

(2)返回参数示例


在经过以上第一大步骤的进行之后,便可以开始我们接下来的代码编写了,在我们的《百度AI人脸识别与检测》项目中,通过以上了解的到的相关知识,完成人脸识别模块的功能。请继续往下面看!


二、完成系统人脸识别功能模块

1、定义人脸识别数据接收和发送信号

在人脸识别完成之后,我们首先需要处理的便是人脸识别信息数据,将这些数据送到PyQT对于功能的控件上显示。但前面的代码我们了解到,在进行人脸检测是在子线程中,而数据的显示是在主线程中的窗口上面,因此,首先我们需要定义一个变量,用该变量存储人脸识别信息,并将子线程中得到的变量传递到主线程。而pyqt5中通过pyqtSignal信号接口实现了子线程与主线程之间的变量传递。
(1)、在detect.py文件中,定义transmit_data1信号,用于子线程与主线程中的人脸识别数据交互,信号类型为字符串型。

transmit_data1 = pyqtSignal(str)  # 定义信号,用于子线程与主线程中的人脸识别数据交互

(2)、代码添加位置如下:

2、编写人脸搜索访问方法

(1)通过人脸搜索API文档规则,在detect.py文件尾部编写访问方法,代码如下所示:

# 人脸识别搜索检测,只识别一个人def face_search(self):request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"params = {"image": self.imageData,"image_type": "BASE64","group_id_list": "class1",}access_token = self.access_tokenrequest_url = request_url + "?access_token=" + access_tokenheaders = {'content-type': 'application/json'}response = requests.post(request_url, data=params, headers=headers)if response:data = response.json()if data['error_msg'] == 'SUCCESS':if data['result']['user_list'][0]['score'] > 90: #大于90分,意味人脸识别成功del [data['result']['user_list'][0]['score']]datetime = QDateTime.currentDateTime()#获取人脸打开时间datetime = datetime.toString()#将获取到的时间转为字符串data['result']['user_list'][0]['datetime'] = datetime#将获取到的时间添加到返回的数据中list1 = [data['result']['user_list'][0]['user_id'],data['result']['user_list'][0]['group_id']]#去除名字和班级self.transmit_data1.emit("学生签到成功\n学生信息如下:\n" + "姓名:" + list1[0] + "\n" + "班级:" + list1[1])#将信号发送给主线程
  • image:通过人脸检测传递过来的图像
  • image_type:图像格式为base64
  • group_id_list:上面我们创建的class1用户组

3、调用函数,进行人脸识别

(1)人脸识别的基础是在人脸检测的基础上进行的,在人脸检测到之后,方可进行人脸识别,因此,在detect.py文件中的人脸检测函数中进行人脸识别方法的调用。

self.face_search()

(2)、代码添加位置如下:

(3)detect.py文件中的代码便修改完成,修改后的代码如下所示:

import requests
from PyQt5.QtCore import QThread, pyqtSignal, QDateTimeclass detect_thread(QThread):transmit_data = pyqtSignal(dict)#定义信号,用于子线程与主线程中的人脸检测数据交互transmit_data1 = pyqtSignal(str)  # 定义信号,用于子线程与主线程中的人脸识别数据交互def __init__(self,access_token):super(detect_thread,self).__init__()self.ok=True#循环控制变量self.condition = False#人脸检测控制变量,是否进行人脸检测self.access_token=access_token#主线程获取的access_token信息传递给子线程并设置为全局变量#run函数执行结束代表线程结束def run(self):while self.ok==True:if self.condition==True:self.detect_face(self.imageData)self.condition=False'''接收主线程传递过来的图像'''def get_imgdata(self,data):#当窗口调用这个槽函数,就把传递的数据存放在线程的变量中self.imageData=data#将接收到图像数据赋值给全局变量self.condition=True#主线程有图像传递过来,改变condition的状态,run函数中运行人脸检测函数'''人脸检测'''def detect_face(self,base64_image):request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"# 请求参数是一个字典,在字典中存储了,要识别的内容params = {"image": base64_image,  # 图片信息字符串"image_type": "BASE64",  # 图片信息的格式"face_field": "gender,age,beauty,mask,emotion,expression,glasses,face_shape",  # 请求识别人脸的熟悉,各个熟悉在字符中用,用逗号隔开"max_face_num": 10#能够检测的最多人脸数}# 访问令牌access_token = self.access_tokenrequest_url = request_url + "?access_token=" + access_token# 设置请求的格式体headers = {'content-type': 'application/json'}# 发送post网络请求,请求百度AI进行人脸检测response = requests.post(request_url, data=params, headers=headers)if response:data = response.json()self.face_search()self.transmit_data.emit(dict(data))#如果返回结果正确,则将返回信息传递给主线程# 人脸识别搜索检测,只识别一个人def face_search(self):request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"params = {"image": self.imageData,"image_type": "BASE64","group_id_list": "class1",}access_token = self.access_tokenrequest_url = request_url + "?access_token=" + access_tokenheaders = {'content-type': 'application/json'}response = requests.post(request_url, data=params, headers=headers)if response:data = response.json()if data['error_msg'] == 'SUCCESS':if data['result']['user_list'][0]['score'] > 90: #大于90分,意味人脸识别成功del [data['result']['user_list'][0]['score']]datetime = QDateTime.currentDateTime()#获取人脸打开时间datetime = datetime.toString()#将获取到的时间转为字符串data['result']['user_list'][0]['datetime'] = datetime#将获取到的时间添加到返回的数据中list1 = [data['result']['user_list'][0]['user_id'],data['result']['user_list'][0]['group_id']]#去除名字和班级self.transmit_data1.emit("学生签到成功\n学生信息如下:\n" + "姓名:" + list1[0] + "\n" + "班级:" + list1[1])#将信号发送给主线程

下面就需要在主线程中进行数据接收显示了!

4、主线程人脸识别数据接收显示

(1)、在function_window.py文件末尾添加显示信息方法

    def get_seach_data(self,data):self.plainTextEdit.setPlainText(data)


(2)、在function_window.py文件中绑定子线程中信号接收

self.detect.transmit_data1.connect(self.get_seach_data)

添加位置如下图:

到这里,人脸识别模块基本完成,function_window.py文件也修改完成。
(3)function_window.py文件修改后的代码内容如下所示:

import base64import cv2
import requests
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMainWindow, QMessageBox
from cameraVideo import camera
from mainWindow import Ui_MainWindow
from detect import detect_thread
class function_window(Ui_MainWindow,QMainWindow):'''初始化函数'''def __init__(self):super(function_window, self).__init__()self.setupUi(self)self.label.setScaledContents(True)#设置图像自适应label显示框self.pushButton.clicked.connect(self.open_Sign)#打开签到事件绑定self.pushButton_2.clicked.connect(self.close_Sign)#关闭签到事件绑定self.access_token=self.get_accessToken()#获取Access_token访问令牌,并复制为全局变量self.start_state=True'''打开签到'''def open_Sign(self):if self.start_state==True:# 启动摄像头self.cameravideo = camera()# 启动定时器进行定时,每隔多长时间进行一次获取摄像头数据进行显示self.timeshow = QTimer(self)self.timeshow.start(10)# 每隔10毫秒产生一个信号timeoutself.timeshow.timeout.connect(self.show_cameradata)self.detect = detect_thread(self.access_token)  # 创建线程self.detect.start()  # 启动线程# 签到500毫秒获取一次,用来获取检测的画面self.faceshow = QTimer(self)self.faceshow.start(500)self.faceshow.timeout.connect(self.get_cameradata)self.detect.transmit_data.connect(self.get_data)self.detect.transmit_data1.connect(self.get_seach_data)self.start_state=Falseelse:QMessageBox.about(self, "提示", "正在检测,请先关闭!")'''关闭签到'''def close_Sign(self):if self.start_state==False:self.faceshow.stop()  # 计时器停止self.detect.ok = False  # 停止run函数运行self.detect.quit()  # 关闭线程# 关闭定时器,不再获取摄像头的数据self.timeshow.stop()self.timeshow.timeout.disconnect(self.show_cameradata)# 关闭摄像头self.cameravideo.colse_camera()self.start_state=True# 判断定时器是否关闭,关闭,则显示为自己设定的图像if self.timeshow.isActive() == False:self.label.setPixmap(QPixmap("image/1.jpg"))self.plainTextEdit_2.clear()else:QMessageBox.about(self, "警告", "关闭失败,存在部分没有关闭成功!")else:QMessageBox.about(self, "提示", "请先开始检测!")#获取人脸检测数据并显示到文本框中def get_data(self,data):if data['error_code']!=0:self.plainTextEdit_2.setPlainText(data['error_msg'])returnelif data['error_msg'] == 'SUCCESS':self.plainTextEdit_2.clear()# 在data字典中键为result对应的值才是返回的检测结果face_num = data['result']['face_num']# print(face_num)if face_num == 0:self.plainTextEdit_2.setPlainText("当前没有人或人脸出现!")returnelse:self.plainTextEdit_2.clear()self.plainTextEdit_2.appendPlainText("检测到人脸!")self.plainTextEdit_2.appendPlainText("——————————————")# 人脸信息获取['result']['face_list']是列表,每个数据就是一个人脸信息,需要取出每个列表信息(0-i)for i in range(face_num):age = data['result']['face_list'][i]['age']  # 年龄# print(age)beauty = data['result']['face_list'][i]['beauty']  # 美观度gender = data['result']['face_list'][i]['gender']['type']  # 性别expression = data['result']['face_list'][i]['expression']['type']face_shape = data['result']['face_list'][i]['face_shape']['type']  # 脸型glasses = data['result']['face_list'][i]['glasses']['type']  # 是否戴眼镜emotion = data['result']['face_list'][i]['emotion']['type']  # 情绪mask = data['result']['face_list'][i]['mask']['type']  # 是否戴口罩# 往窗口中添加文本,参数就是需要的文本信息# print(age,gender,expression,beauty,face_shape,emotion,glasses,mask)self.plainTextEdit_2.appendPlainText("第" + str(i + 1) + "个学生人脸信息:")self.plainTextEdit_2.appendPlainText("——————————————")self.plainTextEdit_2.appendPlainText("年龄:" + str(age))if gender == 'male':gender = "男"else:gender = "女"self.plainTextEdit_2.appendPlainText("性别:" + str(gender))self.plainTextEdit_2.appendPlainText("表情:" + str(expression))self.plainTextEdit_2.appendPlainText("颜值分数:" + str(beauty))self.plainTextEdit_2.appendPlainText("脸型:" + str(face_shape))self.plainTextEdit_2.appendPlainText("情绪:" + str(emotion))if glasses == "none":glasses="否"elif glasses == "common":glasses="是:普通眼镜"else:glasses="是:太阳镜"self.plainTextEdit_2.appendPlainText("是否佩戴眼镜:" + str(glasses))if mask == 0:mask = "否"else:mask = "是"self.plainTextEdit_2.appendPlainText("是否佩戴口罩:" + str(mask))self.plainTextEdit_2.appendPlainText("——————————————")else:print("人脸获取失败!")'''获取图像,并转换为base64格式'''def get_cameradata(self):camera_data1 = self.cameravideo.read_camera()# 把摄像头画面转化为一张图片,然后设置编码为base64编码_, enc = cv2.imencode('.jpg', camera_data1)base64_image = base64.b64encode(enc.tobytes())#产生信号,传递数据self.detect.get_imgdata(base64_image)'''摄像头数据显示'''def show_cameradata(self):#获取摄像头数据pic=self.cameravideo.camera_to_pic()#在lebel框中显示数据、显示画面self.label.setPixmap(pic)'''获取Access_token访问令牌'''def get_accessToken(self):# client_id 为官网获取的AK, client_secret 为官网获取的SKhost = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=TKGXdKC7WPWeADGHmFBN8xAr&client_secret=lsr1tAuxv3tRGmOgZTGgNyri667dfKGg'# 进行网络请求,使用get函数response = requests.get(host)if response:data = response.json()self.access_token = data['access_token']return self.access_tokenelse:QMessageBox(self,"提示","请检查网络连接!")def get_seach_data(self,data):self.plainTextEdit.setPlainText(data)

5、人脸识别运行结果测试

(1)运行程序,打开签到

(2)开始签到

可以看到,签到的数据显示到对应的信息框中,签到成功!
(3)关闭签到


以上就是本次博客的全部内容,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷!

没有人永远青春,但永远有人正青春;只是,林君学长的青春暂告一段路而已!

陈一月的又一天编程岁月^ _ ^

百度AI人脸识别与检测五:学生人脸识别打卡签到系统之百度AI人脸识别相关推荐

  1. 百度AI人脸识别与检测二:学生人脸识别打卡签到系统主界面功能需求和设计以及通过Python实现界面运行

    <百度AI人脸识别与检测>专栏为项目专栏,从零到一,从无到有开发一个学生人脸识别签到系统:主要用到的技术有百度开放平台中的人脸检测.人脸识别.Python图形界面开发PyQt5.线程的管理 ...

  2. 计算机毕业设计-基于微信小程序高校学生课堂扫码考勤签到系统-校园考勤打卡签到小程序

    注意:该项目只展示部分功能,如需了解,评论区咨询即可. 本文目录 1.开发环境 2.系统的设计背景 3 各角色功能模块 3.1 用户 3.2 管理员 4 系统页面展示 4.1 学生端功能模块展示 4. ...

  3. 基于百度API人脸识别课堂签到系统(一)--------人脸检测

    一.前言 今年由于疫情,全国学生的教学方式都从线下转到了线上:线下可以点名进行签到,那么线上应该如何进行准确的签到,防止学生作弊签到的情况呢?因此一款适用于大中小学生的基于人脸识别的课堂签到系统便应运 ...

  4. 基于JAVA人脸识别公司签到系统(Springboot框架+AI人工智能) 开题报告

      本科生毕业论文 基于Java(springboot框架)人脸识别公司签到系统 开题报告 学    院: 专    业: 计算机科学与技术 年    级: 学生姓名: 指导教师:   XXXX大学本 ...

  5. 基于华为云人脸服务接口设计的人脸考勤打卡签到系统

    1. 项目介绍 近几年,生物特征识别技术获得快速发展.人脸作为一种生物特征,具有很强的自身稳定性和个体差异性,是进行身份验证的最理想依据,主要方法包括步态识别.虹膜识别.皮肤芯片.脸像识别.多模态(即 ...

  6. 百度AI人脸识别与检测一:学生人脸识别签到系统简介及百度AI开放平台账号注册和人脸实例应用创建

    <百度AI人脸识别与检测>专栏为项目专栏,从零到一,从无到有开发一个学生人脸识别签到系统:主要用到的技术有百度开放平台中的人脸检测.人脸识别.Python图形界面开发PyQt5.线程的管理 ...

  7. 【优秀课设】基于OpenCV的Python人脸识别、检测、框选(遍历目录下所有照片依次识别 视频随时标注)

    基于OpenCV的Python人脸识别.检测.框选 (遍历目录下所有照片依次识别 视频随时标注) 移步: https://blog.csdn.net/weixin_53403301/article/d ...

  8. dlib实现人脸识别+活体检测

    目录: 一:dlib的shape_predictor_68_face_landmarks模型 二.眨眼检测 三.张口检测 四.眨眼检测+张口检测 五.人脸识别 六.人脸识别+活体检测 七.人脸识别破解 ...

  9. python人脸识别、语音合成、智能签到系统(2)

    基于python+face_recognition+opencv+pyqt5+百度AI实现的人脸识别.语音播报.语音合成.模拟签到系统(2) 人脸识别效果图 简单介绍以及需要的配置在 python人脸 ...

  10. python人脸识别、语音合成、智能签到系统

    基于python+face_recognition+opencv+pyqt5+百度AI实现的人脸识别.语音播报.语音合成.模拟签到系统(1) 人脸识别效果图 源码看最下面 这是新版本地址人脸识别.语音 ...

最新文章

  1. Hello World
  2. ComboBox的数据联动
  3. Git的reflog与log
  4. 干货!操作系统基础知识汇总!转给要面试的同学吧
  5. libevent源码深度剖析十二
  6. QT设置相对路径最简单方法
  7. Perl调用shell命令方法小结
  8. 解决Oracle EM 乱码问题
  9. JS学习总结(7)——对象
  10. js输入身份证号直接转换时间
  11. wap4410n 服务器上限修改,cisco wap4410n设置方法
  12. DM 源码阅读系列文章(七)定制化数据同步功能的实现
  13. WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK
  14. 三个小故事让你一次记住双拼输入法口诀
  15. pytest-mian函数运行
  16. 2022年执法资格刑侦执法考试多选题专项训练题及答案
  17. HTML编写个人日记,HTML学习日记(1-基础)
  18. 手机通用root刷补Magisk教程
  19. EMC VNX5200 故障灯亮,但无任何硬件故障提示
  20. 小清新插画劳动节主题PPT模板

热门文章

  1. 深入浅出MySQL学习笔记之锁问题
  2. 如何选择企业数据加密软件?
  3. oracle 函数的使用
  4. 用python设计数独的心得体会_Python生成数独矩阵
  5. python 知乎美女_听说知乎大神用python爬取高颜值美女,是怎么操作的?
  6. 原生JS和NodeJS之间的区别
  7. 极域电子教室常见问题解决方案
  8. 常识——CE修改器使用
  9. VBA 收集 Word关键字批量处理-Excel版
  10. 合作博弈:联盟、分配和核心core