Initial commit to backup ANSLS
This commit is contained in:
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal 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
205
ANSLIB/ALL_BUILD.vcxproj
Normal file
File diff suppressed because one or more lines are too long
8
ANSLIB/ALL_BUILD.vcxproj.filters
Normal file
8
ANSLIB/ALL_BUILD.vcxproj.filters
Normal 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>
|
||||
135
ANSLIB/ANNHUB-UnitTest/ANNHUB-UnitTest.cpp
Normal file
135
ANSLIB/ANNHUB-UnitTest/ANNHUB-UnitTest.cpp
Normal 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;
|
||||
|
||||
}
|
||||
141
ANSLIB/ANNHUB-UnitTest/ANNHUB-UnitTest.vcxproj
Normal file
141
ANSLIB/ANNHUB-UnitTest/ANNHUB-UnitTest.vcxproj
Normal 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>
|
||||
22
ANSLIB/ANNHUB-UnitTest/ANNHUB-UnitTest.vcxproj.filters
Normal file
22
ANSLIB/ANNHUB-UnitTest/ANNHUB-UnitTest.vcxproj.filters
Normal 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>
|
||||
170
ANSLIB/ANNHUB/ANNHUB.vcxproj
Normal file
170
ANSLIB/ANNHUB/ANNHUB.vcxproj
Normal 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>
|
||||
39
ANSLIB/ANNHUB/ANNHUB.vcxproj.filters
Normal file
39
ANSLIB/ANNHUB/ANNHUB.vcxproj.filters
Normal 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
670
ANSLIB/ANNHUB/ANSANNHUB.cpp
Normal 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
69
ANSLIB/ANNHUB/ANSANNHUB.h
Normal 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
19
ANSLIB/ANNHUB/dllmain.cpp
Normal 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;
|
||||
}
|
||||
|
||||
7
ANSLIB/ANNHUB/framework.h
Normal file
7
ANSLIB/ANNHUB/framework.h
Normal 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
5
ANSLIB/ANNHUB/pch.cpp
Normal 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
18
ANSLIB/ANNHUB/pch.h
Normal 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
|
||||
1471
ANSLIB/ANSCV-UnitTest/ANSCV-UnitTest.cpp
Normal file
1471
ANSLIB/ANSCV-UnitTest/ANSCV-UnitTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
142
ANSLIB/ANSCV-UnitTest/ANSCV-UnitTest.vcxproj
Normal file
142
ANSLIB/ANSCV-UnitTest/ANSCV-UnitTest.vcxproj
Normal 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>
|
||||
25
ANSLIB/ANSCV-UnitTest/ANSCV-UnitTest.vcxproj.filters
Normal file
25
ANSLIB/ANSCV-UnitTest/ANSCV-UnitTest.vcxproj.filters
Normal 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>
|
||||
469
ANSLIB/ANSCV-UnitTest/OpenCVTest.cpp
Normal file
469
ANSLIB/ANSCV-UnitTest/OpenCVTest.cpp
Normal 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
265
ANSLIB/ANSCV/ANSCV.vcxproj
Normal 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>
|
||||
264
ANSLIB/ANSCV/ANSCV.vcxproj.filters
Normal file
264
ANSLIB/ANSCV/ANSCV.vcxproj.filters
Normal 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
1169
ANSLIB/ANSCV/ANSFLV.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
ANSLIB/ANSCV/ANSFLV.h
Normal file
111
ANSLIB/ANSCV/ANSFLV.h
Normal 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
|
||||
861
ANSLIB/ANSCV/ANSFilePlayer.cpp
Normal file
861
ANSLIB/ANSCV/ANSFilePlayer.cpp
Normal 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 (...) { }
|
||||
}
|
||||
117
ANSLIB/ANSCV/ANSFilePlayer.h
Normal file
117
ANSLIB/ANSCV/ANSFilePlayer.h
Normal 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
|
||||
762
ANSLIB/ANSCV/ANSFilePlayer_CV.cpp
Normal file
762
ANSLIB/ANSCV/ANSFilePlayer_CV.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
115
ANSLIB/ANSCV/ANSFilePlayer_CV.h
Normal file
115
ANSLIB/ANSCV/ANSFilePlayer_CV.h
Normal 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
|
||||
212
ANSLIB/ANSCV/ANSGpuFrameOps.h
Normal file
212
ANSLIB/ANSCV/ANSGpuFrameOps.h
Normal 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);
|
||||
}
|
||||
}
|
||||
25
ANSLIB/ANSCV/ANSGpuFrameRegistry.cpp
Normal file
25
ANSLIB/ANSCV/ANSGpuFrameRegistry.cpp
Normal 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 ®
|
||||
}
|
||||
|
||||
// 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
1175
ANSLIB/ANSCV/ANSMJPEG.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
ANSLIB/ANSCV/ANSMJPEG.h
Normal file
111
ANSLIB/ANSCV/ANSMJPEG.h
Normal 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
|
||||
116
ANSLIB/ANSCV/ANSMatRegistry.h
Normal file
116
ANSLIB/ANSCV/ANSMatRegistry.h
Normal 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
5106
ANSLIB/ANSCV/ANSOpenCV.cpp
Normal file
File diff suppressed because it is too large
Load Diff
164
ANSLIB/ANSCV/ANSOpenCV.h
Normal file
164
ANSLIB/ANSCV/ANSOpenCV.h
Normal 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
1198
ANSLIB/ANSCV/ANSRTMP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
ANSLIB/ANSCV/ANSRTMP.h
Normal file
110
ANSLIB/ANSCV/ANSRTMP.h
Normal 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
1512
ANSLIB/ANSCV/ANSRTSP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
ANSLIB/ANSCV/ANSRTSP.h
Normal file
111
ANSLIB/ANSCV/ANSRTSP.h
Normal 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
1221
ANSLIB/ANSCV/ANSSRT.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
ANSLIB/ANSCV/ANSSRT.h
Normal file
110
ANSLIB/ANSCV/ANSSRT.h
Normal 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
|
||||
1158
ANSLIB/ANSCV/ANSVideoPlayer.cpp
Normal file
1158
ANSLIB/ANSCV/ANSVideoPlayer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
ANSLIB/ANSCV/ANSVideoPlayer.h
Normal file
110
ANSLIB/ANSCV/ANSVideoPlayer.h
Normal 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
1758
ANSLIB/ANSCV/ANSWebcam.cpp
Normal file
File diff suppressed because it is too large
Load Diff
140
ANSLIB/ANSCV/ANSWebcam.h
Normal file
140
ANSLIB/ANSCV/ANSWebcam.h
Normal 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
1093
ANSLIB/ANSCV/VideoPlayer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
199
ANSLIB/ANSCV/VideoPlayer.h
Normal file
199
ANSLIB/ANSCV/VideoPlayer.h
Normal 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
106
ANSLIB/ANSCV/dllmain.cpp
Normal 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
7
ANSLIB/ANSCV/framework.h
Normal 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
5
ANSLIB/ANSCV/pch.cpp
Normal 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
18
ANSLIB/ANSCV/pch.h
Normal 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
|
||||
166
ANSLIB/ANSCustomCode/ANSCustomCode.vcxproj
Normal file
166
ANSLIB/ANSCustomCode/ANSCustomCode.vcxproj
Normal 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>
|
||||
39
ANSLIB/ANSCustomCode/ANSCustomCode.vcxproj.filters
Normal file
39
ANSLIB/ANSCustomCode/ANSCustomCode.vcxproj.filters
Normal 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>
|
||||
810
ANSLIB/ANSCustomCode/ANSCustomCodeWeaponDetection.cpp
Normal file
810
ANSLIB/ANSCustomCode/ANSCustomCodeWeaponDetection.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
91
ANSLIB/ANSCustomCode/ANSCustomCodeWeaponDetection.h
Normal file
91
ANSLIB/ANSCustomCode/ANSCustomCodeWeaponDetection.h
Normal 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();
|
||||
};
|
||||
27
ANSLIB/ANSCustomCode/dllmain.cpp
Normal file
27
ANSLIB/ANSCustomCode/dllmain.cpp
Normal 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();
|
||||
}
|
||||
7
ANSLIB/ANSCustomCode/framework.h
Normal file
7
ANSLIB/ANSCustomCode/framework.h
Normal 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/ANSCustomCode/pch.cpp
Normal file
5
ANSLIB/ANSCustomCode/pch.cpp
Normal 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/ANSCustomCode/pch.h
Normal file
13
ANSLIB/ANSCustomCode/pch.h
Normal 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
|
||||
272
ANSLIB/ANSCustomFallDetection/ANSCustomFallDetection.cpp
Normal file
272
ANSLIB/ANSCustomFallDetection/ANSCustomFallDetection.cpp
Normal 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);
|
||||
}
|
||||
35
ANSLIB/ANSCustomFallDetection/ANSCustomFallDetection.h
Normal file
35
ANSLIB/ANSCustomFallDetection/ANSCustomFallDetection.h
Normal 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();
|
||||
};
|
||||
165
ANSLIB/ANSCustomFallDetection/ANSCustomFallDetection.vcxproj
Normal file
165
ANSLIB/ANSCustomFallDetection/ANSCustomFallDetection.vcxproj
Normal 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>
|
||||
@@ -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>
|
||||
19
ANSLIB/ANSCustomFallDetection/dllmain.cpp
Normal file
19
ANSLIB/ANSCustomFallDetection/dllmain.cpp
Normal 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;
|
||||
}
|
||||
|
||||
7
ANSLIB/ANSCustomFallDetection/framework.h
Normal file
7
ANSLIB/ANSCustomFallDetection/framework.h
Normal 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/ANSCustomFallDetection/pch.cpp
Normal file
5
ANSLIB/ANSCustomFallDetection/pch.cpp
Normal 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/ANSCustomFallDetection/pch.h
Normal file
13
ANSLIB/ANSCustomFallDetection/pch.h
Normal 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
|
||||
1146
ANSLIB/ANSCustomFireNSmokeDetection/ANSCustomFireNSmoke.cpp
Normal file
1146
ANSLIB/ANSCustomFireNSmokeDetection/ANSCustomFireNSmoke.cpp
Normal file
File diff suppressed because it is too large
Load Diff
156
ANSLIB/ANSCustomFireNSmokeDetection/ANSCustomFireNSmoke.h
Normal file
156
ANSLIB/ANSCustomFireNSmokeDetection/ANSCustomFireNSmoke.h
Normal 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();
|
||||
};
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
23
ANSLIB/ANSCustomFireNSmokeDetection/dllmain.cpp
Normal file
23
ANSLIB/ANSCustomFireNSmokeDetection/dllmain.cpp
Normal 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();
|
||||
}
|
||||
7
ANSLIB/ANSCustomFireNSmokeDetection/framework.h
Normal file
7
ANSLIB/ANSCustomFireNSmokeDetection/framework.h
Normal 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/ANSCustomFireNSmokeDetection/pch.cpp
Normal file
5
ANSLIB/ANSCustomFireNSmokeDetection/pch.cpp
Normal 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/ANSCustomFireNSmokeDetection/pch.h
Normal file
13
ANSLIB/ANSCustomFireNSmokeDetection/pch.h
Normal 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
|
||||
257
ANSLIB/ANSCustomHelmetDetection/ANSCustomCodeHelmetDetection.cpp
Normal file
257
ANSLIB/ANSCustomHelmetDetection/ANSCustomCodeHelmetDetection.cpp
Normal 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 {};
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
165
ANSLIB/ANSCustomHelmetDetection/ANSCustomHelmetDetection.vcxproj
Normal file
165
ANSLIB/ANSCustomHelmetDetection/ANSCustomHelmetDetection.vcxproj
Normal 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>
|
||||
@@ -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>
|
||||
23
ANSLIB/ANSCustomHelmetDetection/dllmain.cpp
Normal file
23
ANSLIB/ANSCustomHelmetDetection/dllmain.cpp
Normal 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();
|
||||
}
|
||||
7
ANSLIB/ANSCustomHelmetDetection/framework.h
Normal file
7
ANSLIB/ANSCustomHelmetDetection/framework.h
Normal 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/ANSCustomHelmetDetection/pch.cpp
Normal file
5
ANSLIB/ANSCustomHelmetDetection/pch.cpp
Normal 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/ANSCustomHelmetDetection/pch.h
Normal file
13
ANSLIB/ANSCustomHelmetDetection/pch.h
Normal 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
|
||||
449
ANSLIB/ANSCustomRVA/ANSCustomRVA.cpp
Normal file
449
ANSLIB/ANSCustomRVA/ANSCustomRVA.cpp
Normal 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;
|
||||
}
|
||||
40
ANSLIB/ANSCustomRVA/ANSCustomRVA.h
Normal file
40
ANSLIB/ANSCustomRVA/ANSCustomRVA.h
Normal 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();
|
||||
};
|
||||
161
ANSLIB/ANSCustomRVA/ANSCustomRVA.vcxproj
Normal file
161
ANSLIB/ANSCustomRVA/ANSCustomRVA.vcxproj
Normal 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>
|
||||
42
ANSLIB/ANSCustomRVA/ANSCustomRVA.vcxproj.filters
Normal file
42
ANSLIB/ANSCustomRVA/ANSCustomRVA.vcxproj.filters
Normal 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>
|
||||
24
ANSLIB/ANSCustomRVA/dllmain.cpp
Normal file
24
ANSLIB/ANSCustomRVA/dllmain.cpp
Normal 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();
|
||||
}
|
||||
7
ANSLIB/ANSCustomRVA/framework.h
Normal file
7
ANSLIB/ANSCustomRVA/framework.h
Normal 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/ANSCustomRVA/pch.cpp
Normal file
5
ANSLIB/ANSCustomRVA/pch.cpp
Normal 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
13
ANSLIB/ANSCustomRVA/pch.h
Normal 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
|
||||
483
ANSLIB/ANSCustomViolence/ANSCustomViolence.cpp
Normal file
483
ANSLIB/ANSCustomViolence/ANSCustomViolence.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
101
ANSLIB/ANSCustomViolence/ANSCustomViolence.h
Normal file
101
ANSLIB/ANSCustomViolence/ANSCustomViolence.h
Normal 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();
|
||||
};
|
||||
163
ANSLIB/ANSCustomViolence/ANSCustomViolence.vcxproj
Normal file
163
ANSLIB/ANSCustomViolence/ANSCustomViolence.vcxproj
Normal 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>
|
||||
45
ANSLIB/ANSCustomViolence/ANSCustomViolence.vcxproj.filters
Normal file
45
ANSLIB/ANSCustomViolence/ANSCustomViolence.vcxproj.filters
Normal 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>
|
||||
428
ANSLIB/ANSCustomViolence/HDBSCAN.cpp
Normal file
428
ANSLIB/ANSCustomViolence/HDBSCAN.cpp
Normal 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;
|
||||
}
|
||||
12
ANSLIB/ANSCustomViolence/HDBSCAN.h
Normal file
12
ANSLIB/ANSCustomViolence/HDBSCAN.h
Normal 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
|
||||
);
|
||||
}
|
||||
22
ANSLIB/ANSCustomViolence/dllmain.cpp
Normal file
22
ANSLIB/ANSCustomViolence/dllmain.cpp
Normal 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();
|
||||
}
|
||||
7
ANSLIB/ANSCustomViolence/framework.h
Normal file
7
ANSLIB/ANSCustomViolence/framework.h
Normal 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/ANSCustomViolence/pch.cpp
Normal file
5
ANSLIB/ANSCustomViolence/pch.cpp
Normal 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/ANSCustomViolence/pch.h
Normal file
13
ANSLIB/ANSCustomViolence/pch.h
Normal 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
|
||||
178
ANSLIB/ANSDLDOTNET/ANSDLDOTNET.cs
Normal file
178
ANSLIB/ANSDLDOTNET/ANSDLDOTNET.cs
Normal 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
Reference in New Issue
Block a user