使用shading='flat'时pcolormesh维度不匹配错误求助
解决matplotlib pcolormesh维度不匹配错误(audiosegment生成频谱图场景)
我在用audiosegment生成频谱图,通过matplotlib的pcolormesh绘图保存时,一直遇到维度不匹配的错误。我清楚pcolormesh要求C数组(即amplitudes)的维度要比X(times)和Y(freqs)数组小1,也尝试了扩展times和freqs数组,但报错依旧。
我的初始代码:
import os import shutil import audiosegment import numpy as np import matplotlib.pyplot as plt def spectrogram(file, output_dir): seg = audiosegment.from_file(file) freqs, times, amplitudes = seg.spectrogram(window_length_s=0.03, overlap=0.5) amplitudes = 10 * np.log10(amplitudes + 1e-9) times_new = np.resize(times, times.size + 1) freqs_new = np.resize(freqs, freqs.size + 1) print(len(times)) plt.figure(figsize=(10, 4)) plt.pcolormesh(times_new, freqs_new, amplitudes, shading='auto') plt.title("spectrogram " + file.split("/")[-1].split(".")[0]) plt.xlabel("Time [s]") plt.ylabel("Frequency [Hz]") plt.savefig(os.path.join(output_dir, "spectrogram_" + file.split("/")[-1].split(".")[0])) plt.clf() plt.close()
之后我尝试直接扩展数组:
times = np.append(times, times[-1] + (times[-1] - times[-2])) freqs = np.append(freqs, freqs[-1] + (freqs[-1] - freqs[-2])) ... plt.pcolormesh(times, freqs, amplitudes, shading='auto')
问题分析
np.resize的使用错误:它会重复原数组元素填充新长度,导致扩展后的times_new和freqs_new最后一个元素是原数组末尾的重复值,并非正确的边界值。- 需确认维度对应关系:audiosegment返回的
amplitudes维度是(freqs.size, times.size),所以扩展后的times长度必须是times.size + 1,freqs长度必须是freqs.size + 1,才能和amplitudes匹配。
正确解决方案
改用np.append添加正确的边界值,同时加入极端情况的容错处理:
import os import audiosegment import numpy as np import matplotlib.pyplot as plt def spectrogram(file, output_dir): seg = audiosegment.from_file(file) freqs, times, amplitudes = seg.spectrogram(window_length_s=0.03, overlap=0.5) amplitudes = 10 * np.log10(amplitudes + 1e-9) # 扩展时间轴:计算最后一个时间边界 if len(times) >= 2: time_step = times[-1] - times[-2] times_extended = np.append(times, times[-1] + time_step) else: times_extended = np.append(times, times[0] + 0.01) # 扩展频率轴:计算最后一个频率边界 if len(freqs) >= 2: freq_step = freqs[-1] - freqs[-2] freqs_extended = np.append(freqs, freqs[-1] + freq_step) else: freqs_extended = np.append(freqs, freqs[0] + 100) plt.figure(figsize=(10, 4)) plt.pcolormesh(times_extended, freqs_extended, amplitudes, shading='auto') plt.title(f"spectrogram {file.split('/')[-1].split('.')[0]}") plt.xlabel("Time [s]") plt.ylabel("Frequency [Hz]") plt.savefig(os.path.join(output_dir, f"spectrogram_{file.split('/')[-1].split('.')[0]}")) plt.close()
额外说明
shading='auto'在matplotlib 3.3+版本中会自动适配维度,但前提是X/Y数组长度确实比C数组对应维度大1。- 极端情况处理是为了避免音频过短时,
times或freqs仅含单个元素导致的索引错误。 - 用f-string替代字符串拼接,代码更简洁易读。
内容的提问来源于stack exchange,提问作者swaggerMan
相关产品推荐
相关产品推荐

