17890浏览
查看: 17890|回复: 13

[M10项目] 行空板——“AI助听器”

[复制链接]
本帖最后由 云天 于 2023-2-22 22:46 编辑

【项目背景】
行空板——“AI助听器”图1


行空板——“AI助听器”图3

让“聋人”看到声音!
世界上有各种各样的残障人士,这些人或不能说话,或听不见声音。聋人,是听力因先天遗传或后天人为因素而受损的残疾人,也叫听力障碍者,简称听障人。根据最近的全国人口普查统计,全中国大约有2700多万听障人,包括弱听、重听、老化聋等。因为各种不方便让其在这个世界上生活极为不方便。
比如有人敲门,水龙头忘关、孩子在卧室里啼哭,可是“听障人”他们听不见。
【项目设计】
利用人工智能,让模型学习各种声音,使用行空板采集声音,通过物联网将相应文字信息发送给Arduino主板在显示屏上显示并利用灯光提醒,并且利用micro:bit制作的手表进行文字、灯光加震动提醒,让“听障人”看见、感触到声音。
【项目改进】
上一版本使用波形图,本次学生项目作品使用“语谱图”,使训练出来的模型识别声音的种类和准确度更多更高。
行空板——“AI助听器”图2


【演示视频】

【音频信号】

声音以音频信号的形式表示,音频信号具有频率、带宽、分贝等参数,音频信号一般可表示为振幅和时间的函数。这些声音有多种格式,因此计算机可以对其进行读取和分析。例如:mp3 格式、WMA (Windows Media Audio) 格式、wav (Waveform Audio File) 格式。
【语谱图】

语谱图是二战时期发明的一种语音频谱图,一般是通过处理接收的时域信号得到频谱图。
语谱图是频谱分析视图,如果针对语音数据的话,叫语谱图。语谱图的横坐标是时间,纵坐标是频率,坐标点值为语音数据能量。由于是采用二维平面表达三维信息,所以能量值的大小是通过颜色来表示的,颜色深,表示该点的语音能量越强。
语音的时域分析和频域分析是语音分析的两种重要方法,但是都存在着局限性。时域分析对语音信号的频率特性没有直观的了解,频域特性中又没有语音信号随时间的变化关系。而语谱图综合了时域和频域的优点,明显的显示出了语音频谱随时间的变化情况、语谱图的横轴为时间,纵轴为频率,任意给定频率成分在给定时刻的强弱用颜色深浅来表示。颜色深的,频谱值大,颜色浅的,频谱值小。语谱图上不同的黑白程度形成不同的纹路,称之为声纹,不同讲话者的声纹是不一样的,可用作声纹识别。


【录制音频】

使用pyaudio库这个可以进行录音,生成wav文件。PyAudio 提供了 PortAudio 的 Python 语言版本,这是一个跨平台的音频 I/O 库,使用 PyAudio 你可以在 Python 程序中播放和录制音频。为PoTaTudio提供Python绑定,跨平台音频I/O库。使用PyAudio,您可以轻松地使用Python在各种平台上播放和录制音频。
测试程序,使用pyaudio录制5秒声音文件“output.wav”:
  1. import pyaudio
  2. import wave
  3. CHUNK = 1024
  4. FORMAT = pyaudio.paInt16
  5. CHANNELS = 2
  6. RATE = 44100
  7. RECORD_SECONDS = 5
  8. WAVE_OUTPUT_FILENAME = "output.wav"
  9. p = pyaudio.PyAudio()
  10. stream = p.open(format=FORMAT,
  11.                 channels=CHANNELS,
  12.                 rate=RATE,
  13.                 input=True,
  14.                 frames_per_buffer=CHUNK)
  15. print("* recording")
  16. frames = []
  17. for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
  18.     data = stream.read(CHUNK)
  19.     frames.append(data)
  20. print("* done recording")
  21. stream.stop_stream()
  22. stream.close()
  23. p.terminate()
  24. wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
  25. wf.setnchannels(CHANNELS)
  26. wf.setsampwidth(p.get_sample_size(FORMAT))
  27. wf.setframerate(RATE)
  28. wf.writeframes(b''.join(frames))
  29. wf.close()
