Initial commit to backup ANSLS

This commit is contained in:
2026-03-28 11:18:48 +11:00
commit 24dc6c7cd0
1018 changed files with 609226 additions and 0 deletions

44
.gitignore vendored Normal file
View File

@@ -0,0 +1,44 @@
# Build output directories
x64/
x86/
Debug/
Release/
out/
# CLion / CMake
.idea/
cmake-build-debug/
cmake-build-release/
cmake-build-*/
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
# Visual Studio
.vs/
*.user
*.suo
*.sdf
*.opensdf
*.VC.db
*.VC.opendb
ipch/
# Compiled files
*.obj
*.o
*.pch
*.pdb
*.ilk
*.exp
*.lib
*.dll
*.exe
# TortoiseGit
*.orig
# Windows
Thumbs.db
Desktop.ini

205
ANSLIB/ALL_BUILD.vcxproj Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<CustomBuild Include="C:\Projects\ANLS\CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,135 @@
#include "ANSANNHUB.h"
#include <iostream>
#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
std::vector<double> readCSVTo1DArray(const std::string& filename) {
std::vector<double> result;
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Error opening file: " << filename << std::endl;
return result;
}
std::string line;
while (std::getline(file, line)) {
std::stringstream ss(line);
std::string value;
while (std::getline(ss, value, ',')) {
try {
result.push_back(std::stod(value));
}
catch (const std::invalid_argument& e) {
std::cerr << "Invalid number: " << value << std::endl;
}
catch (const std::out_of_range& e) {
std::cerr << "Number out of range: " << value << std::endl;
}
}
}
file.close();
return result;
}
int IRISTest() {
ANSCENTER::ANNHUBAPI* annhubObject;
std::string annhubModelPath = "C:\\ProgramData\\ANSCENTER\\Shared\\annhubmodels\\IRIS_model.ann";
double originalInput[4];
originalInput[0] = 5.8;
originalInput[1] = 2.8;
originalInput[2] = 5.1;
originalInput[3] = 2.4;
double* outputHandle = nullptr;
for (int i = 0; i < 10; i++) {
CreateANNHUBHandle(&annhubObject, "", annhubModelPath.c_str());
auto start = std::chrono::high_resolution_clock::now(); // Start timing
ANNHUB_Inference(&annhubObject, originalInput, 4, &outputHandle);
auto end = std::chrono::high_resolution_clock::now(); // End timing
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); // Calculate elapsed time in milliseconds
printf("Output =[%f, %f, %f]\n", outputHandle[0], outputHandle[1], outputHandle[2]);
std::cout << "Time elapsed: " << elapsed.count() << " ms\n";
ReleaseANNHUBHandle(&annhubObject);
}
std::cout << "End of the application!\n";
}
int XORTest() {
ANSCENTER::ANNHUBAPI* annhubObject;
std::string annhubModelPath = "C:\\ProgramData\\ANSCENTER\\Shared\\annhubmodels\\XOR_model.ann";
double originalInput[2];
double* outputHandle = nullptr;
CreateANNHUBHandle(&annhubObject, "", annhubModelPath.c_str());
originalInput[0] = 0;
originalInput[1] = 0;
ANNHUB_Inference(&annhubObject, originalInput, 2, &outputHandle);
printf("Output =[%f]\n", outputHandle[0]);
originalInput[0] = 0;
originalInput[1] = 1;
ANNHUB_Inference(&annhubObject, originalInput, 2, &outputHandle);
printf("Output =[%f]\n", outputHandle[0]);
originalInput[0] = 1;
originalInput[1] = 0;
ANNHUB_Inference(&annhubObject, originalInput, 2, &outputHandle);
printf("Output =[%f]\n", outputHandle[0]);
originalInput[0] = 1;
originalInput[1] = 1;
ANNHUB_Inference(&annhubObject, originalInput, 2, &outputHandle);
printf("Output =[%f]\n", outputHandle[0]);
ReleaseANNHUBHandle(&annhubObject);
std::cout << "End of the application!\n";
}
int CustomerTest() {
ANSCENTER::ANNHUBAPI* annhubObject;
std::string filename = "C:\\Workstation\\CustomerSupport\\Michael\\ANNHUB\\test.txt";
std::vector<double> data = readCSVTo1DArray(filename);
std::string annhubModelPath = "C:\\Workstation\\CustomerSupport\\Michael\\ANNHUB\\CorrectTrainedModel_lv.ann";
double originalInput[1024] = { 0 }; // Initialize the array with zeros
double* outputHandle = nullptr;
// Copy data to originalInput array
std::copy(data.begin(), data.end(), originalInput);
int createHandle= CreateANNHUBHandle(&annhubObject, "", annhubModelPath.c_str());
printf("Created Handle =%d\n", createHandle);
ANNHUB_Inference(&annhubObject, originalInput, data.size(), &outputHandle);
printf("Output =[%f]\n", outputHandle[0]);
printf("Output =[%f]\n", outputHandle[1]);
ReleaseANNHUBHandle(&annhubObject);
std::cout << "End of the application!\n";
}
int main()
{
CustomerTest();
//XORTest();
//IRISTest();
return 0;
}

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{2098fb16-9144-44b3-90e2-e6cce1ce2762}</ProjectGuid>
<RootNamespace>ANNHUBUnitTest</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Projects\Research\CPlusLibraries;C:\Projects\ANLS\ANSLIB\ANNHUB;C:\Projects\ANLS\include;C:\Projects\ANLS\ANSLIB\ANSLicensingSystem;$(IncludePath)</IncludePath>
<LibraryPath>C:\Projects\Research\CPlusLibraries\LabVIEWHeader;C:\Projects\ANLS\ANSLIB\x64\Release;C:\Projects\ANLS\build\release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>labview-x86_64.lib;ANNHUB.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ANNHUB-UnitTest.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANNHUB-UnitTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{91e0d312-19de-4f70-a149-3c503d5af2bc}</ProjectGuid>
<RootNamespace>ANNHUB</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Projects\Research\CPlusLibraries;C:\Projects\ANLS\include;C:\Projects\ANLS\ANSLIB\ANSLicensingSystem;$(IncludePath)</IncludePath>
<LibraryPath>C:\Projects\Research\CPlusLibraries\LabVIEWHeader;C:\Projects\ANLS\ANSLIB\x64\Release;C:\Projects\ANLS\build\release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANNHUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANNHUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANNHUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANNHUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>labview-x86_64.lib;ANSLicensingSystem.lib;anslicensing.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSANNHUB.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSANNHUB.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSANNHUB.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSANNHUB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

670
ANSLIB/ANNHUB/ANSANNHUB.cpp Normal file
View File

