Windows Algo SDK
The Algo SDK is a software development kit designed specifically for EVS devices. It provides algorithm features and a simple operating model, helping developers easily integrate each feature.
Environment setup
Make sure the following required components are installed in your development environment:
- Operating system: Windows 10 64-bit
- Compiler: a C/C++ compiler for your operating system
- Dependency libraries: make sure the necessary libraries are installed, plus OpenCV. We provide the OpenCV version matching the SDK; configure the environment variables yourself.
- Development tools: an IDE such as Visual Studio 2019
Recommendation: use fully English paths for development.
Algo module overview
The Algo library is divided into three main modules:
OpticalFlow
- Function: an EVS-based optical-flow implementation.
HandDetector
- Function: an EVS-based hand detector implementation.
HumanDetector
- Function: an EVS-based person detector implementation.
Algo directory layout
bin directory: contains all core libraries and their dependencies
docs directory: contains the interface documentation
include directory: contains the interface header files
lib directory: contains the .lib files for all development libraries
models directory: contains the trained-model data
samples_cpp directory: contains simple samples for operating the device; running the samples requires an OpenCV environment
Note: after compiling the samples, you must copy the models directory and the dynamic libraries under the bin directory to the same directory as the .exe executable.
1. OpticalFlow
This API is an EVS-based optical-flow implementation.
Of function
The Of function is the initialization constructor of the optical-flow class. Parameters:
Of(
uint16_t width,
uint16_t height,
uint8_t scale,
uint8_t search_radius,
uint8_t block_dimension);- width: the width of the EVS image.
- height: the height of the EVS image.
- scale: the EVS downsampling factor.
- search_radius: the optical-flow search radius; 4 is generally recommended.
- block_dimension: the image size used for the features involved in optical-flow computation; 21 is generally recommended — larger is more accurate but less efficient.
run function
The run function is the core function that runs the optical-flow algorithm. Parameters:
int run(
const cv::Mat& in_img,
cv::Mat& out_img,
uint8_t stack_nums = 1);- in_img: the EVS input image used to compute optical flow. Usually 0 means no event; 1 and 2 mean positive and negative events respectively.
- out_img: the computed optical-flow image, represented by the CV_8SC2 type. The two channels of each pixel represent the x and y optical-flow magnitudes, and the sign indicates direction.
- stack_nums: the number of EVS stacked frames, default 1 (no stacking); events are usually sparse and need stacking.
showOf function
The showOf function visualizes the optical-flow image produced by run as HVS-space arrows. Parameters:
int showOf(
cv::Mat& of_result,
cv::Mat& of_mask,
uint8_t ratio = 2,
uint8_t step = 2);- of_result: the optical-flow image computed by run.
- of_mask: the resulting optical-flow visualization of of_result.
- ratio: how many times to scale up the visualized optical-flow arrows.
- step: the sparse-sampling factor for the visualized optical-flow arrows.
Example
// 使用光流算法
#include <AlpOpticalFlow/Of.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <thread>
#include <ctime>
#include <regex>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
using namespace ALP;
/**
* @brief 用于存储和管理程序运行时所需的各种变量
*
* 该结构体包含处理 EVS 数据帧所需的成员变量,以及相关的线程和锁。
*/
struct SampleVar
{
// 保护 EVS 数据帧列表的互斥锁
std::mutex evs_mutex_;
// 标记是否关闭数据处理
bool is_close_ = false;
// 播放 EVS 数据的线程
std::unique_ptr<std::thread > evs_thread_;
// 是否开启 EVS 数据存储
bool is_evs_show_ = false;
// evs 图像的宽度
int evs_width_ = 768;
// evs 图像的高度
int evs_height_ = 608;
std::string evs_image_dir_ = "C:/Users/SMTPC-0430/Desktop/Pic/EVS_RAW";//D:/TestData/Human/20250115161806780/evs_raw
// 创建光流类
std::shared_ptr<Of> optical_flow_ = nullptr;
};
std::shared_ptr<SampleVar> var_ = std::make_shared<SampleVar>();
/*
* @brief readRawImage 采用二进制方式读取 .raw 文件,并将其转换为 cv::Mat,以 8-bit 灰度格式解析数据。
*
* 直接使用 cv::imread 读取 .raw 文件会失败,因为它不是标准图片格式。
*
*/
cv::Mat readRawImage(const std::string& filename, int width, int height)
{
std::ifstream file(filename, std::ios::binary);
if (!file) {
std::cerr << "ERROR: Cannot open file: " << filename << std::endl;
return cv::Mat();
}
cv::Mat image(height, width, CV_8UC1); // 8-bit 单通道灰度图
image *= 100;
file.read(reinterpret_cast<char*>(image.data), width * height);
if (file.gcount() != width * height) {
std::cerr << "WARNING: File size mismatch: " << filename << std::endl;
return cv::Mat();
}
return image;
}
/**
* @brief 显示 EVS 图像界面(本地文件版本)
*
* 该函数创建一个新的线程来处理和显示本地存储的EVS图像文件。
* 图像文件将按文件系统顺序循环读取,并计算/显示光流信息。
*/
void displayEVS()
{
var_->evs_thread_ = std::make_unique<std::thread>([&]()
{
var_->is_evs_show_ = true;
std::vector<std::string> image_files;
for (const auto& entry : fs::directory_iterator(var_->evs_image_dir_)) {
if (entry.path().extension() == ".raw") {
image_files.push_back(entry.path().string());
}
}
if (image_files.empty()) {
std::cerr << "ERROR: No image files found in " << var_->evs_image_dir_ << std::endl;
var_->is_evs_show_ = false;
return;
}
std::sort(image_files.begin(), image_files.end()); // 确保按顺序处理
size_t frame_index = 0;
const int frame_delay = 30;
while (!var_->is_close_) {
cv::Mat tem = readRawImage(image_files[frame_index], var_->evs_width_, var_->evs_height_);
if (tem.empty()) {
frame_index = (frame_index + 1) % image_files.size();
continue;
}
cv::Mat out;
if (!var_->optical_flow_->run(tem, out, 10)) {
cv::Mat of_mask;
var_->optical_flow_->showOf(out, of_mask, 10, 3);
cv::namedWindow("of", cv::WINDOW_FREERATIO);
cv::imshow("of", of_mask);
cv::waitKey(1);
}
frame_index = (frame_index + 1) % image_files.size();
std::this_thread::sleep_for(std::chrono::milliseconds(frame_delay));
}
var_->is_evs_show_ = false;
});
}
/**
* @brief 关闭设备
*
* 该函数用于关闭 Eiger 设备,停止所有数据流,并释放相关资源。
*/
void closeDevice()
{
// 等待 EVS 显示线程结束
if (var_->evs_thread_)
{
var_->evs_thread_->join();
var_->evs_thread_ = nullptr;
}
}
int main(int argc, char* argv[])
{
// 创建光流类
var_->optical_flow_ = std::make_shared<Of>(var_->evs_width_, var_->evs_height_, 6, 4, 31);
displayEVS();
closeDevice();
return 0;
}Effect

