目次
1. レコードバッグパッケージ
ここでは私のクラスメートのブログをお勧めします。T265 ros パッケージを記録し、いくつかの問題を解決するには、このブログを参照してください。
2. 左右の画像の分解
ここでは、まず録音パッケージの情報を確認し、次のコマンドを使用してパッケージ名を確認します。
rosbag info <包名>
次の 3 つの情報が見つかりました。
/fisheye1: 左目の画像に対応します
/fisheye2: 右の画像に対応します
/imu: imuに対応する情報
次のスクリプトを使用して、左右の画像を分割します。
import roslib import rosbag import rospy import cv2 from sensor_msgs.msg import Image from cv_bridge import CvBridge from cv_bridge import CvBridgeError path='/home/xxxx/Desktop/left/' class ImageCreator(): def __init__(self): self.bridge = CvBridge() with rosbag.Bag('/home/xxxx/Desktop/out.bag', 'r') as bag: for topic,msg,t in bag.read_messages(): if topic == "/fisheye1": try: cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8") except CvBridgeError as e: print e timestr = "%.6f" % msg.header.stamp.to_sec() image_name = timestr+ ".jpg" cv2.imwrite(path+image_name, cv_image) if __name__ == '__main__': try: image_creator = ImageCreator() except rospy.ROSInterruptException: pass
ここで、 path は画像を保存するパス、 topic は画像に対応するカメラトピック (/fisheye1、/fisheye2) です。%.6f は、小数点以下の桁数を保持するためのものですが、状況に応じて異なります。
スクリプトを実行して、左と右の画像を取得します。
3. IMUデータを削除する
IMU データは、タイムスタンプ、3 つの加速度情報、3 つの角速度情報に分割されます。
次のスクリプトを実行することで、それを分離して csv ファイルを形成できます。
import rosbag import csv from sensor_msgs.msg import Imu bag = rosbag.Bag('/home/xxxx/Desktop/out.bag') csvfile = open('imu.csv', 'w') csvwriter = csv.writer(csvfile) csvwriter.writerow(['timestamp', 'ax', 'ay', 'az', 'wx', 'wy', 'wz']) for topic, msg, t in bag.read_messages(topics=['/imu']): timestamp = msg.header.stamp.to_nsec() ax = msg.linear_acceleration.x ay = msg.linear_acceleration.y az = msg.linear_acceleration.z wx = msg.angular_velocity.x wy = msg.angular_velocity.y wz = msg.angular_velocity.z csvwriter.writerow([timestamp, ax, ay, az, wx, wy, wz]) bag.close() csvfile.close()
スクリプトを実行すると、次の csv ファイルが得られました。
4.eruoc および tum データセットの作成方法
4.1 eruoc データセット形式
写真形式:
まず、左右の画像のタイムスタンプを揃えます。どちらも19ビットです。
その中には、タイムスタンプと画像の関係を保存するファイル data.csv がありますが、これらは実際には同じです。
これはIMUのデータです。
4.2 タイムスタンプの調整
記録されたパケットのタイムスタンプが揃っていないことがわかり、それらを揃える必要があります。
位置合わせの原理: 主に左目画像に両眼画像を使用するため、右目画像を左目画像のタイムスタンプと位置合わせすることで、画像の損失率を最小限に抑えることができます。 IMU。
import os import os import shutil folder1_path = "/home/liuhongwei/Desktop/left" folder2_path = "/home/liuhongwei/Desktop/right" output_folder_path = "/home/liuhongwei/Desktop/righti" folder1_files = sorted(os.listdir(folder1_path)) folder2_files = sorted(os.listdir(folder2_path)) if len(folder1_files) != len(folder2_files): print("no") else: for i in range(len(folder2_files)): source_path = os.path.join(folder2_path, folder2_files[i]) target_path = os.path.join(output_folder_path, folder1_files[i]) shutil.copyfile(source_path, target_path) print("yes")
スクリプトを実行した後、位置が調整されたことがわかりました: (注意: 両眼画像が異なる場合があります。このスクリプトを実行する前に、右目の画像を削除するか、左目の画像で埋める必要があります)
4.3 imu.csv ファイルの書き込み
import rosbag import csv from sensor_msgs.msg import Imu bag = rosbag.Bag('bag包的地址') csvfile = open('imu1.csv', 'w') csvwriter = csv.writer(csvfile) csvwriter.writerow(['timestamp [ns]', 'w_RS_S_x [rad s^-1]', 'w_RS_S_y [rad s^-1]', 'w_RS_S_z [rad s^-1]', 'a_RS_S_x [rad m s^-2]', 'a_RS_S_y [rad m s^-2]', 'a_RS_S_z [rad m s^-2]']) for topic, msg, t in bag.read_messages(topics=['/imu']): timestamp = msg.header.stamp.to_nsec() ax = msg.linear_acceleration.x ay = msg.linear_acceleration.y az = msg.linear_acceleration.z wx = msg.angular_velocity.x wy = msg.angular_velocity.y wz = msg.angular_velocity.z csvwriter.writerow([timestamp, wx, wy, wz, ax, ay, az]) bag.close() csvfile.close()
スクリプトを実行すると、csv ファイルが生成されました。それをチェックしよう:
これまでに、IMU ファイルも生成されました。
tum データセットでは、txt 形式に変換する必要があります。次のスクリプトを実行して、csv で保存された IMU 情報を txt 形式に変換します。
import csv def csv_to_txt(csv_file, txt_file): with open(csv_file, 'r') as file: reader = csv.reader(file) with open(txt_file, 'w') as output_file: writer = csv.writer(output_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) for row in reader: writer.writerow(row) csv_file = 'csv文件的地址' txt_file = '转换保存的txt文件地址' csv_to_txt(csv_file, txt_file)
スクリプトを実行すると、IMU 情報を保存する csv ファイルが txt ファイル形式 (TUM データセット形式) で保存されていることがわかります。
4.4 インデックスファイルの生成
次のスクリプト ファイルを使用して、画像のインデックス ファイルを生成します。
import os import csv def create_image_csv(folder_path, csv_file_path): with open(csv_file_path, 'wb') as csvfile: writer = csv.writer(csvfile) writer.writerow(['TimeStamp', 'Image Name']) for filename in os.listdir(folder_path): if filename.endswith('.jpg') or filename.endswith('.png'): image_name = os.path.splitext(filename)[0] writer.writerow([image_name, filename]) folder_path = '/home/liuhongwei/Desktop/right' csv_file_path = '/home/liuhongwei/Desktop/right.csv' create_image_csv(folder_path, csv_file_path)
図に示すように、生成が完了すると、左右の項目とそのインデックス ファイルに対応するタイムスタンプが次のようになります。
この時点で、ファイルが生成されます。実行した内容を euroc データセットの形式にパッケージ化できます。
TUM データセットの場合、画像のタイムスタンプ ファイルを生成する必要があります。次のスクリプトを使用して、画像シーケンスと対応するタイムスタンプ ファイルを生成します。
import roslib import rosbag import rospy import cv2 from sensor_msgs.msg import Image from cv_bridge import CvBridge from cv_bridge import CvBridgeError path = '要保存的图像序列地址' txt_file = '时间戳文件的地址(自动创建)' # Path to the text file class ImageCreator(): def __init__(self): self.bridge = CvBridge() image_names = [] # List to store image names with rosbag.Bag('录制的bag包地址', 'r') as bag: for topic, msg, t in bag.read_messages(): if topic == "/fisheye1": try: cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8") except CvBridgeError as e: print(e) continue timestr = "%.9f" % msg.header.stamp.to_sec() image_name = timestr.replace('.', '') # Remove periods from the timestamp cv2.imwrite(path + image_name + '.png', cv_image) # Save as PNG format image_names.append(image_name) # Add image name to the list # Save image names to the text file with open(txt_file, 'w') as f: f.write('\n'.join(image_names)) if __name__ == '__main__': try: image_creator = ImageCreator() except rospy.ROSInterruptException: pass
tum データセットに必要なタイムスタンプ情報が生成されたことがわかります。
4. スクリプトによって解凍が完了します。
以下のスクリプトを実行すると、左右の画像を自動で分解し、IMUのcsv情報とtxt情報を自動生成し、タイムスタンプを合わせて、左画像のタイムスタンプを生成します。
# -*- coding: utf-8 -*- import rosbag import csv from sensor_msgs.msg import Imu import os import roslib import rospy import cv2 from sensor_msgs.msg import Image from cv_bridge import CvBridge from cv_bridge import CvBridgeError import shutil def CreateDIR(): folder_name = 'bag_tum' subfolders = ['left', 'righti'] if not os.path.exists(folder_name): os.makedirs(folder_name) # 在主文件夹下创建子文件夹 for subfolder in subfolders: subfolder_path = os.path.join(folder_name, subfolder) if not os.path.exists(subfolder_path): os.makedirs(subfolder_path) def CreateIMUCSV(umpackbag): csvfile = open('imudata.csv', 'w') csvwriter = csv.writer(csvfile) csvwriter.writerow(['timestamp [ns]', 'w_RS_S_x [rad s^-1]', 'w_RS_S_y [rad s^-1]', 'w_RS_S_z [rad s^-1]', 'a_RS_S_x [rad m s^-2]', 'a_RS_S_y [rad m s^-2]', 'a_RS_S_z [rad m s^-2]']) for topic, msg, t in umpackbag.read_messages(topics=['/imu']): timestamp = msg.header.stamp.to_nsec() ax = msg.linear_acceleration.x ay = msg.linear_acceleration.y az = msg.linear_acceleration.z wx = msg.angular_velocity.x wy = msg.angular_velocity.y wz = msg.angular_velocity.z csvwriter.writerow([timestamp, wx, wy, wz, ax, ay, az]) #umpackbag.close() csvfile.close() def TransIMUdatatotxt(): csv_file = './imudata.csv' txt_file = './imudata.txt' with open(csv_file, 'r') as file: reader = csv.reader(file) with open(txt_file, 'w') as output_file: writer = csv.writer(output_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) for i, row in enumerate(reader): if i == 0: writer.writerow(['#' + cell for cell in row]) # 添加#号 else: writer.writerow(row) def SaveImageFishereyeleft(umpackbag): path = './bag_tum//left/' txt_file = './timestamp.txt' bridge = CvBridge() image_names = [] with rosbag.Bag(bagname, 'r') as bag: for topic, msg, t in umpackbag.read_messages(): if topic == "/fisheye1": try: cv_image = bridge.imgmsg_to_cv2(msg, "bgr8") except CvBridgeError as e: print(e) continue timestr = "%.9f" % msg.header.stamp.to_sec() image_name = timestr.replace('.', '') # Remove periods from the timestamp cv2.imwrite(path + image_name + '.png', cv_image) # Save as PNG format image_names.append(image_name) # Add image name to the list with open(txt_file, 'w') as f: f.write('\n'.join(image_names)) def SaveImageFishereyeright(umpackbag): path = './bag_tum//righti/' bridge = CvBridge() image_names = [] with rosbag.Bag(bagname, 'r') as bag: for topic, msg, t in umpackbag.read_messages(): if topic == "/fisheye2": try: cv_image = bridge.imgmsg_to_cv2(msg, "bgr8") except CvBridgeError as e: print(e) continue timestr = "%.9f" % msg.header.stamp.to_sec() image_name = timestr.replace('.', '') # Remove periods from the timestamp cv2.imwrite(path + image_name + '.png', cv_image) # Save as PNG format image_names.append(image_name) # Add image name to the list def dealwithTimeStamp(): folder1_path = './bag_tum//left/' folder2_path = './bag_tum//right/' output_folder_path = './bag_tum//righti/' folder1_files = sorted(os.listdir(folder1_path)) folder2_files = sorted(os.listdir(folder2_path)) if len(folder1_files) != len(folder2_files): print("录制包时左右目图像数量不一致,请手动处理") else: for i in range(len(folder2_files)): source_path = os.path.join(folder2_path, folder2_files[i]) target_path = os.path.join(output_folder_path, folder1_files[i]) shutil.copyfile(source_path, target_path) print("图像序列生成完毕") if os.path.exists(folder2_path): shutil.rmtree(folder2_path) # Press the green button in the gutter to run the script. if __name__ == '__main__': bagname = './road.bag' umpackbag = rosbag.Bag(bagname) CreateDIR() CreateIMUCSV(umpackbag) TransIMUdatatotxt() SaveImageFishereyeleft(umpackbag) SaveImageFishereyeright(umpackbag) dealwithTimeStamp()
以下のスクリプトを実行すると、TUMデータセットとEUROCデータセットに必要なファイル情報がスクリプトの同名フォルダ配下に生成されます。