前面有一个帖《OpenCV检测场景内是否有移动物体》我用树莓派做了一个简单的Motion Detection,放在卫生间的,它会在我上大号时自动播放音乐。

我一个人租房,几个盆友周末时常会找我玩,他们觉得我做的Motion Detection很垃圾。于是我就想恶搞一下,用TensorFlow做一个“人脸识别”,在我上大号时播放音乐,如果是别人就播放《张震讲鬼故事》(@xingCI说放屁声更搞)。

我的任务的训练一个模型可以区分“我”和“其它人”的脸。注意,上面“人脸识别”我是加引号的,其实并不是真正的人脸识别,充其量就是个图像分类。如果你要使用真正的人脸识别,可以试试现成的库OpenFace+dlib《使用OpenFace进行人脸识别》。

有人已经把TensorFlow移植到了树莓派,项目地址tensorflow-on-raspberry-pi。

准备数据

本帖需要使用到两组数据:一组是包含我脸的图像,另一组包含其它人人脸的图像。

其它人人脸的收集

找一堆图片,只要不包含自己就行,然后使用OpenCV提取图像中的大脸。

我使用的数据集是前面几帖用到的:《妹子图》《大脸》《imagenet》

提取图像中的人脸,我使用OpenCV,据说使用dlib效果更好。

other_peoples_faces.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

import cv2
import os
import sys
IMAGE_DIR = '图片目录路径'
OUTPUT_DIR = './other_people'
if not os.path.exists(OUTPUT_DIR):
os.makedirs(OUTPUT_DIR)
# http://blog.topspeedsnail.com/archives/10511
# wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml
face_haar = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
for (dirpath, dirnames, filenames) in os.walk(IMAGE_DIR):
for filename in filenames:
if filename.endswith('.jpg'):
image_path = os.path.join(dirpath, filename)
print('process: ', image_path)
img = cv2.imread(image_path)
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_haar.detectMultiScale(gray_image, 1.3, 5)
for face_x,face_y,face_w,face_h in faces:
face = img[face_y:face_y+face_h, face_x:face_x+face_w]
face = cv2.resize(face, (64, 64))
cv2.imshow("img", face)
cv2.imwrite(os.path.join(OUTPUT_DIR, filename), face)
key = cv2.waitKey(30) & 0xff
if key == 27:
sys.exit(0)

4万多图片,我只提取了1万张脸,应该够使了。

图像大小 64×64

上面是OpenCV做的人脸检测,有了这个数据集又可以反过来训练TensorFlow版本的人脸检测。

斗大熊的脸

给自己拍照1万张,这是我一次拍照最多的一回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

import cv2
import os
import sys
OUTPUT_DIR = './my_faces'
if not os.path.exists(OUTPUT_DIR):
os.makedirs(OUTPUT_DIR)
face_haar = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
cam = cv2.VideoCapture(0)
count = 0
while True:
print(count)
if count < 10000:
_, img = cam.read()
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_haar.detectMultiScale(gray_image, 1.3, 5)
for face_x,face_y,face_w,face_h in faces:
face = img[face_y:face_y+face_h, face_x:face_x+face_w]
face = cv2.resize(face, (64, 64))
cv2.imshow('img', face)
cv2.imwrite(os.path.join(OUTPUT_DIR, str(count)+'.jpg'), face)
count += 1
key = cv2.waitKey(30) & 0xff
if key == 27:
break
else:
break

在镜头前摇头晃脑、摆pose,戴眼镜、耳机,仰天45,写代码,呲牙咧嘴,玩手机。。。一定要多样化,直到拍1万张大脸。

训练模型

训练数据有了,下面开始训练。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