2. HandDetector
HandDetector function
This function constructs a HandDetector object with an initial hand-detector type. Parameters:
HandDetector(HandDetectorType type);- type: aps or evs Currently only supports HumanDetectorType::evs
detect function
Detects on the input image, then gets the result from boxes and landmarks. Parameters:
int detect ( const cv::Mat & image,
std::vector< cv::Rect > & boxes,
std::vector< std::vector< cv::Point2f > > & landmarks ) ;- image: input image
- boxes: the detected hand-box results
- landmarks: the hand keypoints
init function
Initialization function. Parameters:
int init(const std::string& device="cpu");- cpu" or "cuda", defalut is "cpu"
Example
#pragma execution_character_set("utf-8")
/**********************************************
* 此样例为播放保存的evs raw数据 *
***********************************************/
//手势检测
#include <ALPML/HandDetector/hand_detector.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <thread>
#include <ctime>
#include <regex>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
using namespace ALP;
/**
* @brief 用于存储和管理程序运行时所需的各种变量
*
* 该结构体包含处理 APS 和 EVS 数据帧所需的成员变量,以及相关的线程和锁。
*/
struct SampleVar
{
// 保护 EVS 数据帧列表的互斥锁
std::mutex evs_mutex_;
// 标记是否关闭数据处理
bool is_close_ = false;
// 播放 EVS 数据的线程
std::unique_ptr<std::thread > evs_thread_;
// 是否开启 EVS 数据存储
bool is_evs_show_ = false;
// evs 图像的宽度
int evs_width_ = 768;
// evs 图像的高度
int evs_height_ = 608;
// WriterFile类的智能指针
const int play_evs_ = 2;
// 创建手势检测
std::shared_ptr<HandDetector> detector_ = nullptr;
std::string evs_image_dir_ = "C:/Users/SMTPC-0430/Desktop/Pic/EVS_RAW";
};
std::shared_ptr<SampleVar> var_ = std::make_shared<SampleVar>();
/*
* @brief readRawImage 采用二进制方式读取 .raw 文件,并将其转换为 cv::Mat,以 8-bit 灰度格式解析数据。
*
* 直接使用 cv::imread 读取 .raw 文件会失败,因为它不是标准图片格式。
*
*/
cv::Mat readRawImage(const std::string& filename, int width, int height)
{
std::ifstream file(filename, std::ios::binary);
if (!file) {
std::cerr << "ERROR: Cannot open file: " << filename << std::endl;
return cv::Mat();
}
cv::Mat image(height, width, CV_8UC1); // 8-bit 单通道灰度图
image *= 100;
file.read(reinterpret_cast<char*>(image.data), width * height);
if (file.gcount() != width * height) {
std::cerr << "WARNING: File size mismatch: " << filename << std::endl;
return cv::Mat();
}
return image;
}
/**
* @brief 显示 EVS 图像界面
*
* 该函数创建一个新的线程来处理和显示 EVS 数据帧。
* 在这个线程中,会从 `var_->evs_frames_` 列表中获取最新的 EVS 数据帧,
* 并将其转换为 OpenCV 的 Mat 对象进行显示。
*/
void displayEVS()
{
// 创建一个新的线程来处理 EVS 数据帧的显示
var_->evs_thread_ = std::make_unique<std::thread>([&]()
{
// 开始存储EVS数据
var_->is_evs_show_ = true;
std::vector<std::string> image_files;
for (const auto& entry : fs::directory_iterator(var_->evs_image_dir_)) {
if (entry.path().extension() == ".raw") {
image_files.push_back(entry.path().string());
}
}
if (image_files.empty()) {
std::cerr << "ERROR: No image files found in " << var_->evs_image_dir_ << std::endl;
var_->is_evs_show_ = false;
return;
}
std::sort(image_files.begin(), image_files.end()); // 确保按顺序处理
size_t frame_index = 0;
const int frame_delay = 15;
// 主循环,持续处理 EVS 数据直到关闭标志被设置
while (!var_->is_close_)
{
// 获取互斥锁以保护 EVS 数据帧列表
std::unique_lock<std::mutex> locker(var_->evs_mutex_);
const cv::Mat tem = readRawImage(image_files[frame_index], var_->evs_width_, var_->evs_height_);
if (tem.empty()) {
frame_index = (frame_index + 1) % image_files.size();
continue;
}
if (var_->detector_) {
std::vector<cv::Rect> box;
std::vector<std::vector<cv::Point2f>> landmarks;
cv::Mat image = tem;
var_->detector_->detect(image, box, landmarks);
cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
image *= 100;
for (size_t i = 0; i < box.size(); i++) {
cv::rectangle(image, box[i], cv::Scalar(0, 0, 255), 2);
}
for (auto& landmark : landmarks) {
for (auto& point : landmark) {
cv::circle(image, point, 2, cv::Scalar(0, 0, 255), 2);
}
}
cv::imshow("image", image);
cv::waitKey(25);
}
frame_index = (frame_index + 1) % image_files.size();
}
// 停止存储EVS数据
var_->is_evs_show_ = false;
});
}
/**
* @brief 关闭设备
*
* 该函数用于关闭 Eiger 设备,停止所有数据流,并释放相关资源。
*/
void closeDevice()
{
// 等待 EVS 显示线程结束
if (var_->evs_thread_)
{
var_->evs_thread_->join();
var_->evs_thread_ = nullptr;
}
}
int main(int argc, char* argv[])
{
// 创建手势检测
var_->detector_ = std::make_shared<HandDetector>(HandDetectorType::evs);
var_->detector_->init("cpu");
// 启动显示 EVS 图像的线程
displayEVS();
closeDevice();
return 0;
}Effect

