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();