@@ -0,0 +1,670 @@
#include "ANSANNHUB.h"
#include <cstdint>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <memory>
#include <numeric>
#include <sstream>
#include <unordered_map>
#include <condition_variable>
#include <mutex>
// --- Refcounted handle registry infrastructure ---
static std::unordered_map<ANSCENTER::ANNHUBAPI*, int>& ANNHUBHandleRegistry() {
static std::unordered_map<ANSCENTER::ANNHUBAPI*, int> s;
return s;
}
static std::mutex& ANNHUBHandleRegistryMutex() {
static std::mutex m;
return m;
}
static std::condition_variable& ANNHUBHandleRegistryCV() {
static std::condition_variable cv;
return cv;
}
static void RegisterANNHUBHandle(ANSCENTER::ANNHUBAPI* h) {
std::lock_guard<std::mutex> lk(ANNHUBHandleRegistryMutex());
ANNHUBHandleRegistry()[h] = 1;
}
static ANSCENTER::ANNHUBAPI* AcquireANNHUBHandle(ANSCENTER::ANNHUBAPI* h) {
std::lock_guard<std::mutex> lk(ANNHUBHandleRegistryMutex());
auto it = ANNHUBHandleRegistry().find(h);
if (it == ANNHUBHandleRegistry().end()) return nullptr;
it->second++;
return h;
}
static bool ReleaseANNHUBHandleRef(ANSCENTER::ANNHUBAPI* h) {
std::lock_guard<std::mutex> lk(ANNHUBHandleRegistryMutex());
auto it = ANNHUBHandleRegistry().find(h);
if (it == ANNHUBHandleRegistry().end()) return false;
it->second--;
if (it->second <= 0) {
ANNHUBHandleRegistry().erase(it);
ANNHUBHandleRegistryCV().notify_all();
return true;
}
ANNHUBHandleRegistryCV().notify_all();
return false;
}
static bool UnregisterANNHUBHandle(ANSCENTER::ANNHUBAPI* h) {
std::unique_lock<std::mutex> lk(ANNHUBHandleRegistryMutex());
auto it = ANNHUBHandleRegistry().find(h);
if (it == ANNHUBHandleRegistry().end()) return false;
it->second--;
if (!ANNHUBHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
auto it2 = ANNHUBHandleRegistry().find(h);
return it2 == ANNHUBHandleRegistry().end() || it2->second <= 0;
})) {
OutputDebugStringA("WARNING: UnregisterANNHUBHandle timed out after 30s waiting for refcount to reach zero.\n");
}
ANNHUBHandleRegistry().erase(h);
return true;
}
class ANNHUBHandleGuard {
ANSCENTER::ANNHUBAPI* engine;
public:
explicit ANNHUBHandleGuard(ANSCENTER::ANNHUBAPI* e) : engine(e) {}
~ANNHUBHandleGuard() { if (engine) ReleaseANNHUBHandleRef(engine); }
ANNHUBHandleGuard(const ANNHUBHandleGuard&) = delete;
ANNHUBHandleGuard& operator=(const ANNHUBHandleGuard&) = delete;
explicit operator bool() const { return engine != nullptr; }
ANSCENTER::ANNHUBAPI* get() const { return engine; }
};
// --- End handle registry infrastructure ---
static bool ansannhubLicenceValid = false;
// Global once_flag to protect license checking
static std::once_flag ansannhubLicenseOnceFlag;
namespace ANSCENTER {
void ReLu(std::vector<double>& iVal, std::vector<double>& oVal)
{
int dim = iVal.size();
oVal.resize(dim);
for (int i = 0; i < dim; i++)
{
if (iVal[i] >= 0) oVal[i] = iVal[i];
else oVal[i] = 0;
}
}
void LogSig(std::vector<double>& iVal, std::vector<double>& oVal)
{
int dim = iVal.size();
oVal.resize(dim);
for (int i = 0; i < dim; i++)
{
oVal[i] = 1 / (1 + exp(-iVal[i]));
}
}
void TanSig(std::vector<double>& iVal, std::vector<double>& oVal)
{
int dim = iVal.size();
oVal.resize(dim);
for (int i = 0; i < dim; i++)
{
oVal[i] = 2 / (1 + exp(-2 * iVal[i])) - 1;
}
}
void PureLin(std::vector<double>& iVal, std::vector<double>& oVal)
{
oVal = iVal;
}
void SoftMax(std::vector<double>& iVal, std::vector<double>& oVal)
{
double softmaxWeight = 0;
int dim = iVal.size();
oVal.resize(dim);
if (dim == 1) {
oVal[0] = 1 / (1 + exp(-iVal[0]));
}
else {
for (int i = 0; i < dim; i++) {
softmaxWeight = softmaxWeight + exp(iVal[i]);
}
for (int i = 0; i < dim; i++) {
oVal[i] = exp(iVal[i]) / softmaxWeight;
}
}
}
void ActivationFunction(std::vector<double>& iVal, std::vector<double>& oVal, int mode) {
switch (mode) {
case 0:
PureLin(iVal, oVal);
break;
case 1:
ReLu(iVal, oVal);
break;
case 2:
LogSig(iVal, oVal);
break;
case 3:
TanSig(iVal, oVal);
break;
case 4:
SoftMax(iVal, oVal);
break;
default:
TanSig(iVal, oVal);
break;
}
}
static void VerifyGlobalANSANNHUBLicense(const std::string& licenseKey) {
try {
ansannhubLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1000, "ANNHUB-LV");//Default productId=1000
}
catch (std::exception& e) {
//this->_logger.LogFatal("ANSOPENCV::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
}
}
void ANNHUBAPI::CheckLicense() {
//try {
// _licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1000, "ANNHUB-LV");//Default productId=1000
//}
//catch (std::exception& e) {
// //this->_logger.LogFatal("ANSOPENCV::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
//}
try {
// Check once globally
std::call_once(ansannhubLicenseOnceFlag, [this]() {
VerifyGlobalANSANNHUBLicense(_licenseKey);
});
// Update this instance's local license flag
_licenseValid = ansannhubLicenceValid;
}
catch (const std::exception& e) {
//this->_logger.LogFatal("ANNHUBAPI::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
}
}
ANNHUBAPI::ANNHUBAPI()
{
// Control creation
isCreated = 0;
// Structrural parameters
nInputNodes = 1;
nHiddenNodes = 10;
nOutputNodes = 1;
hiddenActivation = 2; // default =2
outputActivation = 2; // default =2;
dataNormalisationModeInput = 0;
dataNormalisationModeOutput = 0;
}
ANNHUBAPI::~ANNHUBAPI() noexcept
{
try {
Destroy();
}
catch (...) {}
}
void ANNHUBAPI::Destroy()
{
if (isCreated != 0) {
FreeNeuralNetwork();
}
}
void ANNHUBAPI::FreeNeuralNetwork()
{
try {
// Clear vectors
IW.clear();
LW.clear();
nInput.clear();
nOutput.clear();
Ib.clear();
Lb.clear();
xminInput.clear();
xmaxInput.clear();
xminOutput.clear();
xmaxOutput.clear();
// Reset the flag indicating whether the network is created
isCreated = 0;
}
catch (const std::exception& e) {
//this->_logger.LogFatal("ANNHUBAPI::FreeNeuralNetwork. Error:", e.what(), __FILE__, __LINE__);
}
}
/*
(x[i]-xmin[i]) (ymax-ymin)
x[i] = ---------------- * +ymin
(xmax[i]-xmin[i])
*/
void ANNHUBAPI::PreProcessing(std::vector<double>& Input)
{
switch (dataNormalisationModeInput) {
case 0: // linear
break;
case 1: // mapminmax
for (int i = 0; i < nInputNodes; i++) {
if (xmaxInput[i] != xminInput[i]) {
Input[i] = (Input[i] - xminInput[i]) * (ymaxInput - yminInput) / (xmaxInput[i] - xminInput[i]) + yminInput;
}
}
break;
default:// minmaxmap
for (int i = 0; i < nInputNodes; i++) {
if (xmaxInput[i] != xminInput[i]) {
Input[i] = (Input[i] - xminInput[i]) * (ymaxInput - yminInput) / (xmaxInput[i] - xminInput[i]) + yminInput;
}
}
break;
}
}
void ANNHUBAPI::PostProcessing(std::vector<double>& Output)
{
switch (dataNormalisationModeOutput) {
case 0: // linear
break;
case 1:
for (int i = 0; i < nOutputNodes; i++) {
if (ymaxOutput != yminOutput) {
Output[i] = (Output[i] - yminOutput) * (xmaxOutput[i] - xminOutput[i]) / (ymaxOutput - yminOutput) + xminOutput[i];
}
}
break;
default:
for (int i = 0; i < nOutputNodes; i++) {
if (ymaxOutput != yminOutput) {
Output[i] = (Output[i] - yminOutput) * (xmaxOutput[i] - xminOutput[i]) / (ymaxOutput - yminOutput) + xminOutput[i];
}
}
break;
}
}
int ANNHUBAPI::ImportANNFromFile(std::string filename)
{
try {
FILE* fp;
int err = fopen_s(&fp, filename.c_str(), "r"); // r: Opens for reading.
if (err != 0) return -2;
float value, randNum;
//0. Check if it the correct type for C language
fscanf_s(fp, "%f", &value);
if (static_cast<int>(value) != 1) return -1; // Assume that the type C is 0
//1. Load random number
fscanf_s(fp, "%f", &randNum);
//2. Structure (IDs)
int trainingEngine, hlAct, olAct, costFunct, prePro, postPro, evalModel;
fscanf_s(fp, "%f", &value); trainingEngine = static_cast<int>(value);
fscanf_s(fp, "%f", &value); hlAct = static_cast<int>(value);
fscanf_s(fp, "%f", &value); olAct = static_cast<int>(value);
fscanf_s(fp, "%f", &value); costFunct = static_cast<int>(value);
fscanf_s(fp, "%f", &value); prePro = static_cast<int>(value);
fscanf_s(fp, "%f", &value); postPro = static_cast<int>(value);
fscanf_s(fp, "%f", &value); evalModel = static_cast<int>(value);
//2.1 Activation function
hiddenActivation = hlAct - 10;
outputActivation = olAct - 10;
//2.2 Data Processing
dataNormalisationModeInput = prePro - 1000;
dataNormalisationModeOutput = postPro - 1000;
// 3. Load neural network structure and min max inputs value for pre-post processing
int ipNodes, hdNodes, opNodes;
fscanf_s(fp, "%f", &value); ipNodes = static_cast<int>(value);
fscanf_s(fp, "%f", &value); hdNodes = static_cast<int>(value);
fscanf_s(fp, "%f", &value); opNodes = static_cast<int>(value);
Create(ipNodes, hdNodes, opNodes);
// 4. Load Input-Hidden weights (extraction formula)
for (int j = 0; j < nInputNodes; j++)
{
for (int i = 0; i < nHiddenNodes; i++)
{
fscanf_s(fp, "%f", &value);
IW[i][j] = value - randNum;
}
}
// 4.1. Load bias Hidden weights
for (int i = 0; i < nHiddenNodes; i++)
{
fscanf_s(fp, "%f", &value);
Ib[i] = value - randNum;
}
// 4.2. Load Hidden_Output weights
for (int j = 0; j < nHiddenNodes; j++)
{
for (int i = 0; i < nOutputNodes ; i++)
{
fscanf_s(fp, "%f", &value);
LW[i][j] = value - randNum;
}
}
// 4.3. Load bias Output weights
for (int i = 0; i < nOutputNodes; i++)
{
fscanf_s(fp, "%f", &value);
Lb[i] = value - randNum;
}
// 5. For Pre-processing
if (dataNormalisationModeInput >= 0) {
// Range settings
fscanf_s(fp, "%f", &value);
yminInput = value - randNum;
fscanf_s(fp, "%f", &value);
ymaxInput = value - randNum;
// Min and max
for (int i = 0; i < nInputNodes; i++) {
fscanf_s(fp, "%f", &value);
xminInput[i] = value - randNum;
}
for (int i = 0; i < nInputNodes; i++) {
fscanf_s(fp, "%f", &value);
xmaxInput[i] = value - randNum;
}
}
// 6. For Post-processing
if (dataNormalisationModeOutput >= 0) {
// Range settings
fscanf_s(fp, "%f", &value);
yminOutput = value - randNum;
fscanf_s(fp, "%f", &value);
ymaxOutput = value - randNum;
for (int i = 0; i < nOutputNodes; i++) {
fscanf_s(fp, "%f", &value);
xminOutput[i] = value - randNum;
}
for (int i = 0; i < nOutputNodes; i++) {
fscanf_s(fp, "%f", &value);
xmaxOutput[i] = value - randNum;
}
}
fclose(fp);
return 0;
}
catch (std::exception& e) {
//this->_logger.LogFatal("ANNHUBAPI::ImportANNFromFile. Error:", e.what(), __FILE__, __LINE__);
return -1;
}
}
void ANNHUBAPI::Create(int inputNodes, int hiddenNodes, int outputNodes)
{
try {
if (isCreated != 0) {
FreeNeuralNetwork();
}
nInputNodes = inputNodes;
nHiddenNodes = hiddenNodes;
nOutputNodes = outputNodes;
nInput.resize(inputNodes);
nOutput.resize(outputNodes);
IW.resize(hiddenNodes, std::vector<double>(inputNodes));
LW.resize(outputNodes, std::vector<double>(hiddenNodes));
Ib.resize(hiddenNodes);
Lb.resize(outputNodes);
xminInput.resize(inputNodes);
xmaxInput.resize(inputNodes);
xminOutput.resize(outputNodes);
xmaxOutput.resize(outputNodes);
isCreated = 1;
}
catch (std::exception& e) {
//this->_logger.LogFatal("ANNHUBAPI::Create. Error:", e.what(), __FILE__, __LINE__);
}
}
bool ANNHUBAPI::Init(std::string licenseKey, std::string modelFilePath) {
try {
_licenseKey = licenseKey;
_modelFilePath = modelFilePath;
CheckLicense();
if (_licenseValid) {
int result = ImportANNFromFile(_modelFilePath);
if (result == 0) return true;
else return false;
}
else {
return false;
}
}
catch (std::exception& e) {
//this->_logger.LogFatal("ANNHUBAPI::Init. Error:", e.what(), __FILE__, __LINE__);
return false;
}
}
std::vector<double> ANNHUBAPI::Inference(std::vector<double> ip) {
try {
int i, j;
std::vector<double> a1(nHiddenNodes), n1(nHiddenNodes), n2(nOutputNodes);
if (!_licenseValid) return {}; // Invalid license
if (isCreated == 0) return {};
// Need to check the input size as well, return {} if it fails
PreProcessing(ip);
//1. Calculate n1
for (i = 0; i < nHiddenNodes; i++) {
n1[i] = 0;
for (j = 0; j < nInputNodes; j++)
{
if (std::isnan(IW[i][j]) || std::isnan(ip[j])) {
continue;
}
n1[i] = n1[i] + IW[i][j] * ip[j];
}
n1[i] = n1[i] + Ib[i];
}
ActivationFunction(n1, a1, hiddenActivation);
// 3. Calculate n2
for (i = 0; i < nOutputNodes; i++) {
n2[i] = 0;
for (j = 0; j < nHiddenNodes; j++) {
n2[i] = n2[i] + LW[i][j] * a1[j];
}
n2[i] = n2[i] + Lb[i];
}
ActivationFunction(n2, nOutput, outputActivation);
PostProcessing(nOutput);
return nOutput;
}
catch (std::exception& e) {
//this->_logger.LogFatal("ANNHUBAPI::Inference. Error:", e.what(), __FILE__, __LINE__);
return {};
}
}
}
extern "C" __declspec(dllexport) int CreateANNHUBHandle(ANSCENTER::ANNHUBAPI * *Handle, const char* licenseKey, const char* modelFilePath) {
if (!Handle || !licenseKey || !modelFilePath) return -1;
try {
if (*Handle) {
if (UnregisterANNHUBHandle(*Handle)) {
(*Handle)->Destroy();
delete *Handle;
}
*Handle = nullptr;
}
auto ptr = std::make_unique<ANSCENTER::ANNHUBAPI>();
bool result = ptr->Init(licenseKey, modelFilePath);
if (result) {
*Handle = ptr.release();
RegisterANNHUBHandle(*Handle);
return 1;
}
*Handle = nullptr;
return 0;
}
catch (...) { return 0; }
}
static int ReleaseANNHUBHandle_Impl(ANSCENTER::ANNHUBAPI** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
UnregisterANNHUBHandle(*Handle);
(*Handle)->Destroy();
delete *Handle;
*Handle = nullptr;
return 0;
}
extern "C" __declspec(dllexport) int ReleaseANNHUBHandle(ANSCENTER::ANNHUBAPI * *Handle) {
__try {
return ReleaseANNHUBHandle_Impl(Handle);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" __declspec(dllexport) int ANNHUB_Inference(ANSCENTER::ANNHUBAPI * *pHandle, double* inputArray, int inputSize, double** outputArray) {
// Check for null pointers
if (pHandle == nullptr || *pHandle == nullptr || inputArray == nullptr || outputArray == nullptr || inputSize <= 0) {
return -1; // Invalid arguments
}
ANNHUBHandleGuard guard(AcquireANNHUBHandle(*pHandle));
if (!guard) return -1;
try {
// Convert inputArray to std::vector
std::vector<double> inputVector(inputArray, inputArray + inputSize);
// Call Inference
std::vector<double> inferenceResult = guard.get()->Inference(inputVector);
int resultSize = inferenceResult.size();
// Allocate memory for the output array
*outputArray = new double[resultSize];
if (*outputArray == nullptr) return -2; // Memory allocation failed
// Copy the inference result to the output array
std::copy(inferenceResult.begin(), inferenceResult.end(), *outputArray);
return 0; // Success
}
catch (const std::exception& e) {
// Log the exception message if you have a logging system
return -5; // Error code for exception in Inference
}
}
extern "C" __declspec(dllexport) int ANNHUB_InferenceLV(ANSCENTER::ANNHUBAPI * *pHandle, double* inputArray, int inputSize, LStrHandle outputHandle) {
// Check for null pointers
if (pHandle == nullptr || *pHandle == nullptr || inputArray == nullptr || outputHandle == nullptr || inputSize <= 0) {
return 0; // Invalid arguments
}
ANNHUBHandleGuard guard(AcquireANNHUBHandle(*pHandle));
if (!guard) return 0;
try {
// Convert inputArray to std::vector
std::vector<double> inputVector(inputArray, inputArray + inputSize);
// Call Inference
std::vector<double> inferenceResult = guard.get()->Inference(inputVector);
int resultSize = inferenceResult.size();
if (resultSize <= 0) return 0; // Error code for empty inference result
std::stringstream ss;
for (size_t i = 0; i < resultSize; ++i)
{
if (i == resultSize - 1) ss << inferenceResult[i];
else ss << inferenceResult[i]<<";";
}
std::string st= ss.str();
int size = st.length();
if (size > 0) {
MgErr error;
error = DSSetHandleSize(outputHandle, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*outputHandle)->cnt = size;
memcpy((*outputHandle)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (const std::exception& e) {
// Log the exception message if you have a logging system
return 0; // Error code for exception in Inference
}
}
// --- V2 entry points: accept handle by value (uint64_t) to avoid LabVIEW buffer reuse bug ---
extern "C" __declspec(dllexport) int ANNHUB_Inference_V2(uint64_t handleVal, double* inputArray, int inputSize, double** outputArray) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANNHUBAPI*>(handleVal);
if (!_v2h) return -1;
if (inputArray == nullptr || outputArray == nullptr || inputSize <= 0) return -1;
ANNHUBHandleGuard guard(AcquireANNHUBHandle(_v2h));
if (!guard) return -1;
try {
std::vector<double> inputVector(inputArray, inputArray + inputSize);
std::vector<double> inferenceResult = guard.get()->Inference(inputVector);
int resultSize = inferenceResult.size();
*outputArray = new double[resultSize];
if (*outputArray == nullptr) return -2;
std::copy(inferenceResult.begin(), inferenceResult.end(), *outputArray);
return 0;
}
catch (const std::exception& e) {
return -5;
}
}
extern "C" __declspec(dllexport) int ANNHUB_InferenceLV_V2(uint64_t handleVal, double* inputArray, int inputSize, LStrHandle outputHandle) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANNHUBAPI*>(handleVal);
if (!_v2h) return 0;
if (inputArray == nullptr || outputHandle == nullptr || inputSize <= 0) return 0;
ANNHUBHandleGuard guard(AcquireANNHUBHandle(_v2h));
if (!guard) return 0;
try {
std::vector<double> inputVector(inputArray, inputArray + inputSize);
std::vector<double> inferenceResult = guard.get()->Inference(inputVector);
int resultSize = inferenceResult.size();
if (resultSize <= 0) return 0;
std::stringstream ss;
for (size_t i = 0; i < resultSize; ++i) {
if (i == resultSize - 1) ss << inferenceResult[i];
else ss << inferenceResult[i] << ";";
}
std::string st = ss.str();
int size = st.length();
if (size > 0) {
MgErr error;
error = DSSetHandleSize(outputHandle, sizeof(int32) + size * sizeof(uChar));
if (error == noErr) {
(*outputHandle)->cnt = size;
memcpy((*outputHandle)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (const std::exception& e) {
return 0;
}
}

69
ANSLIB/ANNHUB/ANSANNHUB.h Normal file
View File

@@ -0,0 +1,69 @@
#ifndef ANSANNHUB_H
#define ANSANNHUB_H
#define ANSANNHUB_API __declspec(dllexport)
#include <iostream>
#include <cstdint>
#include "ANSLicense.h"
#include <vector>
//#include "LabVIEWHeader/extcode.h"
namespace ANSCENTER
{
class ANSANNHUB_API ANNHUBAPI
{
private:
std::vector<double> nInput; //ANN inputs
std::vector<double> nOutput; //ANN outputs
std::vector<std::vector<double>> IW;
std::vector<std::vector<double>> LW;
std::vector<double> Ib;
std::vector<double> Lb;
// Structural parameters
int nInputNodes, nHiddenNodes, nOutputNodes;
int hiddenActivation; // default =2
int outputActivation; // default =2
int dataNormalisationModeInput; // default =1;
int dataNormalisationModeOutput; // default =1;
// Preprocessing and postprocessing settings
std::vector<double> xmaxInput, xminInput; // Maximum and minimum of inputs
double ymaxInput, yminInput; // Maximum and minimum of inputs
std::vector<double> xmaxOutput, xminOutput; // Maximum and minimum of outputs
double ymaxOutput, yminOutput; // Maximum and minimum of outputs
// Control creation
unsigned char isCreated;
std::string _licenseKey;
bool _licenseValid{ false };
bool _isInitialized{ false };
std::string _modelFilePath;
private:
void PreProcessing(std::vector<double>& Input); // mode =0--> linear, mode =1 mapminmax, mode =2 standarddev
void PostProcessing(std::vector<double>& Output); // mode =0--> linear, mode =1 mapminmax, mode =2 standarddev
void Create(int inputNodes, int HiddenNodes, int outputNodes);
void FreeNeuralNetwork();
void CheckLicense();
int ImportANNFromFile(std::string filename);
public:
ANNHUBAPI();
~ANNHUBAPI() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string modelFilePath);
[[nodiscard]] std::vector<double> Inference(std::vector<double> ip);
void Destroy();
[[nodiscard]] int GetOutputNode() { return nOutputNodes; };
};
}
extern "C" __declspec(dllexport) int CreateANNHUBHandle(ANSCENTER::ANNHUBAPI **Handle, const char* licenseKey, const char* modelFilePath);
extern "C" __declspec(dllexport) int ReleaseANNHUBHandle(ANSCENTER::ANNHUBAPI **Handle);
extern "C" __declspec(dllexport) int ANNHUB_Inference(ANSCENTER::ANNHUBAPI **pHandle, double* inputArray, int inputSize, double** outputArray);
extern "C" __declspec(dllexport) int ANNHUB_InferenceLV(ANSCENTER::ANNHUBAPI **pHandle, double* inputArray, int inputSize, LStrHandle outputHandle);
// --- V2 entry points: accept handle by value (uint64_t) to avoid LabVIEW buffer reuse bug ---
extern "C" __declspec(dllexport) int ANNHUB_Inference_V2(uint64_t handleVal, double* inputArray, int inputSize, double** outputArray);
extern "C" __declspec(dllexport) int ANNHUB_InferenceLV_V2(uint64_t handleVal, double* inputArray, int inputSize, LStrHandle outputHandle);
#endif

19
ANSLIB/ANNHUB/dllmain.cpp Normal file
View File

@@ -0,0 +1,19 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) noexcept
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

5
ANSLIB/ANNHUB/pch.cpp Normal file
View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

18
ANSLIB/ANNHUB/pch.h Normal file
View File

@@ -0,0 +1,18 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include <mutex>
#endif //PCH_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{06f42c19-765c-4192-80c0-e97f4257f1c5}</ProjectGuid>
<RootNamespace>ANSCVUnitTest</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\include;C:\Projects\ANLS\TurboJpeg;C:\Projects\Research\CPlusLibraries\QRCode;C:\Projects\ANLS\MediaClient\MediaClient\ffmpeg\include;C:\Projects\ANLS\MediaClient\MediaClient\rtp;C:\Projects\ANLS\MediaClient\MediaClient;C:\Projects\ANLS\MediaClient\MediaClient\rtsp;C:\Projects\ANLS\MediaClient\MediaClient\media;C:\Projects\ANLS\MediaClient\MediaClient\http;C:\Projects\ANLS\MediaClient\MediaClient\bm;C:\Projects\ANLS\ANSLIB\ANSCV;C:\Projects\ANLS\ANSLIB\ANSLicensingSystem;C:\Projects\ANLS\include;C:\ANSLibs\opencv\include;C:\Projects\Research\CPlusLibraries\Onvif\include;C:\Projects\Research\CPlusLibraries;$(IncludePath)</IncludePath>
<LibraryPath>C:\Projects\ANLS\TurboJpeg;C:\Projects\Research\CPlusLibraries\QRCode;C:\Projects\ANLS\MediaClient\lib;C:\Projects\ANLS\ANSLIB\x64\Release;C:\ANSLibs\opencv\x64\vc17\lib;C:\Projects\Research\CPlusLibraries\LabVIEWHeader;C:\Projects\ANLS\build\release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ZXing.lib;RtspClientLibrary.lib;labview-x86_64.lib;ANSLicensingSystem.lib;anslicensing.lib;ANSCV.lib;opencv_img_hash4130.lib;opencv_world4130.lib;turbojpeg.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ANSCV-UnitTest.cpp" />
<ClCompile Include="OpenCVTest.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCV-UnitTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="OpenCVTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,469 @@
//
//bool isRed(Vec3b color) {
// // Define the lower and upper bounds for red color
// Scalar lower_red = Scalar(0, 0, 100); // Adjust as needed
// Scalar upper_red = Scalar(80, 80, 255); // Adjust as needed
//
// // Convert the input color to a scalar for comparison
// Scalar target_color = Scalar(color[0], color[1], color[2]);
//
// // Check if the input color is within the specified range of red
// return (target_color.val[0] >= lower_red.val[0] && target_color.val[0] <= upper_red.val[0] &&
// target_color.val[1] >= lower_red.val[1] && target_color.val[1] <= upper_red.val[1] &&
// target_color.val[2] >= lower_red.val[2] && target_color.val[2] <= upper_red.val[2]);
//}
//
//int DominantColour() {
// // Read the input image
// //cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\redcar.jpg");
// cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\Bluecar.jpeg");
//
// if (image.empty()) {
// std::cout << "Could not open or find the image" << std::endl;
// return -1;
// }
//
// // Reshape the image into a 2D array of pixels
// Mat pixels = image.reshape(1, image.rows * image.cols);
//
// // Convert pixel values to floats
// pixels.convertTo(pixels, CV_32F);
//
// // Define the number of clusters (colors) to find
// int numClusters = 3; // Adjust as needed
//
// // Perform K-means clustering
// Mat labels, centers;
// kmeans(pixels, numClusters, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
//
// // Find the dominant colors
// vector<Vec3b> dominantColors;
// for (int i = 0; i < numClusters; ++i) {
// Vec3b color;
// color[0] = centers.at<float>(i, 0); // Blue
// color[1] = centers.at<float>(i, 1); // Green
// color[2] = centers.at<float>(i, 2); // Red
// dominantColors.push_back(color);
// }
//
// // Print the dominant colors
// cout << "Dominant colors:" << endl;
// for (int i = 0; i < numClusters; ++i) {
// cout << "Color " << i + 1 << ": BGR(" << (int)dominantColors[i][0] << ", " << (int)dominantColors[i][1] << ", " << (int)dominantColors[i][2] << ")" << endl;
// }
//
// // Display the dominant colors
// Mat colorPalette(100, 100 * numClusters, CV_8UC3);
// for (int i = 0; i < numClusters; ++i) {
// rectangle(colorPalette, Point(i * 100, 0), Point((i + 1) * 100, 100), Scalar(dominantColors[i]), -1); // Filled rectangle
// }
// imshow("Dominant Colors", colorPalette);
//
// // Wait for key press to exit
// waitKey(0);
//
// return 0;
//}
//// Function to determine basic color from 8 basic colors based on BGR values
//string getBasicColor(Vec3b color) {
// // Define 8 basic colors and their BGR values
// map<string, Vec3b> basicColors = {
// {"Red", {0, 0, 255}},
// {"Green", {0, 255, 0}},
// {"Blue", {255, 0, 0}},
// {"Yellow", {0, 255, 255}},
// {"Black", {0, 0, 0}},
// {"White", {255, 255, 255}},
// {"Brown", {42, 42, 165}},
// {"Gray", {128, 128, 128}}
// };
//
// string basicColor = "Other";
//
// // Find the basic color closest to the given color
// int minDistance = INT_MAX;
// for (const auto& entry : basicColors) {
// int dist = norm(entry.second, color, NORM_L2SQR);
// if (dist < minDistance) {
// minDistance = dist;
// basicColor = entry.first;
// }
// }
//
// return basicColor;
//}
//
//int GetColour() {
// // Read the image
// Mat image = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\redcar.jpg");
// if (image.empty()) {
// cerr << "Error: Unable to read image." << endl;
// return -1;
// }
//
// // Initialize variables to count occurrences of 8 basic colors
// map<string, int> colorCounts;
// for (const auto& entry : {
// "Red", "Green", "Blue", "Yellow", "Black", "White", "Brown", "Gray"
// }) {
// colorCounts[entry] = 0;
// }
//
// // Iterate over image pixels to count occurrences of 8 basic colors
// for (int i = 0; i < image.rows; ++i) {
// for (int j = 0; j < image.cols; ++j) {
// Vec3b pixelColor = image.at<Vec3b>(i, j);
// string basicColor = getBasicColor(pixelColor);
// colorCounts[basicColor]++;
// }
// }
//
// // Find the dominant basic color
// string dominantBasicColor = "Other";
// int maxCount = 0;
// for (const auto& entry : colorCounts) {
// if (entry.second > maxCount) {
// maxCount = entry.second;
// dominantBasicColor = entry.first;
// }
// }
//
// // Get the BGR color code of the dominant basic color
// Vec3b dominantBGRColor;
// if (dominantBasicColor == "Red")
// dominantBGRColor = Vec3b(0, 0, 255);
// else if (dominantBasicColor == "Green")
// dominantBGRColor = Vec3b(0, 255, 0);
// else if (dominantBasicColor == "Blue")
// dominantBGRColor = Vec3b(255, 0, 0);
// else if (dominantBasicColor == "Yellow")
// dominantBGRColor = Vec3b(0, 255, 255);
// else if (dominantBasicColor == "Black")
// dominantBGRColor = Vec3b(0, 0, 0);
// else if (dominantBasicColor == "White")
// dominantBGRColor = Vec3b(255, 255, 255);
// else if (dominantBasicColor == "Brown")
// dominantBGRColor = Vec3b(42, 42, 165);
// else if (dominantBasicColor == "Gray")
// dominantBGRColor = Vec3b(128, 128, 128);
//
// // Create a new image with the dominant color filled
// Mat dominantColorImage(image.size(), CV_8UC3, dominantBGRColor);
//
// // Display the dominant color in a separate window
// namedWindow("Dominant Color", WINDOW_AUTOSIZE);
// imshow("Dominant Color", dominantColorImage);
// waitKey(0);
//
// return 0;
//}
//
//int DetectRedCar() {
// // Read the input image
// cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\Bluecar.jpeg");
//
// if (image.empty()) {
// cout << "Could not open or find the image" << endl;
// return -1;
// }
//
// // Reshape the image into a 2D array of pixels
// Mat pixels = image.reshape(1, image.rows * image.cols);
//
// // Convert pixel values to floats
// pixels.convertTo(pixels, CV_32F);
//
// // Define the number of clusters (colors) to find
// int numClusters = 3; // Adjust as needed
//
// // Perform K-means clustering
// Mat labels, centers;
// kmeans(pixels, numClusters, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
//
// // Find the dominant colors
// vector<Vec3b> dominantColors;
// for (int i = 0; i < numClusters; ++i) {
// Vec3b color;
// color[0] = centers.at<float>(i, 0); // Blue
// color[1] = centers.at<float>(i, 1); // Green
// color[2] = centers.at<float>(i, 2); // Red
// dominantColors.push_back(color);
// }
//
// // Check if any of the dominant colors are red
// bool redDetected = false;
// for (int i = 0; i < numClusters; ++i) {
// if (isRed(dominantColors[i])) {
// redDetected = true;
// break;
// }
// }
//
// // Print the result
// if (redDetected) {
// cout << "A red car is detected in the image." << endl;
// }
// else {
// cout << "No red car is detected in the image." << endl;
// }
//
// return 0;
//}
//
//double CalculateIoU(const cv::Rect& box1, const cv::Rect& box2) {
// int x1 = std::max(box1.x, box2.x);
// int y1 = std::max(box1.y, box2.y);
// int x2 = std::min(box1.x + box1.width, box2.x + box2.width);
// int y2 = std::min(box1.y + box1.height, box2.y + box2.height);
//
// int intersectionArea = std::max(0, x2 - x1) * std::max(0, y2 - y1);
// int box1Area = box1.width * box1.height;
// int box2Area = box2.width * box2.height;
//
// double iou = static_cast<double>(intersectionArea) / (box1Area + box2Area - intersectionArea);
// return iou;
//}
//void NonMaximumSuppression(std::vector<DetectionObject>& detectedObjects, double iouThreshold) {
// std::sort(detectedObjects.begin(), detectedObjects.end(),
// [](const DetectionObject& a, const DetectionObject& b) {
// return a.confidence > b.confidence;
// });
//
// std::vector<DetectionObject> finalDetections;
// while (!detectedObjects.empty()) {
// finalDetections.push_back(detectedObjects.front());
// detectedObjects.erase(detectedObjects.begin());
//
// for (auto it = detectedObjects.begin(); it != detectedObjects.end(); ) {
// if (CalculateIoU(finalDetections.back().box, it->box) > iouThreshold) {
// it = detectedObjects.erase(it);
// }
// else {
// ++it;
// }
// }
// }
//
// detectedObjects = std::move(finalDetections);
//}
//std::vector<DetectionObject> findMatches(cv::Mat& img, cv::Mat& templ, double threshold) {
// // Create the result matrix
// std::vector<DetectionObject> detectedObjects;
// int result_cols = img.cols - templ.cols + 1;
// int result_rows = img.rows - templ.rows + 1;
// cv::Mat result(result_rows, result_cols, CV_32FC1);
//
// // Perform match
// cv::matchTemplate(img, templ, result, cv::TM_CCOEFF_NORMED);
// cv::normalize(result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
//
// std::vector<cv::Rect> boundingBoxes;
//
// // Threshold and find non-zero locations
// for (int i = 0; i < result.rows; i++) {
// for (int j = 0; j < result.cols; j++) {
// if (result.at<float>(i, j) > threshold) {
// cv::Rect rect(j, i, templ.cols, templ.rows);
// DetectionObject object;
// object.box = rect;
// boundingBoxes.push_back(rect);
// detectedObjects.push_back(object);
// // Optional: Draw rectangles on the image
// cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 2);
// }
// }
// }
// NonMaximumSuppression(detectedObjects, 0.5);
// std::cout << "Bounding box size:" << boundingBoxes.size()<<std::endl;
// std::cout << "detectedObjects box size:" << detectedObjects.size() << std::endl;
//
// return detectedObjects;
//}
//
//int PatternMatching() {
// // Load the image and the template
// cv::Mat img = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\QRSample.jpg", cv::IMREAD_COLOR);
// cv::Mat templ = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\Ultracode.jpg", cv::IMREAD_COLOR);
//
// if (img.empty() || templ.empty()) {
// std::cout << "Could not open or find the image or template" << std::endl;
// return -1;
// }
//
// // Call findMatches with a threshold, e.g., 0.8 for 80% similarity
// std::vector<DetectionObject> matches = findMatches(img, templ, 0.8);
//
// // Display the image with drawn rectangles
// cv::imshow("Matches", img);
// cv::waitKey(0);
//
//
// return 0;
//}
//int TestZingQRcode() {
//
// // load your image data from somewhere. ImageFormat::Lum assumes grey scale image data
//
// cv::Mat inputImage = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\Code128.jpg");
// cv::Mat grayMat;
// if (inputImage.channels() == 3) {
// cv::cvtColor(inputImage, grayMat, cv::COLOR_BGR2GRAY);
// }
// else if (inputImage.channels() == 4) {
// cv::cvtColor(inputImage, grayMat, cv::COLOR_BGRA2GRAY);
// }
// else {
// grayMat = inputImage; // Already grayscale
// }
//
// int width = grayMat.cols;
// int height= grayMat.rows;
// unsigned char* data = grayMat.data;
// auto image = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
// auto options = ZXing::ReaderOptions().setFormats(ZXing::BarcodeFormat::Any);
// auto barcodes = ZXing::ReadBarcodes(image, options);
// if (barcodes.size() > 0) {
// for (const auto& b : barcodes) {
// std::cout << ZXing::ToString(b.format()) << ": " << b.text() << "\n";
// ZXing::Position pos =b.position();
// std::cout<<"Pos 1:("<<pos[0].x<<","<< pos[0].x<<")"<<std::endl;
// }
//
// }
// else {
// std::cout << "Could not find any barcode"<<std::endl;
// }
//
// return 0;
//}
//
//
//
//Vec3f estimateIllumination(Mat& src, float percentile) {
// Mat src_float;
// src.convertTo(src_float, CV_32FC3);
// vector<Mat> channels(3);
// split(src_float, channels);
//
// Mat magnitude = Mat::zeros(src.size(), CV_32FC1);
//
// for (int i = 0; i < 3; i++) {
// Mat sobelx, sobely;
// Sobel(channels[i], sobelx, CV_32F, 1, 0);
// Sobel(channels[i], sobely, CV_32F, 0, 1);
// magnitude += sobelx.mul(sobelx) + sobely.mul(sobely);
// }
//
// sqrt(magnitude, magnitude);
// Mat flatMagnitude = magnitude.reshape(1, 1);
// cv::sort(flatMagnitude, flatMagnitude, SORT_EVERY_ROW + SORT_DESCENDING);
// int thresholdIdx = static_cast<int>(percentile * flatMagnitude.total() / 100.0);
// double threshold = flatMagnitude.at<float>(thresholdIdx);
//
// Mat mask = magnitude >= threshold;
// Scalar meanVal = mean(src_float, mask);
//
// cout << "Estimated illumination: " << meanVal << endl;
// return Vec3f(meanVal[0], meanVal[1], meanVal[2]);
//}
//
//void applyWhiteBalance(Mat& src, Mat& dst, Vec3f illumination) {
// vector<Mat> channels(3);
// src.convertTo(src, CV_32FC3);
// split(src, channels);
//
// for (int i = 0; i < 3; i++) {
// channels[i] /= illumination[i];
// }
//
// merge(channels, dst);
// dst.convertTo(dst, CV_8U);
//}
//
//void simpleWhiteBalance(Mat& src, Mat& dst) {
// // Convert image to floating point for precision
// src.convertTo(dst, CV_32F);
//
// // Split the image into separate color channels
// vector<Mat> channels(3);
// split(dst, channels);
//
// // Calculate the average intensity for each channel
// double avgB = mean(channels[0])[0];
// double avgG = mean(channels[1])[0];
// double avgR = mean(channels[2])[0];
//
// // Calculate the total average intensity
// double avgTotal = (avgB + avgG + avgR) / 3.0;
//
// // Scale each channel to adjust the white balance
// channels[0] *= avgTotal / avgB;
// channels[1] *= avgTotal / avgG;
// channels[2] *= avgTotal / avgR;
//
// // Merge the channels back into one image
// merge(channels, dst);
//
// // Convert back to 8-bit color
// dst.convertTo(dst, CV_8U);
//}
//int AutoWhiteBalance() {
// Mat src = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\cat.jpg");
// if (src.empty()) {
// cout << "Could not open or find the image" << endl;
// return -1;
// }
//
// Mat dst;
// Vec3f illumination = estimateIllumination(src, 0.1); // Top 1% of gradients
// applyWhiteBalance(src, dst, illumination);
//
// //simpleWhiteBalance(src,dst);
// imshow("Original Image", src);
// imshow("White Balanced Image", dst);
// cv::waitKey(0);
//
// return 0;
//}
//
//
//int BrightEnhancement() {
// // Load the input image
// Mat inputImage = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\dark.jpg", IMREAD_COLOR);
//
// // Check if the image was loaded successfully
// if (inputImage.empty()) {
// cout << "Error: Could not open or find the image" << endl;
// return -1;
// }
//
// // Separate the input image into B, G, and R channels
// vector<Mat> channels;
// split(inputImage, channels);
//
// // Enhance brightness for each channel individually
// double brightnessScaleFactor = 1.5; // Scaling factor for brightness enhancement
// for (int i = 0; i < channels.size(); ++i) {
// channels[i] *= brightnessScaleFactor;
// }
//
// // Merge the channels back into a BGR image
// Mat enhancedImage;
// merge(channels, enhancedImage);
//
// // Display original and enhanced images
// namedWindow("Original Image", WINDOW_AUTOSIZE);
// imshow("Original Image", inputImage);
//
// namedWindow("Enhanced Image", WINDOW_AUTOSIZE);
// imshow("Enhanced Image", enhancedImage);
//
// // Wait for a keystroke in the window
// waitKey(0);
//
// // Close all OpenCV windows
// destroyAllWindows();
//
// return 0;
//}

265
ANSLIB/ANSCV/ANSCV.vcxproj Normal file
View File

@@ -0,0 +1,265 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{f33df4e9-d236-4ec8-afce-626536cdc970}</ProjectGuid>
<RootNamespace>ANSCV</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\include;C:\Projects\ANLS\TurboJpeg;C:\Projects\Research\CPlusLibraries\QRCode;C:\Projects\ANLS\MediaClient\MediaClient\libsrt\include;C:\Projects\ANLS\MediaClient\MediaClient\srt;C:\Projects\ANLS\MediaClient\MediaClient\rtmp;C:\Projects\ANLS\MediaClient\MediaClient\directx\include;C:\Projects\ANLS\MediaClient\MediaClient\ffmpeg\include;C:\Projects\ANLS\MediaClient\MediaClient\rtsp;C:\Projects\ANLS\MediaClient\MediaClient\rtp;C:\Projects\ANLS\MediaClient\MediaClient\http;C:\Projects\ANLS\MediaClient\MediaClient\bm;C:\Projects\ANLS\MediaClient\MediaClient\media;C:\Projects\ANLS\MediaClient\MediaClient;C:\Projects\ANLS\MediaClient\MediaClient\openssl\include;C:\Projects\ANLS\ANSLIB\ANSLicensingSystem;C:\Projects\ANLS\include;C:\Projects\Research\CPlusLibraries;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\lib\x64;C:\Projects\ANLS\TurboJpeg;C:\Projects\Research\CPlusLibraries\QRCode;C:\Projects\ANLS\MediaClient\MediaClient\libsrt\lib\x64;C:\Projects\ANLS\MediaClient\MediaClient\zlib\lib\x64;C:\Projects\ANLS\MediaClient\MediaClient\openssl\lib\x64;C:\Projects\ANLS\MediaClient\MediaClient\directx\lib\x64;C:\Projects\ANLS\MediaClient\MediaClient\ffmpeg\lib\x64;C:\Projects\ANLS\MediaClient\lib;C:\Projects\ANLS\build\release;C:\Projects\ANLS\ANSLIB\x64\Release;C:\Projects\Research\CPlusLibraries\LabVIEWHeader;C:\ANSLibs\opencv\x64\vc17\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnabled>false</VcpkgEnabled>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCV_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;HT_STATIC;HTTPS;BACKCHANNEL;METADATA;REPLAY;OVER_HTTP;OVER_WEBSOCKET;__WINDOWS_OS__;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>ZXing.lib;turbojpeg-static.lib;RtspClientLibrary.lib;HttpFlvClientLibrary.lib;HttpMjpegClientLibrary.lib;RtmpClientLibrary.lib;SrtClientLibrary.lib;labview-x86_64.lib;ANSLicensingSystem.lib;anslicensing.lib;d3d9.lib;d3dx9.lib;libcrypto.lib;libssl.lib;zlibwapi.lib;winmm.lib;srt.lib;avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;postproc.lib;swresample.lib;swscale.lib;opencv_img_hash4130.lib;opencv_world4130.lib;nvjpeg.lib;cudart_static.lib;cublasLt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\MediaClient\MediaClient\media\file_player.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\http_flv_player.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\http_mjpeg_player.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\rtmp_player.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\rtsp_player.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\srt_player.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\video_decoder.h" />
<ClInclude Include="..\..\MediaClient\MediaClient\media\video_player.h" />
<ClInclude Include="ANSFilePlayer.h" />
<ClInclude Include="ANSFilePlayer_CV.h" />
<ClInclude Include="ANSFLV.h" />
<ClInclude Include="ANSMJPEG.h" />
<ClInclude Include="ANSOpenCV.h" />
<ClInclude Include="ANSRTMP.h" />
<ClInclude Include="ANSRTSP.h" />
<ClInclude Include="ANSSRT.h" />
<ClInclude Include="ANSVideoPlayer.h" />
<ClInclude Include="ANSWebcam.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_capture.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_capture_win.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_decoder.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_encoder.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_play.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_play_win.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\avcodec_mutex.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\avi_write.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\file_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\http_flv_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\http_mjpeg_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\media_codec.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\media_parse.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\media_util.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\rtmp_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\rtsp_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\srt_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\media\video_decoder.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\video_player.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h264_rtp_rx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h264_util.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h265_rtp_rx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h265_util.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\mjpeg_rtp_rx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\mjpeg_tables.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\ts_parser.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtsp\rtsp_backchannel.cpp" />
<ClCompile Include="..\..\MediaClient\MediaClient\rtsp\rtsp_cln.cpp" />
<ClCompile Include="ANSFilePlayer_CV.cpp" />
<ClCompile Include="ANSGpuFrameRegistry.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ANSFilePlayer.cpp" />
<ClCompile Include="ANSFLV.cpp" />
<ClCompile Include="ANSMJPEG.cpp" />
<ClCompile Include="ANSOpenCV.cpp" />
<ClCompile Include="ANSRTMP.cpp" />
<ClCompile Include="ANSRTSP.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ANSSRT.cpp" />
<ClCompile Include="ANSVideoPlayer.cpp" />
<ClCompile Include="ANSWEBCAM.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,264 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Header Files\Media">
<UniqueIdentifier>{05aa8e22-bc28-4ac4-b0ea-d0489253aacf}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\FilePlayer">
<UniqueIdentifier>{c282a65a-272a-4ac0-bb00-7c4cf7f96be8}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\SRT">
<UniqueIdentifier>{f5164196-d1d3-430e-a719-d558c11a397a}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\FLV">
<UniqueIdentifier>{955ee9b7-3284-4ab2-a194-20f98929dfdc}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\MJPEG">
<UniqueIdentifier>{cf7ae7df-7542-4cc4-bf2c-124dafca3684}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Webcam">
<UniqueIdentifier>{ce775aa0-f6d1-43b9-9a87-254cf13e85c1}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\OpenCV">
<UniqueIdentifier>{fef84e36-6d3d-47d2-97c3-8d2d78f3602a}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\RTSP">
<UniqueIdentifier>{8ee3eec1-7710-480a-a315-7dbbeaa8abe8}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Resource Files\Source Files\RTSP">
<UniqueIdentifier>{0ec3eaa3-667f-4b55-abad-ee408a6f002e}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\Media">
<UniqueIdentifier>{a648146a-58a9-4bdd-b479-2bcea0d86e0e}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\FilePlayer">
<UniqueIdentifier>{0d87ee5b-9174-4d1a-b1b7-cc00d2ea6a6e}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\RTMP">
<UniqueIdentifier>{4e0c3b87-5deb-4d36-96c2-b4509289ff38}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\SRT">
<UniqueIdentifier>{754d69bd-95d3-41c7-a269-5ecf1dff269a}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\FLV">
<UniqueIdentifier>{e7363f41-b96b-4d55-898a-a9819331613e}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\MJPEG">
<UniqueIdentifier>{0cea1a54-e368-41b8-9cff-6e13478b419a}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\Webcam">
<UniqueIdentifier>{4ecd162e-68b6-43d0-beb9-bafc75de044c}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\OpenCV">
<UniqueIdentifier>{9283eb2a-8dc7-411b-bf0e-b29f87f3014c}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\RTMP">
<UniqueIdentifier>{c0976531-4c90-45f3-b363-7c586055521f}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\VideoPlayer">
<UniqueIdentifier>{45d951c9-b4a4-41cb-a74d-216c53300138}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Source Files\VideoPlayer">
<UniqueIdentifier>{2d8ebc33-157d-44b1-8623-d7685bfc11dd}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSRTSP.h">
<Filter>Header Files\RTSP</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\video_decoder.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\rtsp_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\video_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\file_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="ANSFilePlayer.h">
<Filter>Header Files\FilePlayer</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\rtmp_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="ANSRTMP.h">
<Filter>Header Files\RTMP</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\srt_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="ANSSRT.h">
<Filter>Header Files\SRT</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\http_flv_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="ANSFLV.h">
<Filter>Header Files\FLV</Filter>
</ClInclude>
<ClInclude Include="..\..\MediaClient\MediaClient\media\http_mjpeg_player.h">
<Filter>Header Files\Media</Filter>
</ClInclude>
<ClInclude Include="ANSMJPEG.h">
<Filter>Header Files\MJPEG</Filter>
</ClInclude>
<ClInclude Include="ANSWebcam.h">
<Filter>Header Files\Webcam</Filter>
</ClInclude>
<ClInclude Include="ANSOpenCV.h">
<Filter>Header Files\OpenCV</Filter>
</ClInclude>
<ClInclude Include="ANSVideoPlayer.h">
<Filter>Header Files\VideoPlayer</Filter>
</ClInclude>
<ClInclude Include="ANSFilePlayer_CV.h">
<Filter>Header Files\FilePlayer</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Resource Files\Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Resource Files\Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSRTSP.cpp">
<Filter>Resource Files\Source Files\RTSP</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\video_decoder.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\avcodec_mutex.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\media_codec.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\media_parse.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h264_rtp_rx.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h264_util.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h265_rtp_rx.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\h265_util.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\ts_parser.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\mjpeg_tables.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtp\mjpeg_rtp_rx.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\media_util.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_decoder.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_play.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_encoder.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_capture_win.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_play_win.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\avi_write.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\audio_capture.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\rtsp_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\video_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\file_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="ANSFilePlayer.cpp">
<Filter>Resource Files\Source Files\FilePlayer</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtsp\rtsp_cln.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\rtsp\rtsp_backchannel.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\rtmp_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="ANSRTMP.cpp">
<Filter>Resource Files\Source Files\RTMP</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\srt_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="ANSSRT.cpp">
<Filter>Resource Files\Source Files\SRT</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\http_flv_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="ANSFLV.cpp">
<Filter>Resource Files\Source Files\FLV</Filter>
</ClCompile>
<ClCompile Include="..\..\MediaClient\MediaClient\media\http_mjpeg_player.cpp">
<Filter>Resource Files\Source Files\Media</Filter>
</ClCompile>
<ClCompile Include="ANSWEBCAM.cpp">
<Filter>Resource Files\Source Files\Webcam</Filter>
</ClCompile>
<ClCompile Include="ANSOpenCV.cpp">
<Filter>Resource Files\Source Files\OpenCV</Filter>
</ClCompile>
<ClCompile Include="ANSMJPEG.cpp">
<Filter>Resource Files\Source Files\MJPEG</Filter>
</ClCompile>
<ClCompile Include="ANSVideoPlayer.cpp">
<Filter>Resource Files\Source Files\VideoPlayer</Filter>
</ClCompile>
<ClCompile Include="ANSGpuFrameRegistry.cpp">
<Filter>Resource Files\Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSFilePlayer_CV.cpp">
<Filter>Resource Files\Source Files\FilePlayer</Filter>
</ClCompile>
</ItemGroup>
</Project>

1169
ANSLIB/ANSCV/ANSFLV.cpp Normal file

File diff suppressed because it is too large Load Diff

111
ANSLIB/ANSCV/ANSFLV.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef ANSFLV_H
#define ANSFLV_H
#define ANSFLV_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "http_flv_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "http_flv_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
namespace ANSCENTER
{
class ANSFLV_API ANSFLVClient
{
protected:
std::unique_ptr<CHttpFlvPlayer> _playerClient = std::make_unique<CHttpFlvPlayer>();
std::string _username;
std::string _password;
std::string _url;
bool _useFullURL;
int _imageRotateDeg = 0;
int _displayWidth = 0; // 0 = no resize (return original resolution)
int _displayHeight = 0;
cv::Mat _pLastFrame;
std::string _lastJpegImage;
int _imageWidth, _imageHeight;
int64_t _pts;
bool _isPlaying;
std::recursive_mutex _mutex;
public:
ANSFLVClient();
~ANSFLVClient() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Init(std::string licenseKey, std::string username, std::string password, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
[[nodiscard]] bool Pause();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
bool areImagesIdentical(const cv::Mat& img1, const cv::Mat& img2);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegImage(int& width, int& height, int64_t& pts);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
static void SetMaxHWDecoders(int maxDecoders);
static int AutoConfigureHWDecoders(int maxPerGpuOverride = 0);
void SetHWDecoding(int hwMode, int preferredGpu = -1);
bool IsHWDecodingActive();
int GetHWDecodingGpuIndex();
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
void SetImageQuality(int mode); // 0=fast (AI), 1=quality (display)
AVFrame* GetNV12Frame(); // Returns cloned NV12 frame for GPU fast-path (caller must av_frame_free)
AVFrame* GetCudaHWFrame(); // Returns CUDA HW frame (device ptrs) for zero-copy inference
bool IsCudaHWAccel(); // true when decoder uses CUDA (NV12 stays in GPU VRAM)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSFLV", false);
bool _licenseValid{ false };
std::string _licenseKey;
//std::once_flag licenseOnceFlag;
};
}
extern "C" __declspec(dllexport) int CreateANSFLVHandle(ANSCENTER::ANSFLVClient * *Handle, const char* licenseKey, const char* username, const char* password, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSFLVHandle(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) int GetFLVImage(ANSCENTER::ANSFLVClient * *Handle, int& width, int& height, int64_t & timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetFLVStrImage(ANSCENTER::ANSFLVClient * *Handle, int& width, int& height, int64_t & timeStamp, std::string & jpegImage);
extern "C" __declspec(dllexport) int GetFLVCVImage(ANSCENTER::ANSFLVClient** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartFLV(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) int ReconnectFLV(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) int StopFLV(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) int PauseFLV(ANSCENTER::ANSFLVClient** Handle);
extern "C" __declspec(dllexport) int IsFLVPaused(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) int IsFLVRunning(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) int IsFLVRecording(ANSCENTER::ANSFLVClient * *Handle);
extern "C" __declspec(dllexport) void SetFLVAudioVolume(ANSCENTER::ANSFLVClient * *Handle, int volume);
extern "C" __declspec(dllexport) void EnableFLVAudioVolume(ANSCENTER::ANSFLVClient * *Handle, int status);
extern "C" __declspec(dllexport) void SetFLVImageRotation(ANSCENTER::ANSFLVClient * *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxFLV(ANSCENTER::ANSFLVClient** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagFLV(ANSCENTER::ANSFLVClient** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetFLVMaxHWDecoders(int maxDecoders);
extern "C" __declspec(dllexport) int AutoConfigureFLVHWDecoders(int maxPerGpuOverride);
extern "C" __declspec(dllexport) void SetFLVHWDecoding(ANSCENTER::ANSFLVClient** Handle, int hwMode, int preferredGpu = -1);
extern "C" __declspec(dllexport) int IsFLVHWDecodingActive(ANSCENTER::ANSFLVClient** Handle);
extern "C" __declspec(dllexport) int GetFLVHWDecodingGpuIndex(ANSCENTER::ANSFLVClient** Handle);
extern "C" __declspec(dllexport) void SetFLVImageQuality(ANSCENTER::ANSFLVClient** Handle, int mode);
extern "C" __declspec(dllexport) void SetFLVDisplayResolution(ANSCENTER::ANSFLVClient** Handle, int width, int height);
#endif

View File

@@ -0,0 +1,861 @@
#include "ANSFilePlayer.h"
#include "ANSMatRegistry.h"
#include "ANSGpuFrameOps.h"
#include <memory>
#include <cstdint>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/frame.h>
#include "media_codec.h"
static bool ansfileplayerLicenceValid = false;
// Global once_flag to protect license checking
static std::once_flag ansfileplayerLicenseOnceFlag;
namespace ANSCENTER {
#define CHECK_CUDA(call) do { \
cudaError_t err = call; \
if (err != cudaSuccess) { \
std::cout<<"CUDA error: " + std::string(cudaGetErrorString(err)); \
} \
} while (0)
#define CHECK_NVJPEG(call) do { \
nvjpegStatus_t status = call; \
if (status != NVJPEG_STATUS_SUCCESS) { \
std::cout <<"nvJPEG error: " + std::to_string(status); \
} \
} while (0)
ANSFILEPLAYER::ANSFILEPLAYER() {
_url = "";
_imageRotateDeg = 0;
_imageWidth = 0;
_imageHeight = 0;
_pts = 0;
_isPlaying = false;
_lastJpegImage = "";
}
ANSFILEPLAYER::~ANSFILEPLAYER() noexcept {
try {
Destroy();
}
catch (...) {}
}
void ANSFILEPLAYER::Destroy() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
_url = "";
_imageRotateDeg = 0;
_isPlaying = false;
_lastJpegImage = "";
_pLastFrame.release();
if (_playerClient) {
_playerClient->close();
}
}
catch (const std::exception& e) {
_logger.LogError("ANSFILEPLAYER::Destroy. Exception:", e.what(), __FILE__, __LINE__);
}
catch (...) {
_logger.LogError("ANSFILEPLAYER::Destroy.", "Unknown exception", __FILE__, __LINE__);
}
}
void ANSFILEPLAYER::CheckLicense() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
_licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1007, "ANSCV");//Default productId=1005
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSFILEPLAYER::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
}
}
bool ANSFILEPLAYER::Init(std::string licenseKey, std::string url) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_licenseKey = licenseKey;
CheckLicense();
if (!_licenseValid) {
this->_logger.LogError("ANSFILEPLAYER::Init.", "Invalid license", __FILE__, __LINE__);
return false;
}
//network_init();
//sys_buf_init(200);
//rtsp_parse_buf_init(200);
//http_msg_buf_init(200);
_url = url;
return Setup();
}
void ANSFILEPLAYER::SetBBox(cv::Rect bbox) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_playerClient->setBbox(bbox);
}
void ANSFILEPLAYER::SetCrop(bool crop) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_playerClient->setCrop(crop);
}
bool ANSFILEPLAYER::Setup() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return _playerClient->open(_url);
}
bool ANSFILEPLAYER::Reconnect() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_playerClient->close();
Setup();
return Start();
}
bool ANSFILEPLAYER::Start() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_isPlaying = _playerClient->play();
return _isPlaying;
}
bool ANSFILEPLAYER::Stop() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (_playerClient->pause()) {
_isPlaying = false;
return true;
}
else {
return false;
}
}
bool ANSFILEPLAYER::IsPaused() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return _playerClient->isPaused();
}
bool ANSFILEPLAYER::IsPlaying() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return _playerClient->isPlaying();
}
bool ANSFILEPLAYER::IsRecording() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return _playerClient->isRecording();
}
std::string ANSFILEPLAYER::GetJpegImage(int& width, int& height, int64_t& pts) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
// If the player is playing, process the frame
if (_isPlaying) {
// Get a new frame from the player client
_lastJpegImage = _playerClient->getJpegImage(width, height, pts);
// Update internal state variables
_pts = pts;
_imageWidth = width;
_imageHeight = height;
// Return the frame
return _lastJpegImage;
}
// If the player is not playing, return the last known frame
else {
width = _imageWidth;
height = _imageHeight;
pts = _pts;
return _lastJpegImage;
}
}
cv::Mat ANSFILEPLAYER::GetImage(int& width, int& height, int64_t& pts) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!_isPlaying) {
width = _imageWidth;
height = _imageHeight;
pts = _pts;
return _pLastFrame;
}
_pLastFrame.release();
int imgW = 0, imgH = 0;
_pLastFrame = _playerClient->getImage(imgW, imgH, pts);
if (_pLastFrame.empty()) {
width = _imageWidth;
height = _imageHeight;
pts = _pts;
return _pLastFrame;
}
cv::Mat result = _pLastFrame;
// Apply rotation if needed
if (_imageRotateDeg >= 1 && _imageRotateDeg != 0) {
cv::Point2f center(imgW / 2.0f, imgH / 2.0f);
cv::Mat rotMat = cv::getRotationMatrix2D(center, _imageRotateDeg, 1.0);
cv::Mat rotated;
cv::warpAffine(result, rotated, rotMat, result.size(),
cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar());
result = rotated;
}
// Store full-res for inference (before display resize)
_inferenceImage = result;
// Resize for display if display resolution is set
if (_displayWidth > 0 && _displayHeight > 0 &&
(result.cols != _displayWidth || result.rows != _displayHeight)) {
cv::Mat displayResult;
cv::resize(result, displayResult, cv::Size(_displayWidth, _displayHeight),
0, 0, cv::INTER_LINEAR);
result = displayResult;
}
_pts = pts;
width = result.cols;
height = result.rows;
_imageWidth = width;
_imageHeight = height;
return result;
}
void ANSFILEPLAYER::SetDisplayResolution(int width, int height) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_displayWidth = width;
_displayHeight = height;
}
cv::Mat ANSFILEPLAYER::GetInferenceImage() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return _inferenceImage;
}
void ANSFILEPLAYER::EnableAudio(bool status) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_playerClient->enableAudio(status);
}
void ANSFILEPLAYER::SetAudioVolume(int volume) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_playerClient->setVolume(volume);
}
std::string ANSFILEPLAYER::MatToBinaryData(const cv::Mat& image) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!image.empty()) {
if ((image.data != nullptr) && (image.u != nullptr)) {
try {
std::vector<uchar> imageData;
bool success = cv::imencode(".jpg", image, imageData);
if (!success) {
this->_logger.LogError("ANSFILEPLAYER::MatToBinaryData. Error:", "Failed to encode the image.", __FILE__, __LINE__);
return "";
}
std::string binaryData(imageData.begin(), imageData.end());
return binaryData;
}
catch (const std::exception& e) {
this->_logger.LogFatal("ANSFILEPLAYER::MatToBinaryData. Error:", e.what(), __FILE__, __LINE__);
return "";
}
catch (...) {
this->_logger.LogFatal("ANSFILEPLAYER::MatToBinaryData. Error:", "Caught unknown exception!", __FILE__, __LINE__);
return "";
}
}
else return "";
}
else return "";
}
static void VerifyGlobalANSFPLicense(const std::string& licenseKey) {
try {
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1007, "ANSCV");//Default productId=1005
if (!ansfileplayerLicenceValid) { // we also support ANSTS license
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1003, "ANSVIS");//Default productId=1003 (ANSVIS)
}
if (!ansfileplayerLicenceValid) { // we also support ANSTS license
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1008, "ANSTS");//Default productId=1008 (ANSTS)
}
}
catch (std::exception& e) {
ansfileplayerLicenceValid = false;
}
}
}
extern "C" __declspec(dllexport) int CreateANSFilePlayerHandle(ANSCENTER::ANSFILEPLAYER** Handle, const char* licenseKey, const char* url) {
if (!Handle || !licenseKey || !url) return -1;
try {
auto ptr = std::make_unique<ANSCENTER::ANSFILEPLAYER>();
bool result = ptr->Init(licenseKey, url);
if (result) {
*Handle = ptr.release();
extern void anscv_unregister_handle(void*);
extern void anscv_register_handle(void*, void(*)(void*));
anscv_register_handle(*Handle, [](void* p) {
auto* h = static_cast<ANSCENTER::ANSFILEPLAYER*>(p);
try { h->Stop(); } catch (...) {}
try { h->Destroy(); } catch (...) {}
try { delete h; } catch (...) {}
});
return 1;
}
*Handle = nullptr;
return 0;
}
catch (...) { return 0; }
}
extern "C" __declspec(dllexport) int ReleaseANSFilePlayerHandle(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
extern void anscv_unregister_handle(void*);
anscv_unregister_handle(*Handle);
// Destructor calls Destroy() — no need to call it explicitly (avoids double-destroy)
std::unique_ptr<ANSCENTER::ANSFILEPLAYER> ptr(*Handle);
*Handle = nullptr;
return 0;
}
catch (...) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" __declspec(dllexport) int GetFilePlayerStrImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, std::string& jpegImage) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
jpegImage = (*Handle)->GetJpegStringImage(width, height, timeStamp);
if (!jpegImage.empty()) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int GetFilePlayerImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
std::string jpegString = (*Handle)->GetJpegStringImage(width, height, timeStamp);
int size = jpegString.length();
if (size > 0) {
MgErr error;
// Resize the jpegImage handle to hold the image data
error = DSSetHandleSize(jpegImage, sizeof(int32) + size * sizeof(uChar));
// Check if resizing the handle was successful
if (error == noErr) {
// Set the size of the image in the handle
(*jpegImage)->cnt = size;
// Use memcpy to copy the data from the std::string to the LStrHandle's str buffer
memcpy((*jpegImage)->str, jpegString.c_str(), size);
// Return success
return 1;
}
else {
// Return failure if there was an error in resizing the handle
std::cerr << "Error resizing jpegImage handle: " << error << std::endl;
return 0;
}
}
else {
// If the JPEG image string is empty, return failure
std::cerr << "No image data retrieved from FilePlayer client." << std::endl;
return 0;
}
}
catch (const std::exception& e) {
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int GetFilePlayerCVImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image) {
if (!Handle || !(*Handle) || !image) {
std::cerr << "Error: Invalid input parameters in GetFilePlayerCVImage." << std::endl;
return -1;
}
try {
cv::Mat img = (*Handle)->GetImage(width, height, timeStamp);
if (img.empty()) {
return 0;
}
anscv_mat_replace(image, std::move(img));
// Attach NV12/CUDA frames to registry for inference zero-copy (same as ANSRTSP/ANSVideoPlayer).
// CFilePlayer inherits getNV12Frame()/getCudaHWFrame() from CVideoPlayer.
int gpuIdx = (*Handle)->_playerClient->getHWDecodingGpuIndex();
AVFrame* cudaHW = (*Handle)->_playerClient->getCudaHWFrame();
if (cudaHW) {
AVFrame* cpuNV12 = (*Handle)->_playerClient->getNV12Frame();
gpu_frame_attach_cuda(*image, cudaHW, gpuIdx, timeStamp, cpuNV12);
} else {
AVFrame* nv12 = (*Handle)->_playerClient->getNV12Frame();
if (nv12) {
gpu_frame_attach(*image, nv12, gpuIdx, timeStamp);
} else {
// CPU-only fallback: attach full-res BGR clone for ANSRTYOLO
cv::Mat infImg = (*Handle)->GetInferenceImage();
if (!infImg.empty() && infImg.data != (*image)->data) {
(*Handle)->_inferenceClonePrev = (*Handle)->_inferenceCloneCurr;
(*Handle)->_inferenceCloneCurr = infImg.clone();
GpuFrameData data{};
data.avframe = nullptr;
data.yPlane = (*Handle)->_inferenceCloneCurr.data;
data.uvPlane = nullptr;
data.yLinesize = static_cast<int>((*Handle)->_inferenceCloneCurr.step[0]);
data.uvLinesize = 0;
data.width = (*Handle)->_inferenceCloneCurr.cols;
data.height = (*Handle)->_inferenceCloneCurr.rows;
data.pixelFormat = 1000; // ANSCV_PIX_FMT_BGR24
data.gpuIndex = -1;
data.pts = timeStamp;
data.isCudaDevicePtr = false;
data.cpuAvframe = nullptr;
data.cpuYPlane = nullptr;
data.cpuUvPlane = nullptr;
data.cpuYLinesize = 0;
data.cpuUvLinesize = 0;
ANSGpuFrameRegistry::instance().attach(*image, std::move(data));
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
for (void* p : pending) {
AVFrame* stale = static_cast<AVFrame*>(p);
av_frame_free(&stale);
}
}
}
}
return 1;
}
catch (const cv::Exception& e) {
std::cerr << "OpenCV exception in GetFilePlayerCVImage: " << e.what() << std::endl;
return -2;
}
catch (const std::exception& e) {
std::cerr << "Exception in GetFilePlayerCVImage: " << e.what() << std::endl;
return -2;
}
catch (...) {
std::cerr << "Unknown exception in GetFilePlayerCVImage" << std::endl;
return -2;
}
}
extern "C" __declspec(dllexport) int StartFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->Start();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error starting file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int ReconnectFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->Reconnect();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error reconnecting file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int StopFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->Stop();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error stopping file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFilePlayerPaused(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->IsPaused();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is paused: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFilePlayerRunning(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->IsPlaying();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is running: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFilePlayerRecording(ANSCENTER::ANSFILEPLAYER** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->IsRecording();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is recording: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) void SetFilePlayerAudioVolume(ANSCENTER::ANSFILEPLAYER** Handle, int volume)
{
if (Handle == nullptr || *Handle == nullptr) return;
try {
(*Handle)->SetAudioVolume(volume);
}
catch (...) { }
}
extern "C" __declspec(dllexport) void EnableFilePlayerAudioVolume(ANSCENTER::ANSFILEPLAYER** Handle, int status)
{
if (Handle == nullptr || *Handle == nullptr) return;
try {
bool audioStatus = false;
if (status == 1)audioStatus = true;
(*Handle)->EnableAudio(audioStatus);
}
catch (const std::exception& e) {
std::cerr << "Error enabling audio for file player: " << e.what() << std::endl;
}
catch (...) { }
}
extern "C" __declspec(dllexport) void SetFilePlayerImageRotation(ANSCENTER::ANSFILEPLAYER** Handle, double rotationAngle) {
if (Handle == nullptr || *Handle == nullptr) return;
try {
(*Handle)->SetImageRotate(rotationAngle);
}
catch (...) { }
}
extern "C" __declspec(dllexport) int SetBBoxFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle, int x, int y, int width, int height) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
cv::Rect bbox(x, y, width, height);
(*Handle)->SetBBox(bbox);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error setting bounding box for file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int SetCropFlagFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle, int cropFlag) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool crop = false;
if (cropFlag == 1)crop = true;
(*Handle)->SetCrop(crop);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error setting crop flag for file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
// ============================================================================
// V2 functions: accept uint64_t handleVal by value (LabVIEW-safe)
// ============================================================================
extern "C" __declspec(dllexport) int GetFilePlayerImage_V2(uint64_t handleVal, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
std::string jpegString = h->GetJpegStringImage(width, height, timeStamp);
int size = jpegString.length();
if (size > 0) {
MgErr error;
error = DSSetHandleSize(jpegImage, sizeof(int32) + size * sizeof(uChar));
if (error == noErr) {
(*jpegImage)->cnt = size;
memcpy((*jpegImage)->str, jpegString.c_str(), size);
return 1;
}
else {
std::cerr << "Error resizing jpegImage handle: " << error << std::endl;
return 0;
}
}
else {
std::cerr << "No image data retrieved from FilePlayer client." << std::endl;
return 0;
}
}
catch (const std::exception& e) {
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int GetFilePlayerCVImage_V2(uint64_t handleVal, int& width, int& height, int64_t& timeStamp, cv::Mat** image) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h || !image) return -1;
try {
cv::Mat img = h->GetImage(width, height, timeStamp);
if (img.empty()) {
return 0;
}
anscv_mat_replace(image, std::move(img));
// NV12/CUDA registry attach (same as V1)
int gpuIdx = h->_playerClient->getHWDecodingGpuIndex();
AVFrame* cudaHW = h->_playerClient->getCudaHWFrame();
if (cudaHW) {
AVFrame* cpuNV12 = h->_playerClient->getNV12Frame();
gpu_frame_attach_cuda(*image, cudaHW, gpuIdx, timeStamp, cpuNV12);
} else {
AVFrame* nv12 = h->_playerClient->getNV12Frame();
if (nv12) {
gpu_frame_attach(*image, nv12, gpuIdx, timeStamp);
} else {
cv::Mat infImg = h->GetInferenceImage();
if (!infImg.empty() && infImg.data != (*image)->data) {
h->_inferenceClonePrev = h->_inferenceCloneCurr;
h->_inferenceCloneCurr = infImg.clone();
GpuFrameData data{};
data.avframe = nullptr;
data.yPlane = h->_inferenceCloneCurr.data;
data.uvPlane = nullptr;
data.yLinesize = static_cast<int>(h->_inferenceCloneCurr.step[0]);
data.uvLinesize = 0;
data.width = h->_inferenceCloneCurr.cols;
data.height = h->_inferenceCloneCurr.rows;
data.pixelFormat = 1000;
data.gpuIndex = -1;
data.pts = timeStamp;
data.isCudaDevicePtr = false;
data.cpuAvframe = nullptr;
data.cpuYPlane = nullptr;
data.cpuUvPlane = nullptr;
data.cpuYLinesize = 0;
data.cpuUvLinesize = 0;
ANSGpuFrameRegistry::instance().attach(*image, std::move(data));
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
for (void* p : pending) {
AVFrame* stale = static_cast<AVFrame*>(p);
av_frame_free(&stale);
}
}
}
}
return 1;
}
catch (const cv::Exception& e) {
std::cerr << "OpenCV exception in GetFilePlayerCVImage_V2: " << e.what() << std::endl;
return -2;
}
catch (const std::exception& e) {
std::cerr << "Exception in GetFilePlayerCVImage_V2: " << e.what() << std::endl;
return -2;
}
catch (...) {
std::cerr << "Unknown exception in GetFilePlayerCVImage_V2" << std::endl;
return -2;
}
}
extern "C" __declspec(dllexport) int StartFilePlayer_V2(uint64_t handleVal) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool result = h->Start();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error starting file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int ReconnectFilePlayer_V2(uint64_t handleVal) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool result = h->Reconnect();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error reconnecting file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int StopFilePlayer_V2(uint64_t handleVal) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool result = h->Stop();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error stopping file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFilePlayerPaused_V2(uint64_t handleVal) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool result = h->IsPaused();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is paused: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFilePlayerRunning_V2(uint64_t handleVal) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool result = h->IsPlaying();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is running: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFilePlayerRecording_V2(uint64_t handleVal) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool result = h->IsRecording();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is recording: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) void SetFilePlayerAudioVolume_V2(uint64_t handleVal, int volume) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return;
try {
h->SetAudioVolume(volume);
}
catch (...) { }
}
extern "C" __declspec(dllexport) void EnableFilePlayerAudioVolume_V2(uint64_t handleVal, int status) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return;
try {
bool audioStatus = false;
if (status == 1) audioStatus = true;
h->EnableAudio(audioStatus);
}
catch (const std::exception& e) {
std::cerr << "Error enabling audio for file player: " << e.what() << std::endl;
}
catch (...) { }
}
extern "C" __declspec(dllexport) void SetFilePlayerImageRotation_V2(uint64_t handleVal, double rotationAngle) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return;
try {
h->SetImageRotate(rotationAngle);
}
catch (...) { }
}
extern "C" __declspec(dllexport) int SetBBoxFilePlayer_V2(uint64_t handleVal, int x, int y, int width, int height) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
cv::Rect bbox(x, y, width, height);
h->SetBBox(bbox);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error setting bounding box for file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int SetCropFlagFilePlayer_V2(uint64_t handleVal, int cropFlag) {
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
if (!h) return -1;
try {
bool crop = false;
if (cropFlag == 1) crop = true;
h->SetCrop(crop);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error setting crop flag for file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) void SetFilePlayerDisplayResolution(ANSCENTER::ANSFILEPLAYER** Handle, int width, int height) {
if (Handle == nullptr || *Handle == nullptr) return;
try {
(*Handle)->SetDisplayResolution(width, height);
} catch (...) { }
}

View File

@@ -0,0 +1,117 @@
#ifndef ANSFILEPLAYER_H
#define ANSFILEPLAYER_H
#define ANSFILEPLAYER_API __declspec(dllexport)
#include <iostream>
#include <cstdint>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "rtsp_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "file_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <thread>
#include <chrono>
#include <atomic>
#include <turbojpeg.h>
namespace ANSCENTER
{
class ANSFILEPLAYER_API ANSFILEPLAYER
{
public:
std::unique_ptr<CFilePlayer> _playerClient = std::make_unique<CFilePlayer>();
protected:
std::string _url;
double _imageRotateDeg = 0;
cv::Mat _pLastFrame;
std::string _lastJpegImage;
int _imageWidth = 0, _imageHeight = 0;
int64_t _pts = 0;
bool _isPlaying = false;
std::recursive_mutex _mutex;
// Display/inference split (same pattern as ANSVideoPlayer)
int _displayWidth = 0;
int _displayHeight = 0;
cv::Mat _inferenceImage; // full-res, no display resize
public:
// Public: accessed by extern "C" GetFilePlayerCVImage for NV12/CUDA registry attachment
cv::Mat _inferenceCloneCurr; // current clone for registry (keeps data alive)
cv::Mat _inferenceClonePrev; // previous clone (keeps data alive until next frame)
ANSFILEPLAYER();
~ANSFILEPLAYER() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
void SetImageRotate(double mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
void SetDisplayResolution(int width, int height);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] cv::Mat GetInferenceImage();
[[nodiscard]] std::string GetJpegImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string GetJpegStringImage(int& width, int& height, int64_t& pts) {
return GetJpegImage(width, height, pts);
}
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSFilePlayer", false);
bool _licenseValid{ false };
std::string _licenseKey;
};
}
extern "C" __declspec(dllexport) int CreateANSFilePlayerHandle(ANSCENTER::ANSFILEPLAYER* *Handle, const char* licenseKey, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSFilePlayerHandle(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) int GetFilePlayerImage(ANSCENTER::ANSFILEPLAYER* *Handle, int& width, int& height, int64_t & timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetFilePlayerStrImage(ANSCENTER::ANSFILEPLAYER* *Handle, int& width, int& height, int64_t & timeStamp, std::string & jpegImage);
extern "C" __declspec(dllexport) int GetFilePlayerCVImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartFilePlayer(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) int ReconnectFilePlayer(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) int StopFilePlayer(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) int IsFilePlayerPaused(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) int IsFilePlayerRunning(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) int IsFilePlayerRecording(ANSCENTER::ANSFILEPLAYER* *Handle);
extern "C" __declspec(dllexport) void SetFilePlayerAudioVolume(ANSCENTER::ANSFILEPLAYER* *Handle, int volume);
extern "C" __declspec(dllexport) void EnableFilePlayerAudioVolume(ANSCENTER::ANSFILEPLAYER* *Handle, int status);
extern "C" __declspec(dllexport) void SetFilePlayerImageRotation(ANSCENTER::ANSFILEPLAYER* *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetFilePlayerDisplayResolution(ANSCENTER::ANSFILEPLAYER** Handle, int width, int height);
// V2 functions: accept uint64_t handleVal by value (LabVIEW-safe)
extern "C" __declspec(dllexport) int GetFilePlayerImage_V2(uint64_t handleVal, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetFilePlayerCVImage_V2(uint64_t handleVal, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartFilePlayer_V2(uint64_t handleVal);
extern "C" __declspec(dllexport) int ReconnectFilePlayer_V2(uint64_t handleVal);
extern "C" __declspec(dllexport) int StopFilePlayer_V2(uint64_t handleVal);
extern "C" __declspec(dllexport) int IsFilePlayerPaused_V2(uint64_t handleVal);
extern "C" __declspec(dllexport) int IsFilePlayerRunning_V2(uint64_t handleVal);
extern "C" __declspec(dllexport) int IsFilePlayerRecording_V2(uint64_t handleVal);
extern "C" __declspec(dllexport) void SetFilePlayerAudioVolume_V2(uint64_t handleVal, int volume);
extern "C" __declspec(dllexport) void EnableFilePlayerAudioVolume_V2(uint64_t handleVal, int status);
extern "C" __declspec(dllexport) void SetFilePlayerImageRotation_V2(uint64_t handleVal, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxFilePlayer_V2(uint64_t handleVal, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagFilePlayer_V2(uint64_t handleVal, int cropFlag);
#endif

View File

@@ -0,0 +1,762 @@
#include "ANSFilePlayer_CV.h"
#include "ANSMatRegistry.h"
#include <memory>
#include <cstdint>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/frame.h>
#include "media_codec.h"
static bool ansfileplayerLicenceValid = false;
// Global once_flag to protect license checking
static std::once_flag ansfileplayerLicenseOnceFlag;
namespace ANSCENTER {
#define CHECK_CUDA(call) do { \
cudaError_t err = call; \
if (err != cudaSuccess) { \
std::cout<<"CUDA error: " + std::string(cudaGetErrorString(err)); \
} \
} while (0)
#define CHECK_NVJPEG(call) do { \
nvjpegStatus_t status = call; \
if (status != NVJPEG_STATUS_SUCCESS) { \
std::cout <<"nvJPEG error: " + std::to_string(status); \
} \
} while (0)
ANSFILEPLAYER_CV::ANSFILEPLAYER_CV() :_stopThread(std::make_shared<std::atomic<bool>>(false))
{
_resWidth = 0;
_resHeight = 0;
m_bPaused = false;
_crop = false;
_isPlaying = false;
_lastJpegImage = "";
_bbox = cv::Rect(0, 0, 0, 0);
_jpegCompressor = nullptr;
_previousPTS = 0;
_totalFrames = 0;
}
ANSFILEPLAYER_CV::~ANSFILEPLAYER_CV() noexcept {
try {
StopTimerThread();
Destroy();
}
catch (...) {}
}
void ANSFILEPLAYER_CV::Destroy() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
_previousImage.release();
_lastJpegImage = "";
_isPlaying = false;
_resWidth = 0;
_resHeight = 0;
_currentFrame = 0;
_previousPTS = 0;
if (cap.isOpened()) {
cap.release();
}
}
catch (const std::exception& e) {
_logger.LogError("ANSFILEPLAYER_CV::Destroy. Exception:", e.what(), __FILE__, __LINE__);
}
catch (...) {
_logger.LogError("ANSFILEPLAYER_CV::Destroy.", "Unknown exception", __FILE__, __LINE__);
}
}
static void VerifyGlobalANSFPLicense(const std::string& licenseKey) {
try {
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1007, "ANSCV");//Default productId=1005
if (!ansfileplayerLicenceValid) { // we also support ANSTS license
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1003, "ANSVIS");//Default productId=1003 (ANSVIS)
}
if (!ansfileplayerLicenceValid) { // we also support ANSTS license
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1008, "ANSTS");//Default productId=1008 (ANSTS)
}
}
catch (std::exception& e) {
ansfileplayerLicenceValid = false;
}
}
void ANSFILEPLAYER_CV::CheckLicense() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
// Check once globally
std::call_once(ansfileplayerLicenseOnceFlag, [this]() {
VerifyGlobalANSFPLicense(_licenseKey);
});
// Update this instance's local license flag
_licenseValid = ansfileplayerLicenceValid;
}
catch (const std::exception& e) {
this->_logger.LogFatal("ANSFILEPLAYER_CV::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
}
}
bool ANSFILEPLAYER_CV::Init(std::string licenseKey, std::string url) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_licenseKey = licenseKey;
CheckLicense();
if (!_licenseValid) {
_logger.LogError("ANSFILEPLAYER_CV::Init.", "Invalid license", __FILE__, __LINE__);
return false;
}
_url = url;
return Setup();
}
bool ANSFILEPLAYER_CV::Setup() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_currentFrame = 0;
if (cap.isOpened()) return true;
cap.open(_url, cv::CAP_FFMPEG); // USe FFMPEG for better codec support
if (!cap.isOpened()) {
cap.open(_url, cv::CAP_ANY);
if (!cap.isOpened())return false;
}
try {
_resWidth = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
_resHeight = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
_totalFrames = static_cast<int64_t>(cap.get(cv::CAP_PROP_FRAME_COUNT));
_fps = cap.get(cv::CAP_PROP_FPS);
cap.set(cv::CAP_PROP_POS_FRAMES, _currentFrame);
if (_fps > 0) {
if (_timerThread && _timerThread->joinable()) return true; // Exit if the thread is already running
int interval_ms = static_cast<int>(1000 / _fps);
*_stopThread = false;
_timerThread = std::make_shared<std::thread>(&ANSFILEPLAYER_CV::StartTimer, this, _stopThread, interval_ms);
}
return true;
}
catch (std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::Setup:", e.what(), __FILE__, __LINE__);
return false;
}
}
void ANSFILEPLAYER_CV::StartTimer(std::shared_ptr<std::atomic<bool>> stopFlag, int interval_ms) {
while (!stopFlag->load()) {
std::unique_lock<std::mutex> lock(_cvMutex);
// Wait for the specified interval or until stopFlag is set
if (_cv.wait_for(lock, std::chrono::milliseconds(interval_ms), [&]() {
return stopFlag->load();
})) {
break; // Exit the loop if stopFlag is true
}
lock.unlock(); // Unlock to avoid deadlocks in further operations
int delayMs = 0;
int actualSleepTime = interval_ms;
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
auto start = std::chrono::system_clock::now();
if (_isPlaying) {
try {
_currentFrame = static_cast<int64_t>(cap.get(cv::CAP_PROP_POS_FRAMES));
// Add check for _stopThread before blocking operations
if (!cap.grab() || _currentFrame >= _totalFrames - 1) {
if (cap.isOpened()) {
cap.release();
cap.open(_url, cv::CAP_FFMPEG); // USe FFMPEG for better codec support
if (!cap.isOpened()) {
cap.open(_url, cv::CAP_ANY);
}
}
if (cap.isOpened()) {
cap.set(cv::CAP_PROP_POS_FRAMES, 0);
_currentFrame = 0;
}
}
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::StartTimer. Exception occurred:", e.what(), __FILE__, __LINE__);
}
}
auto end = std::chrono::system_clock::now();
delayMs = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Calculate actual sleep time based on any delay introduced
actualSleepTime = interval_ms - delayMs;
if (actualSleepTime < 1) actualSleepTime = 1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(actualSleepTime));
}
}
void ANSFILEPLAYER_CV::StopTimerThread() {
*_stopThread = true; // Signal to stop the thread
_cv.notify_all(); // Notify the condition variable to unblock the thread
if (_timerThread && _timerThread->joinable()) {
_timerThread->join(); // Join the timer thread to ensure cleanup
}
}
bool ANSFILEPLAYER_CV::Reconnect() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
_currentFrame = 0;
if (cap.isOpened()) {
cap.release();
}
Setup();
_isPlaying = cap.isOpened() && cap.grab();
return _isPlaying;
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::Reconnect. Exception occurred:", e.what(), __FILE__, __LINE__);
_currentFrame = 0;
return false;
}
}
bool ANSFILEPLAYER_CV::Start() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
if (!cap.isOpened()) {
cap.open(_url, cv::CAP_FFMPEG);
if (!cap.isOpened()) {
cap.open(_url, cv::CAP_ANY);
}
if (!cap.isOpened()) {
this->_logger.LogError("ANSFILEPLAYER_CV::Start. Exception occurred:", "Failed to open video source: ", __FILE__, __LINE__);
return false;
}
try {
if (!cap.set(cv::CAP_PROP_POS_FRAMES, _currentFrame)) {
this->_logger.LogError("ANSFILEPLAYER_CV::Start. Exception occurred:", "Warning: Unable to seek to frame", __FILE__, __LINE__);
}
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::Start. Exception occurred:", e.what(), __FILE__, __LINE__);
}
}
_isPlaying = cap.isOpened() && cap.grab();
return _isPlaying;
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::Start. Exception occurred:", e.what(), __FILE__, __LINE__);
return false;
}
}
bool ANSFILEPLAYER_CV::Stop() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
if (cap.isOpened()) {
try {
double frame_pos = cap.get(cv::CAP_PROP_POS_FRAMES);
if (frame_pos >= 0) {
_currentFrame = static_cast<int64_t>(frame_pos);
}
else {
_currentFrame = 0;
this->_logger.LogError("ANSFILEPLAYER_CV::Stop. Exception occurred:", "Unable to retrieve current frame position", __FILE__, __LINE__);
}
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::Stop. Exception occurred:", e.what(), __FILE__, __LINE__);
_currentFrame = 0;
}
cap.release();
}
_isPlaying = false;
return true;
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::Stop. Exception occurred:", e.what(), __FILE__, __LINE__);
return false;
}
}
void ANSFILEPLAYER_CV::SetBBox(cv::Rect bbox) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_bbox = bbox;
}
void ANSFILEPLAYER_CV::SetCrop(bool crop) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_crop = crop;
}
bool ANSFILEPLAYER_CV::IsPaused() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return !cap.isOpened();
}
bool ANSFILEPLAYER_CV::IsPlaying() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return cap.isOpened();
}
bool ANSFILEPLAYER_CV::IsRecording() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return false;// do not support recording for webcam
}
cv::Mat ANSFILEPLAYER_CV::GetImage(int& width, int& height, int64_t& pts) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!_isPlaying) {
if (!_previousImage.empty()) {
width = _previousImage.cols;
height = _previousImage.rows;
pts = _previousPTS;
return _previousImage;
}
return cv::Mat();
}
try {
if (!cap.isOpened()) {
if (!_previousImage.empty()) {
width = _previousImage.cols;
height = _previousImage.rows;
pts = _previousPTS;
return _previousImage;
}
return cv::Mat();
}
cv::Mat frame;
if (!cap.read(frame) || frame.empty()) {
// Return last good frame if available
if (!_previousImage.empty()) {
width = _previousImage.cols;
height = _previousImage.rows;
pts = _previousPTS;
return _previousImage;
}
return cv::Mat();
}
cv::Mat result;
// Apply cropping if enabled
if (_crop) {
// Validate and clamp crop region
_bbox.x = std::clamp(_bbox.x, 0, frame.cols - 1);
_bbox.y = std::clamp(_bbox.y, 0, frame.rows - 1);
_bbox.width = std::min(_bbox.width, frame.cols - _bbox.x);
_bbox.height = std::min(_bbox.height, frame.rows - _bbox.y);
if (_bbox.width > 0 && _bbox.height > 0) {
// CRITICAL: Clone to avoid dangling reference
result = frame(_bbox).clone();
}
else {
result = frame.clone();
}
}
else {
result = frame.clone();
}
// Apply rotation if specified
if (_imageRotateDeg > 0) {
// Fast path for 90-degree rotations
if (std::abs(_imageRotateDeg - 90.0) < 0.01) {
cv::rotate(result, result, cv::ROTATE_90_CLOCKWISE);
}
else if (std::abs(_imageRotateDeg - 180.0) < 0.01) {
cv::rotate(result, result, cv::ROTATE_180);
}
else if (std::abs(_imageRotateDeg - 270.0) < 0.01) {
cv::rotate(result, result, cv::ROTATE_90_COUNTERCLOCKWISE);
}
else {
// Arbitrary angle rotation
const cv::Point2f center(result.cols / 2.0f, result.rows / 2.0f);
cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, _imageRotateDeg, 1.0);
cv::Mat rotated;
// Use INTER_LINEAR instead of INTER_CUBIC (2-3x faster, minimal quality loss)
cv::warpAffine(result, rotated, rotationMatrix, result.size(),
cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar());
result = rotated;
}
}
// Update PTS (presentation timestamp)
if (_previousPTS < INT64_MAX) {
_previousPTS++;
}
else {
_previousPTS = 0;
}
// Update cached frame
_previousImage = result;
// Set output parameters
width = result.cols;
height = result.rows;
pts = _previousPTS;
return result;
}
catch (const cv::Exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::GetImage. OpenCV exception:", e.what(), __FILE__, __LINE__);
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::GetImage. Exception:", e.what(), __FILE__, __LINE__);
}
catch (...) {
this->_logger.LogError("ANSFILEPLAYER_CV::GetImage. Unknown exception", "", __FILE__, __LINE__);
}
return cv::Mat();
}
void ANSFILEPLAYER_CV::EnableAudio(bool status) {
// please support audio enable for webcam
}
void ANSFILEPLAYER_CV::SetAudioVolume(int volume) {
// support audio volumne
}
std::string ANSFILEPLAYER_CV::encodeJpegString(const cv::Mat& img, int quality) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!_isPlaying) return _lastJpegImage;
unsigned char* jpegBuf = nullptr;
tjhandle jpegCompressor = nullptr;
try {
// Initialize TurboJPEG compressor
jpegCompressor = tjInitCompress();
if (!jpegCompressor) {
this->_logger.LogError("Failed to initialize TurboJPEG compressor.", tjGetErrorStr(), __FILE__, __LINE__);
return _lastJpegImage;
}
int maxBufferSize = img.cols * img.rows * 3;
jpegBuf = tjAlloc(maxBufferSize);
if (!jpegBuf) {
this->_logger.LogError("Failed to allocate memory for JPEG buffer.", tjGetErrorStr(), __FILE__, __LINE__);
tjDestroy(jpegCompressor);
return _lastJpegImage;
}
long unsigned int jpegSize = maxBufferSize;
int subsamp = TJSAMP_444;
int pixelFormat = img.channels() == 3 ? TJPF_BGR : TJPF_GRAY;
// Compress the image
if (tjCompress2(jpegCompressor, img.data, img.cols, 0, img.rows, pixelFormat,
&jpegBuf, &jpegSize, subsamp, quality, TJFLAG_FASTDCT) != 0) {
this->_logger.LogError("Compression error:", tjGetErrorStr(), __FILE__, __LINE__);
tjFree(jpegBuf);
tjDestroy(jpegCompressor);
return _lastJpegImage;
}
// Create string from JPEG buffer
std::string jpegString(reinterpret_cast<char*>(jpegBuf), jpegSize);
_lastJpegImage = jpegString;
}
catch (const std::exception& e) {
this->_logger.LogError("Exception occurred:", e.what(), __FILE__, __LINE__);
}
// Cleanup resources
if (jpegBuf) tjFree(jpegBuf);
if (jpegCompressor) tjDestroy(jpegCompressor);
return _lastJpegImage;
}
std::string ANSFILEPLAYER_CV::MatToBinaryData(const cv::Mat& image) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
// Check if the image is empty or has invalid data
if (!_isPlaying) return _lastJpegImage;
if (image.empty() || !image.data || !image.u) {
return _lastJpegImage;
}
try {
// Encode the image to a memory buffer
return encodeJpegString(image, 85);
}
catch (const std::exception& e) {
this->_logger.LogFatal("ANSFILEPLAYER_CV::MatToBinaryData. Exception occurred:", e.what(), __FILE__, __LINE__);
}
catch (...) {
this->_logger.LogFatal("ANSFILEPLAYER_CV::MatToBinaryData.", "Unknown exception occurred.", __FILE__, __LINE__);
}
// Return an empty string in case of failure
return _lastJpegImage;
}
std::string ANSFILEPLAYER_CV::GetJpegStringImage(int& width, int& height, int64_t& pts) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!_isPlaying) return _lastJpegImage;
try {
cv::Mat image = GetImage(width, height, pts);
std::string jpegString = MatToBinaryData(image);
image.release();
return jpegString;
}
catch (const std::exception& e) {
this->_logger.LogError("ANSFILEPLAYER_CV::GetJpegStringImage. Exception occurred:", e.what(), __FILE__, __LINE__);
return _lastJpegImage;
}
}
}
extern "C" __declspec(dllexport) int CreateANSFileCVPlayerHandle(ANSCENTER::ANSFILEPLAYER_CV** Handle, const char* licenseKey, const char* url) {
if (!Handle || !licenseKey || !url) return -1;
try {
auto ptr = std::make_unique<ANSCENTER::ANSFILEPLAYER_CV>();
bool result = ptr->Init(licenseKey, url);
if (result) {
*Handle = ptr.release();
extern void anscv_unregister_handle(void*);
extern void anscv_register_handle(void*, void(*)(void*));
anscv_register_handle(*Handle, [](void* p) {
auto* h = static_cast<ANSCENTER::ANSFILEPLAYER_CV*>(p);
try { h->Stop(); } catch (...) {}
try { h->Destroy(); } catch (...) {}
try { delete h; } catch (...) {}
});
return 1;
}
*Handle = nullptr;
return 0;
}
catch (...) { return 0; }
}
extern "C" __declspec(dllexport) int ReleaseANSFileCVPlayerHandle(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
extern void anscv_unregister_handle(void*);
anscv_unregister_handle(*Handle);
// Destructor calls Destroy() <20> no need to call it explicitly (avoids double-destroy)
std::unique_ptr<ANSCENTER::ANSFILEPLAYER_CV> ptr(*Handle);
*Handle = nullptr;
return 0;
}
catch (...) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" __declspec(dllexport) int GetFileCVPlayerStrImage(ANSCENTER::ANSFILEPLAYER_CV** Handle, int& width, int& height, int64_t& timeStamp, std::string& jpegImage) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
jpegImage = (*Handle)->GetJpegStringImage(width, height, timeStamp);
if (!jpegImage.empty()) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int GetFileCVPlayerImage(ANSCENTER::ANSFILEPLAYER_CV** Handle, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
std::string jpegString = (*Handle)->GetJpegStringImage(width, height, timeStamp);
int size = jpegString.length();
if (size > 0) {
MgErr error;
// Resize the jpegImage handle to hold the image data
error = DSSetHandleSize(jpegImage, sizeof(int32) + size * sizeof(uChar));
// Check if resizing the handle was successful
if (error == noErr) {
// Set the size of the image in the handle
(*jpegImage)->cnt = size;
// Use memcpy to copy the data from the std::string to the LStrHandle's str buffer
memcpy((*jpegImage)->str, jpegString.c_str(), size);
// Return success
return 1;
}
else {
// Return failure if there was an error in resizing the handle
std::cerr << "Error resizing jpegImage handle: " << error << std::endl;
return 0;
}
}
else {
// If the JPEG image string is empty, return failure
std::cerr << "No image data retrieved from FilePlayer client." << std::endl;
return 0;
}
}
catch (const std::exception& e) {
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int GetFileCVPlayerCVImage(ANSCENTER::ANSFILEPLAYER_CV** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image) {
if (!Handle || !(*Handle) || !image) {
std::cerr << "Error: Invalid input parameters in GetFilePlayerCVImage." << std::endl;
return -1;
}
try {
cv::Mat img = (*Handle)->GetImage(width, height, timeStamp);
if (img.empty()) {
return 0; // No valid image retrieved
}
// anscv_mat_replace has its own internal registry_mutex <20> no global mutex needed
anscv_mat_replace(image, std::move(img));
return 1; // Success
}
catch (const cv::Exception& e) {
std::cerr << "OpenCV exception in GetFilePlayerCVImage: " << e.what() << std::endl;
return -2;
}
catch (const std::exception& e) {
std::cerr << "Exception in GetFilePlayerCVImage: " << e.what() << std::endl;
return -2;
}
catch (...) {
std::cerr << "Unknown exception in GetFilePlayerCVImage" << std::endl;
return -2;
}
}
extern "C" __declspec(dllexport) int StartFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->Start();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error starting file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int ReconnectFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->Reconnect();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error reconnecting file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int StopFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->Stop();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error stopping file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFileCVPlayerPaused(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->IsPaused();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is paused: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFileCVPlayerRunning(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->IsPlaying();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is running: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int IsFileCVPlayerRecording(ANSCENTER::ANSFILEPLAYER_CV** Handle) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool result = (*Handle)->IsRecording();
if (result) return 1;
else return 0;
}
catch (const std::exception& e) {
std::cerr << "Error checking if file player is recording: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) void SetFileCVPlayerAudioVolume(ANSCENTER::ANSFILEPLAYER_CV** Handle, int volume)
{
if (Handle == nullptr || *Handle == nullptr) return;
try {
(*Handle)->SetAudioVolume(volume);
}
catch (...) {}
}
extern "C" __declspec(dllexport) void EnableFileCVPlayerAudioVolume(ANSCENTER::ANSFILEPLAYER_CV** Handle, int status)
{
if (Handle == nullptr || *Handle == nullptr) return;
try {
bool audioStatus = false;
if (status == 1)audioStatus = true;
(*Handle)->EnableAudio(audioStatus);
}
catch (const std::exception& e) {
std::cerr << "Error enabling audio for file player: " << e.what() << std::endl;
}
catch (...) {}
}
extern "C" __declspec(dllexport) void SetFileCVPlayerImageRotation(ANSCENTER::ANSFILEPLAYER_CV** Handle, double rotationAngle) {
if (Handle == nullptr || *Handle == nullptr) return;
try {
(*Handle)->SetImageRotate(rotationAngle);
}
catch (...) {}
}
extern "C" __declspec(dllexport) int SetBBoxFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle, int x, int y, int width, int height) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
cv::Rect bbox(x, y, width, height);
(*Handle)->SetBBox(bbox);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error setting bounding box for file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}
extern "C" __declspec(dllexport) int SetCropFlagFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle, int cropFlag) {
if (Handle == nullptr || *Handle == nullptr) return -1;
try {
bool crop = false;
if (cropFlag == 1)crop = true;
(*Handle)->SetCrop(crop);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error setting crop flag for file player: " << e.what() << std::endl;
return -1;
}
catch (...) {
return -1;
}
}

