From 917b34bac7daefe4f015ea0c2e68c58144e639f8 Mon Sep 17 00:00:00 2001 From: Sallee1 <885331635@qq.com> Date: Tue, 30 May 2023 16:51:04 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=E9=87=8D=E6=9E=84=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=E7=BC=93=E5=AD=98=EF=BC=8C=E4=BD=BF=E7=94=A8=E4=BA=8C=E8=BF=9B?= =?UTF-8?q?=E5=88=B6=E4=BB=A3=E6=9B=BF=E6=96=87=E6=9C=AC=EF=BC=8C=E5=A4=A7?= =?UTF-8?q?=E5=B9=85=E5=87=8F=E5=B0=8F=E7=BC=93=E5=AD=98=E5=8D=A0=E7=94=A8?= =?UTF-8?q?=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cvAutoTrack/src/resources/Resources.cpp | 773 ++++++++++++------------ cvAutoTrack/src/resources/Resources.h | 187 +++++- cvAutoTrack/src/version/version_tag.tag | 2 +- 3 files changed, 568 insertions(+), 394 deletions(-) diff --git a/cvAutoTrack/src/resources/Resources.cpp b/cvAutoTrack/src/resources/Resources.cpp index 4a7c4b32..b67bec4b 100644 --- a/cvAutoTrack/src/resources/Resources.cpp +++ b/cvAutoTrack/src/resources/Resources.cpp @@ -11,236 +11,236 @@ namespace TianLi::Resource::Utils { - void LoadBitmap_ID2Mat(int IDB, cv::Mat& mat) - { - auto H_Handle = LoadBitmap(GetModuleHandleW(L"CVAUTOTRACK.dll"), MAKEINTRESOURCE(IDB)); - BITMAP bmp; - GetObject(H_Handle, sizeof(BITMAP), &bmp); - int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8; - //int depth = bmp.bmBitsPixel == 1 ? 1 : 8; - cv::Mat v_mat; - v_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8UC3, nChannels)); - GetBitmapBits(H_Handle, bmp.bmHeight * bmp.bmWidth * nChannels, v_mat.data); - mat = v_mat; - } - bool HBitmap2MatAlpha(HBITMAP& _hBmp, cv::Mat& _mat) - { - //BITMAP操作 - BITMAP bmp; - GetObject(_hBmp, sizeof(BITMAP), &bmp); - int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8; - //int depth = bmp.bmBitsPixel == 1 ? 1 : 8; - //mat操作 - cv::Mat v_mat; - v_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8UC3, nChannels)); - GetBitmapBits(_hBmp, bmp.bmHeight * bmp.bmWidth * nChannels, v_mat.data); - _mat = v_mat; - return true; - } - //bool - // imdecode_(const cv::Mat& buf, int flags, cv::Mat& mat) - //{ - // CV_Assert(!buf.empty()); - // CV_Assert(buf.isContinuous()); - // CV_Assert(buf.checkVector(1, CV_8U) > 0); - // cv::Mat buf_row = buf.reshape(1, 1); // decoders expects single row, avoid issues with vector columns - - // cv::String filename; - - // cv::ImageDecoder decoder = findDecoder(buf_row); - // if (!decoder) - // return 0; - - // int scale_denom = 1; - // if (flags > IMREAD_LOAD_GDAL) - // { - // if (flags & IMREAD_REDUCED_GRAYSCALE_2) - // scale_denom = 2; - // else if (flags & IMREAD_REDUCED_GRAYSCALE_4) - // scale_denom = 4; - // else if (flags & IMREAD_REDUCED_GRAYSCALE_8) - // scale_denom = 8; - // } - - // /// set the scale_denom in the driver - // decoder->setScale(scale_denom); - - // if (!decoder->setSource(buf_row)) - // { - // filename = tempfile(); - // FILE* f = fopen(filename.c_str(), "wb"); - // if (!f) - // return 0; - // size_t bufSize = buf_row.total() * buf.elemSize(); - // if (fwrite(buf_row.ptr(), 1, bufSize, f) != bufSize) - // { - // fclose(f); - // CV_Error(Error::StsError, "failed to write image data to temporary file"); - // } - // if (fclose(f) != 0) - // { - // CV_Error(Error::StsError, "failed to write image data to temporary file"); - // } - // decoder->setSource(filename); - // } - - // bool success = false; - // try - // { - // if (decoder->readHeader()) - // success = true; - // } - // catch (const cv::Exception& e) - // { - // std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush; - // } - // catch (...) - // { - // std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush; - // } - // if (!success) - // { - // decoder.release(); - // if (!filename.empty()) - // { - // if (0 != remove(filename.c_str())) - // { - // std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush; - // } - // } - // return 0; - // } - - // // established the required input image size - // Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); - - // int type = decoder->type(); - // if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED) - // { - // if ((flags & IMREAD_ANYDEPTH) == 0) - // type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); - - // if ((flags & IMREAD_COLOR) != 0 || - // ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1)) - // type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); - // else - // type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); - // } - - // mat.create(size.height, size.width, type); - - // success = false; - // try - // { - // if (decoder->readData(mat)) - // success = true; - // } - // catch (const cv::Exception& e) - // { - // std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush; - // } - // catch (...) - // { - // std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush; - // } - - // if (!filename.empty()) - // { - // if (0 != remove(filename.c_str())) - // { - // std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush; - // } - // } - - // if (!success) - // { - // mat.release(); - // return false; - // } - - // if (decoder->setScale(scale_denom) > 1) // if decoder is JpegDecoder then decoder->setScale always returns 1 - // { - // resize(mat, mat, Size(size.width / scale_denom, size.height / scale_denom), 0, 0, INTER_LINEAR_EXACT); - // } - - // /// optionally rotate the data if EXIF' orientation flag says so - // if (!mat.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED) - // { - // ApplyExifOrientation(decoder->getExifTag(ORIENTATION), mat); - // } - - // return true; - //} - void LoadPng_ID2Mat(int IDB, cv::Mat& mat) - { - IWICStream* pIWICStream = NULL; - IWICBitmapDecoder* pIDecoder = NULL; - IWICBitmapFrameDecode* pIDecoderFrame = NULL; - IWICBitmapSource* bitmap_source = NULL; - HRSRC imageResHandle = NULL; - HGLOBAL imageResDataHandle = NULL; - void* pImageFile = NULL; - DWORD imageFileSize = 0; - IWICImagingFactory* m_pIWICFactory = NULL; - - HMODULE hModu = GetModuleHandleW(L"CVAUTOTRACK.dll"); - - if (hModu == NULL) throw "Get Dll Instance Fail!"; - - imageResHandle = FindResource(hModu, MAKEINTRESOURCE(IDB), L"PNG"); - imageResDataHandle = LoadResource(hModu, imageResHandle); - pImageFile = LockResource(imageResDataHandle); - imageFileSize = SizeofResource(hModu, imageResHandle); - /* - { - // 2nd - char * ptr_data = (char*)malloc(imageFileSize); - memcpy(ptr_data, pImageFile, imageFileSize); - // to bin file - cv::Mat mat_array = cv::Mat(1, (int)imageFileSize, CV_8UC1, (void*)ptr_data); - // Debug下 imdecode 中 validateInputImageSize 中的 CV_IO_MAX_IMAGE_WIDTH 为0导致CV_Assert失败 - cv::Mat v_mat = cv::imdecode(mat_array, cv::IMREAD_UNCHANGED); - mat = v_mat; - free(ptr_data); - } - */ - - CoInitializeEx(NULL, COINIT_MULTITHREADED); - - CoCreateInstance( - CLSID_WICImagingFactory, - NULL, - CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&m_pIWICFactory) - ); - - m_pIWICFactory->CreateStream(&pIWICStream); - - pIWICStream->InitializeFromMemory( - reinterpret_cast(pImageFile), - imageFileSize); - m_pIWICFactory->CreateDecoderFromStream( - pIWICStream, // The stream to use to create the decoder - NULL, // Do not prefer a particular vendor - WICDecodeMetadataCacheOnLoad, // Cache metadata when needed - &pIDecoder); // Pointer to the decoder - pIDecoder->GetFrame(0, &pIDecoderFrame); - - bitmap_source = pIDecoderFrame; - - UINT width = 0, height = 0, depht = 4; - bitmap_source->GetSize(&width, &height); - { - std::vector buffer(width * height * depht); - bitmap_source->CopyPixels(NULL, width * depht, static_cast(buffer.size()), buffer.data()); - HBITMAP hPngMat = CreateBitmap(width, height, 1, 8 * depht, buffer.data()); - HBitmap2MatAlpha(hPngMat, mat); - DeleteObject(hPngMat); - } - DeleteObject(bitmap_source); - CoFreeUnusedLibraries(); - CoUninitialize(); - } + void LoadBitmap_ID2Mat(int IDB, cv::Mat& mat) + { + auto H_Handle = LoadBitmap(GetModuleHandleW(L"CVAUTOTRACK.dll"), MAKEINTRESOURCE(IDB)); + BITMAP bmp; + GetObject(H_Handle, sizeof(BITMAP), &bmp); + int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8; + //int depth = bmp.bmBitsPixel == 1 ? 1 : 8; + cv::Mat v_mat; + v_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8UC3, nChannels)); + GetBitmapBits(H_Handle, bmp.bmHeight * bmp.bmWidth * nChannels, v_mat.data); + mat = v_mat; + } + bool HBitmap2MatAlpha(HBITMAP& _hBmp, cv::Mat& _mat) + { + //BITMAP操作 + BITMAP bmp; + GetObject(_hBmp, sizeof(BITMAP), &bmp); + int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8; + //int depth = bmp.bmBitsPixel == 1 ? 1 : 8; + //mat操作 + cv::Mat v_mat; + v_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8UC3, nChannels)); + GetBitmapBits(_hBmp, bmp.bmHeight * bmp.bmWidth * nChannels, v_mat.data); + _mat = v_mat; + return true; + } + //bool + // imdecode_(const cv::Mat& buf, int flags, cv::Mat& mat) + //{ + // CV_Assert(!buf.empty()); + // CV_Assert(buf.isContinuous()); + // CV_Assert(buf.checkVector(1, CV_8U) > 0); + // cv::Mat buf_row = buf.reshape(1, 1); // decoders expects single row, avoid issues with vector columns + + // cv::String filename; + + // cv::ImageDecoder decoder = findDecoder(buf_row); + // if (!decoder) + // return 0; + + // int scale_denom = 1; + // if (flags > IMREAD_LOAD_GDAL) + // { + // if (flags & IMREAD_REDUCED_GRAYSCALE_2) + // scale_denom = 2; + // else if (flags & IMREAD_REDUCED_GRAYSCALE_4) + // scale_denom = 4; + // else if (flags & IMREAD_REDUCED_GRAYSCALE_8) + // scale_denom = 8; + // } + + // /// set the scale_denom in the driver + // decoder->setScale(scale_denom); + + // if (!decoder->setSource(buf_row)) + // { + // filename = tempfile(); + // FILE* f = fopen(filename.c_str(), "wb"); + // if (!f) + // return 0; + // size_t bufSize = buf_row.total() * buf.elemSize(); + // if (fwrite(buf_row.ptr(), 1, bufSize, f) != bufSize) + // { + // fclose(f); + // CV_Error(Error::StsError, "failed to write image data to temporary file"); + // } + // if (fclose(f) != 0) + // { + // CV_Error(Error::StsError, "failed to write image data to temporary file"); + // } + // decoder->setSource(filename); + // } + + // bool success = false; + // try + // { + // if (decoder->readHeader()) + // success = true; + // } + // catch (const cv::Exception& e) + // { + // std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush; + // } + // catch (...) + // { + // std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush; + // } + // if (!success) + // { + // decoder.release(); + // if (!filename.empty()) + // { + // if (0 != remove(filename.c_str())) + // { + // std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush; + // } + // } + // return 0; + // } + + // // established the required input image size + // Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); + + // int type = decoder->type(); + // if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED) + // { + // if ((flags & IMREAD_ANYDEPTH) == 0) + // type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); + + // if ((flags & IMREAD_COLOR) != 0 || + // ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1)) + // type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); + // else + // type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); + // } + + // mat.create(size.height, size.width, type); + + // success = false; + // try + // { + // if (decoder->readData(mat)) + // success = true; + // } + // catch (const cv::Exception& e) + // { + // std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush; + // } + // catch (...) + // { + // std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush; + // } + + // if (!filename.empty()) + // { + // if (0 != remove(filename.c_str())) + // { + // std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush; + // } + // } + + // if (!success) + // { + // mat.release(); + // return false; + // } + + // if (decoder->setScale(scale_denom) > 1) // if decoder is JpegDecoder then decoder->setScale always returns 1 + // { + // resize(mat, mat, Size(size.width / scale_denom, size.height / scale_denom), 0, 0, INTER_LINEAR_EXACT); + // } + + // /// optionally rotate the data if EXIF' orientation flag says so + // if (!mat.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED) + // { + // ApplyExifOrientation(decoder->getExifTag(ORIENTATION), mat); + // } + + // return true; + //} + void LoadPng_ID2Mat(int IDB, cv::Mat& mat) + { + IWICStream* pIWICStream = NULL; + IWICBitmapDecoder* pIDecoder = NULL; + IWICBitmapFrameDecode* pIDecoderFrame = NULL; + IWICBitmapSource* bitmap_source = NULL; + HRSRC imageResHandle = NULL; + HGLOBAL imageResDataHandle = NULL; + void* pImageFile = NULL; + DWORD imageFileSize = 0; + IWICImagingFactory* m_pIWICFactory = NULL; + + HMODULE hModu = GetModuleHandleW(L"CVAUTOTRACK.dll"); + + if (hModu == NULL) throw "Get Dll Instance Fail!"; + + imageResHandle = FindResource(hModu, MAKEINTRESOURCE(IDB), L"PNG"); + imageResDataHandle = LoadResource(hModu, imageResHandle); + pImageFile = LockResource(imageResDataHandle); + imageFileSize = SizeofResource(hModu, imageResHandle); + /* + { + // 2nd + char * ptr_data = (char*)malloc(imageFileSize); + memcpy(ptr_data, pImageFile, imageFileSize); + // to bin file + cv::Mat mat_array = cv::Mat(1, (int)imageFileSize, CV_8UC1, (void*)ptr_data); + // Debug下 imdecode 中 validateInputImageSize 中的 CV_IO_MAX_IMAGE_WIDTH 为0导致CV_Assert失败 + cv::Mat v_mat = cv::imdecode(mat_array, cv::IMREAD_UNCHANGED); + mat = v_mat; + free(ptr_data); + } + */ + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + CoCreateInstance( + CLSID_WICImagingFactory, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&m_pIWICFactory) + ); + + m_pIWICFactory->CreateStream(&pIWICStream); + + pIWICStream->InitializeFromMemory( + reinterpret_cast(pImageFile), + imageFileSize); + m_pIWICFactory->CreateDecoderFromStream( + pIWICStream, // The stream to use to create the decoder + NULL, // Do not prefer a particular vendor + WICDecodeMetadataCacheOnLoad, // Cache metadata when needed + &pIDecoder); // Pointer to the decoder + pIDecoder->GetFrame(0, &pIDecoderFrame); + + bitmap_source = pIDecoderFrame; + + UINT width = 0, height = 0, depht = 4; + bitmap_source->GetSize(&width, &height); + { + std::vector buffer(width * height * depht); + bitmap_source->CopyPixels(NULL, width * depht, static_cast(buffer.size()), buffer.data()); + HBITMAP hPngMat = CreateBitmap(width, height, 1, 8 * depht, buffer.data()); + HBitmap2MatAlpha(hPngMat, mat); + DeleteObject(hPngMat); + } + DeleteObject(bitmap_source); + CoFreeUnusedLibraries(); + CoUninitialize(); + } } using namespace TianLi::Resource::Utils; #ifdef USED_BINARY_IMAGE @@ -250,193 +250,186 @@ using namespace TianLi::Resource::Utils; Resources::Resources() { #ifdef USED_BINARY_IMAGE - PaimonTemplate = TianLi::Resources::Load::load_image("paimon"); - StarTemplate = TianLi::Resources::Load::load_image("star"); - MinimapCailbTemplate = TianLi::Resources::Load::load_image("cailb"); - UID = TianLi::Resources::Load::load_image("uid_"); - UIDnumber[0] = TianLi::Resources::Load::load_image("uid0"); - UIDnumber[1] = TianLi::Resources::Load::load_image("uid1"); - UIDnumber[2] = TianLi::Resources::Load::load_image("uid2"); - UIDnumber[3] = TianLi::Resources::Load::load_image("uid3"); - UIDnumber[4] = TianLi::Resources::Load::load_image("uid4"); - UIDnumber[5] = TianLi::Resources::Load::load_image("uid5"); - UIDnumber[6] = TianLi::Resources::Load::load_image("uid6"); - UIDnumber[7] = TianLi::Resources::Load::load_image("uid7"); - UIDnumber[8] = TianLi::Resources::Load::load_image("uid8"); - UIDnumber[9] = TianLi::Resources::Load::load_image("uid9"); - - cv::cvtColor(StarTemplate, StarTemplate, cv::COLOR_RGB2GRAY); - cv::cvtColor(UID, UID, cv::COLOR_RGB2GRAY); - for (int i = 0; i < 10; i++) - { - cv::cvtColor(UIDnumber[i], UIDnumber[i], cv::COLOR_RGB2GRAY); - } + PaimonTemplate = TianLi::Resources::Load::load_image("paimon"); + StarTemplate = TianLi::Resources::Load::load_image("star"); + MinimapCailbTemplate = TianLi::Resources::Load::load_image("cailb"); + UID = TianLi::Resources::Load::load_image("uid_"); + UIDnumber[0] = TianLi::Resources::Load::load_image("uid0"); + UIDnumber[1] = TianLi::Resources::Load::load_image("uid1"); + UIDnumber[2] = TianLi::Resources::Load::load_image("uid2"); + UIDnumber[3] = TianLi::Resources::Load::load_image("uid3"); + UIDnumber[4] = TianLi::Resources::Load::load_image("uid4"); + UIDnumber[5] = TianLi::Resources::Load::load_image("uid5"); + UIDnumber[6] = TianLi::Resources::Load::load_image("uid6"); + UIDnumber[7] = TianLi::Resources::Load::load_image("uid7"); + UIDnumber[8] = TianLi::Resources::Load::load_image("uid8"); + UIDnumber[9] = TianLi::Resources::Load::load_image("uid9"); + + cv::cvtColor(StarTemplate, StarTemplate, cv::COLOR_RGB2GRAY); + cv::cvtColor(UID, UID, cv::COLOR_RGB2GRAY); + for (int i = 0; i < 10; i++) + { + cv::cvtColor(UIDnumber[i], UIDnumber[i], cv::COLOR_RGB2GRAY); + } #endif // - LoadBitmap_ID2Mat(IDB_BITMAP_PAIMON, PaimonTemplate); - LoadBitmap_ID2Mat(IDB_BITMAP_STAR, StarTemplate); - - LoadPng_ID2Mat(IDB_PNG_MINIMAP_CAILB, MinimapCailbTemplate); - - LoadBitmap_ID2Mat(IDB_BITMAP_UID_, UID); - LoadBitmap_ID2Mat(IDB_BITMAP_UID0, UIDnumber[0]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID1, UIDnumber[1]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID2, UIDnumber[2]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID3, UIDnumber[3]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID4, UIDnumber[4]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID5, UIDnumber[5]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID6, UIDnumber[6]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID7, UIDnumber[7]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID8, UIDnumber[8]); - LoadBitmap_ID2Mat(IDB_BITMAP_UID9, UIDnumber[9]); - - cv::cvtColor(StarTemplate, StarTemplate, cv::COLOR_RGBA2GRAY); - cv::cvtColor(UID, UID, cv::COLOR_RGBA2GRAY); - for (int i = 0; i < 10; i++) - { - cv::cvtColor(UIDnumber[i], UIDnumber[i], cv::COLOR_RGBA2GRAY); - } - - // install(); + LoadBitmap_ID2Mat(IDB_BITMAP_PAIMON, PaimonTemplate); + LoadBitmap_ID2Mat(IDB_BITMAP_STAR, StarTemplate); + + LoadPng_ID2Mat(IDB_PNG_MINIMAP_CAILB, MinimapCailbTemplate); + + LoadBitmap_ID2Mat(IDB_BITMAP_UID_, UID); + LoadBitmap_ID2Mat(IDB_BITMAP_UID0, UIDnumber[0]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID1, UIDnumber[1]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID2, UIDnumber[2]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID3, UIDnumber[3]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID4, UIDnumber[4]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID5, UIDnumber[5]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID6, UIDnumber[6]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID7, UIDnumber[7]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID8, UIDnumber[8]); + LoadBitmap_ID2Mat(IDB_BITMAP_UID9, UIDnumber[9]); + + cv::cvtColor(StarTemplate, StarTemplate, cv::COLOR_RGBA2GRAY); + cv::cvtColor(UID, UID, cv::COLOR_RGBA2GRAY); + for (int i = 0; i < 10; i++) + { + cv::cvtColor(UIDnumber[i], UIDnumber[i], cv::COLOR_RGBA2GRAY); + } + + // install(); } Resources::~Resources() { - PaimonTemplate.release(); - MinimapCailbTemplate.release(); - StarTemplate.release(); - - UID.release(); - UIDnumber[0].release(); - UIDnumber[1].release(); - UIDnumber[2].release(); - UIDnumber[3].release(); - UIDnumber[4].release(); - UIDnumber[5].release(); - UIDnumber[6].release(); - UIDnumber[7].release(); - UIDnumber[8].release(); - UIDnumber[9].release(); - release(); + PaimonTemplate.release(); + MinimapCailbTemplate.release(); + StarTemplate.release(); + + UID.release(); + UIDnumber[0].release(); + UIDnumber[1].release(); + UIDnumber[2].release(); + UIDnumber[3].release(); + UIDnumber[4].release(); + UIDnumber[5].release(); + UIDnumber[6].release(); + UIDnumber[7].release(); + UIDnumber[8].release(); + UIDnumber[9].release(); + release(); } Resources& Resources::getInstance() { - static Resources instance; - return instance; + static Resources instance; + return instance; } void Resources::install() { - if (is_installed == false) - { - LoadPng_ID2Mat(IDB_PNG_GIMAP, MapTemplate); - is_installed = true; - } + if (is_installed == false) + { + LoadPng_ID2Mat(IDB_PNG_GIMAP, MapTemplate); + is_installed = true; + } } void Resources::release() { - if (is_installed == true) - { - MapTemplate.release(); - MapTemplate = cv::Mat(); - is_installed = false; - } + if (is_installed == true) + { + MapTemplate.release(); + MapTemplate = cv::Mat(); + is_installed = false; + } } bool Resources::map_is_embedded() { - return true; + return true; } +inline void MapKeypointCache::serialize(std::string outFileName) +{ + std::ofstream ofs(outFileName, std::fstream::out | std::fstream::binary); + Tianli::Resources::Utils::serializeStream ss(ofs); + ss << this->bulid_time; + ss << this->bulid_version; + ss << this->hessian_threshold; + ss << this->octave; + ss << this->octave_layers; + ss << this->extended; + ss << this->upRight; + ss << this->keyPoints; + ss << this->descriptors; + ss.align(); + ofs.close(); +} + +inline void MapKeypointCache::deSerialize(std::string infileName) +{ + std::ifstream ifs(infileName, std::fstream::out | std::fstream::binary); + Tianli::Resources::Utils::deSerializeStream dss(ifs); + dss >> this->bulid_time; + dss >> this->bulid_version; + dss >> this->hessian_threshold; + dss >> this->octave; + dss >> this->octave_layers; + dss >> this->extended; + dss >> this->upRight; + dss >> this->keyPoints; + dss >> this->descriptors; + ifs.close(); +} + + bool save_map_keypoint_cache(std::vector& keypoints, cv::Mat& descriptors, double hessian_threshold, int octaves, int octave_layers, bool extended, bool upright) { - cv::Ptr detector = cv::xfeatures2d::SURF::create(hessian_threshold, octaves, octave_layers, extended, upright); - detector->detectAndCompute(Resources::getInstance().MapTemplate, cv::noArray(), keypoints, descriptors); - - cv::FileStorage fs("cvAutoTrack_Cache.xml", cv::FileStorage::WRITE); - - std::string build_time = __DATE__ " " __TIME__; - fs << "build_time" << build_time; - fs << "build_version" << TianLi::Version::build_version; - fs << "hessian_threshold" << hessian_threshold; - fs << "octaves" << octaves; - fs << "octave_layers" << octave_layers; - fs << "extended" << extended; - fs << "upright" << upright; - - fs << "keypoints" << keypoints; - fs << "descriptors" << descriptors; - - fs << "build_version_end" << TianLi::Version::build_version; //防止缓存写入一半导致过期 - fs.release(); - return true; + cv::Ptr detector = cv::xfeatures2d::SURF::create(hessian_threshold, octaves, octave_layers, extended, upright); + detector->detectAndCompute(Resources::getInstance().MapTemplate, cv::noArray(), keypoints, descriptors); + + std::string build_time = __DATE__ " " __TIME__; + + MapKeypointCache cache( + build_time, TianLi::Version::build_version, hessian_threshold, + octaves, octave_layers, extended, upright, + keypoints, descriptors); + + cache.serialize("cvAutoTrack_Cache.xml"); + + return true; } -bool load_map_keypoint_cache(std::vector& keypoints, cv::Mat& descriptors, double hessian_threshold, int octaves, int octave_layers, bool extended, bool upright) +bool load_map_keypoint_cache(std::vector& keypoints, cv::Mat& descriptors) { - cv::FileStorage fs; - if (std::filesystem::exists("cvAutoTrack_Cache.xml") == false) - { - return false; - } - try { - fs = cv::FileStorage("cvAutoTrack_Cache.xml", cv::FileStorage::READ); - } - catch (std::exception) //缓存损坏 - { - return false; - }; - //获取xml版本,如果不符,则重建 - std::string r_build_version = ""; - std::string r_build_version_end = ""; - fs["build_version"] >> r_build_version; - fs["build_version_end"] >> r_build_version_end; - - //版本不匹配 - if (r_build_version != TianLi::Version::build_version || r_build_version_end != TianLi::Version::build_version) - { - return false; - } - - - double r_hessian_threshold = 1; - int r_octaves = 1; - int r_octave_layers = 1; - bool r_extended = false; - bool r_upright = false; - - fs["hessian_threshold"] >> r_hessian_threshold; - fs["octaves"] >> r_octaves; - fs["octave_layers"] >> r_octave_layers; - fs["extended"] >> r_extended; - fs["upright"] >> r_upright; - - if (r_hessian_threshold != hessian_threshold || r_octaves != octaves || r_octave_layers != octave_layers || r_extended != extended || r_upright != upright) - { - return false; - } - - fs["keypoints"] >> keypoints; - fs["descriptors"] >> descriptors; - fs.release(); - return true; + if (std::filesystem::exists("cvAutoTrack_Cache.xml") == false) + { + return false; + } + + MapKeypointCache cache; + try { + cache.deSerialize("cvAutoTrack_Cache.xml"); + } + catch (std::exception){ //缓存损坏 + return false; + } + + if (cache.bulid_version._Equal(cache.bulid_version_end)) //写入不完整 + return false; + + keypoints = cache.keyPoints; + descriptors = cache.descriptors; + return true; } -bool get_map_keypoint(std::vector& keypoints, cv::Mat& descriptors, double hessian_threshold, int octaves, int octave_layers, bool extended, bool upright) +bool get_map_keypoint(std::vector& keypoints, cv::Mat& descriptors) { - if (std::filesystem::exists("cvAutoTrack_Cache.xml") == false) - { - return save_map_keypoint_cache(keypoints, descriptors, hessian_threshold, octaves, octave_layers, extended, upright); - } - else - { - if (load_map_keypoint_cache(keypoints, descriptors, hessian_threshold, octaves, octave_layers, extended, upright) == false) - { - return save_map_keypoint_cache(keypoints, descriptors, hessian_threshold, octaves, octave_layers, extended, upright); - } - else - { - return true; - } - } -} \ No newline at end of file + if (load_map_keypoint_cache(keypoints, descriptors) == false) + { + return save_map_keypoint_cache(keypoints, descriptors); + } + else + { + return true; + } +} diff --git a/cvAutoTrack/src/resources/Resources.h b/cvAutoTrack/src/resources/Resources.h index 8d537c06..57a0fc87 100644 --- a/cvAutoTrack/src/resources/Resources.h +++ b/cvAutoTrack/src/resources/Resources.h @@ -26,12 +26,193 @@ class Resources void install(); void release(); public: - void get_map_keypoint_cache(); + //void get_map_keypoint_cache(); bool map_is_embedded(); private: bool is_installed = false; }; +class MapKeypointCache { + +public: + std::string bulid_time; + std::string bulid_version; + float hessian_threshold; + WORD octave; + WORD octave_layers; + WORD extended; + WORD upRight; + std::vector keyPoints; + cv::Mat descriptors; + std::string bulid_version_end; + + MapKeypointCache() {} + + MapKeypointCache(std::string bulid_time, + std::string bulid_version, + float hessian_threshold, + WORD octave, + WORD octave_layer, + WORD extended, + WORD upRight, + std::vector keyPoints, + cv::Mat descriptors): + bulid_time(bulid_time),bulid_version(bulid_version),hessian_threshold(hessian_threshold), + octave(octave),octave_layers(octave_layer),extended(extended),upRight(upRight), + keyPoints(keyPoints),descriptors(descriptors), bulid_version_end(bulid_version){} + + void serialize(std::string outfileName); + void deSerialize(std::string infileName); +}; +namespace Tianli::Resources::Utils +{ + class serializeStream + { + private: + std::ostream& fileOut; + public: + //将流对齐到size(2的幂次)的整数倍 + void align(int size = 4) { + int p = 0; + for (p = 0; size != 1; p++) + size >>= 1; + size <<= p; + + int fsLen = fileOut.tellp(); + int addLen = (fsLen >> p << p) + size - fsLen; + if (addLen != size) { + char* emptyBinarys = new char[addLen]; + memset(emptyBinarys, 0, addLen); + fileOut.write(emptyBinarys,addLen); + delete[] emptyBinarys; + } + } + + serializeStream(std::ostream& fileOut) :fileOut(fileOut) {} + + void operator <<(const std::string& s) + { + align(sizeof(DWORD)); + DWORD size = s.size()+1; + fileOut.write((char*)&size, sizeof(DWORD)); + fileOut.write(s.c_str(), size); + } + + template + requires std::is_integral_v || std::is_floating_point_v + void operator <<(const Digital& d) + { + align(sizeof(Digital)); + fileOut.write((char*)&d,sizeof(d)); + } + + void operator <<(const std::vector& points) + { + align(sizeof(DWORD)); + DWORD size = points.size() * sizeof(cv::KeyPoint); + fileOut.write((char*)&size, sizeof(DWORD)); + + const cv::KeyPoint* keyPointPtr = points.data(); + fileOut.write((char*)keyPointPtr, size); + } + + void operator <<(const cv::Mat& mat) + { + align(sizeof(DWORD)); + std::vector buf; + cv::imencode(".tiff", mat, buf,std::vector(cv::IMWRITE_TIFF_COMPRESSION,8)); + + DWORD size = buf.size(); + fileOut.write((char*)&size, sizeof(DWORD)); + + const uchar* bytes = buf.data(); + fileOut.write((char*)bytes, size); + } + }; + + class deSerializeStream + { + private: + std::istream& fileIn; + public: + deSerializeStream(std::istream& fileIn) :fileIn(fileIn) {} + + void align(int size = 4) //将流对齐到size(2的幂次)的整数倍 + { + int p = 0; + for (p = 0; size != 1; p++) + size >>= 1; + size <<= p; + + int fsLen = fileIn.tellg(); + int addLen = (fsLen >> p << p) + size - fsLen; + if (addLen != size) { + fileIn.ignore(addLen); + } + } + + void operator >>(std::string& s) + { + align(sizeof(DWORD)); + DWORD size; + if (fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read((char*)&size, sizeof(DWORD)); + if (size > MAXSHORT) throw std::exception("解析到的字符串过长"); + + char* bytes = new char[size]; + if (fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read(bytes,size); + + s = std::string(bytes); + + delete[] bytes; + } + + template + requires std::is_integral_v || std::is_floating_point_v + void operator >>(Digital & d) + { + align(sizeof(Digital)); + if(fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read((char*)&d, sizeof(d)); + } + + void operator >>(std::vector& points) + { + align(sizeof(DWORD)); + DWORD size; + if (fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read((char*)&size, sizeof(DWORD)); + + char* bytes = new char[size]; + if (fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read(bytes, size); + + cv::KeyPoint* keyPointPtr = (cv::KeyPoint*)bytes; + points = std::vector(keyPointPtr, keyPointPtr + size / sizeof(cv::KeyPoint)); + + delete[] bytes; + } + + void operator >>(cv::Mat& mat) + { + align(sizeof(DWORD)); + DWORD size; + if (fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read((char*)&size, sizeof(DWORD)); + + char* bytes = new char[size]; + if (fileIn.eof()) throw std::exception("尝试读取已经为空的流"); + fileIn.read(bytes, size); + + std::vector inputArray(bytes, bytes + size); + mat = cv::imdecode(inputArray, cv::IMREAD_ANYDEPTH | cv::IMREAD_UNCHANGED); + + delete[] bytes; + } + }; +} bool save_map_keypoint_cache(std::vector& keypoints, cv::Mat& descriptors, double hessian_threshold = 1, int octaves = 1, int octave_layers = 1, bool extended = false, bool upright = false); -bool load_map_keypoint_cache(std::vector& keypoints, cv::Mat& descriptors, double hessian_threshold = 1, int octaves = 1, int octave_layers = 1, bool extended = false, bool upright = false); -bool get_map_keypoint(std::vector& keypoints, cv::Mat& descriptors, double hessian_threshold = 1, int octaves = 1, int octave_layers = 1, bool extended = false, bool upright = false); \ No newline at end of file +bool load_map_keypoint_cache(std::vector& keypoints, cv::Mat& descriptors); + +bool get_map_keypoint(std::vector& keypoints, cv::Mat& descriptors); \ No newline at end of file diff --git a/cvAutoTrack/src/version/version_tag.tag b/cvAutoTrack/src/version/version_tag.tag index a8d1f4fb..8a1ab868 100644 --- a/cvAutoTrack/src/version/version_tag.tag +++ b/cvAutoTrack/src/version/version_tag.tag @@ -1 +1 @@ -7.8.1 +7.8.54