复制代码
【批量生成语谱图】

行空板——“AI助听器”图11


行空板——“AI助听器”图10


行空板——“AI助听器”图4


行空板——“AI助听器”图5


使用Librosa库批量生成各类声音的语谱图,如敲门声、水龙头流水声、婴儿啼哭声、警报声等。
Librosa是一个用于音频、音乐分析、处理的python工具包,一些常见的时频处理、特征提取、绘制声音图形等功能应有尽有,功能十分强大。
Librosa语音频谱图
  1. librosa.display.specshow(data, x_axis=None, y_axis=None, sr=22050, hop_length=512)
复制代码

参数:
data:要显示的矩阵
sr :采样率
hop_length :帧移
x_axis 、y_axis :x和y轴的范围
频率类型
‘linear’,‘fft’,‘hz’:频率范围由 FFT 窗口和采样率确定
‘log’:频谱以对数刻度显示
‘mel’:频率由mel标度决定
时间类型
time:标记以毫秒,秒,分钟或小时显示。值以秒为单位绘制。
s:标记显示为秒。
ms:标记以毫秒为单位显示。
所有频率类型均以Hz为单位绘制

  1. #加载模块:
  2. import pyaudio
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. from tqdm import tqdm
  6. from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
  7. import librosa.display
  8. import pandas as pd
  9. import librosa
  10. def record_audio(record_second):
  11.     global wave
  12.     CHUNK = 1024
  13.     FORMAT = pyaudio.paInt16
  14.     CHANNELS = 1
  15.     RATE = 44100
  16.   
  17.     p = pyaudio.PyAudio()
  18.     stream = p.open(format=FORMAT,
  19.                     channels=CHANNELS,
  20.                     rate=RATE,
  21.                     input=True,
  22.                     frames_per_buffer=CHUNK)
  23.     audio_data = []
  24.     print("* recording")
  25.     for i in tqdm(range(0, int(RATE / CHUNK * record_second))):
  26.         data = stream.read(CHUNK)
  27.         audio_data.append(data)
  28.     audio_samples = librosa.core.samples_to_frames(
  29.         np.frombuffer(b''.join(audio_data), dtype=np.int16),
  30.         CHANNELS,
  31.         hop_length=CHUNK
  32.         )
  33.     wave = audio_samples[5500:5500+int(1 * RATE)]/2**16
  34.     print("* done recording")
  35.     stream.stop_stream()
  36.     stream.close()
  37.     p.terminate()
  38. for i in range(50):
  39. #录制音频
  40.     record_audio(record_second=2)
  41. #加载音频:
  42.     window_size = 1024
  43.     window = np.hanning(window_size)
  44.     stft  = librosa.core.spectrum.stft(wave, n_fft=window_size, hop_length=512, window=window)
  45.     out = 2 * np.abs(stft) / np.sum(window)
  46. # For plotting headlessly
  47.     fig = plt.figure(figsize=(2.24, 2.24))
  48.     ax = fig.add_subplot(111)
  49.     ax.axes.xaxis.set_visible(False)
  50.     ax.axes.yaxis.set_visible(False)[indent]#生成语音频谱图
  51.     p = librosa.display.specshow(librosa.amplitude_to_db(out, ref=np.max), ax=ax, y_axis='log', x_axis='time')
  52.     fig.savefig('save'+str(i)+'.jpg')
复制代码
注:需在行空板程序所在目录建立相应文件夹,如“door”,生成图像后,拷贝到电脑,使用ML训练模型。

【硬件制作过程】
一、行空板主控
按钮接行空板引脚21(用于关闭提醒),LED灯接引脚22(用于亮灯提醒)。
行空板——“AI助听器”图7