View File

@@ -0,0 +1,115 @@
#ifndef ANSFILEPLAYER_H
#define ANSFILEPLAYER_H
#define ANSFILEPLAYER_API __declspec(dllexport)
#include <iostream>
#include <cstdint>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "rtsp_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "file_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <thread>
#include <chrono>
#include <atomic>
#include <turbojpeg.h>
namespace ANSCENTER
{
class ANSFILEPLAYER_API ANSFILEPLAYER_CV
{
protected:
cv::VideoCapture cap;
int _resWidth;
int _resHeight;
int64_t _totalFrames;
int64_t _currentFrame;
int64_t _previousPTS;
double _fps;
bool _isPlaying;
std::string _lastJpegImage;
//int64_t _previousPTS;
cv::Mat _previousImage;
bool m_bPaused;
int _imageRotateDeg = 0;
std::string _url;
cv::Rect _bbox;
bool _crop;
std::recursive_mutex _mutex;
std::shared_ptr<std::atomic<bool>> _stopThread;
std::shared_ptr<std::thread> _timerThread;
std::mutex _cvMutex;
std::condition_variable _cv;
//EngineType engineType;
//// Initialize nvJPEG structures
//nvjpegHandle_t nv_handle;
//nvjpegEncoderState_t nv_enc_state;
//nvjpegEncoderParams_t nv_enc_params;
//cudaStream_t stream;
tjhandle _jpegCompressor;
public:
ANSFILEPLAYER_CV();
~ANSFILEPLAYER_CV() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
[[nodiscard]] bool Stop();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegStringImage(int& width, int& height, int64_t& pts);
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSFilePlayer_CV", false);
bool _licenseValid{ false };
//std::once_flag licenseOnceFlag;
std::string _licenseKey;
private:
std::string encodeJpegString(const cv::Mat& img, int quality = 80);
//std::string encodeMatToJpegWithNvJPEG(const cv::Mat& inputMat, int quality = 80);
//void uploadPlanarBGRToGPU(const cv::Mat& inputMat, unsigned char** data);
void StartTimer(std::shared_ptr<std::atomic<bool>> stopFlag, int interval_ms);
void StopTimerThread();
};
}
extern "C" __declspec(dllexport) int CreateANSFileCVPlayerHandle(ANSCENTER::ANSFILEPLAYER_CV** Handle, const char* licenseKey, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSFileCVPlayerHandle(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) int GetFileCVPlayerImage(ANSCENTER::ANSFILEPLAYER_CV** Handle, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetFileCVPlayerStrImage(ANSCENTER::ANSFILEPLAYER_CV** Handle, int& width, int& height, int64_t& timeStamp, std::string& jpegImage);
extern "C" __declspec(dllexport) int GetFileCVPlayerCVImage(ANSCENTER::ANSFILEPLAYER_CV** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) int ReconnectFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) int StopFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) int IsFileCVPlayerPaused(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) int IsFileCVPlayerRunning(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) int IsFileCVPlayerRecording(ANSCENTER::ANSFILEPLAYER_CV** Handle);
extern "C" __declspec(dllexport) void SetFileCVPlayerAudioVolume(ANSCENTER::ANSFILEPLAYER_CV** Handle, int volume);
extern "C" __declspec(dllexport) void EnableFileCVPlayerAudioVolume(ANSCENTER::ANSFILEPLAYER_CV** Handle, int status);
extern "C" __declspec(dllexport) void SetFileCVPlayerImageRotation(ANSCENTER::ANSFILEPLAYER_CV** Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagFileCVPlayer(ANSCENTER::ANSFILEPLAYER_CV** Handle, int cropFlag);
#endif

View File

@@ -0,0 +1,212 @@
#pragma once
// ANSGpuFrameOps.h — FFmpeg-aware convenience functions for ANSGpuFrameRegistry.
//
// This header requires FFmpeg headers (libavutil/frame.h) and provides
// typed attach/invalidate/remove operations that handle av_frame_clone/free.
//
// NEW DESIGN: Instead of storing AVFrame* references (which lock NVDEC surfaces),
// we snapshot the CPU NV12 planes into malloc'd buffers and release the AVFrames
// immediately. This prevents decoder surface pool exhaustion when many clones
// hold references to the same frame.
//
// Include this in ANSCV/ANSRTSP (which link FFmpeg). For projects without
// FFmpeg (ANSODEngine), include ANSGpuFrameRegistry.h directly and use
// gpu_frame_lookup() + the GpuFrameData plane pointers.
#include "ANSGpuFrameRegistry.h"
extern "C" {
#include "libavutil/frame.h"
}
#include <cstring>
#include <cstdlib>
namespace anscv_gpu_ops {
namespace detail {
// Snapshot NV12 Y and UV planes from an AVFrame into malloc'd buffers.
// Returns true on success. Caller owns the output buffers.
inline bool snapshotNV12Planes(const AVFrame* nv12,
uint8_t*& outY, int& outYLinesize,
uint8_t*& outUV, int& outUVLinesize,
int& outWidth, int& outHeight) {
if (!nv12 || !nv12->data[0] || !nv12->data[1])
return false;
outWidth = nv12->width;
outHeight = nv12->height;
outYLinesize = nv12->width; // Packed (no alignment padding)
outUVLinesize = nv12->width; // UV interleaved: width bytes per row
size_t yBytes = static_cast<size_t>(outYLinesize) * outHeight;
size_t uvBytes = static_cast<size_t>(outUVLinesize) * (outHeight / 2);
outY = static_cast<uint8_t*>(std::malloc(yBytes));
outUV = static_cast<uint8_t*>(std::malloc(uvBytes));
if (!outY || !outUV) {
std::free(outY);
std::free(outUV);
outY = nullptr;
outUV = nullptr;
return false;
}
// Copy line-by-line (source may have padding via linesize > width)
const int srcYLinesize = nv12->linesize[0];
const int srcUVLinesize = nv12->linesize[1];
for (int row = 0; row < outHeight; ++row) {
std::memcpy(outY + row * outYLinesize,
nv12->data[0] + row * srcYLinesize,
outWidth);
}
for (int row = 0; row < outHeight / 2; ++row) {
std::memcpy(outUV + row * outUVLinesize,
nv12->data[1] + row * srcUVLinesize,
outWidth);
}
return true;
}
} // namespace detail
} // namespace anscv_gpu_ops
// Attach NV12/YUV frame keyed by cv::Mat* pointer.
// Snapshots CPU NV12 planes into owned malloc'd buffers, then releases the AVFrame.
// TAKES OWNERSHIP of nv12 — caller must NOT av_frame_free after this call.
inline void gpu_frame_attach(cv::Mat* mat, AVFrame* nv12, int gpuIdx, int64_t pts) {
if (!mat || !nv12) return;
GpuFrameData data{};
data.gpuIndex = gpuIdx;
data.pts = pts;
data.pixelFormat = nv12->format;
data.width = nv12->width;
data.height = nv12->height;
// Snapshot NV12 planes to owned buffers
bool ok = anscv_gpu_ops::detail::snapshotNV12Planes(
nv12,
data.cpuYPlane, data.cpuYLinesize,
data.cpuUvPlane, data.cpuUvLinesize,
data.width, data.height);
// Keep legacy pointers for backward compat during transition
data.yPlane = data.cpuYPlane;
data.uvPlane = data.cpuUvPlane;
data.yLinesize = data.cpuYLinesize;
data.uvLinesize = data.cpuUvLinesize;
// Store AVFrame for legacy cleanup (will be freed by drain_pending)
data.avframe = nv12;
void* old = ANSGpuFrameRegistry::instance().attach(mat, std::move(data));
if (old) {
AVFrame* oldFrame = static_cast<AVFrame*>(old);
av_frame_free(&oldFrame);
}
// Free stale entries evicted by TTL or previous attach
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
for (void* p : pending) {
AVFrame* stale = static_cast<AVFrame*>(p);
av_frame_free(&stale);
}
}
// Attach CUDA HW frame — keeps CUDA device pointers for zero-copy inference.
// TAKES OWNERSHIP of cudaFrame AND cpuNV12 — caller must NOT av_frame_free after.
//
// Primary path: yPlane/uvPlane point to CUDA device pointers from the cloned
// AVFrame (data[0]/data[1]). The cloned AVFrame keeps the NVDEC surface alive
// until gpu_frame_remove() is called after inference. With 4 cameras each
// holding ~1 surface, this uses 4 of NVDEC's 25-32 surface pool — safe.
//
// Fallback: cpuYPlane/cpuUvPlane hold CPU-side NV12 snapshot for cross-GPU
// inference (when decode GPU != inference GPU, CUDA device ptrs aren't
// accessible from another GPU context).
inline void gpu_frame_attach_cuda(cv::Mat* mat, AVFrame* cudaFrame, int gpuIdx, int64_t pts,
AVFrame* cpuNV12 = nullptr) {
if (!mat || !cudaFrame) return;
GpuFrameData data{};
data.gpuIndex = gpuIdx;
data.pts = pts;
data.width = cudaFrame->width;
data.height = cudaFrame->height;
data.pixelFormat = 23; // AV_PIX_FMT_NV12 — the underlying sw_format
// Primary: CUDA device pointers from NVDEC (zero-copy on same GPU)
data.isCudaDevicePtr = true;
data.yPlane = cudaFrame->data[0]; // CUDA device ptr: Y plane
data.uvPlane = cudaFrame->data[1]; // CUDA device ptr: UV plane
data.yLinesize = cudaFrame->linesize[0];
data.uvLinesize = cudaFrame->linesize[1];
// Fallback: snapshot CPU NV12 for cross-GPU inference
if (cpuNV12) {
anscv_gpu_ops::detail::snapshotNV12Planes(
cpuNV12,
data.cpuYPlane, data.cpuYLinesize,
data.cpuUvPlane, data.cpuUvLinesize,
data.width, data.height);
}
// Store AVFrames for cleanup (cudaFrame keeps NVDEC surface alive)
data.avframe = cudaFrame;
data.cpuAvframe = cpuNV12;
void* old = ANSGpuFrameRegistry::instance().attach(mat, std::move(data));
if (old) {
AVFrame* oldFrame = static_cast<AVFrame*>(old);
av_frame_free(&oldFrame);
}
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
for (void* p : pending) {
AVFrame* stale = static_cast<AVFrame*>(p);
av_frame_free(&stale);
}
}
// Release entry by cv::Mat* and free any returned AVFrames. Safe if not in map (no-op).
inline void gpu_frame_remove(cv::Mat* mat) {
if (!mat) return;
ANSGpuFrameRegistry::instance().release(mat);
// Free any AVFrames that became pending from this release or prior eviction
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
for (void* p : pending) {
AVFrame* stale = static_cast<AVFrame*>(p);
av_frame_free(&stale);
}
// Free any GPU device pointers that became pending
auto gpuPending = gpu_frame_drain_gpu_pending();
// NOTE: cudaFree requires CUDA context — caller must be on a CUDA-capable thread.
// If not, these will leak. In practice, gpu_frame_remove is called from ANSCV
// camera threads which do have CUDA context.
// For safety, we skip cudaFree here and let NV12PreprocessHelper handle it.
// The GPU pointers are tracked in the budget and will be accounted for.
(void)gpuPending;
}
// Alias for remove — used in ANSCV mutating functions to drop stale GPU data.
inline void gpu_frame_invalidate(cv::Mat* mat) {
gpu_frame_remove(mat);
}
// Run TTL eviction + drain pending. Call periodically from camera threads.
inline void gpu_frame_evict_stale() {
ANSGpuFrameRegistry::instance().evictStaleFrames();
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
for (void* p : pending) {
AVFrame* stale = static_cast<AVFrame*>(p);
av_frame_free(&stale);
}
}

View File

@@ -0,0 +1,25 @@
// ANSGpuFrameRegistry.cpp — Process-wide singleton, compiled into ANSCV.dll.
//
// On Windows, header-only singletons (static local in inline function) create
// separate instances in each DLL. Since gpu_frame_attach() runs in ANSCV.dll
// and gpu_frame_lookup() runs in ANSODEngine.dll, we need a single shared
// instance. This file:
// 1. Defines resolveProcessWide() which owns the canonical singleton.
// 2. Exports a C function so other DLLs can find it via GetProcAddress.
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include "ANSGpuFrameRegistry.h"
// ANSCV.dll owns the process-wide singleton.
ANSGpuFrameRegistry* ANSGpuFrameRegistry::resolveProcessWide() {
static ANSGpuFrameRegistry reg;
return &reg;
}
// Exported so other DLLs (ANSODEngine, etc.) can find this instance at runtime.
extern "C" __declspec(dllexport)
ANSGpuFrameRegistry* ANSGpuFrameRegistry_GetInstance() {
return &ANSGpuFrameRegistry::instance();
}

1175
ANSLIB/ANSCV/ANSMJPEG.cpp Normal file

File diff suppressed because it is too large Load Diff

111
ANSLIB/ANSCV/ANSMJPEG.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef ANSMJPEG_H
#define ANSMJPEG_H
#define ANSMJPEG_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "http_mjpeg_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "http_mjpeg_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
namespace ANSCENTER
{
class ANSMJPEG_API ANSMJPEGClient
{
protected:
std::unique_ptr<CHttpMjpegPlayer> _playerClient = std::make_unique<CHttpMjpegPlayer>();
std::string _username;
std::string _password;
std::string _url;
bool _useFullURL;
int _imageRotateDeg = 0;
int _displayWidth = 0; // 0 = no resize (return original resolution)
int _displayHeight = 0;
cv::Mat _pLastFrame;
std::string _lastJpegImage;
int _imageWidth, _imageHeight;
int64_t _pts;
bool _isPlaying;
std::recursive_mutex _mutex;
public:
ANSMJPEGClient();
~ANSMJPEGClient() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Init(std::string licenseKey, std::string username, std::string password, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool Pause();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
bool areImagesIdentical(const cv::Mat& img1, const cv::Mat& img2);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegImage(int& width, int& height, int64_t& pts);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
static void SetMaxHWDecoders(int maxDecoders);
static int AutoConfigureHWDecoders(int maxPerGpuOverride = 0);
void SetHWDecoding(int hwMode, int preferredGpu = -1);
bool IsHWDecodingActive();
int GetHWDecodingGpuIndex();
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
void SetImageQuality(int mode); // 0=fast (AI), 1=quality (display)
AVFrame* GetNV12Frame(); // Returns cloned NV12 frame for GPU fast-path (caller must av_frame_free)
AVFrame* GetCudaHWFrame(); // Returns CUDA HW frame (device ptrs) for zero-copy inference
bool IsCudaHWAccel(); // true when decoder uses CUDA (NV12 stays in GPU VRAM)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSMJPEG", false);
bool _licenseValid{ false };
std::string _licenseKey;
//std::once_flag licenseOnceFlag;
};
}
extern "C" __declspec(dllexport) int CreateANSMJPEGHandle(ANSCENTER::ANSMJPEGClient * *Handle, const char* licenseKey, const char* username, const char* password, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSMJPEGHandle(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) int GetMJPEGImage(ANSCENTER::ANSMJPEGClient * *Handle, int& width, int& height, int64_t & timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetMJPEGStrImage(ANSCENTER::ANSMJPEGClient * *Handle, int& width, int& height, int64_t & timeStamp, std::string & jpegImage);
extern "C" __declspec(dllexport) int GetMJPEGCVImage(ANSCENTER::ANSMJPEGClient** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartMJPEG(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) int ReconnectMJPEG(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) int StopMJPEG(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) int PauseMJPEG(ANSCENTER::ANSMJPEGClient** Handle);
extern "C" __declspec(dllexport) int IsMJPEGPaused(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) int IsMJPEGRunning(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) int IsMJPEGRecording(ANSCENTER::ANSMJPEGClient * *Handle);
extern "C" __declspec(dllexport) void SetMJPEGAudioVolume(ANSCENTER::ANSMJPEGClient * *Handle, int volume);
extern "C" __declspec(dllexport) void EnableMJPEGAudioVolume(ANSCENTER::ANSMJPEGClient * *Handle, int status);
extern "C" __declspec(dllexport) void SetMJPEGImageRotation(ANSCENTER::ANSMJPEGClient * *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxMJPEG(ANSCENTER::ANSMJPEGClient** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagMJPEG(ANSCENTER::ANSMJPEGClient** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetMJPEGMaxHWDecoders(int maxDecoders);
extern "C" __declspec(dllexport) int AutoConfigureMJPEGHWDecoders(int maxPerGpuOverride);
extern "C" __declspec(dllexport) void SetMJPEGHWDecoding(ANSCENTER::ANSMJPEGClient** Handle, int hwMode, int preferredGpu = -1);
extern "C" __declspec(dllexport) int IsMJPEGHWDecodingActive(ANSCENTER::ANSMJPEGClient** Handle);
extern "C" __declspec(dllexport) int GetMJPEGHWDecodingGpuIndex(ANSCENTER::ANSMJPEGClient** Handle);
extern "C" __declspec(dllexport) void SetMJPEGImageQuality(ANSCENTER::ANSMJPEGClient** Handle, int mode);
extern "C" __declspec(dllexport) void SetMJPEGDisplayResolution(ANSCENTER::ANSMJPEGClient** Handle, int width, int height);
#endif

View File

@@ -0,0 +1,116 @@
#pragma once
// ANSMatRegistry.h — Thread-safe cv::Mat* pointer registry.
// Prevents double-free crashes when LabVIEW calls ReleaseImage on a pointer
// that a stream source (RTSP, VideoPlayer, etc.) has already freed and replaced.
//
// Every cv::Mat* allocated through these functions is tracked in a global set.
// Deletion only proceeds if the pointer is still in the set, guaranteeing each
// pointer is freed exactly once regardless of which thread calls delete first.
//
// Usage:
// Allocate: cv::Mat* p = anscv_mat_new(std::move(img));
// Free: anscv_mat_delete(&p); // safe, no-op if already freed
// Swap: anscv_mat_replace(&p, std::move(newImg)); // atomic old-delete + new-alloc
#include <opencv2/core/mat.hpp>
#include <mutex>
#include <unordered_set>
#include "ANSGpuFrameOps.h"
namespace anscv {
namespace detail {
inline std::mutex& registry_mutex() {
static std::mutex m;
return m;
}
inline std::unordered_set<cv::Mat*>& registry() {
static std::unordered_set<cv::Mat*> s;
return s;
}
} // namespace detail
} // namespace anscv
// Allocate a new cv::Mat on the heap and register it.
inline cv::Mat* anscv_mat_new(cv::Mat&& src) {
cv::Mat* p = new cv::Mat(std::move(src));
{
std::lock_guard<std::mutex> lk(anscv::detail::registry_mutex());
anscv::detail::registry().insert(p);
}
return p;
}
inline cv::Mat* anscv_mat_new(const cv::Mat& src) {
cv::Mat* p = new cv::Mat(src);
{
std::lock_guard<std::mutex> lk(anscv::detail::registry_mutex());
anscv::detail::registry().insert(p);
}
return p;
}
// Delete a cv::Mat* only if it is still in the registry.
// Returns true if deleted, false if pointer was null or already freed.
// Thread-safe: the pointer is removed from the registry AND nulled AND deleted
// all inside the lock, so no other thread can race on the same pointer.
inline bool anscv_mat_delete(cv::Mat** pp) {
if (!pp || !(*pp))
return false;
cv::Mat* toDelete = nullptr;
{
std::lock_guard<std::mutex> lk(anscv::detail::registry_mutex());
// Re-check under lock — another thread may have nulled *pp
if (!*pp)
return false;
auto& reg = anscv::detail::registry();
auto it = reg.find(*pp);
if (it == reg.end()) {
// Not in registry — already freed by another thread.
*pp = nullptr;
return false;
}
toDelete = *pp;
reg.erase(it);
*pp = nullptr; // Null the caller's pointer while still under lock
}
// Release GPU frame data (refcount--, frees NV12+GPU cache when refcount=0)
gpu_frame_remove(toDelete);
// Safe to delete outside lock: pointer is removed from registry and
// *pp is nullptr, so no other thread can reach toDelete.
delete toDelete;
return true;
}
// Atomic replace: delete old image (if still registered), allocate new, assign to *pp.
// The old pointer is only deleted if it is in the registry (prevents double-free
// when LabVIEW already freed it via anscv_mat_delete).
inline void anscv_mat_replace(cv::Mat** pp, cv::Mat&& newImg) {
cv::Mat* newPtr = new cv::Mat(std::move(newImg));
cv::Mat* toDelete = nullptr;
{
std::lock_guard<std::mutex> lk(anscv::detail::registry_mutex());
auto& reg = anscv::detail::registry();
if (pp && *pp) {
auto it = reg.find(*pp);
if (it != reg.end()) {
toDelete = *pp;
reg.erase(it);
}
// If not in registry, another thread already freed it — skip delete
}
*pp = newPtr;
reg.insert(newPtr);
}
if (toDelete) {
// Release GPU frame ref for old Mat (safe with refcounting —
// only frees NV12/GPU cache when refcount reaches 0)
gpu_frame_remove(toDelete);
delete toDelete;
}
// Periodically run TTL eviction (piggybacked on camera thread activity)
gpu_frame_evict_stale();
}

5106
ANSLIB/ANSCV/ANSOpenCV.cpp Normal file

File diff suppressed because it is too large Load Diff

164
ANSLIB/ANSCV/ANSOpenCV.h Normal file
View File

@@ -0,0 +1,164 @@
#ifndef ANSOPENCV_H
#define ANSOPENCV_H
#define ANSOPENCV_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include <opencv2/opencv.hpp>
#define MUTEX_TIMEOUT_MS 45000
namespace fs = std::filesystem;
namespace ANSCENTER
{
std::string CompressJpegToString(const cv::Mat& image, int quality);
struct DetectionObject
{
int classId{ 0 };
int trackId{ 0 };
std::string className{};
float confidence{ 0.0 };
cv::Rect box{};
cv::Mat mask{}; //Json string mask ="point1.x,point1.y,...."
std::vector<float> kps{}; // Pose exsimate keypoint
std::string extraInfo; // More information such as facial recognition
};
class TurboJpegCompressor {
public:
TurboJpegCompressor();
~TurboJpegCompressor() noexcept;
// Delete copy constructor and assignment operator
TurboJpegCompressor(const TurboJpegCompressor&) = delete;
TurboJpegCompressor& operator=(const TurboJpegCompressor&) = delete;
// Your original logic with minimal optimizations
[[nodiscard]] std::string compress(const cv::Mat& image, int quality);
private:
void* _handle = nullptr;
unsigned char* _buffer = nullptr;
unsigned long _bufferSize = 0;
};
/// <summary>
/// // ANSOPENCV class provides various image processing functionalities using OpenCV and ANS Center SDK.
/// </summary>
class ANSOPENCV_API ANSOPENCV
{
public:
[[nodiscard]] bool Init(std::string licenseKey);
void ImageResize(const cv::Mat& inputFrame, int width, int height, cv::Mat& outputFrame);
void ImageResizeWithRatio(const cv::Mat& inputFrame, int width, cv::Mat& outputFrame);
[[nodiscard]] cv::Mat BlurObjects(const cv::Mat& image, const std::vector<cv::Rect>& objects);
[[nodiscard]] cv::Mat BlurBackground(const cv::Mat& image, const std::vector<cv::Rect>& objects);
[[nodiscard]] cv::Mat ToGray(const cv::Mat& image);
[[nodiscard]] cv::Mat ImageDenoise(const cv::Mat& image);
[[nodiscard]] cv::Mat ImageRepair(const cv::Mat& image);
[[nodiscard]] cv::Mat ImageCrop(const cv::Mat& image,const cv::Rect& ROI, int originalImageSize = 0);
[[nodiscard]] cv::Mat ImageResizeV2(const cv::Mat& image, int resizeWidth, int orginalImageSize = 0);
[[nodiscard]] std::string QRDecoder(const cv::Mat& image);
[[nodiscard]] std::string QRDecoderWithBBox(const cv::Mat& image, int maxImageSize, const std::vector<cv::Rect>& bBox);
[[nodiscard]] std::string MatToBase64(const cv::Mat& image);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::vector<cv::Rect> GetBoundingBoxes(std::string strBBoxes);
[[nodiscard]] std::string VectorDetectionToJsonString(const std::vector<DetectionObject>& dets);
[[nodiscard]] std::string PatternMatches(cv::Mat& image, cv::Mat& templateImage, double threshold);
[[nodiscard]] cv::Mat ImageDarkEnhancement(const cv::Mat& img, double brightnessScaleFactor=1.5);
[[nodiscard]] cv::Mat ImageContrastEnhancement(const cv::Mat& img);
[[nodiscard]] cv::Mat ImageWhiteBalance(const cv::Mat& img);
[[nodiscard]] cv::Mat RotateImage(const cv::Mat& image, double angle);
[[nodiscard]] cv::Mat FlipImage(const cv::Mat& image, int flipCode);//flipCode = 0: Vertical flip (around the x-axis). flipCode = 1: Horizontal flip (around the y-axis). flipCode = -1: Both axes, flipping the image horizontally and vertically.
[[nodiscard]] cv::Mat ShiftImage(const cv::Mat& image, int shiftX, int shiftY);
[[nodiscard]] cv::Mat AddGaussianNoise(const cv::Mat& image, double mean, double stddev);
[[nodiscard]] cv::Mat AddSaltAndPepperNoise(const cv::Mat& image, double amount);
[[nodiscard]] cv::Mat AddSpeckleNoise(const cv::Mat& image, double stddev);
static void InitCameraNetwork();
static void DeinitCameraNetwork();
static cv::Mat resizeImageToFit(const cv::Mat& inputImage, int maxWidth, int maxHeight, int& newWidth, int& newHeight);
static bool resizeImage(cv::Mat& inputImage, int resizeWidth, int orginalImageSize=0);
static bool cropImage(cv::Mat& inputImage, const cv::Rect& resizeROI, int originalImageSize=0);
static bool ImagesToMP4(const std::string& imageFolder, const std::string& outputVideoPath, int targetDurationSec);
private:
void CheckLicense();
double CalculateIoU(const cv::Rect& box1, const cv::Rect& box2);
void NonMaximumSuppression(std::vector<DetectionObject>& detectedObjects, double iouThreshold);
std::string EncodeJpegString(const cv::Mat& img, int quality);
SPDLogger& _logger = SPDLogger::GetInstance("ANSCV", false);
std::string _licenseKey;
std::recursive_mutex _mutex;
//std::once_flag licenseOnceFlag; // For one-time license check
bool _licenseValid = false;
public:
};
}
extern "C" __declspec(dllexport) int CreateANSCVHandle(ANSCENTER::ANSOPENCV **Handle, const char* licenseKey);
extern "C" __declspec(dllexport) int ReleaseANSCVHandle(ANSCENTER::ANSOPENCV **Handle);
extern "C" __declspec(dllexport) int ANSCV_ImageResize(ANSCENTER::ANSOPENCV * *Handle,unsigned char* inputImage, unsigned int bufferLength, int width, int height, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageResizeWithRatio(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, int width,LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageToBase64(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageToGray(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageDenoise(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageRepair(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageAutoWhiteBalance(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageBrightEnhance(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, double brightnessScaleFactor, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageContrastEnhance(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ImageCrop(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, int x, int y, int width, int height, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_GetImageSize(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle imageSize);
extern "C" __declspec(dllexport) int ANSCV_GetImageSizeFromImageFile(ANSCENTER::ANSOPENCV** Handle, const char* imageFilePath, LStrHandle imageSize);
extern "C" __declspec(dllexport) int ANSCV_BlurObjects(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, const char* strBboxes, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_BlurBackground(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, const char* strBboxes, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_QRDecoder(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, LStrHandle detectedQRText);
extern "C" __declspec(dllexport) int ANSCV_QRDecoderCV(ANSCENTER::ANSOPENCV** Handle, const cv::Mat &image, std::string& detectedQRText);
extern "C" __declspec(dllexport) int ANSCV_PatternMatchs(ANSCENTER::ANSOPENCV * *Handle, unsigned char* inputImage, unsigned int bufferLength, const char* templateFilePath, double theshold, LStrHandle detectedMatchedLocations);
extern "C" __declspec(dllexport) int ANSCV_RotateImage(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, double angle, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_FlipImage(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, int flipCode, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_ShiftImage(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, int shiftX, int shiftY, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_AddGaussianNoise(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, double mean, double stddev, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_AddSaltAndPepperNoise(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, double amount, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_AddSpeckleNoise(ANSCENTER::ANSOPENCV** Handle, unsigned char* inputImage, unsigned int bufferLength, double stddev, LStrHandle outputImage);
extern "C" __declspec(dllexport) void ANSCV_InitCameraResource();
extern "C" __declspec(dllexport) void ANSCV_FreeCameraResource();
extern "C" __declspec(dllexport) int ANSCV_ResizeImage_Static(unsigned char* inputImage, unsigned int bufferLength, int width,int height, int& newWidth, int&newHeight, LStrHandle outputImage);
// Image reference management functions
extern "C" __declspec(dllexport) int ANSCV_CloneImage_S(cv::Mat **imageIn, cv::Mat** imageOut);
extern "C" __declspec(dllexport) int ANSCV_ReleaseImage_S(cv::Mat** imageIn);
extern "C" __declspec(dllexport) int ANSCV_ReSizeImage_S(cv::Mat** imageIn, int width, int originalImageSize = 0);
extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x, int y, int width, int height, int originalImageSize=0);
extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int width, int quality, int& newWidth, int& newHeight, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_GetImage_CPP(cv::Mat** imageIn, int width, int quality, int& newWidth, int& newHeight, std::string& outputImage);
extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** imageIn, int width, int quality, int& newWidth, int& newHeight, LStrHandle outputImage);
extern "C" __declspec(dllexport) int ANSCV_GetImageInfo_S(cv::Mat** imageIn, int &width, int& height);
extern "C" __declspec(dllexport) int ANSCV_CreateImageFromJpegString_S(unsigned char* inputImage, unsigned int bufferLength,cv::Mat** image);
extern "C" __declspec(dllexport) int ANSCV_CreateImageFromFile_S(const char* imageFilePath, cv::Mat** image);
// Pre-process image functions
extern "C" __declspec(dllexport) int ANSCV_ImageAutoWhiteBalance_S(cv::Mat** imageIn);
extern "C" __declspec(dllexport) int ANSCV_ImageBrightEnhance_S(cv::Mat** imageIn, double brightnessScaleFactor);
extern "C" __declspec(dllexport) int ANSCV_ImageContrastEnhance_S(cv::Mat** imageIn);
extern "C" __declspec(dllexport) int ANSCV_ImageDenoise_S(cv::Mat** imageIn);
extern "C" __declspec(dllexport) int ANSCV_ImageRepair_S(cv::Mat** imageIn);
extern "C" __declspec(dllexport) int ANSCV_ImageToGray_S(cv::Mat** imageIn);
extern "C" __declspec(dllexport) int ANSCV_ImageRotate_S(cv::Mat** imageIn, double angle);
extern "C" __declspec(dllexport) int ANSCV_ImageFlip_S(cv::Mat** imageIn, int flipCode);
// Post-process image functions
extern "C" __declspec(dllexport) int ANSCV_ImageBlurObjects_S(cv::Mat** imageIn, const char* strBboxes);
extern "C" __declspec(dllexport) int ANSCV_ImageBlurBackground_S(cv::Mat** imageIn, const char* strBboxes);
extern "C" __declspec(dllexport) int ANSCV_ImageQRDecoder_S(cv::Mat** imageIn, int maxImageWidth, const char* strBboxes, LStrHandle detectedQRText);
extern "C" __declspec(dllexport) int ANSCV_ImagePatternMatchs_S(cv::Mat** imageIn, const char* templateFilePath, double theshold, LStrHandle detectedMatchedLocations);
extern "C" __declspec(dllexport) int ANSCV_ImagesToMP4_S(const char* imageFolder, const char* outputVideoPath, int targetDurationSec);
#endif

1198
ANSLIB/ANSCV/ANSRTMP.cpp Normal file

File diff suppressed because it is too large Load Diff

110
ANSLIB/ANSCV/ANSRTMP.h Normal file
View File

@@ -0,0 +1,110 @@
#ifndef ANSRTMP_H
#define ANSRTMP_H
#define ANSRTMP_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "rtmp_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "rtmp_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
namespace ANSCENTER
{
class ANSRTMP_API ANSRTMPClient
{
protected:
std::unique_ptr<CRtmpPlayer> _playerClient = std::make_unique<CRtmpPlayer>();
std::string _username;
std::string _password;
std::string _url;
bool _useFullURL;
int _imageRotateDeg = 0;
int _displayWidth = 0; // 0 = no resize (return original resolution)
int _displayHeight = 0;
cv::Mat _pLastFrame;
std::string _lastJpegImage;
int _imageWidth, _imageHeight;
int64_t _pts;
bool _isPlaying;
std::recursive_mutex _mutex;
public:
ANSRTMPClient();
~ANSRTMPClient() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Init(std::string licenseKey, std::string username, std::string password, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
[[nodiscard]] bool Pause();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
bool areImagesIdentical(const cv::Mat& img1, const cv::Mat& img2);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegImage(int& width, int& height, int64_t& pts);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
static void SetMaxHWDecoders(int maxDecoders);
static int AutoConfigureHWDecoders(int maxPerGpuOverride = 0);
void SetHWDecoding(int hwMode, int preferredGpu = -1);
bool IsHWDecodingActive();
int GetHWDecodingGpuIndex();
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
void SetImageQuality(int mode); // 0=fast (AI), 1=quality (display)
AVFrame* GetNV12Frame(); // Returns cloned NV12 frame for GPU fast-path (caller must av_frame_free)
AVFrame* GetCudaHWFrame(); // Returns CUDA HW frame (device ptrs) for zero-copy inference
bool IsCudaHWAccel(); // true when decoder uses CUDA (NV12 stays in GPU VRAM)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSRTMP", false);
bool _licenseValid{ false };
std::string _licenseKey;
//std::once_flag licenseOnceFlag;
};
}
extern "C" __declspec(dllexport) int CreateANSRTMPHandle(ANSCENTER::ANSRTMPClient * *Handle, const char* licenseKey, const char* username, const char* password, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSRTMPHandle(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) int GetRTMPImage(ANSCENTER::ANSRTMPClient * *Handle, int& width, int& height, int64_t & timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetRTMPtrImage(ANSCENTER::ANSRTMPClient * *Handle, int& width, int& height, int64_t & timeStamp, std::string & jpegImage);
extern "C" __declspec(dllexport) int GetRTMPCVImage(ANSCENTER::ANSRTMPClient** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartRTMP(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) int ReconnectRTMP(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) int StopRTMP(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) int PauseRTMP(ANSCENTER::ANSRTMPClient** Handle);
extern "C" __declspec(dllexport) int IsRTMPPaused(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) int IsRTMPRunning(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) int IsRTMPRecording(ANSCENTER::ANSRTMPClient * *Handle);
extern "C" __declspec(dllexport) void SetRTMPAudioVolume(ANSCENTER::ANSRTMPClient * *Handle, int volume);
extern "C" __declspec(dllexport) void EnableRTMPAudioVolume(ANSCENTER::ANSRTMPClient * *Handle, int status);
extern "C" __declspec(dllexport) void SetRTMPImageRotation(ANSCENTER::ANSRTMPClient * *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxRTMP(ANSCENTER::ANSRTMPClient** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagRTMP(ANSCENTER::ANSRTMPClient** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetRTMPMaxHWDecoders(int maxDecoders);
extern "C" __declspec(dllexport) int AutoConfigureRTMPHWDecoders(int maxPerGpuOverride);
extern "C" __declspec(dllexport) void SetRTMPHWDecoding(ANSCENTER::ANSRTMPClient** Handle, int hwMode, int preferredGpu = -1);
extern "C" __declspec(dllexport) int IsRTMPHWDecodingActive(ANSCENTER::ANSRTMPClient** Handle);
extern "C" __declspec(dllexport) int GetRTMPHWDecodingGpuIndex(ANSCENTER::ANSRTMPClient** Handle);
extern "C" __declspec(dllexport) void SetRTMPImageQuality(ANSCENTER::ANSRTMPClient** Handle, int mode);
extern "C" __declspec(dllexport) void SetRTMPDisplayResolution(ANSCENTER::ANSRTMPClient** Handle, int width, int height);
#endif

1512
ANSLIB/ANSCV/ANSRTSP.cpp Normal file

File diff suppressed because it is too large Load Diff

111
ANSLIB/ANSCV/ANSRTSP.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef ANSRTSP_H
#define ANSRTSP_H
#define ANSRTSP_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "rtsp_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "rtsp_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
namespace ANSCENTER
{
class ANSRTSP_API ANSRTSPClient
{
protected:
std::unique_ptr<CRtspPlayer> _playerClient = std::make_unique<CRtspPlayer>();
std::string _username;
std::string _password;
std::string _url;
bool _useFullURL;
int _imageRotateDeg = 0;
int _displayWidth = 0; // 0 = no resize (return original resolution)
int _displayHeight = 0;
cv::Mat _pLastFrame;
std::string _lastJpegImage;
int _imageWidth,_imageHeight;
int64_t _pts;
bool _isPlaying;
std::recursive_mutex _mutex;
public:
ANSRTSPClient();
~ANSRTSPClient() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Init(std::string licenseKey, std::string username, std::string password, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
[[nodiscard]] bool Pause();
void Destroy();
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
void EnableAudio(bool status);
void SetAudioVolume(int volume);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegImage(int& width, int& height, int64_t& pts);
bool areImagesIdentical(const cv::Mat& img1, const cv::Mat& img2);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
static void SetMaxHWDecoders(int maxDecoders);
static int AutoConfigureHWDecoders(int maxPerGpuOverride = 0);
void SetHWDecoding(int hwMode, int preferredGpu = -1);
bool IsHWDecodingActive();
int GetHWDecodingGpuIndex();
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
void SetImageQuality(int mode); // 0=fast (AI), 1=quality (display)
AVFrame* GetNV12Frame(); // Returns cloned NV12 frame for GPU fast-path (caller must av_frame_free)
AVFrame* GetCudaHWFrame(); // Returns CUDA HW frame (device ptrs) for zero-copy inference
bool IsCudaHWAccel(); // true when decoder uses CUDA (NV12 stays in GPU VRAM)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSRTSP", false);
bool _licenseValid{ false };
std::string _licenseKey;
//std::once_flag licenseOnceFlag;
};
}
extern "C" __declspec(dllexport) int CreateANSRTSPHandle(ANSCENTER::ANSRTSPClient * *Handle, const char* licenseKey, const char* username, const char* password, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSRTSPHandle(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) int GetRTSPImage(ANSCENTER::ANSRTSPClient **Handle, int &width, int &height, int64_t& timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetRTSPStrImage(ANSCENTER::ANSRTSPClient * *Handle, int& width, int& height, int64_t & timeStamp, std::string& jpegImage);
extern "C" __declspec(dllexport) int GetRTSPCVImage(ANSCENTER::ANSRTSPClient** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartRTSP(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) int ReconnectRTSP(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) int StopRTSP(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) int PauseRTSP(ANSCENTER::ANSRTSPClient** Handle);
extern "C" __declspec(dllexport) int IsRTSPPaused(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) int IsRTSPRunning(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) int IsRTSPRecording(ANSCENTER::ANSRTSPClient * *Handle);
extern "C" __declspec(dllexport) void SetRTSPAudioVolume(ANSCENTER::ANSRTSPClient * *Handle, int volume);
extern "C" __declspec(dllexport) void EnableRTSPAudioVolume(ANSCENTER::ANSRTSPClient * *Handle, int status);
extern "C" __declspec(dllexport) void SetRTSPImageRotation(ANSCENTER::ANSRTSPClient * *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxRTSP(ANSCENTER::ANSRTSPClient** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagRTSP(ANSCENTER::ANSRTSPClient** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetMaxHWDecoders(int maxDecoders);
extern "C" __declspec(dllexport) int AutoConfigureHWDecoders(int maxPerGpuOverride);
extern "C" __declspec(dllexport) void SetRTSPHWDecoding(ANSCENTER::ANSRTSPClient** Handle, int hwMode, int preferredGpu = -1);
extern "C" __declspec(dllexport) int IsRTSPHWDecodingActive(ANSCENTER::ANSRTSPClient** Handle);
extern "C" __declspec(dllexport) int GetRTSPHWDecodingGpuIndex(ANSCENTER::ANSRTSPClient** Handle);
extern "C" __declspec(dllexport) void SetRTSPImageQuality(ANSCENTER::ANSRTSPClient** Handle, int mode);
extern "C" __declspec(dllexport) void SetRTSPDisplayResolution(ANSCENTER::ANSRTSPClient** Handle, int width, int height);
#endif

1221
ANSLIB/ANSCV/ANSSRT.cpp Normal file

File diff suppressed because it is too large Load Diff

110
ANSLIB/ANSCV/ANSSRT.h Normal file
View File

@@ -0,0 +1,110 @@
#ifndef ANSSRT_H
#define ANSSRT_H
#define ANSSRT_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include "sys_inc.h"
#include "srt_cln.h"
#include "hqueue.h"
#include "http.h"
#include "http_parse.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "srt_player.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
namespace ANSCENTER
{
class ANSSRT_API ANSSRTClient
{
protected:
std::unique_ptr<CSrtPlayer> _playerClient = std::make_unique<CSrtPlayer>();
std::string _username;
std::string _password;
std::string _url;
bool _useFullURL;
int _imageRotateDeg = 0;
int _displayWidth = 0; // 0 = no resize (return original resolution)
int _displayHeight = 0;
cv::Mat _pLastFrame;
std::string _lastJpegImage;
int _imageWidth, _imageHeight;
int64_t _pts;
bool _isPlaying;
std::recursive_mutex _mutex;
public:
ANSSRTClient();
~ANSSRTClient() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Init(std::string licenseKey, std::string username, std::string password, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
[[nodiscard]] bool Pause();
void Destroy();
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
void EnableAudio(bool status);
void SetAudioVolume(int volume);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegImage(int& width, int& height, int64_t& pts);
bool areImagesIdentical(const cv::Mat& img1, const cv::Mat& img2);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
static void SetMaxHWDecoders(int maxDecoders);
static int AutoConfigureHWDecoders(int maxPerGpuOverride = 0);
void SetHWDecoding(int hwMode, int preferredGpu = -1);
bool IsHWDecodingActive();
int GetHWDecodingGpuIndex();
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
void SetImageQuality(int mode); // 0=fast (AI), 1=quality (display)
AVFrame* GetNV12Frame(); // Returns cloned NV12 frame for GPU fast-path (caller must av_frame_free)
AVFrame* GetCudaHWFrame(); // Returns CUDA HW frame (device ptrs) for zero-copy inference
bool IsCudaHWAccel(); // true when decoder uses CUDA (NV12 stays in GPU VRAM)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSSRT", false);
bool _licenseValid{ false };
std::string _licenseKey;
//std::once_flag licenseOnceFlag;
};
}
extern "C" __declspec(dllexport) int CreateANSSRTHandle(ANSCENTER::ANSSRTClient * *Handle, const char* licenseKey, const char* username, const char* password, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSSRTHandle(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) int GetSRTImage(ANSCENTER::ANSSRTClient * *Handle, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetSRTStrImage(ANSCENTER::ANSSRTClient * *Handle, int& width, int& height, int64_t & timeStamp, std::string & jpegImage);
extern "C" __declspec(dllexport) int GetSRTCVImage(ANSCENTER::ANSSRTClient** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartSRT(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) int ReconnectSRT(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) int StopSRT(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) int PauseSRT(ANSCENTER::ANSSRTClient** Handle);
extern "C" __declspec(dllexport) int IsSRTPaused(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) int IsSRTRunning(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) int IsSRTRecording(ANSCENTER::ANSSRTClient * *Handle);
extern "C" __declspec(dllexport) void SetSRTAudioVolume(ANSCENTER::ANSSRTClient * *Handle, int volume);
extern "C" __declspec(dllexport) void EnableSRTAudioVolume(ANSCENTER::ANSSRTClient * *Handle, int status);
extern "C" __declspec(dllexport) void SetSRTImageRotation(ANSCENTER::ANSSRTClient * *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxSRT(ANSCENTER::ANSSRTClient** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagSRT(ANSCENTER::ANSSRTClient** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetSRTMaxHWDecoders(int maxDecoders);
extern "C" __declspec(dllexport) int AutoConfigureSRTHWDecoders(int maxPerGpuOverride);
extern "C" __declspec(dllexport) void SetSRTHWDecoding(ANSCENTER::ANSSRTClient** Handle, int hwMode, int preferredGpu = -1);
extern "C" __declspec(dllexport) int IsSRTHWDecodingActive(ANSCENTER::ANSSRTClient** Handle);
extern "C" __declspec(dllexport) int GetSRTHWDecodingGpuIndex(ANSCENTER::ANSSRTClient** Handle);
extern "C" __declspec(dllexport) void SetSRTImageQuality(ANSCENTER::ANSSRTClient** Handle, int mode);
extern "C" __declspec(dllexport) void SetSRTDisplayResolution(ANSCENTER::ANSSRTClient** Handle, int width, int height);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
#ifndef ANSVIDEOPLAYER_H
#define ANSVIDEOPLAYER_H
#define ANSVIDEOPLAYER_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <thread>
#include <chrono>
#include <atomic>
#include <turbojpeg.h>
#include "file_player.h" // CFilePlayer (FFmpeg HW decode: CUDA/D3D11VA/DXVA2)
#include "video_decoder.h" // HW_DECODING_AUTO, HWDecoderPool
namespace ANSCENTER
{
class ANSVIDEOPLAYER_API ANSVIDEOPLAYER
{
protected:
cv::VideoCapture cap;
int _resWidth;
int _resHeight;
int64_t _totalFrames;
int64_t _currentFrame;
int64_t _previousPTS;
double _fps;
bool _isPlaying;
std::string _lastJpegImage;
cv::Mat _previousImage;
bool m_bPaused;
int _imageRotateDeg = 0;
std::string _url;
cv::Rect _bbox;
bool _crop;
std::recursive_mutex _mutex;
std::mutex _cvMutex;
std::condition_variable _cv;
tjhandle _jpegCompressor;
public:
// --- HW decode state (CFilePlayer composition) ---
// Public: accessed by extern "C" GetVideoPlayerCVImage for NV12/CUDA registry attachment
std::unique_ptr<CFilePlayer> _hwPlayer; // HW decode path (nullptr = CV fallback)
bool _hwDecodeActive = false; // true when _hwPlayer init succeeded
int _hwGpuIndex = -1; // GPU index for registry (-1 = CPU only)
bool _hwCudaAccel = false; // true = NVIDIA CUDA zero-copy available
bool _hwEOF = false; // true when video reached end of file
int64_t _hwFrameCount = 0; // frame counter for EOF detection
int64_t _hwLastPts = 0; // last video PTS for EOF wrap detection
ANSVIDEOPLAYER();
~ANSVIDEOPLAYER() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
[[nodiscard]] bool Stop();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] cv::Mat GetInferenceImage(); // Returns full-res frame for AI inference (no resize/rotation)
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegStringImage(int& width, int& height, int64_t& pts);
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSVideoPlayer", false);
bool _licenseValid{ false };
//std::once_flag licenseOnceFlag;
std::string _licenseKey;
cv::Mat _inferenceCloneCurr; // Heap-cloned full-res (keeps data alive for registry)
cv::Mat _inferenceClonePrev; // Previous clone (keeps data alive during ANSRTYOLO read)
private:
std::string encodeJpegString(const cv::Mat& img, int quality = 80);
int _displayWidth = 0; // 0 = no resize (return original)
int _displayHeight = 0;
cv::Mat _inferenceImage; // Full-res frame for AI inference
};
}
extern "C" __declspec(dllexport) int CreateANSVideoPlayerHandle(ANSCENTER::ANSVIDEOPLAYER** Handle, const char* licenseKey, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSVideoPlayerHandle(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) int GetVideoPlayerImage(ANSCENTER::ANSVIDEOPLAYER** Handle, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetVideoPlayerStrImage(ANSCENTER::ANSVIDEOPLAYER** Handle, int& width, int& height, int64_t& timeStamp, std::string& jpegImage);
extern "C" __declspec(dllexport) int GetVideoPlayerCVImage(ANSCENTER::ANSVIDEOPLAYER** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartVideoPlayer(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) int ReconnectVideoPlayer(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) int StopVideoPlayer(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) int IsVideoPlayerPaused(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) int IsVidedoPlayerRunning(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) int IsVideoPlayerRecording(ANSCENTER::ANSVIDEOPLAYER** Handle);
extern "C" __declspec(dllexport) void SetVideoPlayerAudioVolume(ANSCENTER::ANSVIDEOPLAYER** Handle, int volume);
extern "C" __declspec(dllexport) void EnableVideoPlayerAudioVolume(ANSCENTER::ANSVIDEOPLAYER** Handle, int status);
extern "C" __declspec(dllexport) void SetVideoPlayerImageRotation(ANSCENTER::ANSVIDEOPLAYER** Handle, double rotationAngle);
extern "C" __declspec(dllexport) int SetBBoxVideoPlayer(ANSCENTER::ANSVIDEOPLAYER** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagVideoPlayer(ANSCENTER::ANSVIDEOPLAYER** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetVideoPlayerDisplayResolution(ANSCENTER::ANSVIDEOPLAYER** Handle, int width, int height);
#endif

1758
ANSLIB/ANSCV/ANSWebcam.cpp Normal file

File diff suppressed because it is too large Load Diff

140
ANSLIB/ANSCV/ANSWebcam.h Normal file
View File

@@ -0,0 +1,140 @@
#ifndef ANSWEBCAM_H
#define ANSWEBCAM_H
#define ANSWEBCAM_API __declspec(dllexport)
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <dshow.h>
#include <mutex>
#include <nvjpeg.h>
#include <cuda_runtime.h>
#include <turbojpeg.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
namespace ANSCENTER
{
struct Resolution {
int width;
int height;
Resolution(int w, int h) : width(w), height(h) {}
int getArea() const {
return width * height;
}
bool operator<(const Resolution& other) const {
return getArea() < other.getArea();
}
};
class ANSWEBCAM_API ANSWEBCAMPlayer
{
protected:
// Add this structure definition in the private section
cv::VideoCapture cap;
int _deviceId;
int _resWidth;
int _resHeight;
int _savedResWidth = 0; // Saved resolution for stop/start restore
int _savedResHeight = 0;
bool _enableMaxResolution = false; // false = Full HD default, true = max resolution
int64_t _previousPTS;
cv::Mat _previousImage;
bool m_bPaused;
std::string _lastJpegImage;
bool _isPlaying;
std::vector<std::string> _cameraNames;
int _imageRotateDeg = 0;
std::recursive_mutex _mutex;
cv::Rect _bbox;
bool _crop;
EngineType engineType;
// Initialize nvJPEG structures
nvjpegHandle_t nv_handle;
nvjpegEncoderState_t nv_enc_state;
nvjpegEncoderParams_t nv_enc_params;
cudaStream_t stream;
tjhandle _jpegCompressor;
public:
ANSWEBCAMPlayer();
~ANSWEBCAMPlayer() noexcept;
[[nodiscard]] bool Init(std::string licenseKey, std::string url);
[[nodiscard]] bool Setup();
[[nodiscard]] bool Reconnect();
[[nodiscard]] bool Start();
[[nodiscard]] bool IsPaused();
[[nodiscard]] bool IsPlaying();
[[nodiscard]] bool IsRecording();
[[nodiscard]] bool Stop();
void Destroy();
void EnableAudio(bool status);
void SetAudioVolume(int volume);
[[nodiscard]] cv::Mat GetImage(int& width, int& height, int64_t& pts);
[[nodiscard]] std::string MatToBinaryData(const cv::Mat& image);
[[nodiscard]] std::string GetJpegStringImage(int& width, int& height, int64_t& pts);
[[nodiscard]] static std::string VectorToCommaSeparatedString(const std::vector<std::string>& inputVector);
[[nodiscard]] static std::vector<std::string> ScanWebcamDevices();
[[nodiscard]] static std::string GetSupportedResolutions(int deviceId);
static std::mutex mtx;
void SetImageRotate(int mode) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
_imageRotateDeg = mode;
if (mode > 360) _imageRotateDeg = 360;
};
void SetBBox(cv::Rect bbox);
void SetCrop(bool crop);
void SetDisplayResolution(int width, int height); // Set display output size; 0,0 = original (no resize)
[[nodiscard]] cv::Mat GetInferenceImage(); // Returns full-res frame for AI inference (no resize)
cv::Mat _inferenceCloneCurr; // Heap-cloned full-res (keeps data alive for registry)
cv::Mat _inferenceClonePrev; // Previous clone (keeps data alive during ANSRTYOLO read)
public:
void CheckLicense();
SPDLogger& _logger = SPDLogger::GetInstance("ANSWebcamPlayer", false);
bool _licenseValid{ false };
std::string _licenseKey;
// Resolution management methods
std::vector<Resolution> GetAvailableResolutions(int deviceId);
bool SetBestResolution(int deviceId);
bool SetPreferredResolution(int deviceId);
bool SetResolution(int width, int height);
void SetEnableMaxResolution(bool enable);
std::string GetAvailableResolutionsString(int deviceId);
private:
std::string encodeJpegString(const cv::Mat& img, int quality = 80);
std::string encodeMatToJpegWithNvJPEG(const cv::Mat& inputMat, int quality = 80);
void uploadPlanarBGRToGPU(const cv::Mat& inputMat, unsigned char** data);
int _displayWidth = 0; // 0 = no resize (return original)
int _displayHeight = 0;
cv::Mat _inferenceImage; // Full-res frame for AI inference
};
std::mutex ANSWEBCAMPlayer::mtx; // Definition of the static mutex
}
extern "C" __declspec(dllexport) int CreateANSWebcamPlayerHandle(ANSCENTER::ANSWEBCAMPlayer * *Handle, const char* licenseKey, const char* url);
extern "C" __declspec(dllexport) int CreateANSWebcamPlayerWithMaxResoHandle(ANSCENTER::ANSWEBCAMPlayer * *Handle, const char* licenseKey, const char* url);
extern "C" __declspec(dllexport) int ReleaseANSWebcamPlayerHandle(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) int ScanANSWebcamPlayer(LStrHandle cameraNames);
extern "C" __declspec(dllexport) int ScanStrANSWebcamPlayer(std::vector<std::string> &cameraNameList);
extern "C" __declspec(dllexport) int GetWebcamImage(ANSCENTER::ANSWEBCAMPlayer * *Handle, int& width, int& height, int64_t & timeStamp, LStrHandle jpegImage);
extern "C" __declspec(dllexport) int GetWebcamStrImage(ANSCENTER::ANSWEBCAMPlayer * *Handle, int& width, int& height, int64_t & timeStamp, std::string & jpegImage);
extern "C" __declspec(dllexport) int GetWebcamCVImage(ANSCENTER::ANSWEBCAMPlayer** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image);
extern "C" __declspec(dllexport) int StartWebcamPlayer(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) int ReconnectWebcamPlayer(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) int StopWebcamPlayer(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) int IsWebcamPlayerPaused(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) int IsWebcamPlayerRunning(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) int IsWebcamPlayerRecording(ANSCENTER::ANSWEBCAMPlayer * *Handle);
extern "C" __declspec(dllexport) void SetWebcamPlayerAudioVolume(ANSCENTER::ANSWEBCAMPlayer * *Handle, int volume);
extern "C" __declspec(dllexport) void EnableWebcamPlayerAudioVolume(ANSCENTER::ANSWEBCAMPlayer * *Handle, int status);
extern "C" __declspec(dllexport) void SetWebcamImageRotation(ANSCENTER::ANSWEBCAMPlayer * *Handle, double rotationAngle);
extern "C" __declspec(dllexport) int ScanSupportedResolutions(std::string cameraName,std::vector<std::string> cameraNameList, std::string &supportedResolution);
extern "C" __declspec(dllexport) int SetBBoxANSWebcamPlayer(ANSCENTER::ANSWEBCAMPlayer** Handle, int x, int y, int width, int height);
extern "C" __declspec(dllexport) int SetCropFlagANSWebcamPlayer(ANSCENTER::ANSWEBCAMPlayer** Handle, int cropFlag);
extern "C" __declspec(dllexport) void SetWebcamDisplayResolution(ANSCENTER::ANSWEBCAMPlayer** Handle, int width, int height);
#endif

1093
ANSLIB/ANSCV/VideoPlayer.cpp Normal file

File diff suppressed because it is too large Load Diff

199
ANSLIB/ANSCV/VideoPlayer.h Normal file
View File

@@ -0,0 +1,199 @@
/***************************************************************************************
*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
*
* Redistribution and use in binary forms, with or without modification, are permitted.
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*
****************************************************************************************/
#ifndef VIDEO_PLAYER_H
#define VIDEO_PLAYER_H
#include "sys_inc.h"
#include "hqueue.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "audio_play.h"
#include "avi_write.h"
#include "media_util.h"
#include <list>
#include <string>
typedef struct
{
uint32 SyncTimestamp;
struct timeval SyncTime;
} HTCLOCK;
typedef std::list<AVFrame*> FRAMELIST;
class CVideoPlayer
{
public:
CVideoPlayer();
virtual ~CVideoPlayer();
virtual BOOL open(std::string fileName);
virtual BOOL play() = 0;
virtual void stop() = 0;
virtual BOOL pause() = 0;
virtual void close();
virtual BOOL seek(int pos) { return FALSE; }
virtual BOOL isPlaying() { return m_bPlaying; }
virtual BOOL isPaused() { return m_bPaused; }
virtual void setVolume(int volume);
virtual void snapshot(int videofmt);
virtual BOOL record(std::string baseName);
virtual void stopRecord();
virtual BOOL isRecording() { return m_bRecording; }
virtual BOOL onRecord() { return FALSE; }
virtual int getVideoClock() { return 1000; }
virtual int getAudioClock() { return 1000; }
virtual void setWindowSize(int size);
virtual int64 getElapse() { return 0; }
virtual int64 getDuration() { return 0; }
virtual int getVideoCodec() { return m_nVideoCodec; }
virtual int getAudioCodec() { return m_nAudioCodec; }
virtual void setAuthInfo(std::string acct, std::string pass) { m_acct = acct; m_pass = pass; }
virtual void setRenderMode(int mode) { m_nRenderMode = mode; }
virtual void setHWDecoding(int mode) { m_nHWDecoding = mode; }
virtual void setRtpMulticast(BOOL flag) {}
virtual void setRtpOverUdp(BOOL flag) {}
#ifdef OVER_HTTP
virtual void setRtspOverHttp(int flag, int port) {}
#endif
#ifdef OVER_WEBSOCKET
virtual void setRtspOverWs(int flag, int port) {}
#endif
#ifdef BACKCHANNEL
virtual int getBCFlag() { return 0; }
virtual void setBCFlag(int flag) {}
virtual int getBCDataFlag() { return 0; }
virtual void setBCDataFlag(int flag) {}
virtual void setAudioDevice(int index) {}
#endif
#ifdef REPLAY
virtual int getReplayFlag() { return 0; }
virtual void setReplayFlag(int flag) {}
virtual void setScale(double scale) {}
virtual void setRateControlFlag(int flag) {}
virtual void setImmediateFlag(int flag) {}
virtual void setFramesFlag(int flag, int interval) {}
virtual void setReplayRange(time_t start, time_t end) {}
#endif
BOOL openVideo(int codec, uint8* extradata = NULL, int extradata_size = 0);
BOOL openVideo(enum AVCodecID codec, uint8* extradata = NULL, int extradata_size = 0);
void closeVideo();
BOOL openAudio(int codec, int samplerate, int channels, int bitpersample = 0);
BOOL openAudio(enum AVCodecID codec, int samplerate, int channels, int bitpersample = 0);
void closeAudio();
void playVideo(uint8* data, int len, uint32 ts, uint16 seq);
void playAudio(uint8* data, int len, uint32 ts, uint16 seq);
void recordVideo(uint8* data, int len, uint32 ts, uint16 seq);
void recordAudio(uint8* data, int len, uint32 ts, uint16 seq);
int getVideoWidth();
int getVideoHeight();
double getFrameRate();
int getSampleRate() { return m_nSampleRate; }
int getChannel() { return m_nChannel; }
void onVideoFrame(AVFrame* frame);
void onAudioFrame(AVFrame* frame);
void audioPlayThread();
void videoPlayThread();
//signals:
// void notify(int);
// void snapshoted(AVFrame*);
protected:
void updateClock(HTCLOCK* clock, uint32 ts, int frequency);
BOOL initFrame(AVFrame*& frame, int width, int height, AVPixelFormat pixfmt);
//BOOL initVideoRender(int width, int height);
BOOL doSnapshot(AVFrame* srcframe);
AVFrame* convertFrame(AVFrame* srcframe, AVFrame* dstframe, BOOL updown);
void recordVideoEx(uint8* data, int len, uint32 ts, uint16 seq);
BOOL recordSwitchCheck();
void recordFileSwitch();
protected:
BOOL m_bVideoInited;
BOOL m_bAudioInited;
CVideoDecoder* m_pVideoDecoder;
CAudioDecoder* m_pAudioDecoder;
//CVideoRender* m_pVideoRender;
CAudioPlay* m_pAudioPlay;
BOOL m_bPlaying;
BOOL m_bPaused;
std::string m_acct;
std::string m_pass;
std::string m_sFileName;
std::string m_sBaseName;
//WId m_nVideoWnd;
int m_size;
BOOL m_bSizeChanged;
int m_nRenderMode;
int m_nHWDecoding;
AVPixelFormat m_nDstVideoFmt;
BOOL m_bUpdown;
BOOL m_bSnapshot;
int m_nSnapVideoFmt;
H26XParamSets m_h26XParamSets;
int m_nVideoCodec;
int m_nAudioCodec;
int m_nSampleRate;
int m_nChannel;
int m_nBitPerSample;
AVFrame* m_pSnapFrame;
AVFrame* m_pRenderFrame;
BOOL m_bRecording;
BOOL m_bNalFlag;
AVICTX* m_pAviCtx;
void* m_pRecordMutex;
HTCLOCK m_audioClock;
void* m_pAudioListMutex;
FRAMELIST m_audioFrameList;
BOOL m_audioPlayFlag;
pthread_t m_audioPlayThread;
HTCLOCK m_videoClock;
void* m_pVideoListMutex;
FRAMELIST m_videoFrameList;
BOOL m_videoPlayFlag;
pthread_t m_videoPlayThread;
uint64 m_nLastAudioPts;
time_t m_lastAudioTS;
};
#endif // end of VIDEO_PLAYER_H

106
ANSLIB/ANSCV/dllmain.cpp Normal file
View File

@@ -0,0 +1,106 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <mutex>
#include <unordered_map>
#include <iostream>
#include <functional>
// ── Global handle registry for shutdown cleanup ──────────────────────────
// Streaming handle creators register a stop-callback on creation.
// DLL_PROCESS_DETACH invokes all callbacks so threads exit before DLL unmaps.
static std::mutex& shutdownMutex() {
static std::mutex m;
return m;
}
static std::unordered_map<void*, std::function<void()>>& shutdownRegistry() {
static std::unordered_map<void*, std::function<void()>> r;
return r;
}
// Called by Create*Handle functions to register a cleanup callback
extern "C" void anscv_register_handle(void* handle, void(*stopFn)(void*)) {
if (!handle || !stopFn) return;
std::lock_guard<std::mutex> lk(shutdownMutex());
shutdownRegistry()[handle] = [=]() { stopFn(handle); };
}
// Called by Release*Handle functions to unregister (handle properly cleaned up)
extern "C" void anscv_unregister_handle(void* handle) {
if (!handle) return;
std::lock_guard<std::mutex> lk(shutdownMutex());
shutdownRegistry().erase(handle);
}
// Stop all leaked handles
static void stopAllHandles() {
std::unordered_map<void*, std::function<void()>> copy;
{
std::lock_guard<std::mutex> lk(shutdownMutex());
copy.swap(shutdownRegistry());
}
for (auto& [ptr, fn] : copy) {
try { fn(); } catch (...) {}
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) noexcept
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
// Pin the DLL so it is never unmapped from the process address space.
// ANSCV creates background threads (RTSP receive, timers) that may
// still be running when LabVIEW's CLR/COM shutdown unloads the DLL.
// If the DLL is unmapped while threads are executing its code, the
// threads crash with an access violation at <Unloaded_ANSCV.dll>.
// Pinning keeps the code pages mapped; the OS kills all threads when
// the process exits, so this is safe and is Microsoft's recommended
// pattern for DLLs that own threads.
{
HMODULE hSelf = nullptr;
GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_PIN,
reinterpret_cast<LPCWSTR>(&DllMain),
&hSelf);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
// CRITICAL: Do NOT call stopAllHandles() here.
//
// DllMain holds the OS loader lock (LdrpLoaderLock). Destroying
// streaming handles (CRtspPlayer → CVideoPlayer → CWAudioPlay)
// calls dsound!CThread::Terminate which waits for the DirectSound
// admin thread to exit. That thread needs the loader lock to shut
// down → classic deadlock. (Confirmed by crash dump analysis:
// Thread 0 holds LdrpLoaderLock and waits for dsound thread 331,
// which is blocked on LdrpLoaderLock.)
//
// If lpReserved is non-NULL the process is terminating — the OS
// will tear down all threads and reclaim resources; cleanup is
// unnecessary and dangerous. If lpReserved is NULL (dynamic
// FreeLibrary), LabVIEW should have called Release*Handle first.
// Log leaked handles for diagnostics but do NOT stop them here.
if (lpReserved == nullptr) {
// Dynamic unload — warn about leaked handles (non-blocking)
try {
std::lock_guard<std::mutex> lk(shutdownMutex());
if (!shutdownRegistry().empty()) {
std::cerr << "[ANSCV] WARNING: " << shutdownRegistry().size()
<< " streaming handle(s) leaked at DLL unload."
<< " Call Release*Handle before FreeLibrary." << std::endl;
}
} catch (...) {}
}
break;
}
return TRUE;
}

7
ANSLIB/ANSCV/framework.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

5
ANSLIB/ANSCV/pch.cpp Normal file
View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

18
ANSLIB/ANSCV/pch.h Normal file
View File

@@ -0,0 +1,18 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include <mutex>
#endif //PCH_H

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8b8bec2e-e3f4-4468-a7a2-033fb752e6ac}</ProjectGuid>
<RootNamespace>ANSCustomCode</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>ANSCustomWeaponDetection</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\ProgramData\ANSCENTER\Shared;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\ANSLibs\opencv\x64\vc17\lib;C:\ProgramData\ANSCENTER\Shared;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCUSTOMCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCUSTOMCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCUSTOMCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCUSTOMCODE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>opencv_img_hash4130.lib;opencv_world4130.lib;ANSLIB.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSCustomCodeWeaponDetection.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCustomCodeWeaponDetection.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSCustomCodeWeaponDetection.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSCustomCodeWeaponDetection.cpp">
<Filter>Resource Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,810 @@
#include "ANSCustomCodeWeaponDetection.h"
//#define FNS_DEBUG
ANSCustomWD::ANSCustomWD()
{
// Initialize the model
}
bool ANSCustomWD::OptimizeModel(bool fp16)
{
try {
if (this->_detector == nullptr || this->_filter == nullptr)
{
std::cout << "Model is not initialized." << std::endl;
return false;
}
int vResult = _detector->Optimize(fp16);
int tResult = _filter->Optimize(fp16);
if (vResult != 1 || tResult != 1)
{
std::cout << "Model optimization failed." << std::endl;
return false;
}
std::cout << "Model optimization successful." << std::endl;
return true;
}
catch (const std::exception& e) {
return false;
}
catch (...) {
return false;
}
}
std::vector<CustomObject> ANSCustomWD::RunInference(const cv::Mat& input)
{
return RunInference(input, "CustomCam");
}
bool ANSCustomWD::Destroy()
{
try {
this->_detector.reset();
this->_filter.reset();
return true;
}
catch (const std::exception& e) {
return false;
}
catch (...) {
return false;
}
}
bool ANSCustomWD::Initialize(const std::string& modelDirectory, float detectionScoreThreshold, std::string& labelMap)
{
//1. The modelDirectory is supplied by ANSVIS and contains the path to the model files
_modelDirectory = modelDirectory;
_detectionScoreThreshold = detectionScoreThreshold;
// Detector model configuration
_detectorModelName = "train_last";
_detectorClassName = "classes.names";
_detectorModelType = 4; // Assuming 4 represents TensorRT YoloV11
_detectorDetectionType = 1; // Assuming 1 represents object detection
// Fileter model configuration
_filterModelName = "filter";
_filterClassName = "filter.names";
_filterModelType = 4; // Assuming 4 represents TensorRT YoloV11
_filterDetectionType = 1; // Assuming 1 represents object detection
// Create model instances
_detector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_filter = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_detectorModelType = 4; // Assuming 4 represents TensorRT YoloV11
_detectorDetectionType = 1; // Assuming 1 represents object detection
_filterModelType = 4; // Assuming 4 represents TensorRT YoloV12
_filterDetectionType = 1; // Assuming 1 represents object detection
// Check the hardware type
engineType = _detector->GetEngineType();
if (engineType == 1) {
// detector will be TensorRT (v8, v11) and filter will be TensorRT (v12)
_detectorModelType = 4; // Assuming 4 represents TensorRT YoloV11
_detectorDetectionType = 1; // Assuming 1 represents object detection
_filterModelType = 4; // Assuming 4 represents TensorRT YoloV12
_filterDetectionType = 1; // Assuming 1 represents object detection
std::cout << "NVIDIA GPU detected. Using TensorRT" << std::endl;
}
else {
// detetector will be OpenVINO (v8, v11) and filter will be Yolo (v12)
_detectorModelType = 5; // Assuming 5 represents OpenVINO YoloV11
_detectorDetectionType = 1; // Assuming 1 represents object detection
_filterModelType = 17; // Assuming 17 represents ONNX YoloV12
_filterDetectionType = 1; // Assuming 1 represents object detection
std::cout << "CPU detected. Using OpenVINO and ONNX" << std::endl;
}
//Clear parameters
this->_params.ROI_Config.clear();
this->_params.ROI_Options.clear();
this->_params.Parameters.clear();
this->_params.ROI_Values.clear();
//2. User can start impelementing the initialization logic here
double _modelConfThreshold = 0.5;
double _modelNMSThreshold = 0.5;
std::string licenseKey = "";
#ifdef FNS_DEBUG // Corrected preprocessor directive
_loadEngineOnCreate = true;
#endif
int loadEngineOnCreation = 0; // Load engine on creation
if (_loadEngineOnCreate)loadEngineOnCreation = 1;
int autoEngineDetection = 1; // Auto engine detection
int detectorResult = _detector->LoadModelFromFolder(licenseKey.c_str(),
_detectorModelName.c_str(),
_detectorClassName.c_str(),
detectionScoreThreshold,
_modelConfThreshold,
_modelNMSThreshold, autoEngineDetection,
_detectorModelType,
_detectorDetectionType,
loadEngineOnCreation,
_modelDirectory.c_str(),
labelMap);
int filterResult = _filter->LoadModelFromFolder(licenseKey.c_str(),
_filterModelName.c_str(),
_filterClassName.c_str(),
_detectionScoreThreshold,
_modelConfThreshold,
_modelNMSThreshold, autoEngineDetection,
_filterModelType,
_filterDetectionType,
loadEngineOnCreation,
_modelDirectory.c_str(),
_filterLabelMap);
if ((detectorResult == 1) && (filterResult == 1)) return true;
return false;
}
ANSCustomWD::~ANSCustomWD()
{
Destroy();
}
std::vector<CustomObject> ANSCustomWD::RunInference(const cv::Mat& input, const std::string& camera_id) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
// Early validation
if (input.empty() || input.cols < 10 || input.rows < 10) {
return {};
}
if (!_detector) {
return {};
}
try {
#ifdef FNS_DEBUG
cv::Mat draw = input.clone();
#endif
std::vector<ANSCENTER::Object> output;
// A. Check if detected area is retained and valid
if (_detectedArea.width > 50 && _detectedArea.height > 50) {
output = ProcessExistingDetectedArea(input, camera_id
#ifdef FNS_DEBUG
, draw
#endif
);
}
else {
// B. Find new detected area
ProcessNewDetectedArea(input, camera_id, output
#ifdef FNS_DEBUG
, draw
#endif
);
}
#ifdef FNS_DEBUG
cv::imshow("Combined Detected Areas", draw);
cv::waitKey(1);
#endif
// Convert to CustomObjects
std::vector<CustomObject> results;
if (!output.empty()) {
results.reserve(output.size());
const float scoreThreshold = _detectionScoreThreshold;
for (const auto& obj : output) {
if (obj.confidence >= scoreThreshold) {
CustomObject customObj;
customObj.box = obj.box;
customObj.classId = obj.classId;
customObj.confidence = obj.confidence;
customObj.cameraId = obj.cameraId;
customObj.className = obj.className;
customObj.extraInfo = "Detection Score Threshold:" + std::to_string(scoreThreshold);
results.push_back(std::move(customObj));
}
}
}
if (results.empty()) {
UpdateNoDetectionCondition();
}
return results;
}
catch (const std::exception& e) {
return {};
}
}
std::vector<ANSCENTER::Object> ANSCustomWD::RunFilterGetPersons(const cv::Mat& frame) {
std::vector<ANSCENTER::Object> persons;
if (!_filter) return persons;
std::vector<ANSCENTER::Object> filteredObjects;
_filter->RunInference(frame, "cam", filteredObjects);
for (const auto& obj : filteredObjects) {
if (obj.classId == 0) { // person
persons.push_back(obj);
}
}
return persons;
}
std::vector<ANSCENTER::Object> ANSCustomWD::ProcessExistingDetectedArea(
const cv::Mat& frame,
const std::string& camera_id
#ifdef FNS_DEBUG
, cv::Mat& draw
#endif
) {
std::vector<ANSCENTER::Object> output;
// Validate _detectedArea is within frame bounds
cv::Rect frameRect(0, 0, frame.cols, frame.rows);
_detectedArea &= frameRect;
if (_detectedArea.width <= 0 || _detectedArea.height <= 0) {
_detectedArea = cv::Rect();
UpdateNoDetectionCondition();
return output;
}
#ifdef FNS_DEBUG
cv::rectangle(draw, _detectedArea, cv::Scalar(0, 0, 255), 2); // RED
#endif
cv::Mat activeROI = frame(_detectedArea);
// Run weapon detection on cropped ROI
std::vector<ANSCENTER::Object> detectedObjects;
int detectorDetectionResult = _detector->RunInference(activeROI, camera_id.c_str(), detectedObjects);
if (detectedObjects.empty()) {
UpdateNoDetectionCondition();
return output;
}
// Run filter once for all candidates in this frame
std::vector<ANSCENTER::Object> personDetections = RunFilterGetPersons(frame);
bool filterHadResults = !personDetections.empty() || !_filter;
const float scoreThreshold = _detectionScoreThreshold;
std::vector<ANSCENTER::Object> movementObjects;
int detectedMovementResult = _detector->DetectMovement(activeROI, camera_id.c_str(), movementObjects);
// Convert movement objects to frame coordinates
std::vector<ANSCENTER::Object> weaponRects;
weaponRects.reserve(movementObjects.size());
for (const auto& rect : movementObjects) {
ANSCENTER::Object mObj;
mObj.box = rect.box;
mObj.box.x += _detectedArea.x;
mObj.box.y += _detectedArea.y;
weaponRects.push_back(mObj);
}
#ifdef FNS_DEBUG
for (const auto& rect : weaponRects) {
cv::rectangle(draw, rect.box, cv::Scalar(0, 255, 0), 2); // GREEN
}
#endif
for (auto& detectedObj : detectedObjects) {
// Adjust to frame coordinates
detectedObj.box.x += _detectedArea.x;
detectedObj.box.y += _detectedArea.y;
detectedObj.cameraId = camera_id;
if (detectedObj.confidence <= scoreThreshold) {
UpdateNoDetectionCondition();
continue;
}
const float area_threshold = calculateIoU(_detectedArea, detectedObj.box);
if (area_threshold >= 0.5f) {
UpdateNoDetectionCondition();
continue;
}
#ifdef FNS_DEBUG
cv::rectangle(draw, detectedObj.box, cv::Scalar(0, 255, 255), 2); // Yellow
#endif
if (weaponRects.empty()) {
UpdateNoDetectionCondition();
continue;
}
if (!IsOverlapping(detectedObj, weaponRects, 0)) {
UpdateNoDetectionCondition();
continue;
}
// Process valid detection
if (ProcessWeaponDetection(frame, detectedObj, output, personDetections, filterHadResults
#ifdef FNS_DEBUG
, draw
#endif
)) {
continue;
}
}
return output;
}
bool ANSCustomWD::ProcessWeaponDetection(
const cv::Mat& frame,
ANSCENTER::Object& detectedObj,
std::vector<ANSCENTER::Object>& output,
const std::vector<ANSCENTER::Object>& personDetections,
bool filterHadResults
#ifdef FNS_DEBUG
, cv::Mat& draw
#endif
) {
// Already established as real weapon after FILTERFRAMES consecutive confirmations
if (_realWeaponCheck > FILTERFRAMES) {
AddConfirmedWeaponDetection(frame, detectedObj, output);
return true;
}
// Filter not available - confirm directly
if (!_filter) {
AddConfirmedWeaponDetection(frame, detectedObj, output);
return true;
}
// Filter ran but detected nothing at all - treat as inconclusive
// Require more consecutive frames before confirming without person validation
if (!filterHadResults) {
_realWeaponCheck++;
if (_realWeaponCheck > FILTERFRAMES / 2) {
AddConfirmedWeaponDetection(frame, detectedObj, output);
return true;
}
return false;
}
#ifdef FNS_DEBUG
for (const auto& person : personDetections) {
cv::rectangle(draw, person.box, cv::Scalar(23, 25, 0), 2);
cv::putText(draw, "person",
cv::Point(person.box.x, person.box.y - 10),
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2);
}
#endif
// No persons found - weapon without person context
if (personDetections.empty()) {
_realWeaponCheck = std::max(0, _realWeaponCheck - 1);
if (_realWeaponCheck <= 0) _isRealWeaponFrame = false;
return false;
}
// Check if weapon overlaps with ANY person (use meaningful IoU threshold)
if (IsOverlapping(detectedObj, personDetections, 0.05f)) {
AddConfirmedWeaponDetection(frame, detectedObj, output);
_realWeaponCheck++;
return true;
}
// Detection doesn't overlap with any person
_realWeaponCheck = std::max(0, _realWeaponCheck - 1);
if (_realWeaponCheck <= 0) {
_isRealWeaponFrame = false;
}
return false;
}
void ANSCustomWD::AddConfirmedWeaponDetection(
const cv::Mat& frame,
ANSCENTER::Object& detectedObj,
std::vector<ANSCENTER::Object>& output)
{
output.push_back(detectedObj);
UpdateActiveROI(frame, detectedObj);
_isWeaponDetected = true;
_retainDetectedArea = 0;
_isRealWeaponFrame = true;
}
void ANSCustomWD::ProcessNewDetectedArea(
const cv::Mat& frame,
const std::string& camera_id,
std::vector<ANSCENTER::Object>& output
#ifdef FNS_DEBUG
, cv::Mat& draw
#endif
) {
// Decay _realWeaponCheck gradually instead of hard reset
_isRealWeaponFrame = false;
_realWeaponCheck = std::max(0, _realWeaponCheck - 1);
// Divide image and get priority region
std::vector<ImageSection> sections = divideImage(frame);
const int lowestPriority = getLowestPriorityRegion();
if (_currentPriority > lowestPriority || _currentPriority == 0) {
_currentPriority = getHighestPriorityRegion();
}
else {
_currentPriority++;
}
_detectedArea = getRegionByPriority(_currentPriority);
#ifdef FNS_DEBUG
cv::rectangle(draw, _detectedArea, cv::Scalar(0, 0, 255), 4); // RED
#endif
// Validate _detectedArea is within frame bounds
cv::Rect frameRect(0, 0, frame.cols, frame.rows);
_detectedArea &= frameRect;
if (_detectedArea.width <= 50 || _detectedArea.height <= 50) {
_detectedArea = cv::Rect();
return;
}
cv::Mat detectedROI = frame(_detectedArea);
std::vector<ANSCENTER::Object> detectedObjects;
int detectorResult = _detector->RunInference(detectedROI, camera_id.c_str(), detectedObjects);
if (detectedObjects.empty()) {
_detectedArea = cv::Rect();
return;
}
// Use configurable threshold instead of hardcoded 0.35
const float scanThreshold = std::min(_detectionScoreThreshold, 0.35f);
ANSCENTER::Object* bestDetection = nullptr;
float maxScore = 0.0f;
for (auto& detectedObj : detectedObjects) {
detectedObj.box.x += _detectedArea.x;
detectedObj.box.y += _detectedArea.y;
detectedObj.cameraId = camera_id;
if (detectedObj.confidence <= scanThreshold) {
continue;
}
if (detectedObj.confidence > maxScore) {
maxScore = detectedObj.confidence;
bestDetection = &detectedObj;
}
}
if (!bestDetection) {
_detectedArea = cv::Rect();
return;
}
// Set up tracking area around the best detection
UpdateDetectedAreaFromObject(frame, *bestDetection);
_isWeaponDetected = true;
_retainDetectedArea = 0;
// Validate in the same frame — run filter to check for person overlap
std::vector<ANSCENTER::Object> personDetections = RunFilterGetPersons(frame);
bool filterHadResults = !personDetections.empty() || !_filter;
ProcessWeaponDetection(frame, *bestDetection, output, personDetections, filterHadResults
#ifdef FNS_DEBUG
, draw
#endif
);
}
void ANSCustomWD::UpdateDetectedAreaFromObject(const cv::Mat& frame, const ANSCENTER::Object& detectedObj) {
const int imageSize = std::max(frame.cols, frame.rows);
int cropSize;
if (imageSize > 1920) cropSize = 640;
else if (imageSize > 1280) cropSize = 480;
else if (imageSize > 640) cropSize = 320;
else cropSize = 224;
// Cap cropSize to frame dimensions to avoid negative clamp range (UB)
cropSize = std::min(cropSize, std::min(frame.cols, frame.rows));
if (cropSize <= 0) {
_detectedArea = cv::Rect();
return;
}
const int xc = detectedObj.box.x + detectedObj.box.width / 2;
const int yc = detectedObj.box.y + detectedObj.box.height / 2;
int x1_new = std::clamp(xc - cropSize / 2, 0, frame.cols - cropSize);
int y1_new = std::clamp(yc - cropSize / 2, 0, frame.rows - cropSize);
_detectedArea.x = x1_new;
_detectedArea.y = y1_new;
_detectedArea.width = std::min(cropSize, frame.cols - _detectedArea.x);
_detectedArea.height = std::min(cropSize, frame.rows - _detectedArea.y);
}
// Functions for screen size division
double ANSCustomWD::calculateDistanceToCenter(const cv::Point& center, const cv::Rect& rect) {
cv::Point rectCenter(rect.x + rect.width / 2, rect.y + rect.height / 2);
return std::sqrt(std::pow(rectCenter.x - center.x, 2) + std::pow(rectCenter.y - center.y, 2));
}
std::vector<ANSCustomWD::ImageSection> ANSCustomWD::divideImage(const cv::Mat& image) {
if (image.empty()) {
std::cerr << "Error: Empty image!" << std::endl;
return cachedSections;
}
cv::Size currentSize(image.cols, image.rows);
// Check if the image size has changed
if (currentSize == previousImageSize) {
return cachedSections; // Return cached sections if size is the same
}
// Update previous size
previousImageSize = currentSize;
cachedSections.clear();
int width = image.cols;
int height = image.rows;
int maxDimension = std::max(width, height);
int numSections = 10;// std::max(1, numSections); // Ensure at least 1 section
if (maxDimension <= 2560)numSections = 8;
if (maxDimension <= 1280)numSections = 6;
if (maxDimension <= 960)numSections = 4;
if (maxDimension <= 640)numSections = 2;
if (maxDimension <= 320)numSections = 1;
int gridRows = std::sqrt(numSections);
int gridCols = (numSections + gridRows - 1) / gridRows; // Ensure all sections are covered
int sectionWidth = width / gridCols;
int sectionHeight = height / gridRows;
cv::Point imageCenter(width / 2, height / 2);
std::vector<std::pair<double, ImageSection>> distancePriorityList;
// Create sections and store their distance from the center
for (int r = 0; r < gridRows; ++r) {
for (int c = 0; c < gridCols; ++c) {
int x = c * sectionWidth;
int y = r * sectionHeight;
int w = (c == gridCols - 1) ? width - x : sectionWidth;
int h = (r == gridRows - 1) ? height - y : sectionHeight;
ImageSection section(cv::Rect(x, y, w, h));
double distance = calculateDistanceToCenter(imageCenter, section.region);
distancePriorityList.emplace_back(distance, section);
}
}
// Sort sections based on distance from center, then top-to-bottom, then left-to-right
std::sort(distancePriorityList.begin(), distancePriorityList.end(),
[](const std::pair<double, ImageSection>& a, const std::pair<double, ImageSection>& b) {
if (std::abs(a.first - b.first) > 1e-5) {
return a.first < b.first; // Sort by closest distance to center
}
// If distance is the same, prioritize top to bottom, then left to right
return a.second.region.y == b.second.region.y
? a.second.region.x < b.second.region.x
: a.second.region.y < b.second.region.y;
});
// Assign priority
int priority = 1;
for (auto& entry : distancePriorityList) {
entry.second.priority = priority++;
cachedSections.push_back(entry.second);
}
return cachedSections;
}
int ANSCustomWD::getHighestPriorityRegion() {
if (!cachedSections.empty()) {
return cachedSections.front().priority; // First element has the highest priority
}
return 0; // Return empty rect if no sections exist
}
int ANSCustomWD::getLowestPriorityRegion() {
if (!cachedSections.empty()) {
return cachedSections.back().priority; // Last element has the lowest priority
}
return 0; // Return empty rect if no sections exist
}
cv::Rect ANSCustomWD::getRegionByPriority(int priority) {
for (const auto& section : cachedSections) {
if (section.priority == priority) {
return section.region;
}
}
return cv::Rect(); // Return empty rect if priority not found
}
void ANSCustomWD::UpdateNoDetectionCondition() {
_isRealWeaponFrame = false;
_realWeaponCheck = 0;
if (_isWeaponDetected) {
_retainDetectedArea++;
if (_retainDetectedArea >= RETAINFRAMES) {// Reset detected area after 80 frames
_detectedArea.width = 0;
_detectedArea.height = 0;
_retainDetectedArea = 0;
_isWeaponDetected = false;
}
}
else {
_detectedArea.width = 0;
_detectedArea.height = 0;
_retainDetectedArea = 0;
}
}
float ANSCustomWD::calculateIoU(const cv::Rect& box1, const cv::Rect& box2) {
int x1 = std::max(box1.x, box2.x);
int y1 = std::max(box1.y, box2.y);
int x2 = std::min(box1.x + box1.width, box2.x + box2.width);
int y2 = std::min(box1.y + box1.height, box2.y + box2.height);
int intersectionArea = std::max(0, x2 - x1) * std::max(0, y2 - y1);
int box1Area = box1.width * box1.height;
int box2Area = box2.width * box2.height;
int unionArea = box1Area + box2Area - intersectionArea;
if (unionArea <= 0) return 0.0f;
return static_cast<float>(intersectionArea) / unionArea;
}
bool ANSCustomWD::IsOverlapping(const ANSCENTER::Object& obj, const std::vector<ANSCENTER::Object>& objectList, float iouThreshold)
{
for (const auto& otherObj : objectList)
{
float iou = calculateIoU(obj.box, otherObj.box);
//std::cout << "IoU: " << iou << std::endl;
if (iou > iouThreshold)
{
return true; // Overlapping found
}
}
return false; // No overlapping object found
}
void ANSCustomWD::UpdateActiveROI(const cv::Mat& frame, ANSCENTER::Object detectedObj) {
int cropSize = 640;
int imagegSize = std::max(frame.cols, frame.rows);
if (imagegSize > 1920) cropSize = 640;
else if (imagegSize > 1280) cropSize = 480;
else if (imagegSize > 640) cropSize = 320;
else cropSize = 224;
// Cap cropSize to frame dimensions to avoid negative coordinates
cropSize = std::min(cropSize, std::min(frame.cols, frame.rows));
if (cropSize <= 0) {
_detectedArea = cv::Rect();
return;
}
int xc = detectedObj.box.x + detectedObj.box.width / 2;
int yc = detectedObj.box.y + detectedObj.box.height / 2;
int x1_new = std::clamp(xc - cropSize / 2, 0, frame.cols - cropSize);
int y1_new = std::clamp(yc - cropSize / 2, 0, frame.rows - cropSize);
_detectedArea.x = x1_new;
_detectedArea.y = y1_new;
_detectedArea.width = std::min(cropSize, frame.cols - _detectedArea.x);
_detectedArea.height = std::min(cropSize, frame.rows - _detectedArea.y);
}
bool ANSCustomWD::ConfigureParameters(CustomParams& param)
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
// Clear current parameters
param.ROI_Config.clear();
param.ROI_Options.clear();
param.Parameters.clear();
param.ROI_Values.clear();
//// Fill ROI_Config
//if (this->_params.ROI_Config.empty()) {
// // Traffic Light ROIs
// param.ROI_Config.push_back({ true, false, false, 0, 10, "TrafficLight_One", "All Corners" });
// param.ROI_Config.push_back({ true, false, false, 0, 10, "TrafficLight_Two", "All Corners" });
// param.ROI_Config.push_back({ true, false, false, 0, 10, "TrafficLight_Three", "All Corners" });
// // Vehicle Detector Zones
// param.ROI_Config.push_back({ true, true, false, 0, 10, "CarZone_One", "All Corners" });
// param.ROI_Config.push_back({ true, true, false, 0, 10, "CarZone_Two", "All Corners" });
// param.ROI_Config.push_back({ true, true, false, 0, 10, "CarZone_Three", "All Corners" });
// // Cross Line ROIs
// param.ROI_Config.push_back({ false, false, true, 0, 10, "CrossLine_One", "All Corners" });
// param.ROI_Config.push_back({ false, false, true, 0, 10, "CrossLine_Two", "All Corners" });
// param.ROI_Config.push_back({ false, false, true, 0, 10, "CrossLine_Three", "All Corners" });
//}
//else {
// // Reuse existing ROI_Config
// param.ROI_Config = this->_params.ROI_Config;
//}
//// Safely reuse ROI_Values only if valid
//size_t suspiciousCap = this->_params.ROI_Values.capacity();
//if (!this->_params.ROI_Values.empty() && suspiciousCap < 10000) {
// for (const auto& roi : this->_params.ROI_Values) {
// CustomROIValue roiValue;
// roiValue.Name = roi.Name;
// roiValue.ROIPoints = roi.ROIPoints;
// roiValue.ROIMatch = roi.ROIMatch;
// roiValue.Option = roi.Option;
// roiValue.OriginalImageSize = roi.OriginalImageSize;
// param.ROI_Values.push_back(roiValue);
// }
//}
//else {
// // Use default harcoded values
// param.ROI_Values = {
// // TrafficLight
// {"Centre Point", {{700, 100}, {950, 100}, {950, 200}, {700, 200}}, "Left side", "TrafficLight_One_1", 1920},
// {"Centre Point", {{1000, 100}, {2000, 100}, {2000, 200}, {1000, 200}}, "Left side", "TrafficLight_Two_1", 1920},
// {"Centre Point", {{2100, 100}, {2200, 100}, {2200, 200}, {2100, 200}}, "Left side", "TrafficLight_Three_1", 1920},
// // VehicleDetector
// {"Centre Point", {{700, 650}, {950, 650}, {950, 700}, {600, 700}}, "Inside ROI", "CarZone_One_1", 1920},
// {"Centre Point", {{950, 650}, {1900, 650}, {1900, 770}, {950, 700}}, "Inside ROI", "CarZone_Two_1", 1920},
// {"Centre Point", {{1900, 650}, {2150, 650}, {2150, 770}, {1900, 770}}, "Inside ROI", "CarZone_Three_1", 1920},
// // CrossLine
// {"Centre Point", {{600, 670}, {2150, 750}}, "Above", "CrossLine_One_1", 1920},
// {"Centre Point", {{600, 670}, {2150, 750}}, "Left side", "CrossLine_Two_1", 1920},
// {"Centre Point", {{600, 670}, {2150, 750}}, "Left side", "CrossLine_Three_1", 1920}
// };
//}
//// Add ALPR parameter if ALPR is available
//if (_ALPRVisible) {
// CustomParameter stALPRParam;
// stALPRParam.Name = "ALPR";
// stALPRParam.DataType = "Boolean";
// stALPRParam.NoOfDecimals = 0;
// stALPRParam.MaxValue = 0;
// stALPRParam.MinValue = 0;
// stALPRParam.StartValue = "false";
// stALPRParam.ListItems.clear();
// stALPRParam.DefaultValue = "false";
// stALPRParam.Value = _useALPR ? "true" : "false";
// param.Parameters.push_back(stALPRParam);
//}
//// Add Display TL parameter
//CustomParameter stTLParam;
//stTLParam.Name = "Show Traffic Light";
//stTLParam.DataType = "Boolean";
//stTLParam.NoOfDecimals = 0;
//stTLParam.MaxValue = 0;
//stTLParam.MinValue = 0;
//stTLParam.StartValue = "false";
//stTLParam.ListItems.clear();
//stTLParam.DefaultValue = "false";
//stTLParam.Value = _displayTL ? "true" : "false";
//param.Parameters.push_back(stTLParam);
////Add Traffic Light AI parameter
//CustomParameter stTrafficLightAI;
//stTrafficLightAI.Name = "TrafficLightAI";
//stTrafficLightAI.DataType = "Boolean";
//stTrafficLightAI.NoOfDecimals = 0;
//stTrafficLightAI.MaxValue = 0;
//stTrafficLightAI.MinValue = 0;
//stTrafficLightAI.StartValue = "false";
//stTrafficLightAI.ListItems.clear();
//stTrafficLightAI.DefaultValue = "false";
//stTrafficLightAI.Value = m_bTrafficLightAI ? "true" : "false";
//param.Parameters.push_back(stTrafficLightAI);
return true;
}
catch (const std::exception& e) {
std::cerr << "Error in ConfigureParamaters: " << e.what() << std::endl;
return false;
}
catch (...) {
std::cerr << "Unknown error in ConfigureParamaters." << std::endl;
return false;
}
}

View File

@@ -0,0 +1,91 @@
#include "ANSLIB.h"
#define RETAINFRAMES 80
#define FILTERFRAMES 10
class CUSTOM_API ANSCustomWD : public IANSCustomClass
{
struct ImageSection {
cv::Rect region;
int priority;
ImageSection(const cv::Rect& r) : region(r), priority(0) {}
};
private:
using ANSLIBPtr = std::unique_ptr<ANSCENTER::ANSLIB, decltype(&ANSCENTER::ANSLIB::Destroy)>;
ANSLIBPtr _detector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _filter{ nullptr, &ANSCENTER::ANSLIB::Destroy };
int engineType;
std::string _detectorModelName;
std::string _detectorClassName;
int _detectorModelType; // Assuming 4 represents TensorRT YoloV11
int _detectorDetectionType; // Assuming 1 represents object detection
std::string _filterModelName;
std::string _filterClassName;
std::string _filterLabelMap;
int _filterModelType; // Assuming 1 represents OpenVINO YoloV12
int _filterDetectionType; // Assuming 1 represents object detection
std::recursive_mutex _mutex;
cv::Rect _detectedArea;// Area where weapon is detected
int _retainDetectedArea{ 0 };
bool _isWeaponDetected{ false };
float _detectionScoreThreshold{ 0.5 };
cv::Size previousImageSize = cv::Size(0, 0);
std::vector<ImageSection> cachedSections;
int _currentPriority{ 0 }; // None
int _realWeaponCheck{ 0 };
bool _isRealWeaponFrame{ false };
void UpdateNoDetectionCondition();
std::vector<ANSCENTER::Object> RunFilterGetPersons(const cv::Mat& frame);
// Function to seperate screen size
double calculateDistanceToCenter(const cv::Point& center, const cv::Rect& rect);
std::vector<ImageSection> divideImage(const cv::Mat& image);
int getHighestPriorityRegion();
int getLowestPriorityRegion();
cv::Rect getRegionByPriority(int priority);
// Utilities
float calculateIoU(const cv::Rect& box1, const cv::Rect& box2);
bool IsOverlapping(const ANSCENTER::Object& obj, const std::vector<ANSCENTER::Object>& objectList, float iouThreshold);
void UpdateActiveROI(const cv::Mat& frame, ANSCENTER::Object detectedObj);
std::vector<ANSCENTER::Object> ProcessExistingDetectedArea(
const cv::Mat& frame, const std::string& camera_id
#ifdef FNS_DEBUG
, cv::Mat& draw
#endif
);
bool ProcessWeaponDetection(
const cv::Mat& frame,
ANSCENTER::Object& detectedObj,
std::vector<ANSCENTER::Object>& output,
const std::vector<ANSCENTER::Object>& personDetections,
bool filterHadResults
#ifdef FNS_DEBUG
, cv::Mat& draw
#endif
);
void AddConfirmedWeaponDetection(
const cv::Mat& frame,
ANSCENTER::Object& detectedObj,
std::vector<ANSCENTER::Object>& output);
void ProcessNewDetectedArea(
const cv::Mat& frame,
const std::string& camera_id,
std::vector<ANSCENTER::Object>& output
#ifdef FNS_DEBUG
, cv::Mat& draw
#endif
);
void UpdateDetectedAreaFromObject(const cv::Mat& frame, const ANSCENTER::Object& detectedObj);
public:
bool Initialize(const std::string& modelDiretory,float detectionScoreThreshold, std::string& labelMap)override;
bool OptimizeModel(bool fp16)override;
std::vector<CustomObject> RunInference(const cv::Mat& input)override;
std::vector<CustomObject> RunInference(const cv::Mat& input, const std::string& camera_id)override;
bool Destroy()override;
virtual bool ConfigureParameters(CustomParams& param) override;
ANSCustomWD();
~ANSCustomWD();
};

View File

@@ -0,0 +1,27 @@
#include "pch.h"
#include "ANSCustomCodeWeaponDetection.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// expose the class to the outside world
extern "C" __declspec(dllexport) IANSCustomClass* Create() {
return new ANSCustomWD();
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,272 @@
#include "ANSCustomFallDetection.h"
ANSCustomFallDetector::ANSCustomFallDetector()
{
}
bool ANSCustomFallDetector::OptimizeModel(bool fp16)
{
if (!_detector) return false;
if (_detector->Optimize(fp16) != 0) return false;
return true;
}
std::vector<CustomObject> ANSCustomFallDetector::RunInference(const cv::Mat& input)
{
return RunInference(input, "CustomCam");
}
bool ANSCustomFallDetector::Destroy()
{
_detector.reset();
_motiondetector.reset();
return true;
}
bool ANSCustomFallDetector::Initialize(const std::string& modelDirectory, float detectionScoreThreshold, std::string& labelMap)
{
try {
_modelDirectory = modelDirectory;
_detectionScoreThreshold = detectionScoreThreshold;
// Create detector and motion detector through ANSLIB factory
_detector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_motiondetector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
if (!_detector || !_motiondetector) {
return false;
}
// Check hardware type
engineType = _detector->GetEngineType();
if (engineType == 0) {
_detectorModelType = 4; // TENSORRT
_detectorDetectionType = 1; // DETECTION
}
else {
_detectorModelType = 5; // OPENVINO
_detectorDetectionType = 1; // DETECTION
}
// Motion detector is always CPU-based
_motionModelType = 5; // OPENVINO
_motionDetectionType = 1; // DETECTION
if (_detectionScoreThreshold < 0.25f) _detectionScoreThreshold = 0.25f;
std::string licenseKey = "";
float detConfThreshold = 0.5f;
float detNMSThreshold = 0.5f;
bool autoEngineDetection = true;
bool loadEngineOnCreation = false;
// Load detector model
std::string detLabelMap;
int detResult = _detector->LoadModelFromFolder(
licenseKey.c_str(),
"", "",
_detectionScoreThreshold,
detConfThreshold,
detNMSThreshold,
autoEngineDetection,
_detectorModelType,
_detectorDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
detLabelMap);
if (detResult != 1) {
return false;
}
// Load motion detector (algorithmic, empty model directory)
std::string motionLabelMap;
float motionScoreThreshold = 0.5f;
int motionResult = _motiondetector->LoadModelFromFolder(
licenseKey.c_str(),
"motion", "motion.names",
motionScoreThreshold,
0.5f, 0.5f,
autoEngineDetection,
_motionModelType,
_motionDetectionType,
loadEngineOnCreation,
"",
motionLabelMap);
labelMap = detLabelMap;
return (detResult == 1);
}
catch (const std::exception& e) {
return false;
}
catch (...) {
return false;
}
}
ANSCustomFallDetector::~ANSCustomFallDetector()
{
Destroy();
}
std::vector<CustomObject> ANSCustomFallDetector::RunInference(const cv::Mat& input, const std::string& camera_id) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
std::vector<CustomObject> results;
std::vector<ANSCENTER::Object> output;
if (input.empty())
{
return results;
}
if ((input.cols < 10) ||
(input.rows < 10))
{
return results;
}
try {
if (_detector && _motiondetector) {
// Detect movement using the motion detector
std::vector<ANSCENTER::Object> movementObjects;
_motiondetector->RunInference(input, camera_id.c_str(), movementObjects);
if (!movementObjects.empty()) {
std::vector<ANSCENTER::Object> weaponRects;
for (ANSCENTER::Object& obj : movementObjects) {
weaponRects.push_back(obj);
}
int detectedArea = _detectedArea.width * _detectedArea.height;
if ((!weaponRects.empty()) ||
(detectedArea > 0)) {
if ((_detectedArea.width < 10) || (_detectedArea.height < 10))
{
_detectedArea = GenerateMinimumSquareBoundingBox(weaponRects, 640);
int x1_new = _detectedArea.x;
int y1_new = _detectedArea.y;
_detectedArea.x = std::max(x1_new, 0);
_detectedArea.y = std::max(y1_new, 0);
_detectedArea.width = std::min(640, input.cols - _detectedArea.x);
_detectedArea.height = std::min(640, input.rows - _detectedArea.y);
}
cv::Mat frame = input.clone();
std::vector<ANSCENTER::Object> detectedObjects;
if (_detectedArea.width * _detectedArea.height > 0) {
cv::Mat detectedObj = frame(_detectedArea).clone();
_detector->RunInference(detectedObj, camera_id.c_str(), detectedObjects);
detectedObj.release();
}
frame.release();
// Do detections
float maxScore = 0.0;
if (!detectedObjects.empty()) {
for (auto& detectedObj : detectedObjects) {
detectedObj.box.x += _detectedArea.x;
detectedObj.box.y += _detectedArea.y;
detectedObj.cameraId = camera_id;
if (detectedObj.confidence > this->_detectionScoreThreshold)
{
output.push_back(detectedObj);
if (maxScore < detectedObj.confidence)
{
maxScore = detectedObj.confidence;
int cropSize = 640;
int imagegSize = std::max(input.cols, input.rows);
if (imagegSize > 1920) cropSize = 640;
else if (imagegSize > 1280) cropSize = 480;
else if (imagegSize > 640) cropSize = 320;
else cropSize = 224;
maxScore = detectedObj.confidence;
int x1 = detectedObj.box.x;
int y1 = detectedObj.box.y;
int xc = x1 + detectedObj.box.width / 2;
int yc = y1 + detectedObj.box.height / 2;
int x1_new = std::max(xc - cropSize / 2, 0);
int y1_new = std::max(yc - cropSize / 2, 0);
x1_new = std::min(x1_new, input.cols - cropSize);
y1_new = std::min(y1_new, input.rows - cropSize);
_detectedArea.x = std::max(x1_new, 0);
_detectedArea.y = std::max(y1_new, 0);
_detectedArea.width = std::min(cropSize, input.cols - _detectedArea.x);
_detectedArea.height = std::min(cropSize, input.rows - _detectedArea.y);
}
_isFallDetected = true;
_retainDetectedArea = 0;
}
else
{
if (_isFallDetected) {
_retainDetectedArea++;
if (_retainDetectedArea >= 40) {
_detectedArea.width = 0;
_detectedArea.height = 0;
_retainDetectedArea = 0;
_isFallDetected = false;
}
}
else {
_detectedArea.width = 0;
_detectedArea.height = 0;
_retainDetectedArea = 0;
}
}
}
}
else {
if (_isFallDetected) {
_retainDetectedArea++;
if (_retainDetectedArea >= 40) {
_detectedArea.width = 0;
_detectedArea.height = 0;
_retainDetectedArea = 0;
_isFallDetected = false;
}
}
else {
_detectedArea.width = 0;
_detectedArea.height = 0;
_retainDetectedArea = 0;
}
}
}
}
for (auto obj : output) {
if (obj.confidence >= this->_detectionScoreThreshold) {
CustomObject customObj;
customObj.box = obj.box;
customObj.classId = obj.classId;
customObj.confidence = obj.confidence;
customObj.cameraId = obj.cameraId;
customObj.className = obj.className;
customObj.extraInfo = "Detection Score Threshold:" + std::to_string(_detectionScoreThreshold);
results.push_back(customObj);
}
}
}
return results;
}
catch (std::exception& e) {
return results;
}
}
cv::Rect ANSCustomFallDetector::GenerateMinimumSquareBoundingBox(const std::vector<ANSCENTER::Object>& detectedObjects, int minSize) {
int adMinSize = minSize - 20;
if (adMinSize < 0) adMinSize = 0;
if (detectedObjects.empty()) return cv::Rect(0, 0, minSize, minSize);
int minX = detectedObjects[0].box.x;
int minY = detectedObjects[0].box.y;
int maxX = detectedObjects[0].box.x + detectedObjects[0].box.width;
int maxY = detectedObjects[0].box.y + detectedObjects[0].box.height;
for (const auto& rect : detectedObjects) {
minX = std::min(minX, rect.box.x);
minY = std::min(minY, rect.box.y);
maxX = std::max(maxX, rect.box.x + rect.box.width);
maxY = std::max(maxY, rect.box.y + rect.box.height);
}
int width = maxX - minX;
int height = maxY - minY;
int squareSize = std::max({ width, height, adMinSize });
int centerX = minX + width / 2;
int centerY = minY + height / 2;
int squareX = centerX - squareSize / 2;
int squareY = centerY - squareSize / 2;
return cv::Rect(squareX - 10, squareY - 10, squareSize + 20, squareSize + 20);
}

View File

@@ -0,0 +1,35 @@
#include "ANSLIB.h"
class CUSTOM_API ANSCustomFallDetector : public IANSCustomClass
{
private:
using ANSLIBPtr = std::unique_ptr<ANSCENTER::ANSLIB, decltype(&ANSCENTER::ANSLIB::Destroy)>;
int engineType{ 0 };
ANSLIBPtr _detector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _motiondetector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
std::recursive_mutex _mutex;
cv::Rect _detectedArea;
cv::Rect _previousDetectedArea;
int _retainDetectedArea{ 0 };
bool _isFallDetected{ false };
float _detectionScoreThreshold{ 0.5 };
// ----- Model config -----
int _detectorModelType;
int _detectorDetectionType;
int _motionModelType;
int _motionDetectionType;
cv::Rect GenerateMinimumSquareBoundingBox(const std::vector<ANSCENTER::Object>& detectedObjects, int minSize = 640);
public:
bool Initialize(const std::string& modelDiretory, float detectionScoreThreshold, std::string& labelMap)override;
bool OptimizeModel(bool fp16)override;
std::vector<CustomObject> RunInference(const cv::Mat& input)override;
std::vector<CustomObject> RunInference(const cv::Mat& input, const std::string& camera_id)override;
bool Destroy()override;
ANSCustomFallDetector();
~ANSCustomFallDetector();
};

View File

@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{6cfe14db-72aa-47c6-bd64-b71c5b12ceff}</ProjectGuid>
<RootNamespace>ANSCustomFallDetection</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Projects\ANLS\ANSLIB\ANSLIB;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Projects\ANLS\ANSLIB\x64\Release;C:\ANSLibs\opencv\x64\vc17\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCUSTOMFALLDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCUSTOMFALLDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCUSTOMFALLDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCUSTOMFALLDETECTION_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>ANSLIB.lib;opencv_world4130.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSCustomFallDetection.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCustomFallDetection.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSCustomFallDetection.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSCustomFallDetection.cpp">
<Filter>Resource Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
#include "ANSLIB.h"
#include <deque>
#include <unordered_set>
#define RETAINFRAMES 80
#define FILTERFRAMES 10
//#define FNS_DEBUG
class CUSTOM_API ANSCustomFS : public IANSCustomClass
{
typedef std::pair<cv::Scalar, cv::Scalar> Range;
struct ImageSection {
cv::Rect region;
int priority;
ImageSection(const cv::Rect& r) : region(r), priority(0) {}
};
private:
using ANSLIBPtr = std::unique_ptr<ANSCENTER::ANSLIB, decltype(&ANSCENTER::ANSLIB::Destroy)>;
int engineType{ 0 };
ANSLIBPtr _motiondetector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _detector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _filter{ nullptr, &ANSCENTER::ANSLIB::Destroy };
std::recursive_mutex _mutex;
cv::Rect _detectedArea;
cv::Rect _previousDetectedArea;
int _retainDetectedArea{ 0 };
bool _isFireNSmokeDetected{ false };
float _detectionScoreThreshold{ 0.5 };
std::vector<cv::Mat> _frameHistory;
std::deque <cv::Mat> _frameQueue;
std::string _filterLabels;
int _realFireCheck{ 0 };
bool _isRealFireFrame{ false };
double _hsvThreshold;
std::vector<Range> _smoke_colour;
std::vector<Range> _fire_colour;
// ----- Model config -----
int _detectorModelType;
int _detectorDetectionType;
int _filterModelType;
int _filterDetectionType;
int _motionModelType;
int _motionDetectionType;
// Add these constants at class level
int MIN_ROI_SIZE = 50;
float SMOKE_CONFIDENCE_THRESHOLD = 0.7f;
float DETECTION_CONFIDENCE_THRESHOLD = 0.5f;
float MAX_AREA_OVERLAP = 0.5f;
int MAX_MOTION_TRACKING = 10;
int FILTER_VERIFICATION_FRAMES = 10;
int MIN_IMAGE_SIZE = 10;
float INCLUSIVE_IOU_THRESHOLD = 0.001f;
float MOTION_SENSITIVITY = 0.5f;
// Excluded filter class IDs
const std::unordered_set<int> EXCLUDED_FILTER_CLASSES =
{
13, // bench
59, // bed
60, // dining table
68, // microwave
69, // oven
70 // toaster
};
cv::Size previousImageSize = cv::Size(0, 0);
std::vector<ImageSection> cachedSections;
int _currentPriority{ 0 };
bool _readROIs{ false };
std::vector<cv::Rect> _exclusiveROIs;
float _smokeDetetectionThreshold{ 0 };
float _motionSpecificity{ 0 };
cv::Rect GenerateMinimumSquareBoundingBox(const std::vector<ANSCENTER::Object>& detectedObjects, int minSize = 640);
void UpdateNoDetectionCondition();
bool detectStaticFire(std::deque<cv::Mat>& frameQueue);
bool detectScreenFlicker(const std::vector<cv::Mat>& frames);
bool detectReflection(const cv::Mat& frame);
bool MajorityColourInFrame(cv::Mat frame, Range range, float area_threshold);
bool MajorityColourInFrame(cv::Mat frame, std::vector<Range> ranges, float area_threshold);
bool DetectFireNSmokeColourInFrame(const cv::Mat& frame, const cv::Rect& bBox, const std::vector<Range>& ranges, float area_threshold);
bool IsFireDetected(const cv::Mat image, const cv::Rect bBox);
bool IsSmokeDetected(const cv::Mat image, const cv::Rect bBox);
float calculateIoU(const cv::Rect& box1, const cv::Rect& box2);
bool IsOverlapping(const ANSCENTER::Object& obj, const std::vector<ANSCENTER::Object>& objectList, float iouThreshold = 0.5);
bool IsOverlapping(const ANSCENTER::Object& obj, const std::vector<cv::Rect>& objectList, float iouThreshold = 0.5);
bool IsROIOverlapping(const cv::Rect& obj, const std::vector<cv::Rect>& objectList, float iouThreshold = 0.5);
bool IsDetectedAreaValid(const cv::Rect& area) const;
bool IsFireOrSmoke(int classId, float confidence) const;
bool ValidateMotionCorrelation(const std::vector<cv::Rect>& fireNSmokeRects) const;
void UpdatePositiveDetection();
void ResetDetectedArea();
void UpdatePriorityRegion(const cv::Mat& frame);
int CalculateOptimalCropSize(const cv::Mat& frame) const;
void RefineDetectedArea(const cv::Mat& frame, const ANSCENTER::Object& detection);
std::vector<CustomObject> ConvertToCustomObjects(const std::vector<ANSCENTER::Object>& objects);
void ResetDetectionState();
void GetModelParameters();
std::vector<ANSCENTER::Object> ProcessExistingDetectedArea(const cv::Mat& frame, const std::string& camera_id, cv::Mat& draw);
bool ProcessValidDetection(const cv::Mat& frame, const std::string& camera_id, cv::Mat& draw, ANSCENTER::Object& detectedObj, std::vector<ANSCENTER::Object>& output);
void AddConfirmedDetection(ANSCENTER::Object& detectedObj, std::vector<ANSCENTER::Object>& output);
#ifdef FNS_DEBUG
void DisplayDebugFrame(cv::Mat& draw) {
cv::resize(draw, draw, cv::Size(1920, (1920 * draw.rows) / draw.cols));
cv::imshow("Combined Detected Areas", draw);
cv::waitKey(1);
}
#endif
// Function to separate screen size
double calculateDistanceToCenter(const cv::Point& center, const cv::Rect& rect);
std::vector<ImageSection> divideImage(const cv::Mat& image);
int getHighestPriorityRegion();
int getLowestPriorityRegion();
cv::Rect getRegionByPriority(int priority);
std::vector<ANSCENTER::Object> ProcessExistingDetectedArea(
const cv::Mat& frame,
const std::string& camera_id,
const std::vector<cv::Rect>& fireNSmokeRects, cv::Mat& draw);
bool ProcessDetectedObject(
const cv::Mat& frame,
ANSCENTER::Object& detectedObj,
const std::string& camera_id,
const std::vector<cv::Rect>& fireNSmokeRects,
std::vector<ANSCENTER::Object>& output, cv::Mat& draw);
bool ValidateWithFilter(
const cv::Mat& frame,
const ANSCENTER::Object& detectedObj,
const std::string& camera_id,
std::vector<ANSCENTER::Object>& output, cv::Mat& draw);
std::vector<ANSCENTER::Object> FindNewDetectedArea(
const cv::Mat& frame,
const std::string& camera_id, cv::Mat& draw);
std::vector<ANSCENTER::Object> FindMovementObjects(
const cv::Mat& frame,
const std::string& camera_id, cv::Mat& draw);
std::vector<ANSCENTER::Object> FindExcludedObjects(
const cv::Mat& frame,
const std::string& camera_id, cv::Mat& draw);
public:
bool Initialize(const std::string& modelDiretory, float detectionScoreThreshold, std::string& labelMap) override;
bool OptimizeModel(bool fp16) override;
bool ConfigureParameters(CustomParams& param) override;
std::vector<CustomObject> RunInference(const cv::Mat& input) override;
std::vector<CustomObject> RunInference(const cv::Mat& input, const std::string& camera_id) override;
bool Destroy() override;
ANSCustomFS();
~ANSCustomFS();
};

View File

@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{fa30545e-c8cd-4d6d-b738-0bf4e51f7947}</ProjectGuid>
<RootNamespace>ANSCustomFireNSmokeDetection</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Projects\ANLS\ANSLIB\ANSLIB;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Projects\ANLS\ANSLIB\x64\Release;C:\ANSLibs\opencv\x64\vc17\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCUSTOMFIRENSMOKEDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCUSTOMFIRENSMOKEDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCUSTOMFIRENSMOKEDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCUSTOMFIRENSMOKEDETECTION_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>ANSLIB.lib;opencv_world4130.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSCustomFireNSmoke.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCustomFireNSmoke.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSCustomFireNSmoke.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSCustomFireNSmoke.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "ANSCustomFireNSmoke.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// expose the class to the outside world
extern "C" __declspec(dllexport) IANSCustomClass* Create() {
return new ANSCustomFS();
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,257 @@
#include "ANSCustomCodeHelmetDetection.h"
static std::string toUpperCase(const std::string& input) {
std::string result = input;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::toupper(c); });
return result;
}
ANSCustomHMD::ANSCustomHMD() {
_isInitialized = false;
_readROIs = false;
}
ANSCustomHMD::~ANSCustomHMD() {
Destroy();
}
bool ANSCustomHMD::Destroy() {
try {
_detector.reset();
_classifier.reset();
_isInitialized = false;
return true;
}
catch (...) {
return false;
}
}
bool ANSCustomHMD::OptimizeModel(bool fp16) {
try {
if (!_detector || !_classifier) return false;
int detectorResult = _detector->Optimize(fp16);
int classifierResult = _classifier->Optimize(fp16);
if ((detectorResult != 1) || (classifierResult != 1)) return false;
else return true;
}
catch (...) {
return false;
}
}
bool ANSCustomHMD::Initialize(const std::string& modelDirectory, float detectionScoreThreshold, std::string& labelMap) {
try {
_modelDirectory = modelDirectory;
_detectionScoreThreshold = detectionScoreThreshold;
_isInitialized = false;
// Create model instances using factory pattern (ABI-safe)
_detector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_classifier = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
// NVIDIA GPU: Use TensorRT
_detectorModelType = 31; // TENSORRT
_detectorDetectionType = 1; // DETECTION
_classifierModelType = 31; // TENSORRT
_classifierDetectionType = 0; // CLASSIFICATION
//Check the hardware type
engineType = _detector->GetEngineType();
if (engineType == 1) {
// NVIDIA GPU: Use TensorRT
_detectorModelType = 31; // TENSORRT
_detectorDetectionType = 1; // DETECTION
_classifierModelType = 31; // TENSORRT
_classifierDetectionType = 0; // CLASSIFICATION
std::cout << "NVIDIA GPU detected. Using TensorRT" << std::endl;
}
else {
// CPU/Other: Use YOLO
_detectorModelType = 3; // YOLOV8/YOLOV11
_detectorDetectionType = 1; // DETECTION
_classifierModelType = 20; // ANSONNXCL
_classifierDetectionType = 0; // CLASSIFICATION
std::cout << "CPU detected. Using YOLO/ANSONNXCL" << std::endl;
}
if (_detectionScoreThreshold < 0.25f) _detectionScoreThreshold = 0.25f;
// classId: 0=license plate, 1=motorcyclist, 2=helmet, 3=no_helmet
labelMap = "license plate,motorcyclist,helmet,no_helmet";
#ifdef FNS_DEBUG
this->_loadEngineOnCreate = true;
#endif
int loadEngineOnCreation = _loadEngineOnCreate ? 1 : 0;
int autoEngineDetection = 1;
std::string licenseKey = "";
// Load detector model
float detScoreThreshold = _detectionScoreThreshold;
float detConfThreshold = 0.5f;
float detNMSThreshold = 0.5f;
std::string detLabelMap;
int detResult = _detector->LoadModelFromFolder(
licenseKey.c_str(),
"detector", "detector.names",
detScoreThreshold, detConfThreshold, detNMSThreshold,
autoEngineDetection,
_detectorModelType, _detectorDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
detLabelMap);
if (detResult != 1) {
std::cerr << "ANSCustomHMD::Initialize: Failed to load detector model." << std::endl;
return false;
}
// Load classifier model
float clsScoreThreshold = 0.25f;
float clsConfThreshold = 0.5f;
float clsNMSThreshold = 0.5f;
int clsResult = _classifier->LoadModelFromFolder(
licenseKey.c_str(),
"classifier", "classifier.names",
clsScoreThreshold, clsConfThreshold, clsNMSThreshold,
autoEngineDetection,
_classifierModelType, _classifierDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
_classifierLabels);
if (clsResult != 1) {
std::cerr << "ANSCustomHMD::Initialize: Failed to load classifier model." << std::endl;
return false;
}
_isInitialized = true;
return true;
}
catch (const std::exception& e) {
std::cerr << "ANSCustomHMD::Initialize: Exception: " << e.what() << std::endl;
return false;
}
catch (...) {
std::cerr << "ANSCustomHMD::Initialize: Unknown exception." << std::endl;
return false;
}
}
bool ANSCustomHMD::ConfigureParameters(CustomParams& param) {
param.ROI_Config.clear();
param.ROI_Options.clear();
param.Parameters.clear();
param.ROI_Values.clear();
return true;
}
std::vector<CustomObject> ANSCustomHMD::RunInference(const cv::Mat& input) {
return RunInference(input, "CustomCam");
}
std::vector<CustomObject> ANSCustomHMD::RunInference(const cv::Mat& input, const std::string& camera_id) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!_isInitialized || !_detector) {
return {};
}
if (input.empty() || input.cols < 10 || input.rows < 10) {
return {};
}
try {
// One-time parameter reading
if (!_readROIs) {
for (const auto& param : _params.Parameters) {
if (param.Name.find("ALPR") != std::string::npos) {
std::string paramValue = toUpperCase(param.Value);
// ALPR feature currently disabled
}
}
_readROIs = true;
}
// Run object detection
std::vector<ANSCENTER::Object> detectionResults;
_detector->RunInference(input, camera_id.c_str(), detectionResults);
if (detectionResults.empty()) {
return {};
}
std::vector<CustomObject> results;
results.reserve(detectionResults.size());
const cv::Rect frameBounds(0, 0, input.cols, input.rows);
const float scoreThreshold = _detectionScoreThreshold;
for (const auto& obj : detectionResults) {
if (obj.confidence < scoreThreshold) {
continue;
}
CustomObject customObject;
customObject.confidence = obj.confidence;
customObject.box = obj.box;
customObject.cameraId = camera_id;
switch (obj.classId) {
case 0: { // License plate
customObject.classId = 0;
customObject.className = "license plate";
customObject.extraInfo = "license plate";
results.push_back(std::move(customObject));
break;
}
case 1: { // Motorcycle
customObject.classId = 1;
customObject.className = "motorcyclist";
results.push_back(std::move(customObject));
break;
}
case 2: // Helmet
case 3: { // No helmet - classify to confirm
// Validate bounding box
if ((obj.box & frameBounds) != obj.box) {
continue;
}
if (!_classifier) {
continue;
}
cv::Mat croppedImage = input(obj.box);
std::vector<ANSCENTER::Object> classifierResults;
_classifier->RunInference(croppedImage, camera_id.c_str(), classifierResults);
if (classifierResults.empty()) {
continue;
}
const bool isNoHelmet = (classifierResults[0].classId == 1);
customObject.classId = isNoHelmet ? 3 : 2;
customObject.className = isNoHelmet ? "no_helmet" : "helmet";
results.push_back(std::move(customObject));
break;
}
default:
break;
}
}
return results;
}
catch (const std::exception& e) {
std::cerr << "ANSCustomHMD::RunInference: Exception: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "ANSCustomHMD::RunInference: Unknown exception." << std::endl;
}
return {};
}

View File

@@ -0,0 +1,33 @@
#include "ANSLIB.h"
//#define FNS_DEBUG
class CUSTOM_API ANSCustomHMD : public IANSCustomClass
{
private:
using ANSLIBPtr = std::unique_ptr<ANSCENTER::ANSLIB, decltype(&ANSCENTER::ANSLIB::Destroy)>;
std::recursive_mutex _mutex;
int engineType{ 0 };
ANSLIBPtr _detector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _classifier{ nullptr, &ANSCENTER::ANSLIB::Destroy };
// ----- Model config -----
int _detectorModelType;
int _detectorDetectionType;
int _classifierModelType;
int _classifierDetectionType;
std::string _classifierLabels;
bool _isInitialized{ false };
bool _readROIs{ false };
public:
bool Initialize(const std::string& modelDiretory, float detectionScoreThreshold, std::string& labelMap) override;
bool OptimizeModel(bool fp16) override;
bool ConfigureParameters(CustomParams& param) override;
std::vector<CustomObject> RunInference(const cv::Mat& input) override;
std::vector<CustomObject> RunInference(const cv::Mat& input, const std::string& camera_id) override;
bool Destroy() override;
ANSCustomHMD();
~ANSCustomHMD();
};

View File

@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{c1ccb674-e333-4a8b-baf9-cce18dbd3f21}</ProjectGuid>
<RootNamespace>ANSCustomHelmetDetection</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>C:\Projects\ANLS\ANSLIB\x64\Release;C:\ANSLibs\opencv\x64\vc17\lib;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Projects\ANLS\ANSLIB\ANSLIB;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCUSTOMHELMETDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCUSTOMHELMETDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCUSTOMHELMETDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCUSTOMHELMETDETECTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>ANSLIB.lib;opencv_world4130.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSCustomCodeHelmetDetection.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCustomCodeHelmetDetection.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSCustomCodeHelmetDetection.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSCustomCodeHelmetDetection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "ANSCustomCodeHelmetDetection.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// expose the class to the outside world
extern "C" __declspec(dllexport) IANSCustomClass* Create() {
return new ANSCustomHMD();
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,449 @@
#include "ANSCustomRVA.h"
struct ExtractedInfo {
std::string revision;
std::string model;
std::string serialNumber;
};
ExtractedInfo extractDeviceInfo(const std::string& jsonText) {
ExtractedInfo info;
std::smatch match;
std::regex revPattern("\"class_name\":\"Rev:([^\"]+)\"");
if (std::regex_search(jsonText, match, revPattern)) {
info.revision = match[1].str();
}
std::regex modelPattern("\"class_name\":\"Model:([^\"]+)\"");
if (std::regex_search(jsonText, match, modelPattern)) {
info.model = match[1].str();
}
std::regex snPattern("\"class_name\":\"S[\\\\\/]*N:([^\"]+)\"");
if (std::regex_search(jsonText, match, snPattern)) {
info.serialNumber = match[1].str();
}
return info;
}
std::string extractQRCodeValue(const std::string& jsonText) {
std::smatch match;
// Step 1: Find the entire QRCode object
std::regex objectPattern("\\{[^{}]*\"extra_info\":\"QRCode\"[^{}]*\\}");
if (std::regex_search(jsonText, match, objectPattern)) {
std::string qrObject = match[0].str();
// Step 2: Extract class_name from that object
std::regex namePattern("\"class_name\":\"([^\"]+)\"");
std::smatch nameMatch;
if (std::regex_search(qrObject, nameMatch, namePattern)) {
return nameMatch[1].str();
}
}
return "";
}
std::string toUpperCase(const std::string& input) {
std::string result = input;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::toupper(c); });
return result;
}
ANSCustomRVA::ANSCustomRVA()
{
_isInitialized = false;
_readROIs = false;
// Default values
_numberOfScrews = 4;
_numberOfScrewsPCB = 1;
_numberOfPowerCable = 1;
_numberOfBMPRO = 1;
_numberOfLabel = 1;
_numberOfPlasticPackge = 1;
}
ANSCustomRVA::~ANSCustomRVA()
{
Destroy();
}
bool ANSCustomRVA::Destroy()
{
try {
_detector.reset();
if (ansOCRHandle != nullptr) { ReleaseANSOCRHandle(&ansOCRHandle); ansOCRHandle = nullptr; }
if (ansOpenCVHandle != nullptr) { ReleaseANSCVHandle(&ansOpenCVHandle); ansOpenCVHandle = nullptr; }
return true;
}
catch (const std::exception& e) {
return false;
}
catch (...) {
return false;
}
}
bool ANSCustomRVA::OptimizeModel(bool fp16)
{
try {
if (!_detector) return false;
if (_detector->Optimize(fp16) != 0) return false;
return true;
}
catch (const std::exception& e) {
return false;
}
catch (...) {
return false;
}
}
bool ANSCustomRVA::Initialize(const std::string& modelDirectory, float detectionScoreThreshold, std::string& labelMap)
{
try {
_modelDirectory = modelDirectory;
_detectionScoreThreshold = detectionScoreThreshold;
// Initialize the OCR engine
if (ansOCRHandle != nullptr) ReleaseANSOCRHandle(&ansOCRHandle);
std::string licenseKey = "";
std::string ocrModelFilePath = "C:\\ProgramData\\ANSCENTER\\Shared\\ANS_GenericOCR_v1.0.zip";
int language = 0; // English
int engine = 0;
int ocrCreateResult = CreateANSOCRHandle(&ansOCRHandle, licenseKey.c_str(), ocrModelFilePath.c_str(), "", language, engine);
// Initialize ANSCV
if (ansOpenCVHandle != nullptr) ReleaseANSCVHandle(&ansOpenCVHandle);
int qrCreateResult = CreateANSCVHandle(&ansOpenCVHandle, licenseKey.c_str());
// Create detector through ANSLIB factory
_detector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
if (!_detector) {
_isInitialized = false;
return false;
}
// Check hardware type
engineType = _detector->GetEngineType();
if (engineType == 0) {
_detectorModelType = 4; // TENSORRT
_detectorDetectionType = 1; // DETECTION
}
else {
_detectorModelType = 5; // OPENVINO
_detectorDetectionType = 1; // DETECTION
}
if (_detectionScoreThreshold < 0.25f) _detectionScoreThreshold = 0.25f;
float detConfThreshold = 0.5f;
float detNMSThreshold = 0.5f;
bool autoEngineDetection = true;
bool loadEngineOnCreation = _loadEngineOnCreate;
#ifdef FNS_DEBUG
loadEngineOnCreation = true;
#endif
std::string detLabelMap;
int detResult = _detector->LoadModelFromFolder(
licenseKey.c_str(),
"rva",
"rva.names",
_detectionScoreThreshold,
detConfThreshold,
detNMSThreshold,
autoEngineDetection,
_detectorModelType,
_detectorDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
detLabelMap);
if (detResult != 1) {
_isInitialized = false;
return false;
}
labelMap = detLabelMap;
if (ocrCreateResult * qrCreateResult > 0) {
_isInitialized = true;
}
else {
_isInitialized = false;
return false;
}
return true;
}
catch (const std::exception& e) {
return false;
}
catch (...) {
return false;
}
}
bool ANSCustomRVA::ConfigureParameters(CustomParams& param) {
// Configure parameters for the model, if needed
param.ROI_Config.clear();
param.ROI_Options.clear();
param.Parameters.clear();
param.ROI_Values.clear();
CustomParameter numberOfScrews;
numberOfScrews.Name = "No_Screws";
numberOfScrews.DataType = "Integer";
numberOfScrews.NoOfDecimals = 0;
numberOfScrews.MaxValue = 100;
numberOfScrews.MinValue = 0;
numberOfScrews.StartValue = "4";
numberOfScrews.ListItems.clear();
numberOfScrews.DefaultValue = "4";
param.Parameters.push_back(numberOfScrews);
CustomParameter numberOfScrewsPCB;
numberOfScrewsPCB.Name = "No_Screws_PCB";
numberOfScrewsPCB.DataType = "Integer";
numberOfScrewsPCB.NoOfDecimals = 0;
numberOfScrewsPCB.MaxValue = 100;
numberOfScrewsPCB.MinValue = 0;
numberOfScrewsPCB.StartValue = "1";
numberOfScrewsPCB.ListItems.clear();
numberOfScrewsPCB.DefaultValue = "1";
param.Parameters.push_back(numberOfScrewsPCB);
CustomParameter numberOfPowerCable;
numberOfPowerCable.Name = "No_Power_Cable";
numberOfPowerCable.DataType = "Integer";
numberOfPowerCable.NoOfDecimals = 0;
numberOfPowerCable.MaxValue = 100;
numberOfPowerCable.MinValue = 0;
numberOfPowerCable.StartValue = "1";
numberOfPowerCable.ListItems.clear();
numberOfPowerCable.DefaultValue = "1";
param.Parameters.push_back(numberOfPowerCable);
CustomParameter numberOfBMPPRO;
numberOfBMPPRO.Name = "No_BMPRO";
numberOfBMPPRO.DataType = "Integer";
numberOfBMPPRO.NoOfDecimals = 0;
numberOfBMPPRO.MaxValue = 100;
numberOfBMPPRO.MinValue = 0;
numberOfBMPPRO.StartValue = "1";
numberOfBMPPRO.ListItems.clear();
numberOfBMPPRO.DefaultValue = "1";
param.Parameters.push_back(numberOfBMPPRO);
CustomParameter numberOfLabel;
numberOfLabel.Name = "No_Label";
numberOfLabel.DataType = "Integer";
numberOfLabel.NoOfDecimals = 0;
numberOfLabel.MaxValue = 100;
numberOfLabel.MinValue = 0;
numberOfLabel.StartValue = "1";
numberOfLabel.ListItems.clear();
numberOfLabel.DefaultValue = "1";
param.Parameters.push_back(numberOfLabel);
CustomParameter numberOfPlasticPackage;
numberOfPlasticPackage.Name = "No_PlasticPackage";
numberOfPlasticPackage.DataType = "Integer";
numberOfPlasticPackage.NoOfDecimals = 0;
numberOfPlasticPackage.MaxValue = 100;
numberOfPlasticPackage.MinValue = 0;
numberOfPlasticPackage.StartValue = "1";
numberOfPlasticPackage.ListItems.clear();
numberOfPlasticPackage.DefaultValue = "1";
param.Parameters.push_back(numberOfPlasticPackage);
return true;
}
std::vector<CustomObject> ANSCustomRVA::RunInference(const cv::Mat& input)
{
return RunInference(input, "CustomCam");
}
std::vector<CustomObject> ANSCustomRVA::RunInference(const cv::Mat& input, const std::string& camera_id) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
std::vector<CustomObject> results;
if (!_isInitialized) {
return results;
}
if (input.empty() || input.cols < 10 || input.rows < 10) {
return results;
}
try {
#ifdef FNS_DEBUG
// Default values for debug
_numberOfScrews = 4;
_numberOfScrewsPCB = 1;
_numberOfPowerCable = 1;
_numberOfBMPRO = 1;
_numberOfLabel = 1;
_numberOfPlasticPackge = 1;
#else
//1. Read the ROI parameters only once
if (!_readROIs) {
for (auto& param : _params.Parameters) {
if (param.Name.find("No_Screws") != std::string::npos) {
_numberOfScrews = std::stoi("4");// std::stoi(param.Value);
}
else if (param.Name.find("No_Screws_PCB") != std::string::npos) {
_numberOfScrewsPCB = std::stoi("1");// std::stoi(param.Value);
}
else if (param.Name.find("No_Power_Cable") != std::string::npos) {
_numberOfPowerCable = std::stoi(param.Value);
}
else if (param.Name.find("No_BMPRO") != std::string::npos) {
_numberOfBMPRO = std::stoi(param.Value);
}
else if (param.Name.find("No_Label") != std::string::npos) {
_numberOfLabel = std::stoi(param.Value);
}
else if (param.Name.find("No_PlasticPackage") != std::string::npos) {
_numberOfPlasticPackge = std::stoi(param.Value);
}
}
_readROIs = true;
}
#endif
// 2. Do general detections
const cv::Mat& frame = input;
std::vector<ANSCENTER::Object> detectionResults;
_detector->RunInference(frame, camera_id.c_str(), detectionResults);
if (detectionResults.empty()) {
return results;
}
int numOfScrews = 0;
int numOfScrewsPCB = 0;
int numOfPowerCable = 0;
int numOfBMPRO = 0;
int numOfLabel = 0;
int numOfPlasticPackage = 0;
std::string qrCodeData;
std::string ocrText;
// Count the number of detected objects
// 3. Process the detection results
for (const auto& detection : detectionResults) {
CustomObject customObject;
customObject.classId = detection.classId;
customObject.confidence = detection.confidence;
customObject.box = detection.box;
customObject.cameraId = camera_id;
// Add additional information based on the class ID
switch (detection.classId)
{
case 0: // Screw
numOfScrews++;
break;
case 1: // Screw PCB
numOfScrewsPCB++;
break;
case 2: // Power Cable
numOfPowerCable++;
break;
case 3: // BMPRO
numOfBMPRO++;
break;
case 4: // Label
{
numOfLabel++;
cv::Rect ocrBox(customObject.box.x, customObject.box.y, 4 * customObject.box.width / 5, 1.3 * customObject.box.height / 4);
cv::Rect qrBox(customObject.box.x, customObject.box.y + customObject.box.height / 5, 1 * customObject.box.width / 4, 2 * customObject.box.height / 5);
cv::Mat ocrImage = frame(ocrBox);
cv::Mat qrImage = frame(qrBox);
for (int i = 0; i <= 5; i++) {
ocrText.clear(); // Bug fix: was ocrText.empty() which doesn't clear
qrCodeData.clear();
RunInferenceCV(&ansOCRHandle, ocrImage, ocrText);
ANSCV_QRDecoderCV(&ansOpenCVHandle, qrImage, qrCodeData);
ExtractedInfo ocrInfoDetail = extractDeviceInfo(ocrText);
std::string qrInfoDetail = extractQRCodeValue(qrCodeData);
if (!ocrText.empty() &&
!qrCodeData.empty() &&
!qrInfoDetail.empty() &&
!ocrInfoDetail.model.empty() &&
!ocrInfoDetail.revision.empty()) {
break; // Exit the loop if OCR or QR code data is found
}
// sleep for a short duration to allow OCR/QR code detection to stabilize
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
#ifdef FNS_DEBUG
std::cout << "OCR Text: " << ocrText << std::endl;
std::cout << "QR Text: " << qrCodeData << std::endl;
cv::imshow("OCR Image", ocrImage);
cv::imshow("QR Image", qrImage);
cv::waitKey(1);
#endif
ocrImage.release();
qrImage.release();
break;
}
case 5: // Plastic Package
numOfPlasticPackage++;
break;
}
results.push_back(customObject);
}
// 4. Check if the number of detected objects matches the expected counts
CustomObject passfailObject;
passfailObject.confidence = 1;
passfailObject.box.x = 50;
passfailObject.box.y = 50;
passfailObject.box.width = input.cols - 50;
passfailObject.box.height = input.rows - 50;
passfailObject.cameraId = camera_id;
std::string extraInfo;
ExtractedInfo ocrInfo = extractDeviceInfo(ocrText);
std::string qrInfo = extractQRCodeValue(qrCodeData);
// we need to extract SN and Rev instead using ocr information
std::string sn = qrInfo;
if (sn.empty()) sn = ocrInfo.serialNumber;
extraInfo = "SN:" + sn + "; Model:" + ocrInfo.model + "; REV:" + ocrInfo.revision;
if ((numOfScrews == _numberOfScrews) &&
(numOfScrewsPCB == _numberOfScrewsPCB) &&
(numOfPowerCable == _numberOfPowerCable) &&
(numOfBMPRO == _numberOfBMPRO) &&
(numOfLabel == _numberOfLabel) &&
(numOfPlasticPackage == _numberOfPlasticPackge))
{
passfailObject.classId = 6; // PASS
passfailObject.className = "PASS";
}
else {
passfailObject.classId = 7; // FAILED
passfailObject.className = "FAIL";
std::string summary = "; Screws:" + std::to_string(numOfScrews) + " out of " + std::to_string(_numberOfScrews) +
"; Screws_PCB:" + std::to_string(numOfScrewsPCB) + " out of " + std::to_string(_numberOfScrewsPCB) +
"; Power Cables:" + std::to_string(numOfPowerCable) + " out of " + std::to_string(_numberOfPowerCable) +
"; BMPROs:" + std::to_string(numOfBMPRO) + " out of " + std::to_string(_numberOfBMPRO) +
"; Labels:" + std::to_string(numOfLabel) + " out of " + std::to_string(_numberOfLabel) +
"; Plastic Packages: " + std::to_string(numOfPlasticPackage) + " of " + std::to_string(_numberOfPlasticPackge);
extraInfo = extraInfo + summary;
}
passfailObject.extraInfo = extraInfo;
results.push_back(passfailObject);
#ifdef FNS_DEBUG
std::cout << "RVA Attributes:" << extraInfo << std::endl;
#endif
}
catch (const std::exception& e) {
}
catch (...) {
}
return results;
}

View File

@@ -0,0 +1,40 @@
#include "ANSLIB.h"
#include <ANSOCRBase.h>
#include "ANSOpenCV.h"
//#define FNS_DEBUG
class CUSTOM_API ANSCustomRVA : public IANSCustomClass
{
private:
using ANSLIBPtr = std::unique_ptr<ANSCENTER::ANSLIB, decltype(&ANSCENTER::ANSLIB::Destroy)>;
std::recursive_mutex _mutex;
int engineType{ 0 };
ANSLIBPtr _detector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSCENTER::ANSOCRBase* ansOCRHandle = nullptr;
ANSCENTER::ANSOPENCV* ansOpenCVHandle = nullptr;
// ----- Model config -----
int _detectorModelType;
int _detectorDetectionType;
std::string _classifierLabels;
bool _isInitialized{ false };
bool _readROIs{ false };
int _numberOfScrews;
int _numberOfScrewsPCB;
int _numberOfPowerCable;
int _numberOfBMPRO;
int _numberOfLabel;
int _numberOfPlasticPackge;
public:
bool Initialize(const std::string& modelDiretory, float detectionScoreThreshold, std::string& labelMap)override;
bool OptimizeModel(bool fp16)override;
bool ConfigureParameters(CustomParams& param)override;
std::vector<CustomObject> RunInference(const cv::Mat& input)override;
std::vector<CustomObject> RunInference(const cv::Mat& input, const std::string& camera_id)override;
bool Destroy()override;
ANSCustomRVA();
~ANSCustomRVA();
};

View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{53abafe4-0a2d-474b-acf1-e7c16e778c0b}</ProjectGuid>
<RootNamespace>ANSCustomRVA</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>C:\Projects\ANLS\ANSLIB\x64\Release;C:\ANSLibs\opencv\x64\vc17\lib;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Projects\ANLS\ANSLIB\ANSLIB;C:\Projects\ANLS\ANSLIB\ANSOCR;C:\Projects\ANLS\ANSLIB\ANSCV;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCUSTOMRVA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCUSTOMRVA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCUSTOMRVA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCUSTOMRVA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>ANSLIB.lib;opencv_world4130.lib;ANSOCR.lib;ANSCV.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSCustomRVA.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCustomRVA.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\PaddleOCR">
<UniqueIdentifier>{7714b184-cf00-456b-a78c-5dda7ea182ae}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSCustomRVA.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSCustomRVA.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,24 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "ANSCustomRVA.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// expose the class to the outside world
extern "C" __declspec(dllexport) IANSCustomClass* Create() {
return new ANSCustomRVA();
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

13
ANSLIB/ANSCustomRVA/pch.h Normal file
View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,483 @@
#include "ANSCustomViolence.h"
#include "HDBSCAN.h"
ANSCustomViolence::ANSCustomViolence() {
}
bool ANSCustomViolence::Destroy() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
_movinetDetector.reset();
_personDetector.reset();
_fightDetector.reset();
_prevCrowdTracks.clear();
_crowdTracksHistory.clear();
_crowdCropBoxes.clear();
_isInitialized = false;
return true;
}
catch (...) {
return false;
}
}
ANSCustomViolence::~ANSCustomViolence() {
Destroy();
}
bool ANSCustomViolence::Initialize(const std::string& modelDirectory, float detectionScoreThreshold, std::string& labelMap) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
std::string _personLabelMap;
std::string _fightLabelMap;
std::string _movienetLabelMap;
_modelDirectory = modelDirectory;
_detectionScoreThreshold = detectionScoreThreshold;
_isInitialized = false;
_prevCrowdTracks.clear();
_nextCrowdTrackId = 1;
_crowdCropBoxes.clear();
_crowdFrameCount = 0;
_crowdAlertActive = false;
// Create model instances using factory pattern (ABI-safe)
_personDetector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_fightDetector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_movinetDetector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_personModelType = 4; // TENSORRT
_personDetectionType = 1; // DETECTION
_fightModelType = 4; // TENSORRT
_fightDetectionType = 1; // DETECTION
_movinetModelType = 27; // MOVIENET
_movinetDetectionType = 0; // CLASSIFICATION
// Check the hardware type
engineType = _personDetector->GetEngineType();
if (engineType == 1) {
// NVIDIA GPU: Use TensorRT
_personModelType = 4; // TENSORRT
_personDetectionType = 1; // DETECTION
_fightModelType = 4; // TENSORRT
_fightDetectionType = 1; // DETECTION
_movinetModelType = 27; // MOVIENET
_movinetDetectionType = 0; // CLASSIFICATION
std::cout << "NVIDIA GPU detected. Using TensorRT" << std::endl;
}
else {
// CPU/Other: Use OpenVINO
_personModelType = 5; // OPENVINO
_personDetectionType = 1; // DETECTION
_fightModelType = 5; // OPENVINO
_fightDetectionType = 1; // DETECTION
_movinetModelType = 27; // MOVIENET
_movinetDetectionType = 0; // CLASSIFICATION
std::cout << "CPU detected. Using OpenVINO" << std::endl;
}
if (this->_detectionScoreThreshold < 0.25f) this->_detectionScoreThreshold = 0.25f;
// classId: 0=Normal, 1=Violence, 2=person, 3=crowd, 4=fighting, 5=normal_fight
labelMap = "Normal,Violence,person,crowd,fighting,normal_fight";
#ifdef VD_DEBUG
this->_loadEngineOnCreate = true;
#endif
int loadEngineOnCreation = _loadEngineOnCreate ? 1 : 0;
int autoEngineDetection = 1;
std::string licenseKey = "";
// Load person detector model
float personScoreThreshold = 0.5f;
float personConfThreshold = 0.5f;
float personNMSThreshold = 0.5f;
int personResult = _personDetector->LoadModelFromFolder(
licenseKey.c_str(),
"person", "person.names",
personScoreThreshold, personConfThreshold, personNMSThreshold,
autoEngineDetection,
_personModelType, _personDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
_personLabelMap);
if (personResult != 1) return false;
// Load fight detector model
float fightScoreThreshold = 0.25f;
float fightConfThreshold = 0.5f;
float fightNMSThreshold = 0.5f;
int fightResult = _fightDetector->LoadModelFromFolder(
licenseKey.c_str(),
"fightOD", "fightOD.names",
fightScoreThreshold, fightConfThreshold, fightNMSThreshold,
autoEngineDetection,
_fightModelType, _fightDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
_fightLabelMap);
if (fightResult != 1) return false;
// Load MoviNet temporal model
float movinetScoreThreshold = this->_detectionScoreThreshold;
float movinetConfThreshold = 0.5f;
float movinetNMSThreshold = 0.5f;
int movinetResult = _movinetDetector->LoadModelFromFolder(
licenseKey.c_str(),
"MoviNet151", "MoviNet151.names",
movinetScoreThreshold, movinetConfThreshold, movinetNMSThreshold,
autoEngineDetection,
_movinetModelType, _movinetDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
_movienetLabelMap);
if (movinetResult != 1) return false;
_isInitialized = true;
return true;
}
catch (const std::exception& ex) {
return false;
}
}
bool ANSCustomViolence::OptimizeModel(bool fp16)
{
if (!_personDetector || !_fightDetector) return false;
int personDetectionResult = _personDetector->Optimize(fp16);
int fightDetectionResult = _fightDetector->Optimize(fp16);
if ( (personDetectionResult != 1) ||
(fightDetectionResult != 1)) return false;
else return true;
}
bool ANSCustomViolence::ConfigureParameters(CustomParams& param) {
return true;
}
std::vector<CustomObject> ANSCustomViolence::RunInference(const cv::Mat& input)
{
return RunInference(input, "CustomCam");
}
std::vector<CustomObject> ANSCustomViolence::RunInference(const cv::Mat& input, const std::string& camera_id)
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
std::vector<CustomObject> results;
try {
if (!_isInitialized || !_personDetector || !_fightDetector) {
return results;
}
// Per-camera frame counter (fixes global counter bug for multi-camera)
int& frameCounter = _frameCounterPerCamera[camera_id];
frameCounter++;
const int currentFrameIdx = frameCounter;
// ----- Constants -----
const float personConfThr = static_cast<float>(_detectionScoreThreshold);
const float clusterEps = 600.0f;
const int clusterMinPts = 2;
const float fightConfThr = DEFAULT_FIGHT_DETECTION_THRESHOLD;
const float bboxExpandScale = 1.5f;
const float bboxDriftThresh = 0.5f;
const int bboxDriftCheckAt = 4;
bool currentFrameHasCrowd = false;
// ==============================================================
// Helper: Run fight detector on a bbox region
// ==============================================================
auto runFightDetector = [&](const cv::Rect& safeBbox) -> CustomObject {
cv::Mat cropped = input(safeBbox).clone();
std::vector<ANSCENTER::Object> fightResults;
_fightDetector->RunInference(cropped, camera_id.c_str(), fightResults);
bool hasFight = false;
float fightConf = 0.0f;
for (const auto& obj : fightResults) {
float conf = static_cast<float>(obj.confidence);
if (obj.classId == 1 && conf >= fightConfThr) {
hasFight = true;
fightConf = conf;
break;
}
else if (obj.classId == 0 && conf > fightConf) {
fightConf = conf;
}
}
CustomObject fightObj;
fightObj.classId = hasFight ? 4 : 5;
fightObj.className = hasFight ? "fighting" : "normal_fight";
fightObj.confidence = fightConf;
fightObj.box = safeBbox;
fightObj.cameraId = camera_id;
return fightObj;
};
// ==============================================================
// Helper: Feed MoviNet with bbox-stabilized crop
// ==============================================================
auto runMovinet = [&](const cv::Rect& currentBbox, int trackId) {
if (!_movinetDetector) return;
auto& cropState = _trackCropStates[trackId];
// Lock bbox at the start of each 16-frame window
if (!cropState.isLocked) {
cropState.lockedBbox = currentBbox;
cropState.isLocked = true;
cropState.framesSinceLock = 0;
}
cropState.framesSinceLock++;
// Check for significant crowd drift — re-lock if crowd moved too far
if (cropState.framesSinceLock > bboxDriftCheckAt) {
float overlap = CalculateOverlap(cropState.lockedBbox, currentBbox);
if (overlap < bboxDriftThresh) {
cropState.lockedBbox = currentBbox;
cropState.framesSinceLock = 1;
}
}
// Crop with the locked bbox
cv::Rect lockedRoi = cropState.lockedBbox
& cv::Rect(0, 0, input.cols, input.rows);
if (lockedRoi.width <= 0 || lockedRoi.height <= 0) return;
cv::Mat movinetCrop = input(lockedRoi).clone();
std::string movinetCamId = MakeMovinetCameraId(camera_id, trackId);
std::vector<ANSCENTER::Object> movinetResults;
_movinetDetector->RunInference(movinetCrop, movinetCamId.c_str(), movinetResults);
for (const auto& mr : movinetResults) {
CustomObject movinetObj;
movinetObj.classId = (mr.classId == 1) ? 1 : 0;
movinetObj.className = mr.className;
movinetObj.confidence = mr.confidence;
movinetObj.box = lockedRoi;
movinetObj.cameraId = camera_id;
results.push_back(movinetObj);
// Inference completed — unlock for next window
cropState.isLocked = false;
cropState.framesSinceLock = 0;
}
};
// ==============================================================
// Helper: Combined fight + movinet for a region
// ==============================================================
auto processCrowdRegion = [&](const cv::Rect& expandedBbox, int trackId) {
cv::Rect safeBbox = expandedBbox & cv::Rect(0, 0, input.cols, input.rows);
if (safeBbox.width <= 0 || safeBbox.height <= 0) return;
// Fight detection (always uses live bbox)
CustomObject fightObj = runFightDetector(safeBbox);
results.push_back(fightObj);
// MoviNet (uses locked bbox for spatial consistency)
runMovinet(safeBbox, trackId);
};
// ==============================================================
// BLOCK 1: Person detection
// ==============================================================
std::vector<ANSCENTER::Object> personResults;
_personDetector->RunInference(input, camera_id.c_str(), personResults);
std::vector<cv::Rect> boxes;
std::vector<int> personIds;
if (!personResults.empty()) {
boxes.reserve(personResults.size());
personIds.reserve(personResults.size());
for (const auto& p : personResults) {
float conf = static_cast<float>(p.confidence);
if (conf < personConfThr) continue;
boxes.push_back(p.box);
personIds.push_back(p.trackId);
CustomObject personObj;
personObj.classId = 2;
personObj.className = "person";
personObj.confidence = conf;
personObj.box = p.box;
personObj.cameraId = camera_id;
personObj.trackId = p.trackId;
results.push_back(personObj);
}
}
// ==============================================================
// BLOCK 2: Clustering + Crowd tracking
// ==============================================================
std::vector<cv::Rect> crowdBoxes;
std::vector<int> groupTrackIds;
if (!boxes.empty()) {
auto clusters = HDBSCAN::cluster(boxes, clusterEps, clusterMinPts);
std::vector<std::vector<int>> crowdPersonIds;
for (const auto& c : clusters) {
if (static_cast<int>(c.size()) < clusterMinPts) continue;
cv::Rect clusterBox;
bool first = true;
std::vector<int> ids;
for (int idx : c) {
if (idx < 0 || idx >= static_cast<int>(boxes.size())) continue;
if (first) { clusterBox = boxes[idx]; first = false; }
else { clusterBox |= boxes[idx]; }
ids.push_back(personIds[idx]);
}
if (!first) {
crowdBoxes.push_back(clusterBox);
crowdPersonIds.push_back(std::move(ids));
}
}
// --- Assign crowd track IDs by person-ID overlap ---
if (!crowdBoxes.empty()) {
currentFrameHasCrowd = true;
_crowdFrameCount++;
if (_crowdFrameCount >= 2) _crowdAlertActive = true;
_noFightFrameCount = 0;
groupTrackIds.reserve(crowdBoxes.size());
for (size_t gIdx = 0; gIdx < crowdBoxes.size(); ++gIdx) {
std::set<int> pidSet(crowdPersonIds[gIdx].begin(),
crowdPersonIds[gIdx].end());
int assignedId = -1;
int bestOverlap = 0;
for (const auto& prev : _prevCrowdTracks) {
int overlap = 0;
for (int pid : pidSet) {
if (std::find(prev.personIds.begin(),
prev.personIds.end(), pid)
!= prev.personIds.end())
++overlap;
}
if (overlap > bestOverlap && overlap >= 1) {
bestOverlap = overlap;
assignedId = prev.trackId;
}
}
if (assignedId == -1) assignedId = _nextCrowdTrackId++;
groupTrackIds.push_back(assignedId);
}
// Update tracking state
_prevCrowdTracks.clear();
for (size_t gIdx = 0; gIdx < crowdBoxes.size(); ++gIdx) {
CrowdTrackInfo info;
info.bbox = crowdBoxes[gIdx];
info.trackId = groupTrackIds[gIdx];
info.frameIdx = currentFrameIdx;
info.personIds = crowdPersonIds[gIdx];
_prevCrowdTracks.push_back(info);
_crowdTracksHistory.push_back(info);
}
// Prune old history
const int cutoff = currentFrameIdx - _crowdMaxAge;
_crowdTracksHistory.erase(
std::remove_if(_crowdTracksHistory.begin(),
_crowdTracksHistory.end(),
[cutoff](const CrowdTrackInfo& c) {
return c.frameIdx < cutoff;
}),
_crowdTracksHistory.end());
// Output crowd objects
for (size_t gIdx = 0; gIdx < crowdBoxes.size(); ++gIdx) {
CustomObject crowdObj;
crowdObj.classId = 3;
crowdObj.className = "crowd";
crowdObj.confidence = 1.0f;
crowdObj.box = crowdBoxes[gIdx];
crowdObj.cameraId = camera_id;
crowdObj.trackId = groupTrackIds[gIdx];
results.push_back(crowdObj);
}
}
}
// ==============================================================
// BLOCK 3: Fight detection + MoviNet for each active crowd
// ==============================================================
for (size_t gIdx = 0; gIdx < crowdBoxes.size(); ++gIdx) {
cv::Rect expanded = ExpandBbox(crowdBoxes[gIdx], bboxExpandScale, input.size());
int trackId = groupTrackIds[gIdx];
_crowdCropBoxes[trackId] = expanded;
processCrowdRegion(expanded, trackId);
}
// ==============================================================
// BLOCK 4: Alert mode — no crowd, monitor last known region
// ==============================================================
if (_crowdAlertActive && !currentFrameHasCrowd && !_crowdCropBoxes.empty()) {
int nearestTrackId = -1;
if (!_prevCrowdTracks.empty()) {
nearestTrackId = _prevCrowdTracks[0].trackId;
}
else {
for (const auto& [tid, _] : _crowdCropBoxes) {
if (tid > nearestTrackId) nearestTrackId = tid;
}
}
if (nearestTrackId != -1 && _crowdCropBoxes.count(nearestTrackId)) {
processCrowdRegion(_crowdCropBoxes[nearestTrackId], nearestTrackId);
}
// Decay alert mode
_noFightFrameCount++;
if (_noFightFrameCount >= ALERT_DECAY_FRAMES) {
_crowdAlertActive = false;
_crowdCropBoxes.clear();
_noFightFrameCount = 0;
}
}
else if (!currentFrameHasCrowd) {
_crowdFrameCount = 0;
}
// ==============================================================
// BLOCK 5: Clean up local stale tracking state
// ==============================================================
if (currentFrameIdx % 50 == 0) {
std::set<int> activeIds;
for (const auto& ct : _prevCrowdTracks) activeIds.insert(ct.trackId);
for (const auto& [tid, _] : _crowdCropBoxes) activeIds.insert(tid);
for (auto it = _trackCropStates.begin(); it != _trackCropStates.end(); ) {
if (activeIds.find(it->first) == activeIds.end()) {
it = _trackCropStates.erase(it);
}
else {
++it;
}
}
for (auto it = _crowdCropBoxes.begin(); it != _crowdCropBoxes.end(); ) {
if (activeIds.find(it->first) == activeIds.end()) {
it = _crowdCropBoxes.erase(it);
}
else {
++it;
}
}
}
return results;
}
catch (const std::exception& e) {
std::cerr << "RunInference error: " << e.what() << std::endl;
return results;
}
}

View File

@@ -0,0 +1,101 @@
#include "ANSLIB.h"
const int SEQUENCE_FRAMES = 16;
const int VALID_VIOLENCE_FRAMES = 8;
const float DEFAULT_FIGHT_DETECTION_THRESHOLD = 0.5f;
//#define VD_DEBUG
class CUSTOM_API ANSCustomViolence : public IANSCustomClass
{
private:
using ANSLIBPtr = std::unique_ptr<ANSCENTER::ANSLIB, decltype(&ANSCENTER::ANSLIB::Destroy)>;
std::recursive_mutex _mutex;
int engineType{ 0 };
ANSLIBPtr _personDetector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _fightDetector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
ANSLIBPtr _movinetDetector{ nullptr, &ANSCENTER::ANSLIB::Destroy };
// ----- Model config -----
std::string _fightLabelMap;
std::string _fightClassName;
std::string _fightModelName;
std::string _personModelName;
std::string _personClassName;
std::string _personLabelMap;
int _fightModelType;
int _fightDetectionType;
int _personModelType;
int _personDetectionType;
int _movinetModelType;
int _movinetDetectionType;
// ----- Crowd tracking -----
struct CrowdTrackInfo {
cv::Rect bbox;
int trackId;
int frameIdx;
std::vector<int> personIds;
};
std::vector<CrowdTrackInfo> _prevCrowdTracks;
std::vector<CrowdTrackInfo> _crowdTracksHistory;
int _nextCrowdTrackId = 1;
std::map<int, cv::Rect> _crowdCropBoxes;
int _crowdMaxAge = 3;
// ----- Alert state -----
int _crowdFrameCount = 0;
bool _crowdAlertActive = false;
int _noFightFrameCount = 0;
static constexpr int ALERT_DECAY_FRAMES = 30;
// ----- Per-camera frame counter -----
std::map<std::string, int> _frameCounterPerCamera;
// ----- MoviNet bbox stabilization per crowd track -----
struct TrackCropState {
cv::Rect lockedBbox;
bool isLocked = false;
int framesSinceLock = 0;
};
std::map<int, TrackCropState> _trackCropStates;
// ----- Initialization flag -----
bool _isInitialized{ false };
// ----- Helpers -----
static std::string MakeMovinetCameraId(const std::string& camera_id, int trackId) {
return camera_id + "_crowd_" + std::to_string(trackId);
}
static float CalculateOverlap(const cv::Rect& r1, const cv::Rect& r2) {
cv::Rect inter = r1 & r2;
if (inter.empty()) return 0.0f;
float interArea = static_cast<float>(inter.width * inter.height);
float minArea = std::min(
static_cast<float>(r1.width * r1.height),
static_cast<float>(r2.width * r2.height));
return (minArea > 0) ? (interArea / minArea) : 0.0f;
}
static cv::Rect ExpandBbox(const cv::Rect& bbox, float scale, const cv::Size& frameSize) {
int cx = bbox.x + bbox.width / 2;
int cy = bbox.y + bbox.height / 2;
int nw = static_cast<int>(bbox.width * scale);
int nh = static_cast<int>(bbox.height * scale);
cv::Rect expanded(cx - nw / 2, cy - nh / 2, nw, nh);
return expanded & cv::Rect(0, 0, frameSize.width, frameSize.height);
}
public:
bool Initialize(const std::string& modelDirectory, float detectionScoreThreshold,
std::string& labelMap) override;
bool OptimizeModel(bool fp16) override;
bool ConfigureParameters(CustomParams& param) override;
std::vector<CustomObject> RunInference(const cv::Mat& input) override;
std::vector<CustomObject> RunInference(const cv::Mat& input,
const std::string& camera_id) override;
bool Destroy() override;
ANSCustomViolence();
~ANSCustomViolence();
};

View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{51ceb303-8a6f-4821-8328-bd037ca97714}</ProjectGuid>
<RootNamespace>ANSCustomViolence</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Projects\ANLS\ANSLIB\ANSLIB;C:\ANSLibs\opencv\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Projects\ANLS\ANSLIB\x64\Release;C:\ANSLibs\opencv\x64\vc17\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;ANSCUSTOMVIOLENCE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;ANSCUSTOMVIOLENCE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;ANSCUSTOMVIOLENCE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;ANSCUSTOMVIOLENCE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>ANSLIB.lib;opencv_world4130.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ANSCustomViolence.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="HDBSCAN.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ANSCustomViolence.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="HDBSCAN.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ANSCustomViolence.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HDBSCAN.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ANSCustomViolence.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HDBSCAN.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,428 @@
#include "pch.h"
#include "HDBSCAN.h"
#include <queue>
#include <cmath>
#include <algorithm>
#include <limits>
#include <unordered_map>
#include <set>
#include <vector>
namespace
{
float sqrDistance(const cv::Point2f& a, const cv::Point2f& b)
{
float dx = a.x - b.x;
float dy = a.y - b.y;
return dx * dx + dy * dy;
}
float distance(const cv::Point2f& a, const cv::Point2f& b)
{
return std::sqrt(sqrDistance(a, b));
}
// Simple KD-Tree node for 2D points (optimized for k-NN search)
struct KDNode2D {
cv::Point2f point;
int index;
KDNode2D* left;
KDNode2D* right;
int axis; // 0 = x, 1 = y
KDNode2D(const cv::Point2f& p, int idx, int ax = 0)
: point(p), index(idx), left(nullptr), right(nullptr), axis(ax) {
}
};
// Build KD-Tree for 2D points (simplified, but effective for small-medium datasets)
KDNode2D* buildKDTree(std::vector<cv::Point2f>& points, std::vector<int>& indices, int depth = 0)
{
if (indices.empty()) return nullptr;
if (indices.size() == 1) {
return new KDNode2D(points[indices[0]], indices[0], depth % 2);
}
int axis = depth % 2;
int median = static_cast<int>(indices.size() / 2);
// Partial sort to find median
std::nth_element(indices.begin(), indices.begin() + median, indices.end(),
[&](int a, int b) {
return axis == 0 ? (points[a].x < points[b].x) : (points[a].y < points[b].y);
});
int rootIdx = indices[median];
KDNode2D* node = new KDNode2D(points[rootIdx], rootIdx, axis);
std::vector<int> leftIndices(indices.begin(), indices.begin() + median);
std::vector<int> rightIndices(indices.begin() + median + 1, indices.end());
node->left = buildKDTree(points, leftIndices, depth + 1);
node->right = buildKDTree(points, rightIndices, depth + 1);
return node;
}
// Find k nearest neighbors using KD-Tree (max-heap to keep k smallest)
void findKNN(KDNode2D* node, const cv::Point2f& query, int k,
std::priority_queue<std::pair<float, int>>& heap)
{
if (!node) return;
float dist = sqrDistance(node->point, query);
// Use max-heap to keep k smallest distances
if (heap.size() < static_cast<size_t>(k)) {
heap.push({ dist, node->index });
}
else if (dist < heap.top().first) {
heap.pop();
heap.push({ dist, node->index });
}
int axis = node->axis;
float diff = (axis == 0) ? (query.x - node->point.x) : (query.y - node->point.y);
float diffSq = diff * diff;
KDNode2D* nearNode = nullptr;
KDNode2D* farNode = nullptr;
if (diff <= 0) {
nearNode = node->left;
farNode = node->right;
}
else {
nearNode = node->right;
farNode = node->left;
}
if (nearNode) findKNN(nearNode, query, k, heap);
if (farNode && (heap.size() < static_cast<size_t>(k) || diffSq < heap.top().first)) {
findKNN(farNode, query, k, heap);
}
}
// Delete KD-Tree
void deleteKDTree(KDNode2D* node)
{
if (!node) return;
deleteKDTree(node->left);
deleteKDTree(node->right);
delete node;
}
// Union-Find data structure for MST clustering (optimized)
class UnionFind {
private:
std::vector<int> parent;
std::vector<int> rank;
std::vector<int> size;
public:
UnionFind(int n) : parent(n), rank(n, 0), size(n, 1) {
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // Path compression
}
return parent[x];
}
void unite(int x, int y) {
int px = find(x);
int py = find(y);
if (px == py) return;
// Union by rank
if (rank[px] < rank[py]) {
std::swap(px, py);
}
parent[py] = px;
size[px] += size[py];
if (rank[px] == rank[py]) {
rank[px]++;
}
}
int getSize(int x) {
return size[find(x)];
}
};
// Edge structure for MST
struct Edge {
int u, v;
float weight;
bool operator<(const Edge& other) const {
return weight < other.weight;
}
};
// Calculate mutual reachability distance (HDBSCAN* core concept)
// This is the key difference from DBSCAN - uses max(distance, coreDist1, coreDist2)
inline float mutualReachabilityDist(
const cv::Point2f& p1, const cv::Point2f& p2,
float coreDist1, float coreDist2)
{
float d = distance(p1, p2);
return std::max({ d, coreDist1, coreDist2 });
}
inline float bottomY(const cv::Rect& b)
{
return static_cast<float>(b.y + b.height);
}
inline bool isBottomAligned(const cv::Rect& a, const cv::Rect& b, float bottomDiffRatio)
{
const float maxH = static_cast<float>(std::max(a.height, b.height));
if (maxH <= 0.0f) return false;
const float diff = std::abs(bottomY(a) - bottomY(b));
return diff <= maxH * bottomDiffRatio;
}
inline bool isCenterClose(const cv::Rect& a, const cv::Rect& b,
const cv::Point2f& ca, const cv::Point2f& cb)
{
const float maxW = static_cast<float>(std::max(a.width, b.width));
if (maxW <= 0.0f) return false;
return distance(ca, cb) <= (2.0f * maxW);
}
}
// HDBSCAN* implementation - Full algorithm matching the original paper:
// 1. Calculate core distance (k-th nearest neighbor) using KD-Tree for speed
// 2. Build MST using mutual reachability distance (not Euclidean distance)
// 3. Extract clusters from MST using stability-based selection (hierarchical clustering)
// 4. Filter clusters by minPts and stability
std::vector<std::vector<int>> HDBSCAN::cluster(const std::vector<cv::Rect>& boxes,
float eps,
int minPts,
float bottomDiffRatio)
{
std::vector<std::vector<int>> clusters;
const int n = static_cast<int>(boxes.size());
if (n == 0 || minPts < 2) return clusters;
if (n < minPts) return clusters;
std::vector<cv::Point2f> points;
points.reserve(n);
for (const auto& b : boxes) {
points.emplace_back(b.x + b.width * 0.5f, b.y + b.height * 0.5f);
}
// ===== 1. Calculate core distance using KD-Tree (optimized k-NN search) =====
std::vector<float> coreDist(n, 0.0f);
std::vector<cv::Point2f> pointsCopy = points;
std::vector<int> indices(n);
for (int i = 0; i < n; ++i) indices[i] = i;
KDNode2D* kdTree = buildKDTree(pointsCopy, indices);
for (int i = 0; i < n; ++i) {
std::priority_queue<std::pair<float, int>> heap;
findKNN(kdTree, points[i], minPts, heap);
if (heap.size() >= static_cast<size_t>(minPts)) {
coreDist[i] = std::sqrt(heap.top().first);
}
else if (heap.size() > 0) {
float maxDist = 0.0f;
while (!heap.empty()) {
maxDist = std::max(maxDist, std::sqrt(heap.top().first));
heap.pop();
}
coreDist[i] = maxDist;
}
else {
coreDist[i] = 0.0f;
}
}
deleteKDTree(kdTree);
// ===== 2. Build MST using mutual reachability distance =====
std::vector<Edge> edges;
const size_t maxEdges = (n < 100) ? (n * (n - 1) / 2) : (n * 10);
edges.reserve(std::min(maxEdges, static_cast<size_t>(n * (n - 1) / 2)));
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
float mrDist = mutualReachabilityDist(
points[i], points[j],
coreDist[i], coreDist[j]);
if (eps > 0 && mrDist > eps) continue;
edges.push_back({ i, j, mrDist });
if (edges.size() >= maxEdges && n > 100) {
goto build_mst;
}
}
}
build_mst:
std::sort(edges.begin(), edges.end());
UnionFind uf(n);
std::vector<Edge> mstEdges;
mstEdges.reserve(n - 1);
for (const auto& e : edges) {
if (uf.find(e.u) != uf.find(e.v)) {
uf.unite(e.u, e.v);
mstEdges.push_back(e);
if (static_cast<int>(mstEdges.size()) >= n - 1) {
break;
}
}
}
// ===== 3. Extract clusters from MST =====
std::sort(mstEdges.begin(), mstEdges.end());
struct ClusterInfo {
int root;
int size;
float birthWeight;
float deathWeight;
float stability;
bool isActive;
};
std::vector<ClusterInfo> clusterInfo(n);
for (int i = 0; i < n; ++i) {
clusterInfo[i] = { i, 1, 0.0f, std::numeric_limits<float>::max(), 0.0f, true };
}
UnionFind clusterUF(n);
std::vector<int> clusterSizes(n, 1);
for (const auto& e : mstEdges) {
int rootU = clusterUF.find(e.u);
int rootV = clusterUF.find(e.v);
if (rootU != rootV) {
int sizeU = clusterSizes[rootU];
int sizeV = clusterSizes[rootV];
if (sizeU >= minPts && clusterInfo[rootU].isActive) {
float lambdaDeath = e.weight;
float lambdaBirth = clusterInfo[rootU].birthWeight;
clusterInfo[rootU].stability = (lambdaDeath - lambdaBirth) * sizeU;
clusterInfo[rootU].deathWeight = lambdaDeath;
clusterInfo[rootU].isActive = false;
}
if (sizeV >= minPts && clusterInfo[rootV].isActive) {
float lambdaDeath = e.weight;
float lambdaBirth = clusterInfo[rootV].birthWeight;
clusterInfo[rootV].stability = (lambdaDeath - lambdaBirth) * sizeV;
clusterInfo[rootV].deathWeight = lambdaDeath;
clusterInfo[rootV].isActive = false;
}
clusterUF.unite(e.u, e.v);
int newRoot = clusterUF.find(e.u);
int newSize = sizeU + sizeV;
clusterSizes[newRoot] = newSize;
float minBirth = std::min(clusterInfo[rootU].birthWeight, clusterInfo[rootV].birthWeight);
if (minBirth == 0.0f) minBirth = e.weight;
clusterInfo[newRoot] = {
newRoot, newSize, minBirth,
std::numeric_limits<float>::max(), 0.0f, true
};
}
}
for (int i = 0; i < n; ++i) {
int root = clusterUF.find(i);
if (clusterInfo[root].isActive && clusterSizes[root] >= minPts) {
float maxWeight = mstEdges.empty() ? 0.0f : mstEdges.back().weight;
clusterInfo[root].stability = (maxWeight - clusterInfo[root].birthWeight) * clusterSizes[root];
}
}
// ===== 4. Extract clusters with positive stability =====
std::unordered_map<int, std::vector<int>> clusterMap;
std::set<int> processedRoots;
for (int i = 0; i < n; ++i) {
int root = clusterUF.find(i);
int clusterSize = clusterSizes[root];
if (clusterSize >= minPts && clusterInfo[root].stability >= -0.001f) {
if (processedRoots.find(root) == processedRoots.end()) {
clusterMap[root] = std::vector<int>();
processedRoots.insert(root);
}
clusterMap[root].push_back(i);
}
}
// Convert to output format + filter by bottom alignment
for (auto& pair : clusterMap) {
std::vector<int> filtered;
filtered.reserve(pair.second.size());
for (int idx : pair.second) {
bool hasNeighbor = false;
for (int other : pair.second) {
if (idx == other) continue;
if (isBottomAligned(boxes[idx], boxes[other], bottomDiffRatio)) {
hasNeighbor = true;
break;
}
}
if (hasNeighbor) {
filtered.push_back(idx);
}
}
// Extra rule: if cluster size is 2 or 3, enforce center distance <= max width
std::vector<int> proximityFiltered;
if (filtered.size() == 2) {
int a = filtered[0];
int b = filtered[1];
if (isCenterClose(boxes[a], boxes[b], points[a], points[b])) {
proximityFiltered = filtered;
}
}
else if (filtered.size() == 3) {
std::vector<bool> keep(3, true);
for (int i = 0; i < 3; ++i) {
for (int j = i + 1; j < 3; ++j) {
int a = filtered[i];
int b = filtered[j];
if (!isCenterClose(boxes[a], boxes[b], points[a], points[b])) {
keep[i] = false;
keep[j] = false;
}
}
}
for (int i = 0; i < 3; ++i) {
if (keep[i]) {
proximityFiltered.push_back(filtered[i]);
}
}
}
else {
proximityFiltered = std::move(filtered);
}
if (static_cast<int>(proximityFiltered.size()) >= minPts) {
clusters.push_back(std::move(proximityFiltered));
}
}
return clusters;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <vector>
#include <opencv2/opencv.hpp>
namespace HDBSCAN
{
std::vector<std::vector<int>> cluster(
const std::vector<cv::Rect>& boxes,
float eps,
int minPts,
float bottomDiffRatio = 0.2f
);
}

View File

@@ -0,0 +1,22 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "ANSCustomViolence.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) IANSCustomClass* Create() {
return new ANSCustomViolence();
}

View File

@@ -0,0 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX // Prevent windows.h from defining min/max macros
// which break std::min / std::max (C2589)
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,178 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
namespace ANSCENTER
{
public class ANSDLDOTNET
{
// Import the CreateANSODHandle_CS function
[DllImport(@"C:\ProgramData\ANSCENTER\Shared\ANSODEngine.dll", EntryPoint = "CreateANSODHandle_CS", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr CreateANSODHandle_CS(ref IntPtr handle,
string licenseKey,
string modelFilePath,
string modelFileZipPassword,
float modelThreshold,
float modelConfThreshold,
float modelNMSThreshold,
int autoDetectEngine,
int modelType,
int detectionType,
int loadEngineOnCreation);
// Import the RunInferenceImagePath_CS function
[DllImport(@"C:\ProgramData\ANSCENTER\Shared\ANSODEngine.dll", EntryPoint = "RunInferenceImagePath_CS", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr RunInferenceImagePath_CS(ref IntPtr handle, string imageFilePath);
[DllImport(@"C:\ProgramData\ANSCENTER\Shared\ANSODEngine.dll", EntryPoint = "ReleaseANSODHandle", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReleaseANSODHandle(ref IntPtr handle);
// Helper function to convert IntPtr to a C# string
public static string PtrToStringAnsi(IntPtr ptr)
{
return Marshal.PtrToStringAnsi(ptr);
}
private IntPtr handle;
static string CheckFileInZip(string zipFilePath)
{
// Ensure the zip file exists
if (!File.Exists(zipFilePath))
{
//Console.WriteLine("Zip file does not exist.");
return null; // or return string.Empty;
}
// Open the zip file
using (ZipArchive archive = ZipFile.OpenRead(zipFilePath))
{
// Iterate through the entries in the zip file
foreach (ZipArchiveEntry entry in archive.Entries)
{
// Check if the entry's name ends with .txt extension (case-insensitive)
if (entry.Name.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(entry.Name);
//Console.WriteLine($"Found .txt file: {fileNameWithoutExtension}");
return fileNameWithoutExtension;
}
}
}
// No .txt file found
//Console.WriteLine("No .txt file found inside the zip file.");
return null; // or return string.Empty;
}
private int GetModelType(string modelFilePath, ref int modelType, ref int detectionType)
{
modelType = 5; // Default model type
detectionType = 1;
if (!System.IO.File.Exists(modelFilePath))
{
return 0;
}
// Open the zip file
string txtFileName = CheckFileInZip(modelFilePath);
// Output the result
if (!string.IsNullOrEmpty(txtFileName))
{
switch (txtFileName)
{
case "openvino":
//Console.WriteLine("File is 'openvino'.");
modelType = 5; // OPENVINO
detectionType = 1;
break;
case "openvino10":
//Console.WriteLine("File is 'openvino10'.");
modelType = 15; // Default model type
detectionType = 1;
break;
case "tensorrt":
//Console.WriteLine("File is 'tensorrt'.");
modelType = 4; // TENSORRT
detectionType = 1;
break;
case "tensorrt10":
//Console.WriteLine("File is 'tensorrt10'.");
modelType = 14; // Default model type
detectionType = 1;
break;
default:
//Console.WriteLine("File name does not match any known cases.");
modelType = 5; // Default model type
detectionType = 1;
break;
}
return 1;
}
else
{
return 0;
}
}
public ANSDLDOTNET() {
handle = IntPtr.Zero;
}
public string Init(string licenseKey, string modelFilePath, string modelFileZipPassword, float detectionScore, int loadEngineOnCreation) {
int modelType = 1;
int detectionType = 1;
string enginePath = "C:\\ProgramData\\ANSCENTER\\Shared\\ANSODEngine.dll";
// 1. Check if the model file exists
if (!System.IO.File.Exists(modelFilePath))
{
return "ERROR: Model file does not exist";
}
//2. Check if engine path exists
if (!System.IO.File.Exists(enginePath))
{
return "ERROR: Engine path does not exist. Please install ANS Core Engine.";
}
//3. Get the model type
GetModelType(modelFilePath, ref modelType, ref detectionType);
IntPtr resultPtr = CreateANSODHandle_CS(ref handle,
licenseKey,
modelFilePath,
modelFileZipPassword,
0.5f,
detectionScore,
0.4f,
1, // autoDetectEngine
modelType, // modelType
detectionType,
loadEngineOnCreation); // load Engine on creation
return PtrToStringAnsi(resultPtr);
}
public int Release()
{
int result = ReleaseANSODHandle(ref handle);
return result;
}
// Call RunInferenceImagePath_CS to run inference on an image
public string RunInferenceFromImage(string imageFilePath)
{
IntPtr inferenceResultPtr = RunInferenceImagePath_CS(ref handle, imageFilePath);
string inferenceResult = PtrToStringAnsi(inferenceResultPtr);
return inferenceResult;
}
}
}

Some files were not shown because too many files have changed in this diff Show More