最近在做一个简单的人脸比对项目,需要采集一些真实场景的人脸图像用于测试。目前网上的明星照片比较多,因此写一个Python脚本可以自动获取明星人脸图像,并且使用opencv库对采集的人脸图像进行一定程度的验证、过滤,尽可能保留人脸区域较大的、正面的图像。
完整代码如下:
import os
import sys
import time
import urllib
import requests
import re
from bs4 import BeautifulSoup
import time
from xpinyin import Pinyin
import cv2
header = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'
}
url = "https://cn.bing.com/images/async?q={0}&first={1}&count={2}&scenario=ImageBasicHover&datsrc=N_I&layout=ColumnBased&mmasync=1&dgState=c*9_y*2226s2180s2072s2043s2292s2295s2079s2203s2094_i*71_w*198&IG=0D6AD6CBAF43430EA716510A4754C951&SFX={3}&iid=images.5599"
# 创建人脸检测器
face_detecter = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
def findImgUrlFromHtml(html,savepath, rule, count,countNum):
'''从缩略图列表页中找到原图的url,并返回这一页的图片数量'''
soup = BeautifulSoup(html, "lxml")
link_list = soup.find_all("a", class_="iusc")
url = []
for link in link_list:
result = re.search(rule, str(link))
# 将字符串"amp;"删除
url = result.group(0)
# 组装完整url
url = url[8:len(url)]
# 打开网址
try:
# 爬取图片
r = requests.get(url, timeout=10)
imgpath = os.path.join(savepath,str(count + 1) + '.jpg')
with open(imgpath,'wb') as f:
f.write(r.content)
# 检索图片有效性
img = cv2.imread(imgpath)
if img is None:
os.remove(imgpath)
continue
# 检查图片规格
h,w,_=img.shape
if w < 600:
os.remove(imgpath)
continue
# 检查是否存在明显的正面人脸照片
if w != 512:
newh = int(512.0* h / w)
img = cv2.resize(img, (512,newh))
faces = face_detecter.detectMultiScale(image=img, scaleFactor=1.1, minNeighbors=5)
if len(faces)==0:
os.remove(imgpath)
continue
# 更新数量
count += 1
print("图片+1,成功保存第 " + str(count) + " 张图")
except Exception as e:
time.sleep(1)
print("本张图片获取异常,跳过...")
if count+1>countNum:
return count
return count
def getStartHtml(url, key, sfx):
'''获取缩略图列表页'''
page = urllib.request.Request(url.format(key, 1, 10, sfx),headers=header)
html = urllib.request.urlopen(page)
return html
if __name__ == '__main__':
# 定义初始化参数
pinyin = Pinyin() # 中文转拼音类实例
fileList = list() # 最终的文件列表
countNum = 5 # 每个人物爬取数量
data_root = 'starimgs' # 图像保存根目录
# 读取明星列表
f = open("names.txt", encoding='utf-8')
nameList = f.read().splitlines()
# 逐个人物开始爬取
id = 0
for ch_name in nameList:
print('开始爬取 ' + ch_name +' 的图片')
# 获取英文名
en_name = pinyin.get_pinyin(ch_name)
en_name = en_name.split('-')
en_name = en_name[0].capitalize()+'' + \
''.join(en_name[1:]).capitalize()
# 定义爬取参数
key = urllib.parse.quote(ch_name)
sfx = 1
count = 0
# 创建保存路径
savepath = os.path.join(data_root, en_name)
if not os.path.exists(savepath):
os.makedirs(savepath)
else:
continue
# 定义爬取正则式
rule = re.compile(r"\"murl\"\:\"http\S[^\"]+")
while count < countNum:
html = getStartHtml(url, key, sfx)
count = findImgUrlFromHtml(html,savepath, rule, count,countNum)
#first = count + 1
sfx += 1
print('人物 '+ ch_name +en_name+' 爬取完成')
# 添加进有效名单
txt = str(id) + '_' + en_name + '_' +ch_name + '\n'
fileList.append(txt)
id += 1
# 保存标签文件
list_path = 'label.txt'
if os.path.exists(''):
os.remove(list_path)
with open(os.path.join(list_path), 'w', encoding='utf-8') as f:
for filename in fileList:
f.write(filename) # 写入list.txt
print('全部处理完毕')
上述代码运行前需要在本地建立一个包含明星名字的names.txt文件,内容如下所示:
王一博
何炅
韩庚
王俊凯
杨紫
王源
张杰
易烊千玺
迪丽热巴
赵丽颖
胡歌
最终爬取效果如下:
本项目初步采集100多位明星照片,完整代码和图像数据下载链接如下:
链接:https://pan.baidu.com/s/1P4q6lbqk-uHXGTcm_8mXgw?pwd=ylgc
提取码:ylgc