行空板——“AI助听器”图6
二、“掌控板”手表
将震动马达接“掌控宝”的M2接口,并粘在表带上。当掌控板收到信息后,启动震动马达开始震动,提醒“听障人”查看屏幕提示信息。
行空板——“AI助听器”图8

行空板——“AI助听器”图9
【训练模型】
将图片上传到“英艻AI训练平台”进行模型训练。类型有[size=18.6667px]“background”[size=18.6667px]、“door”、“water”。
行空板——“AI助听器”图12

【电脑推理测试】
下载模型,放到程序相应目录下。
  1. #加载模块:
  2. import pyaudio
  3. #from unihiker import Audio
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. from PIL import Image, ImageOps #Install pillow instead of PIL
  7. from tqdm import tqdm
  8. from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
  9. import librosa.display
  10. import pandas as pd
  11. import librosa
  12. from keras.models import load_model
  13. # 禁用科学符号
  14. np.set_printoptions(suppress=True)
  15. #内容.config(text="加载模型")
  16. # 加载模型
  17. model = load_model('keras_model.h5', compile=False)
  18. # 加载标签
  19. class_names  = ['background','jianpan','desktop']
  20. #创建正确形状的数组以输入keras模型
  21. #可以放入阵列的图像的“长度”或数量为
  22. #由形状元组中的第一位置(在这种情况下为1)确定。
  23. data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)
  24. #录制声音函数
  25. def record_audio(record_second):
  26.     global wave
  27.     CHUNK = 1024
  28.     FORMAT = pyaudio.paInt16
  29.     CHANNELS = 1
  30.     RATE = 44100
  31.    
  32.     p = pyaudio.PyAudio()
  33.     stream = p.open(format=FORMAT,
  34.                     channels=CHANNELS,
  35.                     rate=RATE,
  36.                     input=True,
  37.                     frames_per_buffer=CHUNK)
  38.     audio_data = []
  39.     print("* recording")
  40.     for i in tqdm(range(0, int(RATE / CHUNK * record_second))):
  41.         data = stream.read(CHUNK)
  42.         audio_data.append(data)
  43.     audio_samples = librosa.core.samples_to_frames(
  44.         np.frombuffer(b''.join(audio_data), dtype=np.int16),
  45.         CHANNELS,
  46.         hop_length=CHUNK
  47.         )
  48.     wave = audio_samples[5500:5500+int(1 * RATE)]/2**16
  49.     print("* done recording")
  50.     stream.stop_stream()
  51.     stream.close()
  52.     p.terminate()
  53. while(True):
  54. [/indent][indent]   #录制音频
  55.     record_audio(record_second=2)
  56.     #加载音频保存语谱图
  57.    window_size = 1024
  58.     window = np.hanning(window_size)
  59.     stft  = librosa.core.spectrum.stft(wave, n_fft=window_size, hop_length=512, window=window)
  60.     out = 2 * np.abs(stft) / np.sum(window)
  61.     #绘制
  62.     fig = plt.figure(figsize=(2.24, 2.24))
  63.     ax = fig.add_subplot(111)[/indent][indent]   #不显示横纵坐标轴
  64.     ax.axes.xaxis.set_visible(False)
  65.     ax.axes.yaxis.set_visible(False)[/indent]   #生成语音频谱图保存
  66.     p = librosa.display.specshow(librosa.amplitude_to_db(out, ref=np.max), ax=ax, y_axis='log', x_axis='time')
  67.     fig.savefig('wave.jpg')
  68.    #打开语音频谱图
  69.     image = Image.open('wave.jpg').convert('RGB')
  70.     #将图像转换为numpy数组
  71.     image_array = np.asarray(image)
  72.     # 图像规格化
  73.     normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1
  74.     #将图像加载到数组中
  75.     data[0] = normalized_image_array
  76.     # 运行推断
  77.     prediction = model.predict(data)
  78.    
  79.     index = np.argmax(prediction)
  80.     #获取标签
  81.     class_name = class_names[index]
  82.     #获取置信度
  83.     confidence_score = prediction[0][index]
  84.     print('Class:', class_name)
  85.     print('Confidence score:', confidence_score)
