From 8ad78387eaee824edb37577e31c2f37be462aeb2 Mon Sep 17 00:00:00 2001 From: wangchongwu <759291707@qq.com> Date: Thu, 6 Feb 2025 17:52:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=87=E4=BB=B6=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 + ReadMe.md | 3 + main.cpp | 53 +++++-- stitch/CMakeLists.txt | 33 ++--- stitch/src/API_VideoStitch.h | 4 + stitch/src/Arith_BATask.cpp | 10 +- stitch/src/Arith_VideoStitch.cpp | 67 +++++++++ stitch/src/Arith_VideoStitch.h | 11 +- stitch/src/FileCache.cpp | 124 +++++++++++++++++ stitch/src/FileCache.h | 38 +++++ stitch/src/StitchStruct.h | 10 ++ stitch/src/utils/FileCache.cpp | 179 ------------------------ stitch/src/utils/FileCache.cpp.1 | 229 +++++++++++++++++++++++++++++++ stitch/src/utils/FileCache.h | 55 -------- stitch/src/utils/FileCache.h.1 | 56 ++++++++ 15 files changed, 604 insertions(+), 270 deletions(-) create mode 100644 stitch/src/FileCache.cpp create mode 100644 stitch/src/FileCache.h delete mode 100644 stitch/src/utils/FileCache.cpp create mode 100644 stitch/src/utils/FileCache.cpp.1 delete mode 100644 stitch/src/utils/FileCache.h create mode 100644 stitch/src/utils/FileCache.h.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cb6a8f..671d3e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.5.0) project(stitch VERSION 0.1.0 LANGUAGES C CXX) +set(CMAKE_CXX_STANDARD 17) + SET(ArithStitchDir stitch) IF(WIN32) diff --git a/ReadMe.md b/ReadMe.md index 346dca6..606e7a6 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -7,3 +7,6 @@ 【初步设想】:建立二级文件缓存,其中第一级存储原始帧(图像+H矩阵等),第二级存储生成的标准瓦片。当系统工作时,根据当前视野范围和XYZ瓦片等级(X),开始从2级缓存搜索瓦片,如果存在瓦片则直接加载,如果不存在则从1级缓存读取原始帧生成瓦片,并将瓦片加入2级缓存。 【关键技术】:文件缓存技术、标准瓦片转换技术 +- 2 20250205 + +上述开发计划存在问题,拼接算法应是后台服务,应当生成标准产品,而不随着显示更改逻辑,这里考虑生成谷歌瓦片,并通过流传输到显示端,由显控处理显示逻辑。 \ No newline at end of file diff --git a/main.cpp b/main.cpp index b824cdb..5ed4b65 100644 --- a/main.cpp +++ b/main.cpp @@ -4,8 +4,26 @@ #include "PlatformDefine.h" #include #include "opencv2/opencv.hpp" +#include using namespace std; using namespace cv; +class GaussianRandom { +public: + GaussianRandom(double mean = 0.0, double stddev = 1.0, double amplitude = 1.0) + : generator(std::random_device{}()), + distribution(mean, stddev), + amplitude(amplitude) {} + + double generate() { + return amplitude * distribution(generator); + } + +private: + std::mt19937 generator; + std::normal_distribution distribution; + double amplitude; +}; + void Map16BitTo8Bit(unsigned short *psh16BitData, long lDataLen, BYTE *pby8BitData) { @@ -92,10 +110,12 @@ int main(int, char**) GD_VIDEO_FRAME_S pan = { 0 };//输出全景 cv::Mat mat_pan;//全景显示 - //return 0; - FILE* file = fopen("../20241219152917_4.xraw","rb"); + + //FILE* file = fopen("/media/wang/WORK/wangchongwu_gitea_2023/20241219152917_4.xraw","rb"); + FILE* file = fopen("D:/wangchongwu_gitea_2023/20241219152917_4.xraw", "rb"); //FILE* file = fopen("/home/wang/data62/729dataset/ir_1280_1024_para40_y16/5.xraw","rb"); - + GaussianRandom gr(0.0, 1, 0.2); + for (size_t i = 0; i < 600; i++) { @@ -104,7 +124,6 @@ int main(int, char**) S729paras_IR Paras_IR = { 0 }; memcpy(&Paras_IR, (unsigned char*)(pFrameIR + IMAGE_WIDTH_IR*IMAGE_HEIGHT_IR), sizeof(S729paras_IR)); - FrameInfo info = {0}; info.nFrmID = i; @@ -128,6 +147,12 @@ int main(int, char**) info.nWidth = IMAGE_WIDTH_IR; info.nHeight = IMAGE_HEIGHT_IR; + + info.craft.stAtt.fYaw += gr.generate(); + info.craft.stAtt.fPitch += gr.generate(); + info.craft.stAtt.fRoll += gr.generate(); + + Map16BitTo8Bit(pFrameIR,IMAGE_WIDTH_IR*IMAGE_HEIGHT_IR,pImageIR); cv::Mat mat_src(IMAGE_HEIGHT_IR, IMAGE_WIDTH_IR, CV_8UC1, pImageIR); @@ -156,24 +181,32 @@ int main(int, char**) { continue; } - cout << info.craft.stPos.B << " " <GeoStitch(frame,info); // 基于地理+BA拼接 - auto nNum = stitcher->BAStitch(frame,info); + //auto nNum = stitcher->BAStitch(frame,info); + + // test接口 + //if (info.nFrmID == 30 || info.nFrmID == 40) + { + auto a = stitcher->ReceiveFrame(frame,info); + } + + stitcher->ProcFrame(); //cout << nNum << endl; //imshow("src", mat_src); - //waitKey(0); + //waitKey(1); } - // imshow("pan", mat_pan); + //imshow("pan", mat_pan); // waitKey(1); @@ -182,7 +215,7 @@ int main(int, char**) // 读入所有帧,执行一次全局BA - stitcher->BAOpt(); + //stitcher->BAOpt(); //waitKey(0); diff --git a/stitch/CMakeLists.txt b/stitch/CMakeLists.txt index a59393c..e16324a 100644 --- a/stitch/CMakeLists.txt +++ b/stitch/CMakeLists.txt @@ -12,23 +12,20 @@ endif() IF(WIN32) set(OpenCV_DIR "D:/opencv410_vc17") - set(CMAKE_TOOLCHAIN_FILE "D:/wangchongwu_gitea_2023/vcpkg-2025.01.13/scripts/buildsystems/vcpkg.cmake") + set(Ceres_DIR "C:/Lib/ceres") + ELSE(WIN32) - set(OpenCV_DIR "/home/wcw/opencv-3.4.16/install/share/OpenCV") -ENDIF(WIN32) + +ENDIF(WIN32) + find_package(Ceres REQUIRED) include_directories(${CERES_INCLUDE_DIRS}) - - find_package(OpenMP REQUIRED) include_directories(${CERES_INCLUDE_DIRS}) - - - # 公共头文件(放置在最前面,所有后面定义的模块才都能找到) SET(ArithTrkPubInc ${CMAKE_SOURCE_DIR}/public_include) include_directories(${ArithTrkPubInc}) # 引入算法公共头文件 @@ -37,9 +34,6 @@ include_directories(${ArithTrkPubInc}) # 引入算法公共头文件 link_directories(${OpenCV_LIBS_DIR}) include_directories(${OpenCV_INCLUDE_DIRS}) - - - set(ArithSrcDIR_MAIN "src") # 库源文件路径 # 使用当前目录、Common目录源码构建 @@ -60,16 +54,15 @@ target_link_libraries(${LIB_STITCH} OpenMP::OpenMP_CXX ${OpenCV_LIBS} ${CERES_LIBRARIES} - ) +) -# # gcc编译器要求0警告 -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # 只导出指明的符号 - add_definitions(-fvisibility=hidden) +# # # gcc编译器要求0警告 +# if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +# # 只导出指明的符号 +# add_definitions(-fvisibility=hidden) - # 警告:必须在如下编译器配置下编译通过 - target_compile_options(${LIB_STITCH} PRIVATE -Werror -Wreturn-type) -endif() +# # 警告:必须在如下编译器配置下编译通过 +# target_compile_options(${LIB_STITCH} PRIVATE -Werror -Wreturn-type) +# endif() set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/Bin) # 输出算法库路径 - diff --git a/stitch/src/API_VideoStitch.h b/stitch/src/API_VideoStitch.h index ba761d6..2dedac0 100644 --- a/stitch/src/API_VideoStitch.h +++ b/stitch/src/API_VideoStitch.h @@ -36,6 +36,10 @@ public: // 获取全景图 virtual GD_VIDEO_FRAME_S ExportPanAddr() = 0; + virtual SINT32 ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para) = 0; + + virtual SINT32 ProcFrame() = 0; + public: static API_VideoStitch* Create(SINT32 nWidth, SINT32 nHeight); static void Destroy(API_VideoStitch* obj); diff --git a/stitch/src/Arith_BATask.cpp b/stitch/src/Arith_BATask.cpp index c2a9fd0..bc8cd56 100644 --- a/stitch/src/Arith_BATask.cpp +++ b/stitch/src/Arith_BATask.cpp @@ -128,7 +128,7 @@ void BA_Task::Test() //#define SHOW_MATCH void BA_Task::optimizeBA() { - remap(_origMatrix, "_origMatrix"); + //remap(_origMatrix, "_origMatrix"); // 计算匹配性矩阵 CalMatchMat(0.3); @@ -192,7 +192,7 @@ void BA_Task::optimizeBA() _FeaMatcher->matchFeatures_WithH(_FeaPtVec[i], _FeaDespVec[i], _FeaPtVec[j], _FeaDespVec[j], _origMatrix[i], _origMatrix[j], matches); // 图像特征匹配点对超过N对才认为有效 - if (matches.size() > 50) + if (matches.size() > 20) { _MatchMat.at(i, j) = matches.size(); _MatchMat.at(j, i) = matches.size(); @@ -231,7 +231,7 @@ void BA_Task::optimizeBA() cv::KeyPoint keypoint_i = _FeaPtVec[i][mc.queryIdx]; cv::KeyPoint keypoint_j = _FeaPtVec[j][mc.trainIdx]; - ceres::LossFunction* loss_function = new ceres::HuberLoss(15); + ceres::LossFunction* loss_function = new ceres::HuberLoss(35); cv::Mat H1 = _origMatrix[i]; cv::Mat H2 = _origMatrix[j]; @@ -249,7 +249,7 @@ void BA_Task::optimizeBA() // 配置求解器 ceres::Solver::Options options; - options.max_num_iterations = 1; // 增加最大迭代次数 + options.max_num_iterations = 6; // 增加最大迭代次数 options.function_tolerance = 1e-8; // 设置更严格的函数值容忍度 options.gradient_tolerance = 1e-10; // 设置更严格的梯度容忍度 options.parameter_tolerance = 1e-10; // 设置更严格的参数容忍度 @@ -274,7 +274,7 @@ void BA_Task::optimizeBA() std::cout << summary.BriefReport() << std::endl; - remap(_currMatrix, "_currMatrix"); + //remap(_currMatrix, "_currMatrix"); cv::waitKey(0); diff --git a/stitch/src/Arith_VideoStitch.cpp b/stitch/src/Arith_VideoStitch.cpp index 2d31718..7cdd3de 100644 --- a/stitch/src/Arith_VideoStitch.cpp +++ b/stitch/src/Arith_VideoStitch.cpp @@ -26,6 +26,8 @@ VideoStitch::VideoStitch(SINT32 nWidth, SINT32 nHeight) memset(&_pan, 0, sizeof(GD_VIDEO_FRAME_S)); _BATask = new BA_Task(_GeoStitcher); + + _cache = new FileCache(5,"./cache"); } VideoStitch::~VideoStitch() @@ -119,6 +121,71 @@ SINT32 VideoStitch::BAOpt() return 0; } +SINT32 VideoStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para) +{ + cout << "recv:" << para.nFrmID << endl; + + + // 构造单帧缓存 + auto _t_frame_cache = std::make_shared(); + + _t_frame_cache->_para = para; + _t_frame_cache->_frame_info = img; + + int imgSize = 0; + + if(img.enPixelFormat == GD_PIXEL_FORMAT_GRAY_Y8) + { + imgSize = img.u32Height * img.u32Width; + } + if(img.enPixelFormat == GD_PIXEL_FORMAT_RGB_PACKED) + { + imgSize = img.u32Height * img.u32Width * 3; + } + + // 深拷贝图像数据 + memcpy(_t_frame_cache->_data,img.u64VirAddr[0],imgSize); + + auto size = sizeof(_t_frame_cache); + + // 加入文件缓存 + _cache->set(para.nFrmID,_t_frame_cache); + + + + return SINT32(); +} + +SINT32 VideoStitch::ProcFrame() +{ + printf("size:%d\n",_cache->getMemSize()); + std::shared_ptr loadedFrame1; + bool bflag1 = _cache->get(30, loadedFrame1); + + std::shared_ptr loadedFrame2; + auto bflag2 = _cache->get(40,loadedFrame2); + + if (bflag1 && loadedFrame1->_frame_info.u32Height > 0) + { + cv::Mat src1(loadedFrame1->_frame_info.u32Height, loadedFrame1->_frame_info.u32Width, CV_8UC1, loadedFrame1->_data); + imshow("src30",src1); + waitKey(1); + } + + if (bflag2 && loadedFrame2->_frame_info.u32Height > 0) + { + cv::Mat src2(loadedFrame2->_frame_info.u32Height, loadedFrame2->_frame_info.u32Width, CV_8UC1, loadedFrame2->_data); + imshow("src40",src2); + waitKey(0); + } + + + return 0; +} + + + + GD_VIDEO_FRAME_S VideoStitch::ExportPanAddr() { GD_VIDEO_FRAME_S pan_out; diff --git a/stitch/src/Arith_VideoStitch.h b/stitch/src/Arith_VideoStitch.h index a7a975d..f0e5395 100644 --- a/stitch/src/Arith_VideoStitch.h +++ b/stitch/src/Arith_VideoStitch.h @@ -4,6 +4,7 @@ #include "Arith_FeaMatch.h" #include "StitchStruct.h" #include "Arith_BATask.h" +#include "FileCache.h" class VideoStitch:public API_VideoStitch { @@ -22,10 +23,18 @@ public: SINT32 BAStitch(GD_VIDEO_FRAME_S img, FrameInfo para); SINT32 BAOpt(); + // 接收帧 + SINT32 ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para); + + // 处理帧 + SINT32 ProcFrame(); + + + GD_VIDEO_FRAME_S ExportPanAddr(); private: - + FileCache* _cache;//文件缓存,存储外部传入的原始帧信息以及预处理结果 private: diff --git a/stitch/src/FileCache.cpp b/stitch/src/FileCache.cpp new file mode 100644 index 0000000..274631c --- /dev/null +++ b/stitch/src/FileCache.cpp @@ -0,0 +1,124 @@ +#include "FileCache.h" +#include +#include +#include + +namespace fs = std::filesystem; + +// 计算哈希值并转成字符串作为文件名 +static std::string hashKey(const KeyType& key) +{ + std::hash hasher; + return std::to_string(hasher(key)); +} + +FileCache::FileCache(size_t max_size, const std::string& cache_dir) + : max_size_(max_size), cache_dir_(cache_dir) +{ + // 确保缓存目录存在 + if (!fs::exists(cache_dir_)) + { + fs::create_directories(cache_dir_); + } +} + +std::string FileCache::getCacheFilePath(const KeyType& key) const +{ + return cache_dir_ + "/" + hashKey(key) + ".cache"; // 使用哈希作为文件名 +} + +void FileCache::saveToFile(const KeyType& key, const FrameCache& frame) +{ + std::string filePath = getCacheFilePath(key); + std::ofstream ofs(filePath, std::ios::binary); + if (ofs) + { + ofs.write(reinterpret_cast(&frame), sizeof(frame)); + } +} + +bool FileCache::loadFromFile(const KeyType& key, FrameCache& frame) +{ + std::string filePath = getCacheFilePath(key); + std::ifstream ifs(filePath, std::ios::binary); + if (!ifs) + { + return false; + } + ifs.read(reinterpret_cast(&frame), sizeof(frame)); + return true; +} + +void FileCache::evictIfNeeded() +{ + if (cache_.size() < max_size_) + return; + + // 删除最早使用的(LRU 末尾) + KeyType oldest = lru_list_.back(); + lru_list_.pop_back(); + cache_.erase(oldest); + + std::cout << "Evicted cache from memory for key: " << oldest << std::endl; +} + +bool FileCache::get(const KeyType& key, std::shared_ptr& pData) +{ + std::lock_guard lock(mutex_); + + // 检查内存缓存 + auto it = cache_.find(key); + if (it != cache_.end()) + { + // 缓存命中,更新 LRU 顺序 + lru_list_.erase(it->second.second); + lru_list_.push_front(key); + it->second.second = lru_list_.begin(); + + pData = it->second.first; + return true; + } + + // 尝试从文件加载 + auto newData = std::make_shared(); + if (loadFromFile(key, *newData)) + { + evictIfNeeded(); // 超出内存容量时删除最早的 + + // 插入新缓存到内存 + lru_list_.push_front(key); + cache_[key] = {newData, lru_list_.begin()}; + pData = newData; + return true; + } + + return false; +} + +void FileCache::set(const KeyType& key, std::shared_ptr pData) +{ + std::lock_guard lock(mutex_); + + // 如果已存在,则更新 LRU 位置 + auto it = cache_.find(key); + if (it != cache_.end()) + { + lru_list_.erase(it->second.second); + } + else + { + evictIfNeeded(); // 超出内存容量时删除最早的 + } + + // 插入新数据到内存 + lru_list_.push_front(key); + cache_[key] = {pData, lru_list_.begin()}; + + saveToFile(key, *pData); // 将数据存储到磁盘 +} + +size_t FileCache::getMemSize() +{ + std::lock_guard lock(mutex_); + return cache_.size(); +} diff --git a/stitch/src/FileCache.h b/stitch/src/FileCache.h new file mode 100644 index 0000000..31e671b --- /dev/null +++ b/stitch/src/FileCache.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "StitchStruct.h" +// +using KeyType = int; + + +class FileCache +{ +public: + explicit FileCache(size_t max_size, const std::string& cache_dir = "./cache"); + + bool get(const KeyType& key, std::shared_ptr& pData); + void set(const KeyType& key, std::shared_ptr pData); + + size_t getMemSize(); + +private: + size_t max_size_; + std::string cache_dir_; + std::unordered_map, std::list::iterator>> cache_; + std::list lru_list_; + std::mutex mutex_; + + bool loadFromFile(const KeyType& key, FrameCache& frame); + void saveToFile(const KeyType& key, const FrameCache& frame); + void evictIfNeeded(); + + std::string getCacheFilePath(const KeyType& key) const; +}; diff --git a/stitch/src/StitchStruct.h b/stitch/src/StitchStruct.h index 79906eb..39f730a 100644 --- a/stitch/src/StitchStruct.h +++ b/stitch/src/StitchStruct.h @@ -38,4 +38,14 @@ struct Match_Net int imgNo; //! image no. start from 0 vector relatedImgs; //! the position index of overlap-image in visitOrder vector > PointSet; +}; + + +// 帧缓存 +struct FrameCache +{ + FrameInfo _para; + GD_VIDEO_FRAME_S _frame_info; + BYTE8 _data[1920*1080]; + cv::Point2f _pt[500]; }; \ No newline at end of file diff --git a/stitch/src/utils/FileCache.cpp b/stitch/src/utils/FileCache.cpp deleted file mode 100644 index 8ace939..0000000 --- a/stitch/src/utils/FileCache.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "FileCache.h" -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#include -#include -#endif - -namespace fs = std::filesystem; - -FileCache::FileCache(const std::string& cache_dir, size_t max_memory_items) - : cache_dir_(cache_dir), max_memory_items_(max_memory_items) -{ - fs::create_directories(cache_dir_); -} - -FileCache::~FileCache() -{ - // Clean up memory-mapped files - for (auto& [key, mapped_file] : mapped_files_) { - if (mapped_file.data) { - unmap_file(mapped_file.data, mapped_file.size); - } - } -} - -std::string FileCache::hash_key(const std::string& key) const -{ - // Simple hash function (replace with a better one if needed) - std::hash hasher; - size_t hash_value = hasher(key); - std::ostringstream hex_stream; - hex_stream << std::hex << hash_value; - return hex_stream.str(); -} - -std::string FileCache::get_file_path(const std::string& key) const -{ - std::string hashed = hash_key(key); - std::string sub_dir = cache_dir_ + "/" + hashed.substr(0, 2); - fs::create_directories(sub_dir); - return sub_dir + "/" + hashed.substr(2) + ".cache"; -} - -template -std::optional FileCache::get(const std::string& key) -{ - { - std::lock_guard lock(cache_mutex_); - if (memory_cache_.count(key)) { - const auto& data = memory_cache_[key]; - return *reinterpret_cast(data.data()); - } - - if (mapped_files_.count(key)) { - const auto& mapped_file = mapped_files_[key]; - return *reinterpret_cast(mapped_file.data); - } - } - - auto file_path = get_file_path(key); - return load_from_disk(file_path); -} - -template -void FileCache::set(const std::string& key, const T& data) -{ - auto serialized = std::vector(reinterpret_cast(&data), - reinterpret_cast(&data) + sizeof(T)); - - { - std::lock_guard lock(cache_mutex_); - memory_cache_[key] = serialized; - - // Evict if necessary - if (memory_cache_.size() > max_memory_items_) - { - memory_cache_.erase(memory_cache_.begin()); - } - } - - // Async save to disk - auto file_path = get_file_path(key); - async_tasks_.push_back(std::async(std::launch::async, [this, file_path, serialized]() { - save_to_disk(file_path, serialized); - })); -} - -template -bool FileCache::save_to_disk(const std::string& file_path, const T& data) -{ - std::ofstream out(file_path, std::ios::binary); - if (!out) return false; - - out.write(reinterpret_cast(&data), sizeof(data)); - return true; -} - -template -std::optional FileCache::load_from_disk(const std::string& file_path) const -{ - size_t file_size = fs::file_size(file_path); - void* mapped_data = map_file(file_path, file_size); - if (!mapped_data) - { - return std::nullopt; - } - - // Store the mapped file for later use - std::lock_guard lock(cache_mutex_); - mapped_files_[file_path] = {mapped_data, file_size}; - - return *reinterpret_cast(mapped_data); -} - -void FileCache::clear() -{ - std::lock_guard lock(cache_mutex_); - memory_cache_.clear(); - for (const auto& [key, mapped_file] : mapped_files_) { - if (mapped_file.data) - { - unmap_file(mapped_file.data, mapped_file.size); - } - } - mapped_files_.clear(); - for (const auto& entry : fs::directory_iterator(cache_dir_)) - { - fs::remove_all(entry.path()); - } -} - -// Platform-specific memory mapping -void* FileCache::map_file(const std::string& file_path, size_t size) -{ -#ifdef _WIN32 - HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file == INVALID_HANDLE_VALUE) return nullptr; - - HANDLE mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr); - if (!mapping) - { - CloseHandle(file); - return nullptr; - } - - void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, size); - CloseHandle(mapping); - CloseHandle(file); - return data; -#else - int fd = open(file_path.c_str(), O_RDONLY); - if (fd == -1) return nullptr; - - void* data = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - - if (data == MAP_FAILED) { - return nullptr; - } - return data; -#endif -} - -void FileCache::unmap_file(void* data, size_t size) -{ -#ifdef _WIN32 - UnmapViewOfFile(data); -#else - munmap(data, size); -#endif -} diff --git a/stitch/src/utils/FileCache.cpp.1 b/stitch/src/utils/FileCache.cpp.1 new file mode 100644 index 0000000..3f1b7c2 --- /dev/null +++ b/stitch/src/utils/FileCache.cpp.1 @@ -0,0 +1,229 @@ +#include "FileCache.h" +#include +#include +#include +#include +#include "StitchStruct.h" +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif + +#include "openssl/sha.h" + +namespace fs = std::filesystem; + +FileCache::FileCache(const std::string& cache_dir, size_t max_memory_items) + : cache_dir_(cache_dir), max_memory_items_(max_memory_items) +{ + fs::create_directories(cache_dir_); +} + +FileCache::~FileCache() +{ + // Clean up memory-mapped files + for (auto& [key, mapped_file] : mapped_files_) + { + unmap_file(&mapped_file, sizeof(FrameCache)); + } +} + +std::string FileCache::hash_key(const KeyType& key) const +{ + // Convert key to a string representation + std::string key_str = std::to_string(key); + + // Compute SHA-256 hash + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, key_str.c_str(), key_str.size()); + SHA256_Final(hash, &sha256); + + // Convert hash to a hex string + std::ostringstream hex_stream; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + hex_stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i]; + } + + return hex_stream.str(); +} + +std::string FileCache::get_file_path(const KeyType& key) const +{ + std::string hashed = hash_key(key); + return cache_dir_ + "/" + hashed.substr(2) + ".cache"; +} + + +bool FileCache::get(KeyType key,FrameCache* pData) +{ + { + std::lock_guard lock(cache_mutex_); + if (memory_cache_.count(key)) + { + memcpy(pData,&memory_cache_[key],sizeof(FrameCache)); + std::cout << "get from memory_cache_:" << pData->_para.nFrmID << std::endl; + return true; + } + + if (mapped_files_.count(key)) + { + memcpy(pData,&mapped_files_[key],sizeof(FrameCache)); + std::cout << "get from mapped_files_:" << pData->_para.nFrmID << std::endl; + return true; + } + } + + auto file_path = get_file_path(key); + return load_from_disk(file_path,key,pData); +} + + +void FileCache::set(KeyType key, FrameCache* pData) +{ + + std::lock_guard lock(cache_mutex_); + + memcpy(&memory_cache_[key],pData,sizeof(FrameCache)); + + std::cout << "set memory_cache:" << memory_cache_[key]._para.nFrmID < max_memory_items_) + { + memory_cache_.erase(memory_cache_.begin()); + } + + + // Async save to disk + auto file_path = get_file_path(key); + + //save_to_disk(file_path, pData); + async_tasks_.push_back(std::async(std::launch::async, [this, file_path, pData]() { + save_to_disk(file_path, pData); + })); +} + + +bool FileCache::save_to_disk(const std::string& file_path, FrameCache* data) +{ + std::ofstream out(file_path, std::ios::binary); + if (!out) return false; + + auto nsize = sizeof(FrameCache); + + //std::cout << "set file:" << data->_para.nFrmID <(data), sizeof(FrameCache)); + return true; +} + + +bool FileCache::load_from_disk(const std::string& file_path,const KeyType& key,FrameCache* pData) +{ + if (!fs::exists(file_path)) + { + return false; + } + + const char* str = file_path.c_str(); + + size_t file_size = fs::file_size(file_path); + void* mapped_data = map_file(file_path, file_size); + if (!mapped_data) + { + return false; + } + + // Store the mapped file for later use + std::lock_guard lock(cache_mutex_); + + FrameCache* ptr = &mapped_files_[key]; + + // 存储到文件映射中 + memcpy(ptr,mapped_data,sizeof(FrameCache)); + + // 返回 + memcpy(pData,mapped_data,sizeof(FrameCache)); + + + + std::cout << "get from raw_files_:" << pData->_para.nFrmID << std::endl; + + return true; +} + +void FileCache::clear() +{ + std::lock_guard lock(cache_mutex_); + memory_cache_.clear(); + for (const auto& [key, mapped_file] : mapped_files_) + { + unmap_file((void*)&mapped_file, sizeof(FrameCache)); + } + mapped_files_.clear(); + for (const auto& entry : fs::directory_iterator(cache_dir_)) + { + fs::remove_all(entry.path()); + } +} + +SINT32 FileCache::get_mem_size() +{ + return memory_cache_.size(); +} + +SINT32 FileCache::get_file_size() +{ + return mapped_files_.size(); +} + + + +// Platform-specific memory mapping +void* FileCache::map_file(const std::string& file_path, size_t size) +{ +#ifdef _WIN32 + HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == INVALID_HANDLE_VALUE) return nullptr; + + HANDLE mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr); + if (!mapping) + { + CloseHandle(file); + return nullptr; + } + + void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, size); + CloseHandle(mapping); + CloseHandle(file); + return data; +#else + int fd = open(file_path.c_str(), O_RDONLY); + if (fd == -1) return nullptr; + + void* data = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + + if (data == MAP_FAILED) { + return nullptr; + } + return data; +#endif +} + +void FileCache::unmap_file(void* data, size_t size) +{ +#ifdef _WIN32 + UnmapViewOfFile(data); +#else + munmap(data, size); +#endif +} + + diff --git a/stitch/src/utils/FileCache.h b/stitch/src/utils/FileCache.h deleted file mode 100644 index 383109e..0000000 --- a/stitch/src/utils/FileCache.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -class FileCache -{ -public: - FileCache(const std::string& cache_dir = "./tile_cache", size_t max_memory_items = 1000); - ~FileCache(); - - template - std::optional get(const std::string& key); - - template - void set(const std::string& key, const T& data); - - void clear(); - -private: - std::string get_file_path(const std::string& key) const; - std::string hash_key(const std::string& key) const; - - template - bool save_to_disk(const std::string& file_path, const T& data); - - template - std::optional load_from_disk(const std::string& file_path) const; - - std::string cache_dir_; - size_t max_memory_items_; - - // Memory cache - mutable std::mutex cache_mutex_; - std::unordered_map> memory_cache_; - - // Memory-mapped files - struct MappedFile { - void* data; - size_t size; - }; - std::unordered_map mapped_files_; - - // Async tasks - std::vector> async_tasks_; - - // Platform-specific memory mapping - void* map_file(const std::string& file_path, size_t size); - void unmap_file(void* data, size_t size); -}; diff --git a/stitch/src/utils/FileCache.h.1 b/stitch/src/utils/FileCache.h.1 new file mode 100644 index 0000000..bb26d58 --- /dev/null +++ b/stitch/src/utils/FileCache.h.1 @@ -0,0 +1,56 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include "StitchStruct.h" + +typedef int KeyType; + +class FileCache +{ +public: + FileCache(const std::string& cache_dir = "./tile_cache", size_t max_memory_items = 200); + ~FileCache(); + + + bool get(KeyType key,FrameCache* pData); + + void set(KeyType key, FrameCache* pData); + + void clear(); + + SINT32 get_mem_size(); + SINT32 get_file_size(); + +private: + std::string get_file_path(const KeyType& key) const; + std::string hash_key(const KeyType& key) const; + + bool save_to_disk(const std::string& file_path, FrameCache* data); + + + bool load_from_disk(const std::string& file_path,const KeyType& key,FrameCache* pData); + + std::string cache_dir_; + size_t max_memory_items_; + + // Memory cache + mutable std::mutex cache_mutex_; + + std::unordered_map memory_cache_; + + + std::unordered_map mapped_files_; + + // Async tasks + std::vector> async_tasks_; + + // Platform-specific memory mapping + void* map_file(const std::string& file_path, size_t size); + void unmap_file(void* data, size_t size); +};