3. HumanDetector
HumanDetector function
This function constructs a HumanDetector object with an initial detector type. Parameters:
HumanDetector(HumanDetectorType type);- type: aps or evs Currently only supports HumanDetectorType::evs
detect function
Inputs the image to detect, then gets the result from the boxes. Parameters:
int detect(const cv::Mat& image, std::vector<cv::Rect>& boxes);- image: input image
- boxes: output detection boxes
init function
Initialization function. Parameters:
int init ( const std::string & device = "cpu" )- device type:"cpu" or "cuda", defalut is "cpu"
Example
#pragma execution_character_set("utf-8")
/**********************************************
* 此样例为播放保存的evs raw数据 *
***********************************************/
// 人形检测
#include <AlpML/HumanDetector/human_detector.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <thread>
#include <ctime>
#include <regex>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
using namespace ALP;
/**
* @brief 用于存储和管理程序运行时所需的各种变量
*
* 该结构体包含处理 APS 和 EVS 数据帧所需的成员变量,以及相关的线程和锁。
*/
struct SampleVar
{
// 保护 EVS 数据帧列表的互斥锁
std::mutex evs_mutex_;
// 标记是否关闭数据处理
bool is_close_ = false;
// 播放 EVS 数据的线程
std::unique_ptr<std::thread > evs_thread_;
// 是否开启 EVS 数据存储
bool is_evs_show_ = false;
// evs 图像的宽度
int evs_width_ = 768;
// evs 图像的高度
int evs_height_ = 608;
const int play_evs_ = 2;
std::string evs_image_dir_ = "C:/Users/SMTPC-0430/Desktop/Pic/human/EVS_RAW";//D:/TestData/Human/20250115161806780/evs_raw C:/Users/SMTPC-0430/Desktop/Pic/human/EVS_RAW
// 创建人形检测类
std::shared_ptr<ALP::HumanDetector> detector_ = nullptr;
};
std::shared_ptr<SampleVar> var_ = std::make_shared<SampleVar>();
/*
* @brief readRawImage 采用二进制方式读取 .raw 文件,并将其转换为 cv::Mat,以 8-bit 灰度格式解析数据。
*
* 直接使用 cv::imread 读取 .raw 文件会失败,因为它不是标准图片格式。
*
*/
cv::Mat readRawImage(const std::string& filename, int width, int height)
{
std::ifstream file(filename, std::ios::binary);
if (!file) {
std::cerr << "ERROR: Cannot open file: " << filename << std::endl;
return cv::Mat();
}
cv::Mat image(height, width, CV_8UC1); // 8-bit 单通道灰度图
image *= 100;
file.read(reinterpret_cast<char*>(image.data), width * height);
if (file.gcount() != width * height) {
std::cerr << "WARNING: File size mismatch: " << filename << std::endl;
return cv::Mat();
}
return image;
}
/**
* @brief 显示 EVS 图像界面
*
* 该函数创建一个新的线程来处理和显示 EVS 数据帧。
* 在这个线程中,会从 `var_->evs_frames_` 列表中获取最新的 EVS 数据帧,
* 并将其转换为 OpenCV 的 Mat 对象进行显示。
*/
void displayEVS()
{
// 创建一个新的线程来处理 EVS 数据帧的显示
var_->evs_thread_ = std::make_unique<std::thread>([&]()
{
// 开始存储EVS数据
var_->is_evs_show_ = true;
var_->is_evs_show_ = true;
std::vector<std::string> image_files;
for (const auto& entry : fs::directory_iterator(var_->evs_image_dir_)) {
if (entry.path().extension() == ".raw") {
image_files.push_back(entry.path().string());
}
}
if (image_files.empty()) {
std::cerr << "ERROR: No image files found in " << var_->evs_image_dir_ << std::endl;
var_->is_evs_show_ = false;
return;
}
std::sort(image_files.begin(), image_files.end()); // 确保按顺序处理
size_t frame_index = 0;
const int frame_delay = 15;
// 主循环,持续处理 EVS 数据直到关闭标志被设置
while (!var_->is_close_)
{
// 获取互斥锁以保护 EVS 数据帧列表
std::unique_lock<std::mutex> locker(var_->evs_mutex_);
const cv::Mat tem = readRawImage(image_files[frame_index], var_->evs_width_, var_->evs_height_);
if (tem.empty()) {
frame_index = (frame_index + 1) % image_files.size();
continue;
}
if (var_->detector_)
{
std::vector<cv::Rect> box;
cv::Mat image = tem;
var_->detector_->detect(image, box);
cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
image *= 100;
for (size_t i = 0; i < box.size(); i++)
{
cv::rectangle(image, box[i], cv::Scalar(0, 0, 255), 2);
}
cv::imshow("image", image);
cv::waitKey(25);
}
frame_index = (frame_index + 1) % image_files.size();
}
// 停止存储EVS数据
var_->is_evs_show_ = false;
});
}
/**
* @brief 关闭设备
*
* 该函数用于关闭 Eiger 设备,停止所有数据流,并释放相关资源。
*/
void closeDevice()
{
// 等待 EVS 显示线程结束
if (var_->evs_thread_)
{
var_->evs_thread_->join();
var_->evs_thread_ = nullptr;
}
}
int main(int argc, char* argv[])
{
// 创建手势检测
var_->detector_ = std::make_shared<HumanDetector>(HumanDetectorType::evs);
var_->detector_->init("cpu");
// 启动显示 EVS 图像的线程
displayEVS();
closeDevice();
return 0;
}Effect