复制代码


【行空板推理】
下载模型,放到行空板程序相应目录。
利用行空板板载麦克风采集声音,利用matplotlib变换成图片,使用keras加载训练好的模型“keras_model.h5”,进行预测出声音类型。点亮LED灯并通过物联网发送相关信息指令。
  1. #加载模块:
  2. from unihiker import GUI
  3. u_gui=GUI()
  4. 显示=u_gui.draw_text(text="智能提示器",x=0,y=100,font_size=35, color="#0000FF")
  5. 内容=u_gui.draw_text(text="加载库",x=20,y=180,font_size=35, color="#0000FF")
  6. from pinpong.extension.unihiker import *
  7. from pinpong.board import Board,Pin,NeoPixel
  8. import pyaudio
  9. #from unihiker import Audio
  10. import numpy as np
  11. import matplotlib.pyplot as plt
  12. from PIL import Image, ImageOps #Install pillow instead of PIL
  13. from tqdm import tqdm
  14. from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
  15. import librosa.display
  16. import pandas as pd
  17. import librosa
  18. from keras.models import load_model
  19. import siot
  20. Board().begin()
  21. p_p22_out=Pin(Pin.P22, Pin.OUT)
  22. p_p21_in=Pin(Pin.P21, Pin.IN)
  23. np1 = NeoPixel(p_p22_out,1)
  24. np1[0] = (0,0,0)
  25. # 禁用科学符号
  26. np.set_printoptions(suppress=True)
  27. #内容.config(text="加载模型")
  28. # 加载模型
  29. model = load_model('keras_model.h5', compile=False)
  30. # 加载标签
  31. class_names  = ['background','door','water']
  32. #创建正确形状的数组以输入keras模型
  33. #可以放入阵列的图像的“长度”或数量为
  34. #由形状元组中的第一位置(在这种情况下为1)确定。
  35. data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)
  36. 内容.config(text="连物联网")
  37. siot.init(client_id="",server="iot.dfrobot.com.cn",port=1883,user="X8jykxFnR",password="u8jskbFngz")
  38. siot.connect()
  39. siot.loop()
  40. def record_audio(record_second):
  41.     global wave
  42.     CHUNK = 1024
  43.     FORMAT = pyaudio.paInt16
  44.     CHANNELS = 1
  45.     RATE = 44100
  46.    
  47.     p = pyaudio.PyAudio()
  48.     stream = p.open(format=FORMAT,
  49.                     channels=CHANNELS,
  50.                     rate=RATE,
  51.                     input=True,
  52.                     frames_per_buffer=CHUNK)
  53.     audio_data = []
  54.     print("* recording")
  55.     for i in tqdm(range(0, int(RATE / CHUNK * record_second))):
  56.         data = stream.read(CHUNK)
  57.         audio_data.append(data)
  58.     audio_samples = librosa.core.samples_to_frames(
  59.         np.frombuffer(b''.join(audio_data), dtype=np.int16),
  60.         CHANNELS,
  61.         hop_length=CHUNK
  62.         )
  63.     wave = audio_samples[5500:5500+int(1 * RATE)]/2**16
  64.     print("* done recording")
  65.     stream.stop_stream()
  66.     stream.close()
  67.     p.terminate()
  68. while(True):
  69. if (p_p21_in.read_digital()==True):
  70.     siot.publish(topic="1DXAmWJ4g", data="S")
  71.     np1[0] = (0,0,0)
  72. else:
  73.     #录制音频
  74.     内容.config(text="录音中……")
  75.     record_audio(record_second=2)
  76.     内容.config(text="识别中……")
  77.     #加载音频:
  78.     window_size = 1024
  79.     window = np.hanning(window_size)
  80.     stft  = librosa.core.spectrum.stft(wave, n_fft=window_size, hop_length=512, window=window)
  81.     out = 2 * np.abs(stft) / np.sum(window)
  82.     # 绘制
  83.     fig = plt.figure(figsize=(2.24, 2.24))
  84.     ax = fig.add_subplot(111)
  85.     ax.axes.xaxis.set_visible(False)
  86.     ax.axes.yaxis.set_visible(False)
  87.     p = librosa.display.specshow(librosa.amplitude_to_db(out, ref=np.max), ax=ax, y_axis='log', x_axis='time')
  88.     fig.savefig('wave.jpg')
  89.    
  90.     image = Image.open('wave.jpg').convert('RGB')
  91.     #将图像转换为numpy数组
  92.     image_array = np.asarray(image)
  93.     # 规格化图像
  94.     normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1
  95.     # 将图像加载到数组中
  96.     data[0] = normalized_image_array
  97.     # 运行推断
  98.     prediction = model.predict(data)
  99.     index = np.argmax(prediction)
  100.     class_name = class_names[index]
  101.     confidence_score = prediction[0][index]
  102.     if class_name=='background':
  103.        siot.publish(topic="1DXAmWJ4g", data="B")
  104.        np1[0] = (0,0,0)
  105.        内容.config(text='背景音')
  106.     elif class_name=='door':
  107.        siot.publish(topic="1DXAmWJ4g", data="D")
  108.        np1[0] = (0,255,0)
  109.        内容.config(text='敲门')
  110.     elif class_name=='water':
  111.        siot.publish(topic="1DXAmWJ4g", data="W")
  112.        np1[0] = (0,0,255)
  113.        内容.config(text='流水')
  114.     print('Class:', class_name)
  115.     print('Confidence score:', confidence_score)
