目录
一:问题描述 2
二:实现思路 2
2.1 切换点 2
2.1.2 镜头切换点 3
2.1.2 音频切换点。 3
2.2 嘉宾识别 = 人脸识别 & 声纹识别 4
2.2.1 人脸识别 4
2.2.2 声纹识别 5
三:实验环境 5
四:分帧 6
4.1 直方图计算法 6
4.2 图像指纹:hash 7
4.3 SSIM法 8
4.4 实验输出及结果 8
五:人脸识别 10
5.1 数据集的构建 10
5.2 训练集和测试集的构建 12
5.3 数据的处理 15
5.4 人脸识别的历程 17
5.4.1 早期 模板匹配技术 17
5.4.2 中期 voila-jonesVJ框架 17
5.4.3 现在 深度学习 17
5.5 配置神经网络 17
5.5.1 CNN 17
5.5.3 VGG 20
5.5.3 定义损失函数和准确率 21
5.5.4 定义优化方法 22
5.6 训练网络和保存模型 22
5.6.1创建Executor 22
5.6.2展示模型训练曲线 23
5.6.3训练并保存模型 23
5.7 模型评估 25
5.7.1CNN 25
5.7.2VGG 26
5.8 对视频进行识别并且进行可视化输出 27
5.8.1 对视频进行识别 27
5.8.2 将结果可视化输出 30
5.9 实验结果及分析 32
六:音频识别 34
6.1 分段式声纹识别 34
6.2 说话人日志 35
6.2.1 说话人日志原理 35
6.2.2 说话人日志结果分析 36
6.3 数据可视化 37
七:代码查看方式 37
7.1 视频识别: 37
7.2 音频识别: 37
九:参考文献 37
二:实现思路
一开始拿到这个题目是有点懵的,因为我们组里都是信安,并没有学习过机器学习类似的课程,但是这道题目是一定要用到机器学习。再加上这道题老师并没有给出参考代码,所以可以说是完全是“从头开始”。不过功夫不负有心人并且老师给了我们最后一个选题充裕的时间,所以我们才可以将其做出来。
2.1 切换点
而根据问题的描述:根据声音或者视频,给出镜头的切换点,按照时间段给出时间起点和终点。
我们所理解的切换点为两种:镜头切换点和音频切换点。
2.1.2 镜头切换点
对于镜头切换点:对于这个视频来说,可以很明显的看到这个视频的拍摄并不是一个机位拍摄的,而是多机位进行拍摄。每个机位对着一个嘉宾或者主持人。如下图所示:
所以我们想到如果说我们可以找到这个视频的镜头切换点或者说剪辑点,对于一个视频而言后期剪辑会将不同机位拍摄的视频剪辑在一起,而这个剪辑点是很好找的,所以只要找到这视频的剪辑点就相当于找到了这个视频的镜头切换点,就可以将一段视频分段,分成一段只有一个主持人的样子,并且将每一段所对应的时间记录下来生成一个列表,这样就可以达到选题给出的要求。
至于如何找这个剪辑点在之后的第三段:分帧中会提到,这里就不赘述了。
2.1.2 音频切换点。
对比寻找视频切换点,音频切换点就显得不是友好了。
这是我们用来测试的波形图
对于这段音频,当一个人停止说话时就是波谷,然后后面一个人又接话这样就可以判断音频的切换点。
虽然说理论上这样是没有错的,但是实际实现上是有很多纰漏的:当一个人说完了一句话,其实就有停顿,这个时候如果说时音频切换点的话那么一段视频中就有很多很多个切换点,如上图,本文转载自http://www.biyezuopin.vip/onews.asp?id=14818其实里面实际的音频切换点没有几个,但是可以观察到波谷有二十来个左右,所以这种方法一开始就被我们摒弃了,但是不无参考价值。
对于这个切换点我们给出了两种方案:
1:设定相应的步长,分块进行声纹识别,得出说话人队列。
2:说话人日志(Speaker Diarization):基于深度学习的说话人日志,通过深度学习的方法,从训练数据中学习语音和说话人的特征,从而实现说话人“谁在什么时候说话”的目标。
2.2 嘉宾识别 = 人脸识别 & 声纹识别
2.2.1 人脸识别
对于人脸识别这方面,现在技术上已经做的很发达了。比如说图书馆和宿舍用的人脸识别系统:可以说秒识别了。而且识别准确率特别高。
我们在这里先假设我们的人脸识别准确率可以达到90%以上,实际上我们也达到了90%以上。但是在这里我们假设人脸识别是成功的,是可移植的。如果说分帧做好了的话,对于人脸识别的话我们就可以在一段视频中取多帧图片,对其进行人脸识别,然后取匹配结果中的最匹配的那一项作为结果,成为那个片段的标签用来标记这个片段中是哪个嘉宾。
这样我们就可以将嘉宾识别出来。
具体的人脸识别是怎么样实现的之后会有详细的介绍。
2.2.2 声纹识别
对于声纹识别这方面,通过对市面上的调研,声纹识别的应用场景并没有人脸识别广泛。所以对于声纹识别这方面的实现来说,并不是一件简单的事情。
所以对于声纹识别这个部分,我们也像人脸识别一样假设,我们实现的声纹识别准确率可以达到90%以上,(实际上可能最高只有80%)。
通过上面介绍的两种找音频切换点的方案:这样也可以像人脸识别一样得到一项列表,也可以将嘉宾实现出来。
具体的声纹识别是怎么样实现的在之后会有所涉及。
三:实验环境
操作系统:Windows 10 pro
编译环境: Python 3.7.4 + Pychram 2019.3 + Jupyter Notebook
视频播放器:potplayer Mini
from pyaudio import PyAudio, paInt16
import numpy as np
from datetime import datetime
import wave
class recoder:
NUM_SAMPLES = 2000 #pyaudio内置缓冲大小
SAMPLING_RATE = 8000 #取样频率
LEVEL = 500 #声音保存的阈值
COUNT_NUM = 20 #NUM_SAMPLES个取样之内出现COUNT_NUM个大于LEVEL的取样则记录声音
SAVE_LENGTH = 8 #声音记录的最小长度:SAVE_LENGTH * NUM_SAMPLES 个取样
TIME_COUNT = 60 #录音时间,单位s
Voice_String = []
def savewav(self,filename):
wf = wave.open(filename, 'wb')
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(self.SAMPLING_RATE)
wf.writeframes(np.array(self.Voice_String).tostring())
# wf.writeframes(self.Voice_String.decode())
wf.close()
def recoder(self):
pa = PyAudio()
stream = pa.open(format=paInt16, channels=1, rate=self.SAMPLING_RATE, input=True,
frames_per_buffer=self.NUM_SAMPLES)
save_count = 0
save_buffer = []
time_count = self.TIME_COUNT
while True:
time_count -= 1
# print time_count
# 读入NUM_SAMPLES个取样
string_audio_data = stream.read(self.NUM_SAMPLES)
# 将读入的数据转换为数组
audio_data = np.fromstring(string_audio_data, dtype=np.short)
# 计算大于LEVEL的取样的个数
large_sample_count = np.sum( audio_data > self.LEVEL )
print(np.max(audio_data))
# 如果个数大于COUNT_NUM,则至少保存SAVE_LENGTH个块
if large_sample_count > self.COUNT_NUM:
save_count = self.SAVE_LENGTH
else:
save_count -= 1
if save_count < 0:
save_count = 0
if save_count > 0 :
# 将要保存的数据存放到save_buffer中
#print save_count > 0 and time_count >0
save_buffer.append( string_audio_data )
else:
#print save_buffer
# 将save_buffer中的数据写入WAV文件,WAV文件的文件名是保存的时刻
#print "debug"
if len(save_buffer) > 0 :
self.Voice_String = save_buffer
save_buffer = []
print("Recode a piece of voice successfully!")
return True
if time_count==0:
if len(save_buffer)>0:
self.Voice_String = save_buffer
save_buffer = []
print("Recode a piece of voice successfully!")
return True
else:
return False
if __name__ == "__main__":
r = recoder()
r.recoder()
r.savewav("test.wav")