import tensorflow as tf
import cv2
import numpy as np
import os
from sklearn.model_selection import train_test_split
import random
import sys
my_image_path = 'my_faces'
others_image_path = 'other_people'
image_data = []
label_data = []
def get_padding_size(image):
h, w, _ = image.shape
longest_edge = max(h, w)
top, bottom, left, right = (0, 0, 0, 0)
if h < longest_edge:
dh = longest_edge - h
top = dh // 2
bottom = dh - top
elif w < longest_edge:
dw = longest_edge - w
left = dw // 2
right = dw - left
else:
pass
return top, bottom, left, right
def read_data(img_path, image_h=64, image_w=64):
for filename in os.listdir(img_path):
if filename.endswith('.jpg'):
filepath = os.path.join(img_path, filename)
image = cv2.imread(filepath)
top, bottom, left, right = get_padding_size(image)
image_pad = cv2.copyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value=[0, 0, 0])
image = cv2.resize(image_pad, (image_h, image_w))
image_data.append(image)
label_data.append(img_path)
read_data(others_image_path)
read_data(my_image_path)
image_data = np.array(image_data)
label_data = np.array([[0,1] if label == 'my_faces' else [1,0] for label in label_data])
train_x, test_x, train_y, test_y = train_test_split(image_data, label_data, test_size=0.05, random_state=random.randint(0, 100))
# image (height=64 width=64 channel=3)
train_x = train_x.reshape(train_x.shape[0], 64, 64, 3)
test_x = test_x.reshape(test_x.shape[0], 64, 64, 3)
# nomalize
train_x = train_x.astype('float32') / 255.0
test_x = test_x.astype('float32') / 255.0
print(len(train_x), len(train_y))
print(len(test_x), len(test_y))
#############################################################
batch_size = 128
num_batch = len(train_x) // batch_size
X = tf.placeholder(tf.float32, [None, 64, 64, 3])  # 图片大小64x64 channel=3
Y = tf.placeholder(tf.float32, [None, 2])
keep_prob_5 = tf.placeholder(tf.float32)
keep_prob_75 = tf.placeholder(tf.float32)
def panda_joke_cnn():
W_c1 = tf.Variable(tf.random_normal([3, 3, 3, 32], stddev=0.01))
b_c1 = tf.Variable(tf.random_normal([32]))
conv1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(X, W_c1, strides=[1, 1, 1, 1], padding='SAME'), b_c1))
conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
conv1 = tf.nn.dropout(conv1, keep_prob_5)
W_c2 = tf.Variable(tf.random_normal([3, 3, 32, 64], stddev=0.01))
b_c2 = tf.Variable(tf.random_normal([64]))
conv2 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1, W_c2, strides=[1, 1, 1, 1], padding='SAME'), b_c2))
conv2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
conv2 = tf.nn.dropout(conv2, keep_prob_5)
W_c3 = tf.Variable(tf.random_normal([3, 3, 64, 64], stddev=0.01))
b_c3 = tf.Variable(tf.random_normal([64]))
conv3 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2, W_c3, strides=[1, 1, 1, 1], padding='SAME'), b_c3))
conv3 = tf.nn.max_pool(conv3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
conv3 = tf.nn.dropout(conv3, keep_prob_5)
# Fully connected layer
W_d = tf.Variable(tf.random_normal([8*16*32, 512], stddev=0.01))
b_d = tf.Variable(tf.random_normal([512]))
dense = tf.reshape(conv3, [-1, W_d.get_shape().as_list()[0]])
dense = tf.nn.relu(tf.add(tf.matmul(dense, W_d), b_d))
dense = tf.nn.dropout(dense, keep_prob_75)
W_out = tf.Variable(tf.random_normal([512, 2], stddev=0.01))
b_out = tf.Variable(tf.random_normal([2]))
out = tf.add(tf.matmul(dense, W_out), b_out)
return out
def train_cnn():
output = panda_joke_cnn()
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output, Y))
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(output, 1), tf.argmax(Y, 1)), tf.float32))
tf.summary.scalar("loss", loss)
tf.summary.scalar("accuracy", accuracy)
merged_summary_op = tf.summary.merge_all()
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
summary_writer = tf.summary.FileWriter('./log', graph=tf.get_default_graph())
for e in range(50):
for i in range(num_batch):
batch_x = train_x[i*batch_size : (i+1)*batch_size]
batch_y = train_y[i*batch_size : (i+1)*batch_size]
_, loss_, summary = sess.run([optimizer, loss, merged_summary_op], feed_dict={X: batch_x, Y: batch_y, keep_prob_5:0.5, keep_prob_75: 0.75})
summary_writer.add_summary(summary, e*num_batch+i)
print(e*num_batch+i, loss_)
if (e*num_batch+i) % 100 == 0:
acc = accuracy.eval({X: test_x, Y: test_y, keep_prob_5:1.0, keep_prob_75: 1.0})
print(e*num_batch+i, acc)
# save model
if acc > 0.98:
saver.save(sess, "i_am_a_joke.model", global_step=e*num_batch+i)
sys.exit(0)
train_cnn()

准确率曲线:

下面要做的就是在树莓派上使用模型,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

output = panda_joke_cnn()
predict = tf.argmax(output, 1)
saver = tf.train.Saver()
sess = tf.Session()
saver.restore(sess, tf.train.latest_checkpoint('.'))
def is_my_face(image):
res = sess.run(predict, feed_dict={X: [image/255.0], keep_prob_5:1.0, keep_prob_75: 1.0})
if res[0] == 1:
return True
else:
return False
face_haar = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
cam = cv2.VideoCapture(0)
while True:
_, img = cam.read()
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_haar.detectMultiScale(gray_image, 1.3, 5)
for face_x,face_y,face_w,face_h in faces:
face = img[face_y:face_y+face_h, face_x:face_x+face_w]
face = cv2.resize(face, (64, 64))
print(is_my_face(face))
cv2.imshow('img', face)
key = cv2.waitKey(30) & 0xff
if key == 27:
sys.exit(0)
sess.close()

总结:占用内存100多M,准确率还凑合,先用着。

