最近需要写一个工具,提取图片中的人脸,并且识别出相关信息,最后按照一定的规则进行存储。
0.分析
通过上述需求,需要做的是OCR文字识别和人脸识别,语言选择Python
。人脸提取使用的是OpenCV,简单介绍一下,摘自百度百科。
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
文字识别准备使用 Tesseract
Tesseract最初由惠普实验室支持,用于电子版文字识别,1996年被移植到Windows上,1998年进行了C++化,在2005年Tesseract由惠普公司宣布开源。2006年到现在,由Google公司维护开发。
1.准备工作
安装
Tesseract
和pytesseract
安装
opencv
- 使用pip install opencv-python 安装opencv-python
- haar人脸特征分类器下载点击这里下载
- 使用pip install opencv-python 安装opencv-python
后面因为文字识别的准确率实在太低了,不得不换成Excel读取相关信息,后面继续优化
- 使用
pip install xlrd==1.2.0
安装xlrd
解析Excel,高版本的不支持xlsx,所以得装低版本的。
2.编写程序
import cv2
import os
import xlrd
import shutil
from tkinter import *
from tkinter import scrolledtext
import numpy as np
j = 0
width = 200
height = 250
dim = (width, height)
def clicked():
root_path = txt.get() + "\\"
data = xlrd.open_workbook(root_path + txt1.get())
table = data.sheets()[0]
dcit = {}
# 加载人员信息
for rown in range(table.nrows):
dcit[table.cell_value(rown, 4)] = table.cell_value(rown, 2) + "#" + table.cell_value(rown, 6)
for i in os.listdir(root_path):
if i.endswith(".jpg"):
path2 = os.path.join(root_path, i).replace("\\", "\\\\") # 拼接绝对路径
# img = cv2.imread(path2, 1) # 读取一张图片
img = cv2.imdecode(np.fromfile(path2, dtype=np.uint8), -1)
# 提取人脸图片
stxt.insert(INSERT, r"开始提取文件[" + i + "]人脸信息\n")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图片转化成灰度
face_cascade = cv2.CascadeClassifier(
"config\\haarcascade_frontalface_alt2.xml")
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
if len(faces) > 0:
for (x, y, w, h) in faces:
# img = cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cropped = img[y - 60: y + w + 60, x - 30:x + h + 44] # 裁剪坐标为[y0:y1, x0:x1]
resized = cv2.resize(cropped, dim, interpolation=cv2.INTER_AREA)
# cv2.imshow("image", resized)
# 进行xjk和zp分类
idNo = i.split(" ")[0]
if idNo in dcit:
stxt.insert(INSERT, "正在分类[" + idNo + "]\n")
val = dcit[idNo].split("#")
name = val[0]
peopleType = val[1]
folder = os.path.exists(root_path + "Result\\" + peopleType + "\\zp\\")
if not folder:
os.makedirs(root_path + "Result\\" + peopleType + "\\zp\\")
folder = os.path.exists(root_path + "Result\\" + peopleType + "\\xjk\\")
if not folder:
os.makedirs(root_path + "Result\\" + peopleType + "\\xjk\\")
# cv2.imwrite(, resized)
cv2.imencode('.jpg', resized)[1].tofile(
root_path + "Result\\" + peopleType + "\\zp\\" + idNo + '.jpg')
shutil.move(root_path + i, root_path + "Result\\" + peopleType + "\\xjk\\" + idNo + '.jpg')
else:
stxt.insert(INSERT, "表格中没有为[" + idNo + "]的人\n")
# cv2.destroyAllWindows()
else:
stxt.insert(INSERT, "文件[" + i + "]未识别到人脸\n")
stxt.insert(INSERT, "-------------------\n")
stxt.see(END)
stxt.update()
stxt.insert(INSERT, "处理完成.....\n")
tk = Tk()
tk.title("图片分类器")
tk.geometry("310x320")
tk.resizable(width=False, height=False)
lbl0 = Label(tk, text="登记表和图片需要放在一个文件夹下", fg='red', bg='yellow')
lbl = Label(tk, text="图片路径:")
btn = Button(tk, text="开始分类", command=clicked)
default = StringVar(tk, value='C:\\Users\\xxx\\Desktop\\sss\\xjk')
txt = Entry(tk, textvariable=default, width=20)
lbl1 = Label(tk, text="登记表名称:")
default = StringVar(tk, value='11.xlsx')
txt1 = Entry(tk, textvariable=default, width=20)
stxt = scrolledtext.ScrolledText(tk, width=40, height=15)
lbl0.grid(column=0, row=0,columnspan=2)
lbl.grid(column=0, row=1)
txt.grid(column=1, row=1)
lbl1.grid(column=0, row=2)
txt1.grid(column=1, row=2)
btn.grid(column=0, row=3, columnspan=2, sticky=W+E+N+S, padx=5, pady=5)
stxt.grid(column=0, row=4, columnspan=2, sticky=W+E+N+S, padx=5, pady=5)
tk.mainloop()
3.总结
很多时候应该想着去偷懒,只有想着去偷懒才能够自己去写工具,去学习。虽然不是很深入,但是你知识的广度会拓宽。
20210827 更新
为了方便使用者,转成了可执行文件并且做了个简单的界面。今天想起来就更新上
使用 pip install pyinstaller 安装 pyinstaller
使用 pyinstaller -F TestForFun.py -w 生成可执行文件
代码在上面,已经更新过了