复制代码

【掌控板手表程序】
通过物联网接收行空板传来的指令,屏幕显示相应信息,板载LED灯循环闪烁,并驱动马达震动。

行空板——“AI助听器”图13


秦时明月爱侠岚  见习技师

发表于 2023-2-26 13:11:47

可以增加一个功能,将“听到”的语言,翻译成文字,手表上显示出来。
回复

使用道具 举报

云天  初级技神
 楼主|

发表于 2023-2-27 18:48:39

很好的建议
回复

使用道具 举报

腿毛利小五郎  初级技匠

发表于 2023-3-2 19:06:19

很好加油
回复

使用道具 举报

盐焗海盐  见习技师

发表于 2023-3-5 15:11:37

很有意义
回复

使用道具 举报

Mr-k  初级技匠

发表于 2023-3-6 20:43:24

厉害厉害
回复

使用道具 举报

eva-1991  学徒

发表于 2023-3-8 22:03:49

特别棒,向您学习,方便加一下您联系方式吗?想请您指点!我的QQ:249627570!
回复

使用道具 举报

eva-1991  学徒

发表于 2023-3-9 09:01:18

诚心向您学习,加了好友,烦请通过!
回复

使用道具 举报

三春牛-创客  初级技神

发表于 2023-3-28 16:38:57

厉害厉害
回复

使用道具 举报

三春牛-创客  初级技神

发表于 2023-3-28 16:40:48

回复

使用道具 举报

花生编程  中级技匠

发表于 2023-3-28 16:42:20

厉害厉害
回复

使用道具 举报

花生编程  中级技匠

发表于 2023-3-28 16:43:30

赞赞赞赞赞
回复

使用道具 举报

派大星ym  初级技匠

发表于 2023-8-22 00:01:16

酷酷酷酷酷酷酷酷
回复

使用道具 举报

派大星ym  初级技匠

发表于 2023-8-22 00:02:48

666666666666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail