简介与目的
我的毕设项目主要是关于用鸟的声音来判断鸟的种类。研究鸟类鸣声有利于人们掌握其繁殖行为和生活习性等生命活动规律,从而更好地开发和利用经济鸟类,更有效保护濒危珍稀类。同时,鸟鸣声在野生动物监测、农林渔业驱赶害鸟、航空鸟撞以及旅游等方面也具有十分广阔的前景。此外,鸣声的研究还能用来解决鸟类的分类学问题,如对同一种的不同类群及不同种的亲缘关系进行分析和比较,并探讨新种形成的种系发生历史。(鸟类鸣声初探_吕琳娜)
鸟声识别的难点主要在于:一,音频中干扰过多,比如风雨声和其他鸟类的声音等;二,鸟与鸟种类之间的鸣声差别极其微小,人耳尚不能分别,对于计算机来说就更加困难了。
我做这个项目主要是想要比较神经网络的各种参数对鸟声识别准确度的影响,并不仅仅着眼于提高准确度,而在于分析为什么准确度会随着参数而改变,试图发觉神经网络的“潜力”。
项目计划
我将课题分为两部分,音频处理和神经网络。音频处理主要负责1.统一数据格式,2.降噪,尽可能的将音频中的无关信息剔除,如设备产生的噪音和背景噪音等,将无鸟声的部分从音频中减掉,并分片,统计从网站上下载下来的音频时长,确定初步训练集的大小, 3.提取音频特征,将音频转换为最大程度保留鸟声特征的图像,如频谱图(spectrogram)等,人工分析估计图像的效果。
一.音频处理
- 收集数据
这里是我的数据来源: Xeno-canto.这是一个收集全球各地的鸟鸣声的网站,因为有提供api所以不需要爬虫。(数据是可以免费使用的)当然我还是写了一个菜的一批的脚本来下载文件,但太菜了我就不打在这儿了。
因为Xeno是外网,国外的鸟鸣声比较多,所以我选择全英国的鸟类作为研究范围。(如果有时间我来看看中国的)全英国的鸟鸣声大概三万多条。我首先下载了一千多条做实验,最后拿准确率最高的神经网络来对三万条做测试。
这里是音频较多且清晰度较高的20种鸟类:
鸟名 |
---|
Willow Warbler |
Common Chaffinch |
Great Tit |
Eurasian Blue Tit |
Common Blackbird |
Eurasian Tree Sparrow |
Corn Bunting |
Common Whitethroat |
Yellowhammer |
Common Chiffchaff |
Eurasian Wren |
Song Thrush |
European Robin |
Lesser Whitethroat |
Dunnock |
Eurasian Blackcap |
Barn Swallow |
Tawny Owl |
Common Cuckoo |
Little Owl |
-
统一格式
①音频格式
这里我在考虑用mp3还是WAV,因为从官网下载下来的数据就是mp3,mp3是有损压缩,即使转换成WAV也无济于事,而且WAV占据的内存要远大于mp3。所以我打算在画图表时转换成WAV画图,存储还是用mp3存。
②图表格式
频谱图(spectrogram)是一种很好的将声音转化为图像的方法。声音是波的一种,你可以想象声音的三重维度:频率,振幅和时间。
下图是一个人的语音的波形图,它显示了振幅随着时间的变化,但是我们却很难从中清晰地看出频率的变化。
在频谱图视图中,垂直轴以赫兹为单位显示频率,水平轴以时间为单位(就像波形图一样),振幅以亮度表示。黑色背景是寂静,而明亮的橙色曲线是正弦波在音调中向上移动。这使我们可以查看一个频率范围(最低的显示在底部,最高的显示在顶部)以及不同频率下的声音有多响。大声的事件将显示为明亮,而安静的事件将显示为黑暗。(此为正弦波)
它将声音的频率,振幅和时间直观地显示出来,方便我们之后通过图像处理对鸟类的鸣声进行分类。What is a spectrogram?在背景调查的过程中,我发现不少论文都通过梅尔频率倒谱系数(Mel Frequency Cepstrum Coefficient, MFCC)进行声音的特征提取,并取得不错的效果,计划之后有时间来研究一下。
统一之后的格式:
• 存储格式:MP3
• 频谱图输入:WAV
• Bit depth: 16-bits
• Sample rate: 48000Hz (至少质量为A的音频是这个sample rate)
• Audio Channels: Mono(单声道)
import wave
from pydub import AudioSegment
sound1 = AudioSegment.from_mp3("test.mp3")
sound1.export('test.wav',format='wav') #mp3取得参数较难,所以转换成wav
f=wave.open('test.wav','rb')
params=f.getparams()
#Returns a tuple (nchannels, sampwidth, framerate, nframes, comptype, compname), equivalent to output of the get*() methods.
nchannels,sampwidth,framerate,nframes=params[:4]
- 分片
步骤1:因为如果数据很大,神经网络就会很慢,而音频中没有鸟声音的段落占了整体的很大一部分,所以我决定根据基于声音间隙将声音切割为片段。
步骤2:将长短不一的音频分成10秒钟的片段,10秒钟包含了识别鸟类所需要的足够信息,之后会尝试将其分成5秒钟(似乎是一般鸟鸣叫的平均时长?)和1秒钟(这样的话这一秒钟之内不容易包含其他鸟类的声音)去做实验。但显而易见,先分成十秒钟还可以再分,但分短了就没法合起来啦。所以就分成十秒钟。
吐槽:我没有想到这一步花费了我无比长的时间,因为我没有进一步优化代码导致代码效率极低。执行步骤一的顺序如下:读取音频文件-确定切割时间-分段写入新的音频文件。问题在第三步,我的代码竟然是一帧一帧写的吗,巨慢……于是我把问题分成了两步。一:确定分割区间将其存储为.data文件;二:根据切割区间生成新的音频片段,亲身经历是:第一步跑了整整一天都没跑出来……这一步我是这么做的先算出一个“平均值”,然后响度在“平均值”以下的全部删除。因为删除是一帧一帧删除所以很慢。第二步在我不再一帧一帧写之后就变快了。不过还有问题……我是先按照鸟叫的声音(也就是删除无声的片段,然后按照间隙切割)切割,这样切完了之后就不一定是多长时间了,又长又短,长的可以切短,短的……感觉补全有点浪费(比如一秒钟补成五秒)不过暂时只能这样啦,这一步已经超级超时了! - 清洗
- 绘制频谱图