Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[audio_to_spectrogram] Enable publishing frequency vs amplitude plot #2654

Merged
merged 8 commits into from
Nov 19, 2022
18 changes: 18 additions & 0 deletions audio_to_spectrogram/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,21 @@ roslaunch audio_to_spectrogram sample_audio_to_spectrogram.launch
- `~publish_rate` (`Double`, default: `image_width / spectrogram_period`)

Publish rate [Hz] of spectrogram topic.

## spectrum_plot.py

A script to publish frequency vs amplitude plot image.

![](docs/images/spectrum.jpg)

- ### Publishing topics

- `~output/viz` (`sensor_msgs/Image`)

Frequency vs amplitude plot image.

- ### Subscribing topics

- `~spectrum` (`jsk_recognition_msgs/Spectrum`)

Spectrum data calculated from audio by FFT.
Binary file added audio_to_spectrogram/docs/images/spectrum.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 8 additions & 3 deletions audio_to_spectrogram/launch/audio_to_spectrogram.launch
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,15 @@
</rosparam>
</node>

<!-- publish frequency vs amplitude image -->
<node name="spectrum_plot"
pkg="audio_to_spectrogram" type="spectrum_plot.py" >
<remap from="~spectrum" to="/audio_to_spectrum/spectrum_filtered" />
</node>

<group if="$(arg gui)">
<!-- visualize spectrum -->
<node pkg="audio_to_spectrogram" type="spectrum_plot.py" name="spectrum_plot" >
<remap from="~spectrum" to="/audio_to_spectrum/spectrum_filtered" />
<node pkg="image_view" type="image_view" name="spectrum_view" >
<remap from="image" to="/spectrum_plot/output/viz" />
</node>

<!-- visualize spectrogram -->
Expand Down
1 change: 1 addition & 0 deletions audio_to_spectrogram/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<exec_depend>cv_bridge</exec_depend>
<exec_depend>image_view</exec_depend>
<exec_depend>jsk_recognition_msgs</exec_depend>
<exec_depend>jsk_topic_tools</exec_depend>
<exec_depend condition="$ROS_PYTHON_VERSION == 2">python-matplotlib</exec_depend>
<exec_depend condition="$ROS_PYTHON_VERSION == 3">python3-matplotlib</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
Expand Down
26 changes: 22 additions & 4 deletions audio_to_spectrogram/scripts/spectrum_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@

from __future__ import division

import cv_bridge
from jsk_topic_tools import ConnectionBasedTransport
import matplotlib.pyplot as plt
import numpy as np
import rospy
import sensor_msgs.msg

from jsk_recognition_msgs.msg import Spectrum

from audio_to_spectrogram import convert_matplotlib_to_img

class SpectrumPlot():

class SpectrumPlot(ConnectionBasedTransport):

def __init__(self):
super(SpectrumPlot, self).__init__()
# Set matplotlib config
self.fig = plt.figure(figsize=(8, 5))
self.fig.suptitle('Spectrum plot', size=12)
Expand All @@ -23,10 +29,17 @@ def __init__(self):
self.ax.set_xlabel('Frequency [Hz]', fontsize=12)
self.ax.set_ylabel('Amplitude', fontsize=12)
self.line, = self.ax.plot([0, 0], label='Amplitude of Spectrum')
# ROS subscriber
# ROS publisher and subscriber
self.pub_img = self.advertise(
'~output/viz', sensor_msgs.msg.Image, queue_size=1)

def subscribe(self):
self.sub_spectrum = rospy.Subscriber(
'~spectrum', Spectrum, self._cb, queue_size=1000)

def unsubscribe(self):
self.sub_spectrum.unregister()

def _cb(self, msg):
# Plot spectrum
self.amp = np.array(msg.amplitude)
Expand All @@ -35,10 +48,15 @@ def _cb(self, msg):
self.ax.set_xlim((self.freq.min(), self.freq.max()))
self.ax.set_ylim((0.0, 20))
self.ax.legend(loc='upper right')
if self.pub_img.get_num_connections() > 0:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good idea, thanks. I modified the code. 2e86235

bridge = cv_bridge.CvBridge()
img = convert_matplotlib_to_img(self.fig)
img_msg = bridge.cv2_to_imgmsg(img, encoding='rgb8')
img_msg.header = msg.header
self.pub_img.publish(img_msg)


if __name__ == '__main__':
rospy.init_node('spectrum_plot')
SpectrumPlot()
while not rospy.is_shutdown():
plt.pause(.1) # real-time plotting
rospy.spin()
2 changes: 2 additions & 0 deletions audio_to_spectrogram/src/audio_to_spectrogram/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .audio_buffer import AudioBuffer
from .convert_matplotlib import convert_matplotlib_to_img
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
try:
# for python2.x
from StringIO import StringIO as BufIO
except ModuleNotFoundError:
# for python3.x
from io import BytesIO as BufIO

import numpy as np
import PIL


def convert_matplotlib_to_img(fig):
buf = BufIO()
fig.savefig(buf, format="png")
buf.seek(0)
img = np.array(
PIL.Image.open(buf), dtype=np.uint8)
img = img[..., :3]
return img