frame_sync.cpp
Go to the documentation of this file.
1 #include <chrono>
2 #include <iostream>
3 
4 // Includes common necessary includes for development using depthai library
5 #include "depthai/depthai.hpp"
6 
7 static constexpr auto FPS = 30;
8 
9 int main() {
10  dai::Pipeline pipeline;
11 
12  // Define a source - color camera
13  auto camRgb = pipeline.create<dai::node::ColorCamera>();
14  // Since we are saving RGB frames in Script node we need to make the
15  // video pool size larger, otherwise the pipeline will freeze because
16  // the ColorCamera won't be able to produce new video frames.
17  camRgb->setVideoNumFramesPool(10);
18  camRgb->setFps(FPS);
19 
20  auto left = pipeline.create<dai::node::MonoCamera>();
22  left->setCamera("left");
23  left->setFps(FPS);
24 
25  auto right = pipeline.create<dai::node::MonoCamera>();
27  right->setCamera("right");
28  right->setFps(FPS);
29 
30  auto stereo = pipeline.create<dai::node::StereoDepth>();
32  stereo->setLeftRightCheck(true);
33  stereo->setExtendedDisparity(false);
34  stereo->setSubpixel(false);
36  left->out.link(stereo->left);
37  right->out.link(stereo->right);
38 
39  // Script node will sync high-res frames
40  auto script = pipeline.create<dai::node::Script>();
41 
42  // Send both streams to the Script node so we can sync them
43  stereo->disparity.link(script->inputs["disp_in"]);
44  camRgb->video.link(script->inputs["rgb_in"]);
45 
46  script->setScript(R"(
47  FPS=30
48  import time
49  from datetime import timedelta
50  import math
51 
52  # Timestamp threshold (in miliseconds) under which frames will be considered synced.
53  # Lower number means frames will have less delay between them, which can potentially
54  # lead to dropped frames.
55  MS_THRESHOL=math.ceil(500 / FPS)
56 
57  def check_sync(queues, timestamp):
58  matching_frames = []
59  for name, list in queues.items(): # Go through each available stream
60  # node.warn(f"List {name}, len {str(len(list))}")
61  for i, msg in enumerate(list): # Go through each frame of this stream
62  time_diff = abs(msg.getTimestamp() - timestamp)
63  if time_diff <= timedelta(milliseconds=MS_THRESHOL): # If time diff is below threshold, this frame is considered in-sync
64  matching_frames.append(i) # Append the position of the synced frame, so we can later remove all older frames
65  break
66 
67  if len(matching_frames) == len(queues):
68  # We have all frames synced. Remove the excess ones
69  i = 0
70  for name, list in queues.items():
71  queues[name] = queues[name][matching_frames[i]:] # Remove older (excess) frames
72  i+=1
73  return True
74  else:
75  return False # We don't have synced frames yet
76 
77  names = ['disp', 'rgb']
78  frames = dict() # Dict where we store all received frames
79  for name in names:
80  frames[name] = []
81 
82  while True:
83  for name in names:
84  f = node.io[name+"_in"].tryGet()
85  if f is not None:
86  frames[name].append(f) # Save received frame
87 
88  if check_sync(frames, f.getTimestamp()): # Check if we have any synced frames
89  # Frames synced!
90  node.info(f"Synced frame!")
91  for name, list in frames.items():
92  syncedF = list.pop(0) # We have removed older (excess) frames, so at positions 0 in dict we have synced frames
93  node.info(f"{name}, ts: {str(syncedF.getTimestamp())}, seq {str(syncedF.getSequenceNum())}")
94  node.io[name+'_out'].send(syncedF) # Send synced frames to the host
95 
96 
97  time.sleep(0.001) # Avoid lazy looping
98  )");
99 
100  std::vector<std::string> scriptOut{"disp", "rgb"};
101  // Create XLinkOut for disp/rgb streams
102  for(auto& name : scriptOut) {
103  auto xout = pipeline.create<dai::node::XLinkOut>();
104  xout->setStreamName(name);
105  script->outputs[name + "_out"].link(xout->input);
106  }
107 
108  dai::Device device(pipeline);
109 
112  std::vector<std::string> names{"rgb", "disp"};
113  std::map<std::string, std::shared_ptr<dai::DataOutputQueue>> streams;
114  for(auto& name : names) {
115  streams[name] = device.getOutputQueue(name);
116  }
117  while(true) {
118  for(auto& iter : streams) {
119  auto name = iter.first;
120  auto queue = iter.second;
121  auto img = queue->get<dai::ImgFrame>();
122  // Display timestamp/sequence number of two synced frames
123  std::cout << "Stream " << name << ", timestamp: " << img->getTimestamp().time_since_epoch().count()
124  << ", sequence number: " << img->getSequenceNum() << std::endl;
125  }
126  }
127 }
dai::node::XLinkOut
XLinkOut node. Sends messages over XLink.
Definition: XLinkOut.hpp:14
dai::Pipeline
Represents the pipeline, set of nodes and connections between them.
Definition: Pipeline.hpp:100
dai::node::StereoDepth::initialConfig
StereoDepthConfig initialConfig
Definition: StereoDepth.hpp:52
dai::node::StereoDepth
StereoDepth node. Compute stereo disparity and depth from left-right image pair.
Definition: StereoDepth.hpp:15
dai::CameraBoardSocket::CAM_A
@ CAM_A
dai::node::MonoCamera
MonoCamera node. For use with grayscale sensors.
Definition: MonoCamera.hpp:17
dai::node::ColorCamera
ColorCamera node. For use with color sensors.
Definition: ColorCamera.hpp:16
dai::StereoDepthConfig::setExtendedDisparity
StereoDepthConfig & setExtendedDisparity(bool enable)
Definition: StereoDepthConfig.cpp:59
dai::DeviceBase::setLogLevel
void setLogLevel(LogLevel level)
Definition: DeviceBase.cpp:1196
dai::LogLevel::INFO
@ INFO
dai::StereoDepthConfig::setDepthAlign
StereoDepthConfig & setDepthAlign(AlgorithmControl::DepthAlign align)
Definition: StereoDepthConfig.cpp:13
dai::DeviceBase::setLogOutputLevel
void setLogOutputLevel(LogLevel level)
Definition: DeviceBase.cpp:1232
dai::ImgFrame::getTimestamp
std::chrono::time_point< std::chrono::steady_clock, std::chrono::steady_clock::duration > getTimestamp(CameraExposureOffset offset) const
Definition: pipeline/datatype/ImgFrame.cpp:20
dai::StereoDepthConfig::setLeftRightCheck
StereoDepthConfig & setLeftRightCheck(bool enable)
Definition: StereoDepthConfig.cpp:54
dai::Device::getOutputQueue
std::shared_ptr< DataOutputQueue > getOutputQueue(const std::string &name)
Definition: Device.cpp:86
dai::MonoCameraProperties::SensorResolution::THE_400_P
@ THE_400_P
dai::StereoDepthConfig::setSubpixel
StereoDepthConfig & setSubpixel(bool enable)
Definition: StereoDepthConfig.cpp:64
depthai.hpp
dai::node::Script::setScript
void setScript(const std::string &script, const std::string &name="")
Definition: Script.cpp:32
dai::Pipeline::create
std::shared_ptr< N > create()
Definition: Pipeline.hpp:145
dai::node::Script
Definition: Script.hpp:15
dai::node::MonoCamera::setResolution
void setResolution(Properties::SensorResolution resolution)
Set sensor resolution.
Definition: MonoCamera.cpp:82
dai::ImgFrame
Definition: ImgFrame.hpp:25
FPS
static constexpr auto FPS
Definition: frame_sync.cpp:7
dai::StereoDepthConfig::setMedianFilter
StereoDepthConfig & setMedianFilter(MedianFilter median)
Definition: StereoDepthConfig.cpp:27
dai::Device
Definition: Device.hpp:21
dai::node::ColorCamera::setVideoNumFramesPool
void setVideoNumFramesPool(int num)
Set number of frames in preview pool.
Definition: ColorCamera.cpp:526
dai::MedianFilter::KERNEL_7x7
@ KERNEL_7x7
dai::node::XLinkOut::setStreamName
void setStreamName(const std::string &name)
Definition: XLinkOut.cpp:13
main
int main()
Definition: frame_sync.cpp:9


depthai
Author(s): Martin Peterlin
autogenerated on Sat Mar 22 2025 02:58:19