上面方法需要收集两类数据(自己的脸和其他人的脸),有没有办法只使用自己的脸做One-Class分类呢?这样就不需收集其他人的脸了。感觉上可以用autoencoder。

如要转载,请保持本文完整,并注明作者@斗大的熊猫和本文原始地址: http://blog.topspeedsnail.com/archives/10931

TensorFlow练习23: “恶作剧”相关推荐

  1. TensorFlow练习24: GANs-生成对抗网络 (生成明星脸)

    GANs是Generative Adversarial Networks的简写,中文翻译为生成对抗网络,它最早出现在2014年Goodfellow发表的论文中:Generative Adversari ...

  2. tf24: GANs—生成明星脸

    GANs是Generative Adversarial Networks的简写,中文翻译为生成对抗网络,它最早出现在2014年Goodfellow发表的论文中:Generative Adversari ...

  3. ArXiv最火深度学习框架:TensorFlow第一,PyTorch第二!|湾区人工智能

    一年不算短,但也不算长.一年时间,可以让Swift从11位跌倒13位,也可以让PyTorch从第4位飙升194%至第2位! PyTorch狂涨194%,逼近TensorFlow份额 UC伯克利RISE ...

  4. 干货 | 如何使用 CNN 推理机在 IoT 设备上实现深度学习

    作者 | 唐洁 责编 | 何永灿 通过深度学习技术,物联网(IoT)设备能够得以解析非结构化的多媒体数据,智能地响应用户和环境事件,但是却伴随着苛刻的性能和功耗要求.本文作者探讨了两种方式以便将深度学 ...

  5. Tensorflow2.6.0-MKL for C++

    在intel官网看到Optimize AI Applications with Intel® oneAPI Deep Neural Network... 查了一下,好像即使只要有intel,以后CPU ...

  6. 如何使用CNN推理机在IoT设备上实现深度学习

    作者简介: 唐洁,华南理工大学计算机科学与工程学院副教授.主要从事面向无人驾驶和机器人的大数据计算与存储平台.面向人工智能的计算体系架构.面向机器视觉的嵌入式系统研究. 责编:何永灿(heyc@csd ...

  7. 2021-03-13 15:41:23.367561: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could no

    2021-03-13 15:41:23.367561: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could no ...

  8. 最新Win7 +Python3.6.0(Anaconda3-4.3.21)+Tensorflow的安装与配置(不用切换python3.5) 原创 2017年09月23日 15:14:58 标签:pyt

    最新Win7 +Python3.6.0(Anaconda3-4.3.21)+Tensorflow的安装与配置(不用切换python3.5) 一.首先进入Anaconda官网下载  https://ww ...

  9. 吴恩达 深度学习 编程作业(2-3)- TensorFlow Tutorial

    TensorFlow Tutorial Welcome to this week's programming assignment. Until now, you've always used num ...

最新文章

  1. SQL Server2005设置sa登录名
  2. 你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?
  3. Android Picasso最详细的使用指南
  4. ARMLINUX学习笔记(二)
  5. 数值分析(2)-多项式插值: 拉格朗日插值法
  6. IDEA配置-无法读取src/java/main下hbm.xml等资源文件
  7. centos8 默认nginx路径_centos8自定义目录安装nginx(教程详解)
  8. nvidia控制面板点了没反应win7_nvidia控制面板点击没反应 - 卡饭网
  9. 你知道Message.obtain()什么原理吗?
  10. [技巧]QQ密技(一)
  11. 嵌入式开发必须学习qt吗?
  12. 上海亚商投顾:沪指失守3300点 传媒、游戏板块逆市大涨
  13. 【无标题】UBUNTU22.04 WIFI图标显示
  14. 5c标准第二语言,美国语言教学5C标准对中文作为第二语言教学课堂的启示
  15. php xmpphp,给xmpphp添加了几个常用的方法 | 学步园
  16. 应届生面试紧张试试这几个方法
  17. excel-多行内容分组合并-分类汇总(汇总不求和只合并内容)
  18. UltraEdit editplus notepad等的编码问题
  19. Rk3399全接口板 高性能高扩展全能型介绍
  20. python中图像的批量处理

热门文章

  1. 使用redis和mysql的开源项目_干货!带你了解为什么那么多开源项目都是用Redis!...
  2. C# 四舍五入round函数使用的代码
  3. 变步长龙格库塔法matlab代码,matlab 龙格库塔法 变步长龙格库塔法.doc
  4. webuploader 怎么在react中_React 项目性能分析及优化
  5. 正确退出activity_【单选题】下面退出 Activity 错误的方法是
  6. gridcontrol值为0时设置为空_XASSET 4.0入门指南
  7. 第 5 章 Nova - 041 - Resize Instance 操作详解
  8. linux 重定向类型 超级块 i节点
  9. OSChina 周日乱弹 —— 比996更先进的是365工作制
  10. Django 实现分库