Polarity Output
This sample shows how to read PolarityFrame output from DELTA raw data. It
uses a two-phase workflow: first save live sensor data as a .dvs file, then
reopen the saved file with playback and convert PolarityFrame output into
inspectable images and console statistics.
Back to Code Samples.
Example Overview
| Step | SDK API | Purpose |
|---|---|---|
| 1 | scanDevices() / openDevice() |
Find and open a connected DELTA Series camera. |
| 2 | applySensorSetting() |
Apply the recommended sensor setting file. |
| 3 | startStream() |
Start live USB streaming. |
| 4 | startRawSaving() / saveRawBy*() |
Save raw sensor data as a .dvs file. |
| 5 | openFile() / startPlayback() |
Reopen the saved .dvs file for offline conversion. |
| 6 | setFrameGeneration() |
Choose how events are grouped into generated frames. |
| 7 | setOutputType(OutputType::PolarityFrame) |
Generate polarity frame output. |
| 8 | getPolarityFrameBufferSize() |
Get the required polarity frame buffer size. |
| 9 | getPolarityFrame() |
Read per-pixel polarity values. |
| 10 | setReadOverCallback() |
Detect when playback reaches the end of the file. |
Expected Result
When the sample runs successfully, a polarity_frames folder is created under
the save directory. The folder contains the raw data captured during Phase 1,
and it can also contain saved polarity frame images when image saving is
enabled.
polarity_frames/
├─ raw_data/
| └─ year-month-day-hour-minute-second-DELTA.dvs
└─ polarity_0.bmp, polarity_1.bmp, ...
The raw_data folder stores the .dvs raw data file recorded from the camera.
The polarity_* images are created only when save_polarity_images is set to
true. The example uses bmp by default, but the image extension can be
changed with selected_imageformat.
During conversion, the sample opens the saved raw data file, reads
PolarityFrame output, and displays it as a grayscale image.
| Polarity Value | Meaning | Display Color |
|---|---|---|
0 |
ON event | White |
1 |
OFF event | Black |
-1 |
No event at that pixel | Gray |
The console also prints polarity statistics every statPrintInterval frames.
With the default setting, this is printed every 30 processed frames.
[Frame 30] ON: 12186 OFF: 11948 Active: 3.5%
[Frame 60] ON: 13326 OFF: 15063 Active: 4.1%
[Frame 90] ON: 13105 OFF: 17947 Active: 4.5%
[Frame 120] ON: 14357 OFF: 19187 Active: 4.9%
[Frame 150] ON: 19579 OFF: 25215 Active: 6.5%
...
ON and OFF show how many pixels received each polarity in the current
frame. Active shows the percentage of pixels that received either an ON or
OFF event.
Note
PolarityFrame is not a normal brightness image. It stores the latest event
polarity state for each pixel in the generated frame. The displayed image is
a visualization of that polarity state, where ON events are white, OFF
events are black, and pixels without events are gray.
Code Walkthrough
Edit the User Control Panel
The USER CONTROL PANEL section controls camera selection, frame generation,
raw saving mode, statistics printing, optional image saving, and output
directories.
Select a Camera
const std::int32_t selectDeviceIndex = 0;
Select a Frame Generation Mode
const std::string selected_framemode = "FrameEndBased";
const std::int32_t frameEndCount = 1;
// const std::string selected_framemode = "TimeBased";
const std::int32_t framePeriodMs = 16;
// const std::string selected_framemode = "EventCountBased";
const std::int32_t eventsPerFrame = 50000;
Frame generation determines when a new PolarityFrame is produced during
offline conversion.
Select a Raw Saving Mode
const std::string selected_savemode = "Continuous";
// const std::string selected_savemode = "Time";
const std::int32_t durationMs = 5000;
// const std::string selected_savemode = "FrameCount";
const std::uint64_t targetFrames = 100;
// const std::string selected_savemode = "EventCount";
const std::uint64_t targetEvents = 1000000;
Continuous starts saving when you press s and stops when you press q.
Select Polarity Export Options
statPrintInterval controls how often ON/OFF statistics are printed.
const std::uint64_t statPrintInterval = 30;
Set save_polarity_images to true to save polarity frames as image files.
const bool save_polarity_images = false;
const std::string selected_imageformat = "bmp";
const std::uint64_t targetPolarityFrames = 500;
selected_imageformat is used as the output file extension. OpenCV selects the
encoder from that extension, so any OpenCV-supported image format can be used,
such as bmp, png, jpg, jpeg, tiff, or webp.
Select Output Directories
const std::filesystem::path rawSaveDirectory =
std::filesystem::path(DELTA_SAMPLE_ROOT) / "saved_data" / "polarity_frames" / "raw_data";
const std::filesystem::path imageSaveDirectory =
std::filesystem::path(DELTA_SAMPLE_ROOT) / "saved_data" / "polarity_frames";
Phase 1: Capture Raw Data
The example saves a .dvs file first so rendering and image encoding speed do
not affect live capture.
status = delta::startStream(cameraHandle);
status = delta::startRawSaving(cameraHandle, rawSaveDirectoryString.c_str());
Phase 2: Select PolarityFrame Output
The saved file is reopened with playback, and PolarityFrame is selected as
the only processing output.
status = delta::openFile(rawFileString.c_str(), &fileHandle);
status = delta::setPlaybackMode(fileHandle, delta::PlaybackMode::Once);
status = delta::setFrameGeneration(fileHandle, frameGeneration);
status = delta::setOutputType(fileHandle, delta::OutputType::PolarityFrame);
Prepare the Polarity Buffer
PolarityFrame uses one int8_t array with one value per pixel.
const std::uint32_t polBufferSize =
delta::getPolarityFrameBufferSize(fileHandle);
std::vector<std::int8_t> polBuffer(polBufferSize);
delta::PolarityFrame polFrame{};
polFrame.startAddress = polBuffer.data();
polFrame.bufferSize = polBufferSize;
| Value | Meaning | Display Color |
|---|---|---|
0 |
ON event | White |
1 |
OFF event | Black |
-1 |
No event | Gray |
Detect End of Playback
PlaybackMode::Once fires this callback once the file has been fully read. A
few more frames can still be in flight in the processing pipeline at that
point, so the sample keeps polling for a short grace period afterward instead
of stopping immediately.
std::atomic<bool> playbackDone{false};
status = delta::setReadOverCallback(
fileHandle,
[](void* userData) { static_cast<std::atomic<bool>*>(userData)->store(true); },
&playbackDone
);
Once playbackDone is set, the polling loop allows up to 100 consecutive
empty polls to drain any remaining frames before it stops. The loop also
checks for ESC so the sample can be stopped early.
constexpr int kDrainRetriesAfterEnd = 100;
int drainRetries = 0;
while (true) {
status = delta::getPolarityFrame(fileHandle, &polFrame, 0);
if (status != delta::Status::Success) {
if (playbackDone.load() && ++drainRetries >= kDrainRetriesAfterEnd) { break; }
if (cv::waitKey(1) == 27) { break; }
continue;
}
drainRetries = 0;
// ... render and display the frame ...
}
Read and Render PolarityFrame
The sample reads one polarity frame at a time and converts it to a grayscale OpenCV image.
status = delta::getPolarityFrame(fileHandle, &polFrame, 0);
cv::Mat polarityImg(h, w, CV_8UC1);
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
const std::int8_t p = polFrame.startAddress[y * w + x];
if (p == 0) {
polarityImg.at<std::uint8_t>(y, x) = 255;
}
else if (p == 1) {
polarityImg.at<std::uint8_t>(y, x) = 0;
}
else {
polarityImg.at<std::uint8_t>(y, x) = 128;
}
}
}
The sample can display the image, print ON/OFF statistics, and optionally save polarity images.
cv::imshow("Polarity Frame (ON=white, OFF=black, no event=gray)", polarityImg);
Stop Playback
delta::stopPlayback(fileHandle);
delta::closeFile(fileHandle);
cv::destroyAllWindows();