commit ed9bca34db97a528505dae6902d696dad8450391 Author: xiewenji <527774126@qq.com> Date: Fri Jun 26 17:45:01 2026 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..286242b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/build +/lib +/include +/data +/SaveImg +.vscode/launch.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..21af012 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/usr/local/include/opencv4" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c17", + "cppStandard": "gnu++14", + "cppStandard": "c++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e687b0f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,65 @@ +{ + "files.associations": { + "thread": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "array": "cpp", + "atomic": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "bit": "cpp", + "codecvt": "cpp", + "filesystem": "cpp" + } +} \ No newline at end of file diff --git a/AlgorithmModule/CMakeLists.txt b/AlgorithmModule/CMakeLists.txt new file mode 100644 index 0000000..23d89dc --- /dev/null +++ b/AlgorithmModule/CMakeLists.txt @@ -0,0 +1,81 @@ +cmake_minimum_required (VERSION 3.5) + +set(ModuleName "TY_CheckModule") + + +#==============TensorRT 版本控制==================== +# 查找 TensorRT 的头文件路径 +find_path(TENSORRT_INCLUDE_DIR + NAMES NvInfer.h + PATHS /usr/include/x86_64-linux-gnu /usr/local/include +) + +if(NOT TENSORRT_INCLUDE_DIR) + message(FATAL_ERROR "TensorRT headers not found") +endif() + +message(STATUS "TENSORRT_INCLUDE_DIR: " ${TENSORRT_INCLUDE_DIR}) + +# 提取版本号 +file(READ "${TENSORRT_INCLUDE_DIR}/NvInferVersion.h" TENSORRT_VERSION_CONTENTS) +string(REGEX MATCH "#define NV_TENSORRT_MAJOR ([0-9]+)" _ ${TENSORRT_VERSION_CONTENTS}) +set(TRT_MAJOR_VERSION ${CMAKE_MATCH_1}) +message(STATUS "Found TensorRT v${TRT_MAJOR_VERSION}") +# 检查版本 +if(TRT_MAJOR_VERSION VERSION_LESS 10) + message(STATUS " close //#define USE_TERNSORRT10_BIGMODEL") +else() +add_definitions(-DUSE_TERNSORRT10_BIGMODEL=${TEST_VALUE}) + message(STATUS "#define USE_TERNSORRT10_BIGMODEL") + +endif() + +#==============TensorRT 版本控制==================== + +set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations") +find_package(CUDA REQUIRED) +message(STATUS "cuda version: " ${CUDA_VERSION_STRING}) +message(STATUS "cuda CUDA_INCLUDE_DIRS: " ${CUDA_INCLUDE_DIRS}) +include_directories(${CUDA_INCLUDE_DIRS}) +include_directories( +/usr/local/include +/usr/include +#/usr/local/cuda-11.3/targets/x86_64-linux/include +${CMAKE_CURRENT_SOURCE_DIR}/include +${PROJECT_SOURCE_DIR}/include/TensorRT +${PROJECT_SOURCE_DIR}/ConfigModule/include +${PROJECT_SOURCE_DIR}/Common/include +) +link_directories( +/usr/local/lib/ +) +set(CMAKE_CUDA_ARCHITECTURES 86) +set(CMAKE_CUDA_COMPILER "/usr/local/cuda/bin/nvcc") +enable_language(CUDA) +# 用set设置变量不能使用*.cpp +file(GLOB SRC_LISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cu) +add_library(TY_Check SHARED ${SRC_LISTS}) + +target_link_libraries(TY_Check + nvinfer + Config + ${OpenCV_LIBS} + ${CUDA_LIBRARIES} + ) +set(ModuleName "") + +add_subdirectory(example) + + +# make install 安装到/usr/local下 +# 自定义安装前缀 +set(CMAKE_INSTALL_PREFIX /usr/local/polet CACHE PATH "Install path prefix" FORCE) +set(HEADER_FILES include/ImgCheckBase.h include/ImgCheckConfig.h) +# 安装动态库 +install(TARGETS TY_Check + LIBRARY DESTINATION lib # 安装到 CMAKE_INSTALL_PREFIX/lib + ARCHIVE DESTINATION lib/static + RUNTIME DESTINATION bin + PUBLIC_HEADER DESTINATION include) # 安装到 CMAKE_INSTALL_PREFIX/include +# 安装头文件 +install(FILES ${HEADER_FILES} DESTINATION include) \ No newline at end of file diff --git a/AlgorithmModule/example/CMakeLists.txt b/AlgorithmModule/example/CMakeLists.txt new file mode 100644 index 0000000..3a7ba53 --- /dev/null +++ b/AlgorithmModule/example/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required (VERSION 3.5) +find_package( OpenCV REQUIRED ) + +message(STATUS "oPENCV Library status:") +message(STATUS ">version:${OpenCV_VERSION}") +message(STATUS "Include:${OpenCV_INCLUDE_DIRS}") + + +if(CHECK_WORK_Value STREQUAL "POL_ET") + set(PROJECT_NAME "test_POL_ET") +elseif(CHECK_WORK_Value STREQUAL "CELL_ET") + set(PROJECT_NAME "test_CELL_ET") +elseif(CHECK_WORK_Value STREQUAL "FOG_ET") + set(PROJECT_NAME "test_FOG_ET") +else() + set(PROJECT_NAME "test_POL_ET") +endif() + +# 设置程序名称 +project(${PROJECT_NAME}) +set(ModuleName "${PROJECT_NAME}") + +set(CMAKE_CXX_STANDARD 17) + +set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations") + +include_directories( +/usr/local/include +#/usr/local/cuda-12.1/targets/x86_64-linux/include +${CMAKE_CURRENT_SOURCE_DIR}/include +${PROJECT_SOURCE_DIR}/ConfigModule/include +) + +link_directories( +/usr/local/lib/ +) +file(GLOB SRC_LISTS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +add_executable(${PROJECT_NAME} ${SRC_LISTS}) + +target_link_libraries(${PROJECT_NAME} + pthread + z + nvinfer + TY_Check + Config + #/usr/local/cuda-12.1/targets/x86_64-linux/lib/libcudart.so + ${OpenCV_LIBS} +) +# 设置该目标的RPATH +set_target_properties(${PROJECT_NAME} PROPERTIES + BUILD_RPATH "\$ORIGIN" +) +set(ModuleName "") \ No newline at end of file diff --git a/AlgorithmModule/example/CheckDefine.h b/AlgorithmModule/example/CheckDefine.h new file mode 100644 index 0000000..ba3020f --- /dev/null +++ b/AlgorithmModule/example/CheckDefine.h @@ -0,0 +1,49 @@ +/* + * @Descripttion: + * @version: + * @Author: sueRimn + * @Date: 2022-03-16 17:09:11 + * @LastEditors: sueRimn + * @LastEditTime: 2022-09-23 17:43:15 + */ + +#ifndef _CheckDefine_HPP_ +#define _CheckDefine_HPP_ + +#include +#include "BlobBase.h" + +#define SRC_IMAGE_WIDTH 14192 +#define SRC_IMAGE_HEIGHT 10640 + +#define SRC_IMAGE_SIZE 1*SRC_IMAGE_WIDTH *SRC_IMAGE_HEIGHT + +#define AI_BATCH_SIZE 1 + + +enum ERRORDEFINE +{ + RESULT_OK, + ERROR_CHECK_IMG_NULL, // 检测图片为空 + ERROR_CHECK_RESOURCE_NULL, // 检测资源为空 + ERROR_PRECHECK_IMG_NULL, // 预检测图片 异常 + +}; +// 检测控制参数 +struct CheckControlConfigSt +{ + CheckControlConfigSt() + { + } +}; +// 系统运行控制参数 +struct SystmeControlConfigST +{ + CheckControlConfigSt checkControlConfig; //// 检测控制参数 + + SystmeControlConfigST() + { + } +}; + +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/example/ConfigDeal.cpp b/AlgorithmModule/example/ConfigDeal.cpp new file mode 100644 index 0000000..6422be9 --- /dev/null +++ b/AlgorithmModule/example/ConfigDeal.cpp @@ -0,0 +1,187 @@ +#include "ConfigDeal.h" + +/****************************************************************************** +* 功 能:构造函数 +* 参 数:无 +* 返回值:无 +* 备 注: +******************************************************************************/ +CIni::CIni() +{ + memset(m_szKey, 0, sizeof(m_szKey)); + m_fp = NULL; +} + +/****************************************************************************** +* 功 能:析构函数 +* 参 数:无 +* 返回值:无 +* 备 注: +******************************************************************************/ + +CIni::~CIni() +{ + m_Map.clear(); +} + +/****************************************************************************** +* 功 能:打开文件函数 +* 参 数:无 +* 返回值: +* 备 注: +******************************************************************************/ +INI_RES CIni::OpenFile(const char* pathName, const char* type) +{ + string szLine, szMainKey, szLastMainKey, szSubKey; + char strLine[CONFIGLEN] = { 0 }; + KEYMAP mLastMap; + int nIndexPos = -1; + int nLeftPos = -1; + int nRightPos = -1; + m_fp = fopen(pathName, type); + + if (m_fp == NULL) + { + printf("open inifile %s error!\n", pathName); + return INI_OPENFILE_ERROR; + } + + m_Map.clear(); + + while (fgets(strLine, CONFIGLEN, m_fp)) + { + szLine.assign(strLine); + //删除字符串中的非必要字符 + nLeftPos = szLine.find("\n"); + if (string::npos != nLeftPos) + { + szLine.erase(nLeftPos, 1); + } + nLeftPos = szLine.find("\r"); + if (string::npos != nLeftPos) + { + szLine.erase(nLeftPos, 1); + } + //判断是否是主键 + nLeftPos = szLine.find("["); + nRightPos = szLine.find("]"); + if (nLeftPos != string::npos && nRightPos != string::npos) + { + szLine.erase(nLeftPos, 1); + /*nRightPos–-;*/ + nRightPos--; + szLine.erase(nRightPos, 1); + m_Map[szLastMainKey] = mLastMap; + mLastMap.clear(); + szLastMainKey = szLine; + } + else + { + + + //是否是子键 + if (nIndexPos = szLine.find("="), string::npos != nIndexPos) + { + string szSubKey, szSubValue; + szSubKey = szLine.substr(0, nIndexPos); + szSubValue = szLine.substr(nIndexPos + 1, szLine.length() - nIndexPos - 1); + mLastMap[szSubKey] = szSubValue; + } + else + { + //TODO:不符合ini键值模板的内容 如注释等 + } + } + + } + //插入最后一次主键 + m_Map[szLastMainKey] = mLastMap; + + fclose(m_fp); + m_fp = NULL; /* 需要指向空,否则会指向原打开文件地址 */ + + return INI_SUCCESS; +} + +/****************************************************************************** +* 功 能:关闭文件函数 +* 参 数:无 +* 返回值: +* 备 注: +******************************************************************************/ +INI_RES CIni::CloseFile() +{ + + + if (m_fp != NULL) + { + fclose(m_fp); + m_fp = NULL; + } + + return INI_SUCCESS; +} + +/****************************************************************************** +* 功 能:获取[SECTION]下的某一个键值的字符串 +* 参 数: +* char* mAttr 输入参数 主键 +* char* cAttr 输入参数 子键 +* char* value 输出参数 子键键值 +* 返回值: +* 备 注: +******************************************************************************/ +INI_RES CIni::GetKey(const char* mAttr, const char* cAttr, char* pValue) +{ + + KEYMAP mKey = m_Map[mAttr]; + + string sTemp = mKey[cAttr]; + + //printf("___ %s \n", sTemp.c_str()); + strcpy(pValue, sTemp.c_str()); + + return INI_SUCCESS; +} + +/****************************************************************************** +* 功 能:获取整形的键值 +* 参 数: +* cAttr 主键 +* cAttr 子键 +* 返回值:正常则返回对应的数值 未读取成功则返回0(键值本身为0不冲突) +* 备 注: +******************************************************************************/ +int CIni::GetInt(const char* mAttr, const char* cAttr) +{ + int nRes = 0; + + memset(m_szKey, 0, sizeof(m_szKey)); + + if (INI_SUCCESS == GetKey(mAttr, cAttr, m_szKey)) + { + nRes = atoi(m_szKey); + } + return nRes; +} + +/****************************************************************************** +* 功 能:获取键值的字符串 +* 参 数: +* cAttr 主键 +* cAttr 子键 +* 返回值:正常则返回读取到的子键字符串 未读取成功则返回"NULL" +* 备 注: +******************************************************************************/ +char *CIni::GetStr(const char* mAttr, const char* cAttr) +{ + memset(m_szKey, 0, sizeof(m_szKey)); + + if (INI_SUCCESS != GetKey(mAttr, cAttr, m_szKey)) + { + strcpy(m_szKey, "NULL"); + } + + return m_szKey; + +} \ No newline at end of file diff --git a/AlgorithmModule/example/ConfigDeal.h b/AlgorithmModule/example/ConfigDeal.h new file mode 100644 index 0000000..8f09677 --- /dev/null +++ b/AlgorithmModule/example/ConfigDeal.h @@ -0,0 +1,59 @@ + +#ifndef _CONFIGDEAL_HPP_ +#define _CONFIGDEAL_HPP_ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#define CONFIGLEN 256 +#define CheckData_CONFIG_File "../DataConfig/CheckData_Config.ini" + +enum INI_RES +{ + INI_SUCCESS, //成功 + INI_ERROR, //普通错误 + INI_OPENFILE_ERROR, //打开文件失败 + INI_NO_ATTR //无对应的键值 +}; + +// 子键索引 子键值 +typedef map KEYMAP; +// 主键索引 主键值 +typedef map MAINKEYMAP; +// config 文件的基本操作类 + +class CIni +{ +public: + // 构造函数 + CIni(); + + // 析够函数 + virtual ~CIni(); +public: + //获取整形的键值 + int GetInt(const char* mAttr, const char* cAttr); + //获取键值的字符串 + char *GetStr(const char* mAttr, const char* cAttr); + // 打开config 文件 + INI_RES OpenFile(const char* pathName, const char* type); + // 关闭config 文件 + INI_RES CloseFile(); +protected: + // 读取config文件 + INI_RES GetKey(const char* mAttr, const char* cAttr, char* value); +protected: + // 被打开的文件局柄 + FILE* m_fp; + char m_szKey[CONFIGLEN]; + MAINKEYMAP m_Map; +}; + + + +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/example/Image_ReadAndChange.cpp b/AlgorithmModule/example/Image_ReadAndChange.cpp new file mode 100644 index 0000000..08c16ac --- /dev/null +++ b/AlgorithmModule/example/Image_ReadAndChange.cpp @@ -0,0 +1,129 @@ +#include "Image_ReadAndChange.h" +#include "json/json.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +Image_ReadChannel::Image_ReadChannel() +{ + m_ChannelNameList.clear(); +} + +Image_ReadChannel::~Image_ReadChannel() +{ +} +bool Image_ReadChannel::containsChinese(const std::string &str) +{ + for (size_t i = 0; i < str.size(); ++i) + { + if ((unsigned char)str[i] >= 0x80) + { + return true; // 如果有非ASCII字符(可能是中文) + } + } + return false; +} +bool Image_ReadChannel::CompareIgnoreCase(const std::string &str1, const std::string &str2) +{ + // 将 str1 和 str2 转换为小写后进行比较 + std::string lower_str1 = str1; + std::string lower_str2 = str2; + + // 使用 std::transform 将字符串转换为小写 + std::transform(lower_str1.begin(), lower_str1.end(), lower_str1.begin(), ::tolower); + std::transform(lower_str2.begin(), lower_str2.end(), lower_str2.begin(), ::tolower); + + // 比较两个转换后的字符串 + return lower_str1 == lower_str2; +} +int Image_ReadChannel::ReadJsonConfig(std::string json_path) +{ + m_ChannelNameList.erase(m_ChannelNameList.begin(), m_ChannelNameList.end()); + std::string strPath = json_path; + printf("ReadJsonConfig path %s\n", strPath.c_str()); + Json::CharReaderBuilder builder; + builder["collectComments"] = true; + Json::Value root; + std::string err; + std::ifstream ifs(strPath); + if (!ifs.is_open()) + { + printf("error:file is open\n"); + return false; + } + if (!Json::parseFromStream(builder, ifs, &root, &err)) + { + printf("error:parseFromStream\n"); + return false; + } + + for (int i = 0; i < root.size(); i++) + { + printf("Node idx %d /%d \n", i, root.size()); + + ReadImageName tem; + tem.strDetChannle = root[i]["code"].asString(); + std::string strimgname = root[i]["image_name"].asString(); + { + + std::istringstream stream(strimgname); + std::string token; + + // 使用 getline 按照分号分割 + while (std::getline(stream, token, ';')) + { + tem.strImgNameList.push_back(token); + } + } + printf("det name %s img name Num %d \n", tem.strDetChannle.c_str(), tem.strImgNameList.size()); + // 输出分割后的结果 + for (const auto &str : tem.strImgNameList) + { + std::cout << str << std::endl; + } + + m_ChannelNameList.push_back(tem); + } + + return 0; +} + +std::string Image_ReadChannel::strDetName(std::string strImageName) +{ + std::string strDetName = ""; + for (const auto name : m_ChannelNameList) + { + + for (int i = 0; i < name.strImgNameList.size(); i++) + { + // 包含中文 + if (containsChinese(strImageName)) + { + // printf("strImageName %s name.strImgNameList.at(i) %s\n",strImageName.c_str(), name.strImgNameList.at(i).c_str()); + if (strImageName == name.strImgNameList.at(i)) + { + return name.strDetChannle; + } + } + else + { + if (CompareIgnoreCase(strImageName, name.strImgNameList.at(i))) + { + return name.strDetChannle; + } + } + } + } + + return strDetName; +} diff --git a/AlgorithmModule/example/Image_ReadAndChange.h b/AlgorithmModule/example/Image_ReadAndChange.h new file mode 100644 index 0000000..bbc30f8 --- /dev/null +++ b/AlgorithmModule/example/Image_ReadAndChange.h @@ -0,0 +1,56 @@ +/* + * @Author: xiewenji 527774126@qq.com + * @Date: 2025-07-25 09:14:25 + * @LastEditors: xiewenji 527774126@qq.com + * @LastEditTime: 2025-07-26 10:51:45 + * @FilePath: /BOE_CELL_ET/AlgorithmModule/example/Image_ReadAndChange.h + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +/* +//图片基本处理 + */ +#ifndef Image_ReadAndChange_H_ +#define Image_ReadAndChange_H_ + +#include +#include +#include "CheckDefine.h" +#include "ImgCheckConfig.h" +using namespace std; + + +// 图片读取的通道 +class Image_ReadChannel +{ +public: + struct ReadImageName + { + std::string strDetChannle; + std::vector strImgNameList; + + ReadImageName() + { + strImgNameList.clear(); + strDetChannle = ""; + } + }; + +private: + /* data */ +public: + Image_ReadChannel(/* args */); + ~Image_ReadChannel(); + + bool containsChinese(const std::string &str); + + int ReadJsonConfig(std::string json_path); // 加载检测图片名称配置参数 + + bool CompareIgnoreCase(const std::string &str1, const std::string &str2); + + std::string strDetName(std::string strImageName); + +private: + std::vector m_ChannelNameList; +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/example/ImgBasicDeal.cpp b/AlgorithmModule/example/ImgBasicDeal.cpp new file mode 100644 index 0000000..fa633f4 --- /dev/null +++ b/AlgorithmModule/example/ImgBasicDeal.cpp @@ -0,0 +1,166 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ImgBasicDeal.h" +ImgBasicDeal::ImgBasicDeal() +{ + + // DrawBlobErrorCorleList[ERROR_TYPE_OK] = cv::Scalar(128, 128, 128); + // DrawBlobErrorCorleList[ERROR_TYPE_yc] = cv::Scalar(255, 0, 0); +} + +ImgBasicDeal::~ImgBasicDeal() +{ +} + +int ImgBasicDeal::DrawResult(cv::Mat &image_draw, CheckResult result) +{ + +// if (resultimg.channels() == 1) +// { +// cv::cvtColor(resultimg, image_draw, cv::COLOR_GRAY2RGB); // 彩色 可选项 +// } +// else +// { +// image_draw = resultimg.clone(); +// } +// printf("result.blobResult.blobNum %d\n", result.blobResult.blobNum); +// for (int i = 0; i < result.blobResult.blobNum; i++) +// { +// // if (blobs.Pass[i]) +// { +// auto enType = result.blobResult.bloblist[i].UserErrorType; +// if (result.blobResult.bloblist[i].UserErrorType == 0) +// { +// continue; +// } + +// cv::Rect roi = result.blobResult.bloblist[i].blob_ResizeImg; + +// cv::Point pc; +// pc.x = roi.x + roi.width * 0.5; +// pc.y = roi.y + roi.height * 0.5; +// int rw = roi.width * 0.5; +// int rh = roi.height * 0.5; +// int r = std::sqrt(rw * rw + rh * rh) * 1.1 + 8; + +// cv::circle(image_draw, pc, r, DrawBlobErrorCorleList[result.blobResult.bloblist[i].UserErrorType]); + +// // 设置绘制文本的相关参数 +// std::string text = std::to_string(result.blobResult.bloblist[i].UserErrorType) + " A: " + std::to_string(result.blobResult.bloblist[i].JudgArea) + " E: " + std::to_string(result.blobResult.bloblist[i].energy); + +// int baseline; +// // 获取文本框的长宽 +// cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline); +// // 将文本框居中绘制 +// cv::Point origin = CalcTextPosition(pc, r, text_size, image_draw.size(), (ERROR_TYPE_)enType); +// cv::putText(image_draw, text, origin, font_face, font_scale, cv::Scalar(255, 0, 0), thickness, 1, 0); +// } +// } + + return 0; +} +cv::Point ImgBasicDeal::CalcTextPosition(cv::Point pt, int radius, cv::Size text_size, cv::Size image_size, ERROR_TYPE_ type) +{ + cv::Point dst; + int y_offset = 0; + // switch (type) + // { + // case ERROR_TYPE_OK: + // y_offset = 20; + // break; + // case ERROR_TYPE_yc: + // y_offset = 40; + // break; + // default: + // break; + // } + dst.y = (pt.y - y_offset > text_size.height) ? pt.y - y_offset : pt.y + y_offset; + if (dst.y >= image_size.height) + { + dst.y = image_size.height - 1; + } + dst.x = (pt.x + radius + text_size.width > image_size.width) ? pt.x - text_size.width - radius : pt.x + radius; + if (dst.x < 0) + { + dst.x = 0; + } + return dst; +} + +int ImgBasicDeal::DrawResult_small(cv::Mat &image_draw, int i, int j, CheckResult result) +{ + + // cv::cvtColor(result.SamllImgList[i][j].img, image_draw, cv::COLOR_GRAY2RGB); // 彩色 可选项 + // for (int k = 0; k < result.SamllImgList[i][j].qxIndexArr.size(); k++) + // { + // int idx = result.SamllImgList[i][j].qxIndexArr.at(k); + // { + + // float energy; + // float hj; + // cv::Rect roi = result.qxiImageResult.at(idx).SmallImgroi; + + // cv::Point pc; + // pc.x = roi.x + roi.width * 0.5; + // pc.y = roi.y + roi.height * 0.5; + // int rw = roi.width * 0.5; + // int rh = roi.height * 0.5; + // int r = std::sqrt(rw * rw + rh * rh) * 1.5 + 12; + + // cv::Scalar dcolor = cv::Scalar(0, 0, 255); + + // if (result.qxiImageResult.at(idx).type == 0) + // { + // dcolor = cv::Scalar(0, 255, 0); + // } + + // cv::circle(image_draw, pc, r, dcolor); + + // // 设置绘制文本的相关参数 + // char text[1024] = {0}; + // sprintf(text, "A:%.2f E:%.0f", result.qxiImageResult.at(idx).area, result.qxiImageResult.at(idx).energy); + + // int baseline; + // int font_face = cv::FONT_HERSHEY_SIMPLEX; + // double font_scale = 0.5; + // int thickness = 1; + // // 获取文本框的长宽 + // cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline); + + // // 将文本框居中绘制 + // cv::Point origin = cv::Point(roi.x, roi.y - 10); + // if (origin.x + text_size.width > image_draw.cols) + + // { + // origin.x = image_draw.cols - text_size.width; + // } + + // if (origin.y < 10) + + // { + // origin.y = 10; + // } + + // cv::putText(image_draw, text, origin, font_face, font_scale, cv::Scalar(255, 0, 0), thickness, 1, 0); + // } + // } + return 0; +} + +int ImgBasicDeal::DrawPointList(cv::Mat &image_draw, std::vector plist) +{ + + return 0; +} + +int ImgBasicDeal::preDealImg(cv::Mat &srcimg, cv::Mat &image_resize, bool bfilpSrcImg) +{ + + return 0; +} diff --git a/AlgorithmModule/example/ImgBasicDeal.h b/AlgorithmModule/example/ImgBasicDeal.h new file mode 100644 index 0000000..46fa6b2 --- /dev/null +++ b/AlgorithmModule/example/ImgBasicDeal.h @@ -0,0 +1,44 @@ +/* +//图片基本处理 + */ +#ifndef ImgBasicDeal_H_ +#define ImgBasicDeal_H_ + +#include +#include +#include "CheckDefine.h" +#include "ImgCheckConfig.h" +using namespace std; + +class ImgBasicDeal +{ + +public: + ImgBasicDeal(); + ~ImgBasicDeal(); + + /// @brief 画结果信息到图片上 + /// @return + int DrawResult(cv::Mat &image_draw, CheckResult result); + /// @brief 对图像预处理 + /// @param srcimg 原始图 输出 原始图或镜像图 + /// @param resizeimg 裁剪resize到 固定大小的图片 + /// @param bfilpSrcimg 是否镜像原始图 + /// @return + int DrawResult_small(cv::Mat &image_draw, int i, int j, CheckResult result); + int preDealImg(cv::Mat &srcimg, cv::Mat &image_resize, bool bfilpSrcImg = true); + int DrawPointList(cv::Mat &image_draw, std::vector plist); +cv::Point CalcTextPosition(cv::Point pt, int radius, cv::Size text_size, cv::Size image_size, ERROR_TYPE_ type); +public: + int font_face = cv::FONT_HERSHEY_SIMPLEX; + double font_scale = 0.5; + int thickness = 1; + + cv::Scalar Color_Brightness_roi = cv::Scalar(0, 255, 0); + cv::Scalar Color_Brightness_text = cv::Scalar(0, 255, 0); + cv::Scalar DrawBlobErrorCorleList[ERROR_TYPE_COUNT]; + +private: +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/example/JsonCoversion.cpp b/AlgorithmModule/example/JsonCoversion.cpp new file mode 100644 index 0000000..13c1478 --- /dev/null +++ b/AlgorithmModule/example/JsonCoversion.cpp @@ -0,0 +1,35 @@ +#include "JsonCoversion.h" + +JsonCoversion::JsonCoversion() +{ + //ctor +} + +JsonCoversion::~JsonCoversion() +{ + //dtor +} +string JsonCoversion::toJson() +{ + toJsonValue(); + + std::unique_ptr jsonWriter(writerBuilder.newStreamWriter()); + std::ostringstream os; + std::string jsonStr; + jsonWriter->write(root,&os); + jsonStr = os.str(); + return jsonStr; +} + +void JsonCoversion::toObject(string & strBuf) +{ + std::unique_ptr const jsonReader(readerBuilder.newCharReader()); + + JSONCPP_STRING errs; + bool res = jsonReader->parse(strBuf.c_str(), strBuf.c_str()+strBuf.length(), &root, &errs); + if (!res || !errs.empty()) + { + std::cout << "parseJson err. " << errs << std::endl; + } + toObjectFromValue(root); +} diff --git a/AlgorithmModule/example/JsonCoversion.h b/AlgorithmModule/example/JsonCoversion.h new file mode 100644 index 0000000..5419e33 --- /dev/null +++ b/AlgorithmModule/example/JsonCoversion.h @@ -0,0 +1,31 @@ +#ifndef JsonCoversion_H +#define JsonCoversion_H +#include +#include +#include +#include "json/json.h" +using namespace std; + +class JsonCoversion +{ + protected: + Json::Value root; + + // Json::FastWriter writer; //弃用 改用StreamWriterBuilder + Json::StreamWriterBuilder writerBuilder; + + // Json::Reader reader; //弃用 改用CharReaderBuilder + Json::CharReaderBuilder readerBuilder; + public: + JsonCoversion(); + virtual ~JsonCoversion(); + protected: + public: + string toJson(); + void toObject(string & strBuf); + protected: + virtual Json::Value toJsonValue() = 0; + virtual void toObjectFromValue(Json::Value root) = 0; +}; + +#endif // JsonCoversion_H diff --git a/AlgorithmModule/example/Read_Image.cpp b/AlgorithmModule/example/Read_Image.cpp new file mode 100644 index 0000000..742fd03 --- /dev/null +++ b/AlgorithmModule/example/Read_Image.cpp @@ -0,0 +1,470 @@ +#include "Read_Image.h" +#include +// 转小写 +std::string toLower(const std::string &str) +{ + std::string lower = str; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + return lower; +} + +int Extract_Name_Base::Read_Product_Image(std::string strPath) +{ + + return 0; +} + +int Extract_Name_Base::Read_Camera_Product_Image(std::string strPath, int userflag) +{ + + std::vector img_paths; + std::cout << strPath << std::endl; + cv::glob(strPath, img_paths, true); + for (int i = 0; i < img_paths.size(); i++) + { + + string strImagePath = img_paths[i]; + Extract_Info(strImagePath, userflag); + } + + return 0; +} + +int Extract_Name_Base::Read_Product_Camera_Image(std::string strPath) +{ + return 0; +} + +std::shared_ptr Extract_Name_Base::GetProduct(std::string strProductID) +{ + for (int i = 0; i < m_product_Camera_List.size(); i++) + { + if (m_product_Camera_List[i]->strProductID == strProductID) + { + return m_product_Camera_List[i]; + } + } + return std::shared_ptr(); +} + +std::shared_ptr Extract_Name_Base::GetCamera(std::string strProductID, std::string strCamName) +{ + for (int i = 0; i < m_product_Camera_List.size(); i++) + { + if (m_product_Camera_List[i]->strProductID == strProductID) + { + for (int j = 0; j < m_product_Camera_List[i]->camera_list.size(); j++) + { + if (m_product_Camera_List[i]->camera_list[j]->strCamName == strCamName) + { + return m_product_Camera_List[i]->camera_list[j]; + } + } + } + } + return std::shared_ptr(); +} + +std::shared_ptr Extract_Name_Base::GetCamera(std::shared_ptr product, std::string strCamName) +{ + for (int i = 0; i < product->camera_list.size(); i++) + { + if (product->camera_list[i]->strCamName == strCamName) + { + return product->camera_list[i]; + } + } + return std::shared_ptr(); +} + +// 判断目录部分是否包含某些关键词(不区分大小写) +bool Extract_Name_Base::dirPathContains(const fs::path &fullPath, const std::string KeyName) +{ + fs::path parentDir = fullPath.parent_path(); + std::string lowKeyName = toLower(KeyName); + for (const auto &dir : parentDir) + { + std::string dirName = toLower(dir.string()); + + if (dirName == lowKeyName) + { + return true; + } + } + + return false; +} + +Read_Image::Read_Image(/* args */) +{ +} + +Read_Image::~Read_Image() +{ +} + +int Read_Image::Read_Image_List(std::string strPath) +{ + m_extract_CELL_ET.pimage_ReadChannel = pimage_ReadChannel; + m_extract_CELL_ET.m_product_Camera_List.clear(); + int re = m_extract_CELL_ET.Read_Image_List(strPath); + if (re != 0) + { + return re; + } + m_product_Camera_List.clear(); + m_product_Camera_List.assign(m_extract_CELL_ET.m_product_Camera_List.begin(), m_extract_CELL_ET.m_product_Camera_List.end()); + + for (int i = 0; i < m_extract_CELL_ET.m_product_Camera_List.size(); i++) + { + m_extract_CELL_ET.m_product_Camera_List[i]->print(); + } + + // m_extract_BD.m_product_Camera_List.clear(); + // int re = m_extract_BD.Read_Image_List(strPath); + // if (re != 0) + // { + // return re; + // } + // m_product_Camera_List.clear(); + // m_product_Camera_List.assign(m_extract_BD.m_product_Camera_List.begin(), m_extract_BD.m_product_Camera_List.end()); + + // for (int i = 0; i < m_extract_BD.m_product_Camera_List.size(); i++) + // { + // m_extract_BD.m_product_Camera_List[i]->print(); + // } + + return 0; +} + +int Extract_CELL_ET::Extract_Info(std::string strPath, int userflag) +{ + std::cout << strPath << std::endl; + // 1、获取 产品名称 + std::string strProductName = Extract_Product_Name(strPath, userflag); + if (strProductName.empty()) + { + return -1; + } + + std::shared_ptr pProduct = GetProduct(strProductName); + if (pProduct.get() == nullptr) + { + printf("pProduct %s is NULL \n", strProductName.c_str()); + pProduct = std::make_shared(); + pProduct->strProductID = strProductName; + m_product_Camera_List.push_back(pProduct); + } + // 2、获取 相机名称 + std::string strCameraName = Extract_Camera_Name(strPath, userflag); + if (strCameraName.empty()) + { + printf("strCameraName is error \n"); + return -1; + } + std::shared_ptr pCamera = GetCamera(pProduct, strCameraName); + if (pCamera.get() == nullptr) + { + printf("pCamera %s is NULL \n", strCameraName.c_str()); + pCamera = std::make_shared(); + pCamera->strCamName = strCameraName; + pProduct->camera_list.push_back(pCamera); + } + + // 3、获取 通道 + std::string strChannelName = Extract_Channel_Name(strPath,userflag); + if (strChannelName.empty()) + { + printf("strChannelName is NULL \n"); + return -1; + } + fs::path p = fs::path(strPath); + std::string filenameWithoutExt = p.stem().string(); + + std::shared_ptr pImage = std::make_shared(); + + pImage->strProductID = strProductName; + pImage->strCamID = strCameraName; + pImage->strchannelName = strChannelName; + pImage->strName = filenameWithoutExt; + pImage->strPath = strPath; + pCamera->image_list.push_back(pImage); + + return 0; +} + +std::string Extract_CELL_ET::Extract_Camera_Name(std::string strPath, int userflag) +{ + if (userflag == 1) + { + + std::string prefix = "_0_"; + bool bleft = false; + size_t pos1 = strPath.rfind(prefix); + + if (pos1 != std::string::npos) + { + bleft = true; + } + + std::string prefix1 = "工位左"; + bool bleft1 = false; + size_t pos2 = strPath.rfind(prefix1); + + if (pos2 != std::string::npos) + { + bleft1 = true; + } + if (bleft || bleft1) + { + return "left"; + } + else + { + std::string prefix = "_1_"; + bool bright = false; + size_t pos1 = strPath.rfind(prefix); + + if (pos1 != std::string::npos) + { + bright = true; + } + std::string prefix1 = "工位右"; + bool bright1 = false; + size_t pos2 = strPath.rfind(prefix1); + + if (pos2 != std::string::npos) + { + bright1 = true; + } + + if (bright || bright1) + { + return "right"; + } + } + } + else + { + fs::path p = fs::path(strPath); + bool bleft = dirPathContains(p, "left"); + bool bleft1 = dirPathContains(p, "shard_left"); + if (bleft || bleft1) + { + return "left"; + } + else + { + bool bright = dirPathContains(p, "right"); + bool bright1 = dirPathContains(p, "shard_right"); + if (bright || bright1) + { + return "right"; + } + } + } + + return ""; +} + +std::string Extract_CELL_ET::Extract_Product_Name(std::string strPath, int userflag) +{ + + if (userflag == 0) + { + /* code */ + + // std::cout << strPath << std::endl; + fs::path p = fs::path(strPath); + fs::path lastDir = p.parent_path().filename(); + + std::string name = lastDir.string(); + if (name.empty()) + { + return ""; + } + + std::string prefix = "__DB__"; + + if (name.rfind(prefix, 0) == 0) + { // 判断是否以 "__DB__" 开头 + std::string result = name.substr(prefix.length()); + std::cout << "Product name: " << result << std::endl; + return result; + } + else + { + + std::cout << "Product name error: " << name << std::endl; + } + } + else if (userflag == 1) + { + fs::path p = fs::path(strPath); + fs::path lastDir = p.parent_path().filename(); + + std::string name = lastDir.string(); + if (name.empty() || name != "OriginalImage") + { + return ""; + } + + fs::path lastDir123 = p.parent_path().parent_path().filename(); + + std::string sproduct = lastDir123.string(); + // std::cout << "Product name error: " << sproduct << std::endl; + + size_t lastUnderscore = sproduct.find('_'); + if (lastUnderscore == std::string::npos) + return ""; + + std::string strImageproduct = sproduct.substr(0, lastUnderscore); + + // printf("strImageChannel %s\n", strImageproduct.c_str()); + + return strImageproduct; + } + + // // 独特判断 + // if (name.find("__DB__") != std::string::npos) + // { + // } + + return ""; +} + +std::string Extract_CELL_ET::Extract_Channel_Name(std::string strPath, int userflag) +{ + std::string strchannelName = ""; + if (userflag == 1) + { + fs::path p = fs::path(strPath); + std::string filenameWithoutExt = p.stem().string(); + std::cout << "提取的内容: " << filenameWithoutExt << std::endl; + + + if (pimage_ReadChannel) + { + strchannelName = pimage_ReadChannel->strDetName(filenameWithoutExt); + } + } + else + { + fs::path p = fs::path(strPath); + std::string filenameWithoutExt = p.stem().string(); + // std::cout << "提取的内容: " << filenameWithoutExt << std::endl; + + std::string strexName = ""; + size_t pos = filenameWithoutExt.find('^'); + if (pos != std::string::npos && pos + 1 < filenameWithoutExt.size()) + { + strexName = filenameWithoutExt.substr(pos + 1); + std::cout << "提取到的字符串: " << strexName << std::endl; + } + if (pimage_ReadChannel) + { + strchannelName = pimage_ReadChannel->strDetName(strexName); + } + } + + return strchannelName; +} +int Extract_CELL_ET::Read_Image_List(std::string strPath) +{ + std::string strSearchImgPath = strPath + "/*.tif"; + Read_Camera_Product_Image(strSearchImgPath, 0); + + strSearchImgPath = strPath + "/*.png"; + Read_Camera_Product_Image(strSearchImgPath, 1); + + return 0; +} +int Extract_BD::Extract_Info(std::string strPath, int userflag) +{ + std::cout << strPath << std::endl; + // 1、获取 产品名称 + std::string strProductName = Extract_Product_Name(strPath); + if (strProductName.empty()) + { + return -1; + } + + std::shared_ptr pProduct = GetProduct(strProductName); + if (pProduct.get() == nullptr) + { + printf("pProduct %s is NULL \n", strProductName.c_str()); + pProduct = std::make_shared(); + pProduct->strProductID = strProductName; + m_product_Camera_List.push_back(pProduct); + } + // 2、获取 相机名称 + std::string strCameraName = Extract_Camera_Name(strPath); + if (strCameraName.empty()) + { + return -1; + } + std::shared_ptr pCamera = GetCamera(pProduct, strCameraName); + if (pCamera.get() == nullptr) + { + printf("pCamera %s is NULL \n", strCameraName.c_str()); + pCamera = std::make_shared(); + pCamera->strCamName = strCameraName; + pProduct->camera_list.push_back(pCamera); + } + + // 3、获取 通道 + std::string strChannelName = Extract_Channel_Name(strPath); + if (strChannelName.empty()) + { + return -1; + } + fs::path p = fs::path(strPath); + std::string filenameWithoutExt = p.stem().string(); + + std::shared_ptr pImage = std::make_shared(); + + pImage->strProductID = strProductName; + pImage->strCamID = strCameraName; + pImage->strchannelName = strChannelName; + pImage->strName = filenameWithoutExt; + pImage->strPath = strPath; + pCamera->image_list.push_back(pImage); + + return 0; + return 0; +} +std::string Extract_BD::Extract_Camera_Name(std::string strPath, int userflag) +{ + fs::path p = fs::path(strPath); + + return ""; +} +std::string Extract_BD::Extract_Product_Name(std::string strPath, int userflag) +{ + fs::path p = fs::path(strPath); + fs::path lastDir = p.parent_path().filename(); + + std::string name = lastDir.string(); + if (name.empty()) + { + return ""; + } + + size_t pos = name.rfind('-'); // 找最后一个 '-' + if (pos != std::string::npos && pos + 1 < name.size()) + { + return name.substr(pos + 1); + } + return ""; // 没有找到 '-' 或后面没有字符 +} +std::string Extract_BD::Extract_Channel_Name(std::string strPath, int userflag) +{ + return ""; +} +int Extract_BD::Read_Image_List(std::string strPath) +{ + std::string strSearchImgPath = strPath + "/*.jpg"; + Read_Camera_Product_Image(strSearchImgPath, 0); + + return 0; +} \ No newline at end of file diff --git a/AlgorithmModule/example/Read_Image.h b/AlgorithmModule/example/Read_Image.h new file mode 100644 index 0000000..4a201a8 --- /dev/null +++ b/AlgorithmModule/example/Read_Image.h @@ -0,0 +1,192 @@ + +#ifndef Read_Image_HPP_ +#define Read_Image_HPP_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Image_ReadAndChange.h" + +namespace fs = std::filesystem; +using namespace std; + +// 图片信息 +struct Image_Info +{ + std::string strProductID; // 产品ID + std::string strCamID; // 相机名称 + std::string strchannelName; // 通道名称 + std::string strPath; // 完整路径 + std::string strName; // 图片名称 + cv::Mat img; // 图像数据 + long readImg_start; // 读取开始时间 + long readImg_end; // 读取结束时间 + + // 构造函数,调用 Init 初始化 + Image_Info() + { + Init(); + } + + // 初始化函数,重置所有成员变量 + void Init() + { + strProductID = ""; + strCamID = ""; + strchannelName = ""; + strPath = ""; + strName = ""; + img.release(); // 释放图像内存 + readImg_start = 0; + readImg_end = 0; + } + + void print() + { + std::cout << "Product ID: " << strProductID << std::endl; + std::cout << "Camera ID: " << strCamID << std::endl; + std::cout << "Channel Name: " << strchannelName << std::endl; + std::cout << "Image Path: " << strPath << std::endl; + std::cout << "Image Name: " << strName << std::endl; + std::cout << "Read Start Time: " << readImg_start << std::endl; + std::cout << "Read End Time: " << readImg_end << std::endl; + } +}; + +// 相机信息 +struct Camera_File_Info +{ + std::string strCamName; // 相机名称 + std::string strCamPath; // 相机路径 + vector> image_list; // 图片信息列表 + Camera_File_Info() + { + Init(); + } + void Init() + { + strCamName = ""; + strCamPath = ""; + } + int getImgNum() + { + int num = 0; + for (auto item : image_list) + { + num++; + } + return num; + } + void print() + { + printf("************CamName: %s img num %ld\n", strCamName.c_str(), image_list.size()); + // for (auto &item : image_list) + // { + // // item->print(); + // } + } +}; +// 产品信息 +struct Product_File_Info +{ + std::string strProductID; // 产品ID + std::string strProductPath; // 产品路径 + vector> camera_list; // 相机信息列表 + Product_File_Info() + { + Init(); + } + void Init() + { + strProductID = ""; + strProductPath = ""; + } + int getImgNum() + { + int num = 0; + for (auto item : camera_list) + { + num += item->getImgNum(); + } + return num; + } + void print() + { + printf("***strProductID: %s\n", strProductID.c_str()); + for (auto &item : camera_list) + { + item->print(); + } + } +}; +class Extract_Name_Base +{ +public: + virtual int Extract_Info(std::string strPath,int userflag) = 0; + virtual std::string Extract_Camera_Name(std::string strPath,int userflag = 0) = 0; + virtual std::string Extract_Product_Name(std::string strPath,int userflag = 0) = 0; + virtual std::string Extract_Channel_Name(std::string strPath,int userflag = 0) = 0; + virtual int Read_Image_List(std::string strPath) = 0; + int Read_Product_Image(std::string strPath); + int Read_Camera_Product_Image(std::string strPath,int userflag) ; + int Read_Product_Camera_Image(std::string strPath); + std::shared_ptr GetProduct(std::string strProductID); + std::shared_ptr GetCamera(std::string strProductID, std::string strCamName); + std::shared_ptr GetCamera(std::shared_ptr product, std::string strCamName); + + bool dirPathContains(const fs::path &fullPath, const std::string KeyName); + + vector> m_product_Camera_List; + Image_ReadChannel *pimage_ReadChannel; +}; + +class Extract_CELL_ET : public Extract_Name_Base +{ +public: + int Extract_Info(std::string strPath,int userflag = 0); + std::string Extract_Camera_Name(std::string strPath,int userflag = 0); + std::string Extract_Product_Name(std::string strPath,int userflag = 0); + std::string Extract_Channel_Name(std::string strPath,int userflag = 0); + int Read_Image_List(std::string strPath); +}; +class Extract_BD : public Extract_Name_Base +{ +public: + int Extract_Info(std::string strPath,int userflag ); + std::string Extract_Camera_Name(std::string strPath,int userflag = 0); + std::string Extract_Product_Name(std::string strPath,int userflag = 0); + std::string Extract_Channel_Name(std::string strPath,int userflag = 0); + int Read_Image_List(std::string strPath); +}; +class Read_Image +{ +public: + // 图片文件的格式 + enum Image_File_TYPE_ + { + Image_File_Product_Image, // 产品-图片格式 + Image_File_Camera_Product_Image, // 相机-产品-图片格式 + Image_File_Product_Camera_Image, // 产品-相机-图片格式 + }; + +public: + Read_Image(/* args */); + ~Read_Image(); + + int Read_Image_List(std::string strPath); + + Extract_CELL_ET m_extract_CELL_ET; + Extract_BD m_extract_BD; + Image_ReadChannel *pimage_ReadChannel; + +private: +public: + vector> m_product_Camera_List; // 产品相机列表 +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/example/SystemCommonDefine.h b/AlgorithmModule/example/SystemCommonDefine.h new file mode 100644 index 0000000..7de1c57 --- /dev/null +++ b/AlgorithmModule/example/SystemCommonDefine.h @@ -0,0 +1,177 @@ +/* + * @Descripttion: + * @version: + * @Author: sueRimn + * @Date: 2022-03-16 17:09:11 + * @LastEditors: sueRimn + * @LastEditTime: 2022-09-23 17:43:15 + */ + +#ifndef _SYSTEMCOMMONDEFIN1_HPP_ +#define _SYSTEMCOMMONDEFIN1_HPP_ +#include +// working:”检测”, ready:”就绪”, check: “自检”, bad: “故障”, close: “关闭” +// 系统运行状态定义 +enum SYSTEMRUNTYPE_ +{ + SYSTEM_RUN_TYPE_null, + SYSTEM_RUN_TYPE_working, // ”检测” + SYSTEM_RUN_TYPE_ready, // ”就绪” + SYSTEM_RUN_TYPE_check, // “自检” + SYSTEM_RUN_TYPE_bad, // “故障” + SYSTEM_RUN_TYPE_close, // “关闭” + SYSTEM_RUN_TYPE_count, +}; +// + +// 检测状态 离线检测 在线检测 +enum CHECKIMGTRUNTYP_ +{ + CHECK_TYPE_ONLING, // 在线检测 + CHECK_TYPE_OFFLING, // 离线检测 + +}; + +enum Check_Work_Type +{ + Check_Work_NULL, + Check_Work_POL_ET, + Check_Work_CELL_ET, + Check_Work_FOG_ET, + Check_Work_COUNT, + +}; +static const std::string Check_Work_Name[] = + { + "NULL", + "POL_ET", + "CELL_ET", + "FOG_ET", +}; +//------------------------config file define---------------------------------------- + +#define FILE_SYSTEM_RUN_CONFIG "../data/system_param.json" + +#define FILE_THRESHOLDPARARM "/var/aidlux/efs/jdf/model/param.json" +#define FILE_CAM_ROI_PARARM "/var/aidlux/aid-cms/model/roi.json" +#define FILE_AIMODEL_FILE_PATH "/var/aidlux/aid-cms/model/config.json" +#define FILE_CONFIG_ROOR_PATH "/var/aidlux/aid-cms/model/" + +#define FILE_AI_defect_BOE_MODEL_PATH "/home/aidlux/BOE/UseModel/defect.engine" +#define FILE_AI_classis_BOE_MODEL_PATH "/home/aidlux/BOE/UseModel/class.engine" + +#define FILE_CHECKIMG_CONFIG "../DataConfig/check_Config.ini" + +#define FILE_SAVEOKIMG_PATH "/home/aidlux/xwj/OKImg/" + +// #define FILE_SAVEALLIMG_PATH "/home/aidlux/JBL/imageData/" +#define FILE_SAVEALLIMG_PATH "/ssd/SaveImg/" +#define FILE_SAVENGIMG_PATH "/ssd/NGImg/" + +// #define MAX_NAM_LEN 64 + +// 字符长度 +#define MAX_STR_LEN 128 +// url长度 +#define MAX_ULR_LEN 256 + +#define MAX_GPU_NUM 2 + +// ncnn 行人检测 跟踪 检测最大 线程个数 +#define MAX_PERSONTRACKER_THREAD_NUM 4 + +// 共享内存检测最大 线程个数 +#define MAX_SHARMEMORYCHECK_THREAD_NUM 2 + +// 行人+跌倒检测 算法 资源 起止 +#define SHARMEMORYCHECK_THREAD_PERSON_IDX_START 0 +#define SHARMEMORYCHECK_THREAD_PERSON_IDX_END 6 + +// 离岗行人 算法 资源 起止 +#define SHARMEMORYCHECK_THREAD_Departure_PERSON_IDX_START 7 +#define SHARMEMORYCHECK_THREAD_Departure_PERSON_IDX_END 7 + +// 属性检测 算法 资源 起止 +#define SHARMEMORYCHECK_THREAD_ATTRIBUTE_IDX_START 9 +#define SHARMEMORYCHECK_THREAD_ATTRIBUTE_IDX_END 9 + +#define USERSHAREKEY 476550 + +#define SHARED_MEM_LEN IMAGE_WIDTH *IMAGE_HEIGHT * 3 + +#define HTTP_SERVER_PATTERN_CAMCONFIG "/api/camera/param" +#define HTTP_SERVER_PATTERN_CAMCHECKROI "/api/camera/roi" +#define HTTP_SERVER_PATTERN_PARAM_ADD "/param/add" +#define HTTP_SERVER_PATTERN_PREVIEW "/preview" +#define HTTP_SERVER_PATTERN_SWITCH "/switch" +#define HTTP_SERVER_PATTERN_DETECT_OPEN_ALL "/api/detect/open/all" +#define HTTP_SERVER_PATTERN_PLC_STATE "/api/plc/state" +#define HTTP_SERVER_PATTERN_PLC_SET_STATE "/api/plc/set/state" + +#define IMAGE_SIZE (2048 * 1792) + +enum START_SYSTEM_STEP_ +{ + START_SYSTEM_STEP_LoadConfig, + START_SYSTEM_STEP_InitCheck, + START_SYSTEM_STEP_PreCheck, + START_SYSTEM_STEP_CamIO, + START_SYSTEM_STEP_Complete, +}; +struct SystemConfigParam +{ + std::string Analysis_Config_path; + std::string Analysis_Config_path_Cam2; + std::string Check_Config_path; + std::string channel_Config_path; + + std::string preCheckImg_Path; // 预处理图片 + int Use_CPU_StartIdx; // 使用 CPU的开始核 + int preCHeck_YX; // 异显检测 : 1 :用异显1模型 检测; 2:用异显2模型 检测; 其他:不进行异显检测 + int preCHeck_defect; // 缺陷检测模型,1:用wtb btw hb4 等进检测; 其他 用模型进行检测 + SystemConfigParam() + { + Use_CPU_StartIdx = 0; + preCheckImg_Path = "../data/t1.tif"; + preCHeck_YX = 0; + preCHeck_defect = 0; + channel_Config_path = ""; + } + bool valid() + { + if (Analysis_Config_path.size() && + Check_Config_path.size() && + preCheckImg_Path.size() && + Use_CPU_StartIdx >= 0) + { + return true; + } + return false; + } +}; + +enum THREAD_CPU_ +{ + THREAD_CPU_Main_Det, + THREAD_CPU_Main_readImg, + THREAD_CPU_Main_saveImg, + THREAD_CPU_CheckSo, + THREAD_CPU_Count, +}; + +struct CPU_ID_INFO_ +{ + int startIdx; + int num; + CPU_ID_INFO_() + { + startIdx = 0; + num = 0; + } + void set(int sidx, int num) + { + this->startIdx = sidx; + this->num = num; + } +}; +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/example/deal.cpp b/AlgorithmModule/example/deal.cpp new file mode 100644 index 0000000..9127ecd --- /dev/null +++ b/AlgorithmModule/example/deal.cpp @@ -0,0 +1,2556 @@ +#include "deal.h" +#include "json/json.h" +#include +#include +#include +#include +#include + +std::string ExtractFileNameWithoutExtension(const std::string &strImgPath) +{ + // 查找最后一个斜杠 '/' 或 '\' 的位置 + size_t lastSlashPos = strImgPath.find_last_of("/\\"); + + // 如果没有找到斜杠,默认整个字符串是文件名 + std::string fileName = (lastSlashPos == std::string::npos) + ? strImgPath + : strImgPath.substr(lastSlashPos + 1); + // 查找最后一个点 '.' 的位置 + size_t lastDotPos = fileName.find_last_of('.'); + // 如果没有找到点号,或者点号在第一个字符的位置,则返回完整文件名 + if (lastDotPos == std::string::npos || lastDotPos == 0) + { + return fileName; + } + + // 返回去掉扩展名的部分 + return fileName.substr(0, lastDotPos); +} +std::string GetFileName(const std::string &strImgPath) +{ + // 查找最后一个斜杠 '/' 或 '\' 的位置 + size_t lastSlashPos = strImgPath.find_last_of("/\\"); + + // 如果没有找到斜杠,默认整个字符串是文件名 + std::string fileName = (lastSlashPos == std::string::npos) + ? strImgPath + : strImgPath.substr(lastSlashPos + 1); + // 查找最后一个点 '.' 的位置 + + return fileName; +} +bool customSort(const AI_Det_Channel_ &a, const AI_Det_Channel_ &b) +{ + // 特定规则排序: "a" 排第一, "b" 排第二, "L" 排最后 + if (a.strChannel == "Up-Particle" && b.strChannel != "Up-Particle") + { + return true; // "a" 排在前面 + } + if (a.strChannel != "Up-Particle" && b.strChannel == "Up-Particle") + { + return false; + } + + if (a.strChannel == "Down-Particle" && b.strChannel != "Down-Particle" && b.strChannel != "Up-Particle") + { + return true; // "b" 排第二 + } + if (a.strChannel != "Down-Particle" && b.strChannel == "Down-Particle") + { + return false; + } + + if (a.strChannel == "L0" && b.strChannel != "L0" && b.strChannel != "Up-Particle" && b.strChannel != "Down-Particle") + { + return false; // "L" 排最后 + } + if (a.strChannel != "L0" && b.strChannel == "L0") + { + return true; + } + + // 对其他情况使用字典顺序排序 + return a.strChannel < b.strChannel; +} + +// 定义图片读取函数 +void readImage(const std::string &filename) +{ + cv::Mat image = cv::imread(filename); + if (image.empty()) + { + std::cerr << "Error: Unable to read image " << filename << std::endl; + return; + } + + // // 在这里可以添加对图像的处理操作 + // // 例如:显示图像、保存图像、进行其他处理等 + + // // 示例:显示图像 + // cv::imshow(filename, image); + // cv::waitKey(0); + // cv::destroyWindow(filename); +} + +int _sysmkdir_1(const std::string &dir) +{ + int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (ret && errno == EEXIST) + { + // printf("dir[%s] already exist.\n", dir.c_str()); + } + else if (ret) + { + printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno)); + return -1; + } + else + { + printf("create dir[%s] success.\n", dir.c_str()); + } + return 0; +} +std::string __getParentDir_1(const std::string &dir) +{ + std::string pdir = dir; + if (pdir.length() < 1 || (pdir[0] != '/')) + { + return ""; + } + while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/')) + pdir = pdir.substr(0, pdir.length() - 1); + + pdir = pdir.substr(0, pdir.find_last_of('/')); + return pdir; +} +int _sysmkdirs_1(const std::string &dir) +{ + int ret = 0; + if (dir.empty()) + return -1; + std::string pdir; + if ((ret = _sysmkdir_1(dir)) == -1) + { + pdir = __getParentDir_1(dir); + if ((ret = _sysmkdirs_1(pdir)) == 0) + { + ret = _sysmkdirs_1(dir); + } + } + + return ret; +} + +long getcurTime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000; +} +deal::deal() +{ + nLastCheckAnalysisyThreadIdx = 0; + m_nCamIdx = 0; + m_nCurUseCPUIDX = 0; + m_nSaveDetprocessImg = 0; + m_DetResult.Init(); + for (int i = 0; i < READ_IMG_THREAD_NUM; i++) + { + m_nReadStausList[i] = ReadImg_Status_IDE; + } + m_nreadImg_Stop = false; + m_strCurDate = ""; + m_nReadThread_type = READ_THREAD_TYPE_NULL; + + for (int i = 0; i < Status_Type_Count; i++) + { + m_DetStatusList[i] = Thread_Status_IDE; + } + m_nTestNum = 9999999; + m_pALLImgCheckAnalysisy = NULL; + + m_check_Work_Type = Check_Work_NULL; + + m_nTestAI = 0; +} + +deal::~deal() +{ +} + +int deal::start() +{ + + // 配置系统运行的cup核数。 + InitCPUIDX(); + // 读取系统配置文件 + int re = ReadSystemConfig(FILE_SYSTEM_RUN_CONFIG); + if (re == false) + { + printf("ReadSystemConfig error\n"); + return 1; + } + m_image_ReadChannel.ReadJsonConfig(m_system_param.channel_Config_path); + // 初始化参数模块 + InitConfig(); + printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************LoadCheckImgConfig\n"); + // 载入参数 + LoadCheckImgConfig(); + printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************InitCheckAnalysisy\n"); + + // 初始化检测库 + InitCheckAnalysisy(); + printf("\n\n\n\n\n\n\n\n\n\n\n**********************************************************Check\n"); + std::string str = "/home/aidlux/BOE/images/*.tif"; + + if (m_nRunType == RUNTYPE_RUN_Align) + { + std::string str1 = "/home/aidlux/BOE/Align/Big/"; + + m_nReadThread_type = READ_THREAD_Detect; + StartThread(THREAD_RUN_Only_ReadImg); + Det_Edge_Test_OneImg(); + return 0; + } + if (m_nRunType == RUNTYPE_RUN_Pre_BigImg || + m_nRunType == RUNTYPE_RUN_Pre_BigImg_Cam2) + { + std::string str1 = "/home/aidlux/BOE/Edge/Big/"; + _sysmkdirs_1(str1); + str1 = "/home/aidlux/BOE/Edge/Result/"; + _sysmkdirs_1(str1); + str1 = "/home/aidlux/BOE/Edge/Smasll/"; + _sysmkdirs_1(str1); + + m_nReadThread_type = READ_THREAD_TYPE_READIMG; + StartThread(THREAD_RUN_Only_ReadImg); + preCheck(); + return 0; + } + // 测试mark线 + if (m_nRunType == RUNTYPE_RUN_File_MarkLine_Test) + { + + std::string str1 = "/home/aidlux/BOE/MarkLine/"; + _sysmkdirs_1(str1); + + m_nReadThread_type = READ_THREAD_TYPE_READIMG; + StartThread(THREAD_RUN_Only_ReadImg); + + Det_Funtion_Test(); + return 0; + } + + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_TEST || + m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + + std::string str1 = "/home/aidlux/BOE/Edge/Big/"; + _sysmkdirs_1(str1); + str1 = "/home/aidlux/BOE/Edge/Result/"; + _sysmkdirs_1(str1); + str1 = "/home/aidlux/BOE/Edge/Smasll/"; + _sysmkdirs_1(str1); + + m_nReadThread_type = READ_THREAD_TYPE_READIMG; + StartThread(THREAD_RUN_Only_ReadImg); + // Det_Edge_Test_OneImg(); + Det_Funtion_Test(); + return 0; + } + + m_nReadThread_type = READ_THREAD_TYPE_READIMG; + // 文件夹套图处理 + if (RUNTYPE_RUN_File_BigImg == m_nRunType) + { + std::string str1 = "/home/aidlux/BOE/AI/"; + _sysmkdirs_1(str1); + str = m_strCheckFilePath; + LoadProductID(str); + } + // getchar(); + m_nSystemCheckType = CHECK_TYPE_OFFLING; + StartThread(THREAD_RUN_ALL); + return 0; +} + +int deal::LoadCheckImgConfig() +{ + + LoadCheckConfig(); + LoadAnalysisConfig(); + + return 0; +} + +int deal::InitCheckAnalysisy() +{ + int re = 0; + int m_nMAX_GPU_NUM = MAX_GPU_NUM; + if (m_nMAX_GPU_NUM <= 0) + { + printf(">>>>error GPU error %d \n", m_nMAX_GPU_NUM); + return 2; + } + int startidx = m_CPUInfo[THREAD_CPU_CheckSo].startIdx; + int cpunum = m_CPUInfo[THREAD_CPU_CheckSo].num; + m_RunConfig.nCpu_start_Idx = startidx; + m_RunConfig.nCpu_num = cpunum; + m_pALLImgCheckAnalysisy = ALLImgCheckBase::GetInstance(); + re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)&m_RunConfig, CHECK_CONFIG_Run); + re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)m_pConfig, CHECK_CONFIG_Module); + re = m_pALLImgCheckAnalysisy->UpdateConfig((void *)m_pConfig_Cam2, CHECK_CONFIG_Module_Cam2); + + VERSION_INFO tm; + tm.InterfaceVersion = ALL_INTERFACE_VERSION; + tm.ConfigVersion = CONFIGBASE_VERSION; + tm.ResultVersion = RESULT_VERSION; + re = m_pALLImgCheckAnalysisy->RunStart(&tm); + if (re != 0) + { + printf("RunStart Fail %d\n", re); + return re; + } + + // printf(">>>> m_pResultJsonCheckAnalysisy Start \n"); + // m_RunConfig.nCpu_num = 0; + // m_RunConfig.flag2 = 1; // 表示 当前方法 只进行 json结果复测。 + // m_pResultJsonCheckAnalysisy = ALLImgCheckBase::GetInstance(); + // re = m_pResultJsonCheckAnalysisy->UpdateConfig((void *)&m_RunConfig, CHECK_CONFIG_Run); + // re = m_pResultJsonCheckAnalysisy->UpdateConfig((void *)m_pConfig, CHECK_CONFIG_Module); + // re = m_pResultJsonCheckAnalysisy->UpdateConfig((void *)m_pConfig_Cam2, CHECK_CONFIG_Module_Cam2); + + // re = m_pResultJsonCheckAnalysisy->RunStart(&tm); + // if (re != 0) + // { + // printf("Rejson RunStart Fail \n"); + // return re; + // } + // printf(">>>> Rejson Start Succ \n"); + + printf(">>>> ImgCheckThread Start Succ \n"); + return 0; +} + +int deal::InitConfig() +{ + m_pConfig = ConfigBase::GetInstance(); + m_pConfig_Cam2 = ConfigBase::GetInstance(); + printf("init configModel %s\n", m_pConfig->GetErrorInfo().c_str()); + return 0; +} + +int deal::InitSaveImgPath() +{ + return 0; +} + +int deal::LoadCheckConfig() +{ + Json::Reader json_reader; + Json::Value json_value; + std::ifstream infile(m_system_param.Check_Config_path, ios::binary); + + if (infile.is_open()) + { + if (json_reader.parse(infile, json_value)) + { + + m_pConfig->UpdateJSONConfig((void *)&json_value, ConfigType_Check_XL); + m_pConfig_Cam2->UpdateJSONConfig((void *)&json_value, ConfigType_Check_XL); + + printf("m_pConfig ConfigType_Check_XL %s\n", m_pConfig->GetErrorInfo().c_str()); + } + else + { + printf("11****%s fail \n", m_system_param.Check_Config_path.c_str()); + } + } + else + { + printf("22****%s fail \n", m_system_param.Check_Config_path.c_str()); + infile.close(); + return 1; + } + infile.close(); + // 从参数 获取 图片大小信息 + m_pConfig->GetConfig(ConfigType_Image_In, &m_ImgInfo_src); + m_pConfig->GetConfig(ConfigType_Image_out, &m_ImgInfo_result); + m_ImgInfo_src.print("m_ImgInfo_src"); + m_ImgInfo_result.print("m_ImgInfo_result"); + + return 0; +} +int deal::LoadAnalysisConfig() +{ + Json::Reader json_reader; + Json::Value json_value; + std::ifstream infile(m_system_param.Analysis_Config_path, ios::binary); + printf("Analysis_Config_path %s \n", m_system_param.Analysis_Config_path.c_str()); + if (infile.is_open()) + { + if (json_reader.parse(infile, json_value)) + { + + m_pConfig->UpdateJSONConfig((void *)&json_value, ConfigType_Analysisy_Common_XL); + + printf("m_pConfig ConfigType_Analysisy_Common_XL %s\n", m_pConfig->GetErrorInfo().c_str()); + } + else + { + printf("****%s fail \n", m_system_param.Analysis_Config_path.c_str()); + } + } + else + { + printf("****%s fail \n", m_system_param.Analysis_Config_path.c_str()); + infile.close(); + return 1; + } + infile.close(); + // 相机2的参数 + { + Json::Reader json_reader2; + Json::Value json_value2; + std::ifstream infile2(m_system_param.Analysis_Config_path_Cam2, ios::binary); + printf("Analysis_Config_path_Cam2 %s \n", m_system_param.Analysis_Config_path_Cam2.c_str()); + if (infile2.is_open()) + { + if (json_reader2.parse(infile2, json_value2)) + { + + m_pConfig_Cam2->UpdateJSONConfig((void *)&json_value2, ConfigType_Analysisy_Common_XL); + + printf("m_pConfig_Cam2 ConfigType_Analysisy_Common_XL %s\n", m_pConfig_Cam2->GetErrorInfo().c_str()); + } + else + { + printf("****%s fail \n", m_system_param.Analysis_Config_path_Cam2.c_str()); + } + } + else + { + printf("****%s fail \n", m_system_param.Analysis_Config_path_Cam2.c_str()); + infile2.close(); + return 1; + } + infile2.close(); + } + + return 0; +} +int deal::StartThread(THREAD_RUN_TYPE type) +{ + m_bExit = false; + // 只读图线程 + if (type == THREAD_RUN_ALL) + { + + // 开启检测线程 + ptr_DealImgthread = std::make_shared(&deal::DealImg, this); + // 结果处理线程 + // ptr_Resultthread = std::make_shared(&deal::ResultThread, this); + + for (int i = 0; i < Save_IMG_THREAD_NUM; ++i) + { + // 创建线程,并使用 std::make_shared 创建 shared_ptr + std::shared_ptr threadPtr = std::make_shared(&deal::ResultThread, this, i); + // 将 shared_ptr 添加到 vector 中 + ptr_ResultthreadList.push_back(threadPtr); + } + + // 结果拷贝线程 + ptr_GetResultthread = std::make_shared(&deal::GetResultThread, this); + } + + for (int i = 0; i < READ_IMG_THREAD_NUM; ++i) + { + // 创建线程,并使用 std::make_shared 创建 shared_ptr + std::shared_ptr threadPtr = std::make_shared(&deal::ReadImgThread, this, i); + // 将 shared_ptr 添加到 vector 中 + threadArray.push_back(threadPtr); + } + + return 0; +} + +int deal::StopThread() +{ + return 0; +} +int deal::preCheck() +{ + printf(">>> preCheck start \n"); + + std::string strRoot = "../data/img/t1"; + std::string strProductID = "A00000000"; + { + // std::ifstream file(strRoot); + // bool bhave = file.good(); + // printf("t1 = %d \n", bhave); + // if (!bhave) + { + READ_IMG_INFO read; + readTestImg(read); + strRoot = read.strpath; + strProductID = read.strproduct; + printf("strSearchImg strRoot %s\n", strRoot.c_str()); + + std::ifstream file123(strRoot); + bool bhave = file123.good(); + if (!bhave) + { + printf("read img path error %s\n", bhave, strRoot.c_str()); + return 1; + } + } + } + + // 获取图片路径 + + std::string strSearchImg = strRoot; + + Read_Image dfe; + dfe.pimage_ReadChannel = &m_image_ReadChannel; + int re = dfe.Read_Image_List(strSearchImg); + if (re != 0) + { + return re; + } + if (dfe.m_product_Camera_List.size() <= 0) + { + return -1; + } + int idx = 0; + for (int i = 0; i < dfe.m_product_Camera_List.size(); i++) + { + if (dfe.m_product_Camera_List[i]->strProductID == strProductID) + { + idx = i; + break; + } + } + std::shared_ptr product = dfe.m_product_Camera_List[idx]; + + int AllImgNum = product->getImgNum(); + printf("product %s img num %d \n", product->strProductID.c_str(), AllImgNum); + + bool bhaveL255 = true; + for (const auto pcam : product->camera_list) + { + bool b255 = false; + for (const auto pimage : pcam->image_list) + { + printf("came %s channel %s \n", pcam->strCamName.c_str(), pimage->strchannelName.c_str()); + if (pimage->strchannelName == "L255") + { + printf("111 L255 Img \n"); + b255 = true; + break; + } + } + if (!b255) + { + bhaveL255 = false; + break; + } + } + if (!bhaveL255) + { + printf("error --- No L255 Img \n"); + return 1; + } + long t1 = getcurTime(); + // 读图现场都开启 + setReadThreadStart(); + // 遍历所有图片 开始读图处理 + + for (const auto pcam : product->camera_list) + { + + for (const auto pimage : pcam->image_list) + { + std::shared_ptr tem = std::make_shared(); + tem->strCamID = pcam->strCamName; + tem->strchannelName = pimage->strchannelName; + tem->strName = pimage->strName; + tem->strProductID = pimage->strProductID; + tem->strPath = pimage->strPath; + InsertReadImgInfo(tem); + } + } + + // int preDetNum = 10; + // for (int i_det = 0; i_det < preDetNum; i_det++) + { + IN_IMG_Status_ temstatus = IN_IMG_Status_Start; + std::shared_ptr tempDetImageInfo = nullptr; + + int pushImgNum = 0; + long det_time_start = getcurTime(); + int GetImgNum = 0; + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程 + int ThreadIdx = GetReadImgCompleteThreadIdx(); + if (ThreadIdx < 0) + { + continue; + } + std::shared_ptr pDetImageInfo = nullptr; + pDetImageInfo = m_ReadImgThread_Result[ThreadIdx]; + + // 开始送到检测进行处理 + if (pDetImageInfo != nullptr) + { + printf(">>> %s----start \n", pDetImageInfo->strName.c_str()); + tempDetImageInfo = pDetImageInfo; + int re = SendImgToCheck(pDetImageInfo, temstatus); + if (re != 0) + { + continue; + } + } + SetStatus_List(ThreadIdx, Thread_Status_READY); + GetImgNum++; + pushImgNum++; + + if (IN_IMG_Status_Start == temstatus) + { + temstatus = IN_IMG_Status_Other; + } + + // 图是否都读取完了。 + bool bReadCompleted = false; + + if (GetImgNum >= AllImgNum) + { + bReadCompleted = true; + } + + // 退出 + if (bReadCompleted) + { + SendImgToCheck(tempDetImageInfo, IN_IMG_Status_End); + break; + } + } + printf(">>> preCheck push img end total push %d img \n", pushImgNum); + int getresultNum = 0; + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟消费过程 + // 处理结果 + + std::shared_ptr checkResult; + int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult); + printf("Get result %d/%d -- %s nresult=%d\n", getresultNum + 1, pushImgNum, checkResult->in_shareImage->strChannel.c_str(), checkResult->nresult); + saveImg("/home/aidlux/BOE/CELL_ET/testresult/", checkResult); + getresultNum++; + if (getresultNum >= pushImgNum) + { + printf(">>> preCheck all %d results collected \n", getresultNum); + break; + } + } + } + printf(">>> ALL preCheck complete \n"); + return 0; +} + +std::string deal::readTestImg() +{ + std::string strRoot = "../data/img/TestImg.json"; + printf("Reading Img config %s\n", strRoot.c_str()); + Json::CharReaderBuilder builder; + builder["collectComments"] = true; + Json::Value root; + std::string err; + std::ifstream ifs(strRoot); + if (!ifs.is_open()) + { + printf("error:file is open\n"); + return ""; + } + if (!Json::parseFromStream(builder, ifs, &root, &err)) + { + printf("error:parseFromStream\n"); + return ""; + } + std::string imgpath = ""; + imgpath = root["TestImg_Path"].asString(); + + return imgpath; +} + +int deal::readTestImg(READ_IMG_INFO &read) +{ + std::string strRoot = "../data/img/TestImg.json"; + printf("Reading Img config %s\n", strRoot.c_str()); + Json::CharReaderBuilder builder; + builder["collectComments"] = true; + Json::Value root; + std::string err; + std::ifstream ifs(strRoot); + if (!ifs.is_open()) + { + printf("error:file is open\n"); + return 1; + } + if (!Json::parseFromStream(builder, ifs, &root, &err)) + { + printf("error:parseFromStream\n"); + return 1; + } + std::string imgpath = ""; + read.strpath = root["TestImg_Path"].asString(); + read.strproduct = root["ProductID"].asString(); + return 0; +} + +int deal::repeatCheck() +{ + + return 0; +} + +int deal::saveImg(std::string strpath, std::shared_ptr result) +{ + std::string strroot = strpath; + std::string strroot_qx = strpath; + if (result->in_shareImage->imgstr != "") + { + strroot += result->in_shareImage->imgstr; + strroot += "/"; + strroot_qx += result->in_shareImage->imgstr; + strroot_qx += "/"; + } + + if (strpath != "") + { + + strroot_qx += "qx/"; + + if (result->nProductResult != 0) + { + strroot += "NG/"; + } + else + { + strroot += "OK/"; + } + + if (result->in_shareImage->strImgProductID != "") + { + strroot += result->in_shareImage->strImgProductID + "/"; + } + + if (result->nresult != 0) + { + strroot += "NG/"; + } + else + { + if (result->nYS_result != 0) + { + strroot += "OK/YS/"; + } + else + { + strroot += "OK/OK/"; + } + } + } + // printf("result->nresult %d %d \n", result->nresult, result->nYS_result); + // printf("%s\n", strroot.c_str()); + _sysmkdirs_1(strroot); + std::string str_saveName = ""; + // getchar(); + if (result->in_shareImage->strImgProductID != "") + { + strroot += result->in_shareImage->strImgProductID; + str_saveName += result->in_shareImage->strImgProductID; + } + if (result->in_shareImage->camera_Name != "") + { + strroot += "_" + result->in_shareImage->camera_Name; + str_saveName += "_" + result->in_shareImage->camera_Name; + } + if (result->in_shareImage->strChannel != "") + { + strroot += "_" + result->in_shareImage->strChannel; + str_saveName += "_" + result->in_shareImage->strChannel; + } + if (result->in_shareImage->strImgName != "") + { + strroot += "_" + result->in_shareImage->strImgName; + str_saveName += "_" + result->in_shareImage->strImgName; + } + { + std::string strcam = std::to_string(result->in_shareImage->camera_ID); + strroot += "_" + strcam; + str_saveName += "_" + strcam; + } + + writeLog(strroot, result->det_LogList); + WriteJsonString(strroot, result->strResultJson); + // printf("%s \n", strroot.c_str()); + std::string str = strroot + "_RE_Resultimg.png"; + if (!result->resultimg.empty()) + { + cv::imwrite(str, result->resultimg); + } + std::string str123 = strroot + "_RE_CutImg.png"; + if (!result->cutSrcimg.empty()) + { + cv::imwrite(str123, result->cutSrcimg); + } + std::string str123r = strroot + "_RE_CutDrawImg.png"; + if (!result->SrcResultImg.empty()) + { + cv::imwrite(str123r, result->SrcResultImg); + } + std::string strMask = strroot + "_RE_AIMask.png"; + + if (!result->resultMaskImg.empty()) + { + cv::imwrite(strMask, result->resultMaskImg); + } + std::string str_qx; + for (int i = 0; i < result->qxImageResult.size(); i++) + { + std::string str = strroot + "_RE_" + std::to_string(i) + "_Src.png"; + cv::imwrite(str, result->qxImageResult.at(i).srcImg); + str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; + // printf("-1-- %s\n", str_qx.c_str()); + _sysmkdirs_1(str_qx); + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_Src.png"; + // printf("-2-- %s\n", str_qx.c_str()); + cv::imwrite(str_qx, result->qxImageResult.at(i).srcImg); + str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_Small.png"; + cv::imwrite(str_qx, result->qxImageResult.at(i).resizeImg); + + { + str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_AI_In.png"; + if (!result->qxImageResult.at(i).AI_in_Img.empty()) + { + cv::imwrite(str_qx, result->qxImageResult.at(i).AI_in_Img); + } + + str_qx = strroot_qx + result->qxImageResult.at(i).strTypeName + "/"; + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_AI_In_mask.png"; + if (!result->qxImageResult.at(i).AI_out_img.empty()) + { + cv::imwrite(str_qx, result->qxImageResult.at(i).AI_out_img); + } + } + + // printf("-1111-- %s\n", str_qx.c_str()); + std::string str1 = strroot + "_RE_" + std::to_string(i) + "_Small.png"; + cv::imwrite(str1, result->qxImageResult.at(i).resizeImg); + } + for (int i = 0; i < result->YS_ImageResult.size(); i++) + { + std::string str = strroot + "_RE_" + std::to_string(i) + "_YS_Src.png"; + cv::imwrite(str, result->YS_ImageResult.at(i).srcImg); + str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; + // printf("-3-- %s\n", str_qx.c_str()); + _sysmkdirs_1(str_qx); + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_Src.png"; + // printf("-4-- %s\n", str_qx.c_str()); + cv::imwrite(str_qx, result->YS_ImageResult.at(i).srcImg); + str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_Small.png"; + cv::imwrite(str_qx, result->YS_ImageResult.at(i).resizeImg); + { + str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_AI_In.png"; + if (!result->YS_ImageResult.at(i).AI_in_Img.empty()) + { + cv::imwrite(str_qx, result->YS_ImageResult.at(i).AI_in_Img); + } + + str_qx = strroot_qx + result->YS_ImageResult.at(i).strTypeName + "/"; + str_qx += str_saveName + "_RE_" + std::to_string(i) + "_YS_AI_In_mask.png"; + if (!result->YS_ImageResult.at(i).AI_out_img.empty()) + { + cv::imwrite(str_qx, result->YS_ImageResult.at(i).AI_out_img); + } + } + // printf("-1111-- %s\n", str_qx.c_str()); + std::string str1 = strroot + "_RE_" + std::to_string(i) + "_YS_Small.png"; + cv::imwrite(str1, result->YS_ImageResult.at(i).resizeImg); + } + return 0; +} + +int deal::writeLog(std::string strSavePath, std::vector logList) +{ + std::string str = strSavePath + ".txt"; + // 打开文件 + std::ofstream outFile(str); + + // 检查文件是否成功打开 + if (!outFile) + { + std::cerr << "Failed to open file." << std::endl; + return 1; + } + + // 将vector中的内容写入文件 + for (const auto &str : logList) + { + // printf("%s \n",str.c_str()); + outFile << str << std::endl; + } + + // 关闭文件 + outFile.close(); + + return 0; +} + +int deal::WriteJsonString(std::string strSavePath, std::string strjson) +{ + + std::string str = strSavePath + ".json"; + // 打开文件 + std::ofstream outFile(str); + + // 检查文件是否成功打开 + if (!outFile) + { + std::cerr << "Failed to open file." << std::endl; + return 1; + } + + // 将vector中的内容写入文件 + outFile << strjson << std::endl; + + // 关闭文件 + outFile.close(); + return 0; +} + +void deal::ResultThread(int id) +{ + std::vector vi; + int startidx = m_CPUInfo[THREAD_CPU_Main_saveImg].startIdx; + int cpunum = m_CPUInfo[THREAD_CPU_Main_saveImg].num; + // for (int i = 0; i < cpunum; i++) + // { + // vi.push_back(startidx + i); + // } + vi.push_back(startidx + id); + auto nRet = set_cpu_id(vi); + printf("THREAD_CPU_Main_saveImg %d bind cpu ret %d startidx %d num %d\n", id, nRet, startidx + id, 1); + + int re = 0; + cv::Mat detImg; + int kkkkk = 0; + static int saveidx = 0; + while (!m_bExit) + { + std::shared_ptr dealResult; + mutex_Result_list.lock(); + if (m_Result_list.size() > 0) + { + dealResult = m_Result_list.front(); + m_Result_list.pop(); + if (m_Result_list.size() > 10) + { + printf("Result_list size %ld \n", m_Result_list.size()); + } + + mutex_Result_list.unlock(); + } + else + { + mutex_Result_list.unlock(); + usleep(10000); + continue; + } + + { + updataResltInfo(dealResult); + } + + { + if (true) + { + // 存图 + saveImg("/home/aidlux/BOE/ResultImg/", dealResult); + } + + { + // 存 检测统计 日志 + mutex_DetResult_.lock(); + m_DetResult.print(false); + std::string strlog = "/home/aidlux/BOE/ResultImg/"; + if (m_strCurDate != "") + { + strlog += m_strCurDate; + strlog += "/result"; + } + else + { + strlog += "/result"; + } + + writeLog(strlog, m_DetResult.strlist); + mutex_DetResult_.unlock(); + } + } + + usleep(5 * 1000); + } +} +int deal::set_cpu_id(const std::vector &cpu_set_vec) +{ + // for cpu affinity + int nRet = 0; +#ifdef __linux + cpu_set_t _cur_cpu_set; + CPU_ZERO(&_cur_cpu_set); + for (auto _id : cpu_set_vec) + { + CPU_SET(_id, &_cur_cpu_set); + } + if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set)) + { + perror("set cpu affinity failed: "); + printf("Warning: set cpu affinity failed ... ...\n"); + nRet = -1; + } +#endif //__linux + return nRet; +} + +void deal::GetDealResultToQueu() +{ + + // 处理结果 + + std::shared_ptr checkResult; + if (!m_pALLImgCheckAnalysisy) + { + return; + } + + int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult); + + if (re == 0) + { + mutex_Result_list.lock(); + m_Result_list.push(checkResult); + mutex_Result_list.unlock(); + } + else + { + printf("Check error >>>>>>>>>>>>>>>>> \n"); + } + + return; +} +bool deal::ReadSystemConfig(const std::string &strPath) +{ + + printf("Reading system config %s\n", strPath.c_str()); + Json::CharReaderBuilder builder; + builder["collectComments"] = true; + Json::Value root; + std::string err; + std::ifstream ifs(strPath); + if (!ifs.is_open()) + { + printf("error:file is open\n"); + return false; + } + if (!Json::parseFromStream(builder, ifs, &root, &err)) + { + printf("error:parseFromStream\n"); + return false; + } + m_system_param.Use_CPU_StartIdx = root["Use_CPU_StartIdx"].asInt(); + // path + m_system_param.Analysis_Config_path = root["Analysis_Config_path"].asString(); + m_system_param.Analysis_Config_path_Cam2 = root["Analysis_Config_path_Cam2"].asString(); + m_system_param.Check_Config_path = root["Check_Config_path"].asString(); + m_system_param.channel_Config_path = root["channel_Config_path"].asString(); + + m_system_param.preCheckImg_Path = root["preCheckImg_Path"].asString(); + m_system_param.preCHeck_YX = root["preCHeck_YX"].asInt(); + m_system_param.preCHeck_defect = root["preCHeck_defect"].asInt(); + m_nCurUseCPUIDX = m_system_param.Use_CPU_StartIdx; + + return m_system_param.valid(); +} +int deal::GetJcImageInfo(std::string strpath, std::vector &jcImageInfoList) +{ + LoadOfflineCheckImg(strpath); + jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end()); + + // 遍历每一套图片 + for (int idx = 0; idx < m_OffLineCheckImgNameList.size(); idx++) + { + std::string path = m_OffLineCheckImgNameList.at(idx); + JC_IMAGE_INFO_ tem; + int re = GetImgInfo_POL_ET(path, &tem); + } + // getchar(); + return 0; +} +int deal::GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector &jcImageInfoList) +{ + // 1、获取图片路径 + std::vector img_paths; + std::string strs1 = strSearchImg + "/*.tif"; + cv::glob(strs1, img_paths, true); + printf("%d \n", img_paths.size()); + + jcImageInfoList.erase(jcImageInfoList.begin(), jcImageInfoList.end()); + + // 遍历每一套图片 + for (int idx = 0; idx < img_paths.size(); idx++) + { + // printf("---- %d / %d %s----\n", idx, m_OffLineCheckImgNameList.size(), m_OffLineCheckImgNameList.at(idx).c_str()); + + std::string path = img_paths.at(idx); + + JC_IMAGE_INFO_ tem; + int re = 0; + + { + re = GetImgInfo_POL_ET(path, &tem); + if (re != 0) + { + continue; + } + } + tem.strProductID = strProductID; + + jcImageInfoList.push_back(tem); + } + + { + std::vector img_paths; + std::string strs1 = strSearchImg + "/*.png"; + cv::glob(strs1, img_paths, true); + printf("%d \n", img_paths.size()); + + // 遍历每一套图片 + for (int idx = 0; idx < img_paths.size(); idx++) + { + // printf("---- %d / %d %s----\n", idx, m_OffLineCheckImgNameList.size(), m_OffLineCheckImgNameList.at(idx).c_str()); + + std::string path = img_paths.at(idx); + + JC_IMAGE_INFO_ tem; + int re = 0; + + { + re = GetImgInfo_POL_ET_PNG(path, &tem); + if (re != 0) + { + continue; + } + } + tem.strProductID = strProductID; + + jcImageInfoList.push_back(tem); + } + } + + return 0; +} +int deal::GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo) +{ + + if (pImageInfo == NULL) + { + return 1; + } + + string strName = ExtractFileNameWithoutExtension(strImgPath); + printf("strName %s \n", strName.c_str()); + size_t lastUnderscore = strName.rfind('_'); + if (lastUnderscore == std::string::npos) + return 1; // 没有找到最后一个 '_' + + size_t secondLastUnderscore = strName.rfind('_', lastUnderscore - 1); + if (secondLastUnderscore == std::string::npos) + return 1; // 没有找到倒数第二个 '_' + + std::string strImageChannel = strName.substr(secondLastUnderscore + 1, lastUnderscore - secondLastUnderscore - 1); + + printf("strImageChannel %s\n", strImageChannel.c_str()); + std::string strChannle = m_image_ReadChannel.strDetName(strImageChannel); + if (strChannle == "") + { + return 1; + } + + pImageInfo->strchannelName = strChannle; + pImageInfo->strName = strChannle; + pImageInfo->strPath = strImgPath; + pImageInfo->strCamID = "0"; + // printf("strImgPath %s strChannel %s\n", strImgPath.c_str(), strChannle.c_str()); + + // 使用 find 函数检查是否包含 "_左" + if (strImgPath.find("_工位右") != std::string::npos) + { + pImageInfo->strCamID = "1"; + ; + } + + return 0; +} +int deal::GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo) +{ + + if (pImageInfo == NULL) + { + return 1; + } + + string strImageChannel = ExtractFileNameWithoutExtension(strImgPath); + printf("strImageChannel %s\n", strImageChannel.c_str()); + std::string strChannle = m_image_ReadChannel.strDetName(strImageChannel); + if (strChannle == "") + { + return 1; + } + + pImageInfo->strchannelName = strChannle; + pImageInfo->strName = strChannle; + pImageInfo->strPath = strImgPath; + pImageInfo->strCamID = "0"; + // printf("strImgPath %s strChannel %s\n", strImgPath.c_str(), strChannle.c_str()); + + // 使用 find 函数检查是否包含 "_左" + if (strImgPath.find("_工位右") != std::string::npos) + { + pImageInfo->strCamID = "1"; + ; + } + return 0; +} +int deal::ReadTestImgaData() +{ + std::string strPath = "../data/testImg.json"; + printf("ReadTestImgaData config %s\n", strPath.c_str()); + Json::CharReaderBuilder builder; + builder["collectComments"] = true; + Json::Value root; + std::string err; + std::ifstream ifs(strPath); + if (!ifs.is_open()) + { + printf("error:file is open\n"); + return false; + } + if (!Json::parseFromStream(builder, ifs, &root, &err)) + { + printf("error:parseFromStream\n"); + return false; + } + m_TestJC_ImageDate.erase(m_TestJC_ImageDate.begin(), m_TestJC_ImageDate.end()); + { + auto value = root["img_date"]; + if (value.isObject()) + { + auto arr = value["date"]; + std::cout << arr << std::endl; + if (arr.isArray()) + { + + // 遍历数组中的每个元素 + for (int i = 0; i < arr.size(); i++) + { + + // 读取对象中的属性值 + std::string strdata = arr[i].asString(); + m_TestJC_ImageDate.push_back(strdata); + + // 输出属性值 + std::cout << "date: " << strdata << std::endl; + } + } + } + } + // getchar(); + return 0; +} +int deal::InitDetData() +{ + m_read_ImgNum = 0; + return 0; +} +int deal::InsertDetResult(ReadImgInfo tem) +{ + std::lock_guard lock(mtx_List[Mutex_Type_DetResult]); + m_DetResultList.push_back(tem); + + return 0; +} +int deal::GetUpMaskImg(cv::Mat inImg, cv::Rect roi, cv::Mat &maskimg) +{ + // 定义滑动窗口的大小和步长 + int windowWidth = 128; + int windowHeight = 128; + int stepX = 110; // 横向步长 + int stepY = 110; // 纵向步长 + + maskimg = cv::Mat(roi.height, roi.width, CV_8U, cv::Scalar(0)); + int sx = roi.x; + int ex = roi.x + roi.width; + int sy = roi.y; + int ey = roi.y + roi.height; + + cv::Rect detroi; + detroi.width = windowWidth; + detroi.height = windowHeight; + cv::Rect maskroi; + maskroi.width = windowWidth; + maskroi.height = windowHeight; + cv::Mat temmask; + // 遍历图像,使用滑动窗口 + for (int y = sy; y <= ey; y += stepY) + { + detroi.y = y; + if (detroi.y + windowHeight > ey) + { + detroi.y = ey - windowHeight; + } + maskroi.y = detroi.y - sy; + + for (int x = sx; x <= ex; x += stepX) + { + detroi.x = x; + if (detroi.x + windowWidth > ex) + { + detroi.x = ex - windowWidth; + } + maskroi.x = detroi.x - sx; + int thresholdValue = 30; // 初始阈值,OTSU将自动计算 + int maxVal = 255; // 最大值 + double otsuThreshold; + + cv::Scalar mean, stddev; + cv::meanStdDev(inImg(detroi), mean, stddev); + + int varianceImg; + varianceImg = mean[0] + 1 * mean[0]; + if (mean[0] > 100) + { + continue; + } + + // 使用 OTSU 阈值处理 + otsuThreshold = cv::threshold(inImg(detroi), temmask, thresholdValue, maxVal, cv::THRESH_BINARY | cv::THRESH_OTSU); + thresholdValue = otsuThreshold; + + if (thresholdValue < 30) + { + thresholdValue = 30; + } + if (thresholdValue < varianceImg) + { + thresholdValue = varianceImg; + } + + if (thresholdValue > 100) + { + continue; + } + // std::cout << "varianceImg value is: " << varianceImg << std::endl; + // std::cout << "OTSU threshold value is: " << otsuThreshold << std::endl; + // std::cout << "stddev[0] value is: " << stddev[0] << std::endl; + otsuThreshold = cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY); + // cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY + cv::THRESH_OTSU); + // 提取当前窗口 + + // cv::rectangle(inImg, detroi, cv::Scalar(255, 0, 0)); + } + } + // cv::imwrite("inImg1123.png", inImg); + // cv::imwrite("maskimg.png", maskimg); + // getchar(); + return 0; +} +int deal::SendImgToCheck(std::shared_ptr pDetImageInfo, IN_IMG_Status_ status) +{ + + if (pDetImageInfo == nullptr) + { + return -1; + } + if (status == IN_IMG_Status_End) + { + std::shared_ptr tem = std::make_shared(); + tem->strImgProductID = pDetImageInfo->strProductID; + tem->Status = -1; + if (m_nTestAI == 1) + { + tem->otherValue_1 = 181; + } + + if (m_pALLImgCheckAnalysisy) + { + m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem); + } + return 0; + } + + std::shared_ptr tem = std::make_shared(); + + tem->strChannel = pDetImageInfo->strchannelName; + // printf("==================== %s \n", tem->strChannel.c_str()); + + tem->strImgName = pDetImageInfo->strName; + tem->strImgProductID = pDetImageInfo->strProductID; + tem->imgstr = m_strCurDate; + tem->camera_ID = 0; + if (pDetImageInfo->strCamID == "1") + { + tem->camera_ID = 1; + } + + if (m_nTestAI == 1) + { + tem->otherValue_1 = 181; + } + tem->camera_Name = pDetImageInfo->strCamID; + tem->getImgTimeMs = getcurTime(); + tem->readImg_start = pDetImageInfo->readImg_start; + tem->readImg_end = pDetImageInfo->readImg_end; + tem->Status = status; + tem->Det_Mode = DET_MODE_Det; + tem->img = pDetImageInfo->img; + if (m_nSaveDetprocessImg == 1) + { + tem->bsaveProcessImg = true; + } + + int re = 0; + if (m_pALLImgCheckAnalysisy) + { + re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem); + } + + return re; +} +void deal::GetResultThread() +{ + std::vector vi; + vi.push_back(18); + auto nRet = set_cpu_id(vi); + printf("bind cpu ret %d, %d\n", nRet, 18); + int re = 0; + + int nsleep1 = 2 * 1000; + + while (!m_bExit) + { + // 1、拷贝检测结果到队列 + GetDealResultToQueu(); + usleep(nsleep1); + } +} +void deal::ReadImgThread(int id) +{ + std::vector vi; + int startidx = m_CPUInfo[THREAD_CPU_Main_readImg].startIdx; + int cpunum = m_CPUInfo[THREAD_CPU_Main_readImg].num; + // for (int i = 0; i < cpunum; i++) + // { + // vi.push_back(startidx + i); + // } + vi.push_back(startidx + id); + auto nRet = set_cpu_id(vi); + printf("THREAD_CPU_Main_readImg %d bind cpu ret %d startidx %d num %d\n", id, nRet, startidx + id, 1); + + int nsleep1 = 200 * 1000; + int readThreadIdx = id; + while (!m_bExit) + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程 + + // 读图模式 + if (READ_THREAD_TYPE_READIMG == m_nReadThread_type) + { + Thread_ReadImg(readThreadIdx); + } + else if (READ_THREAD_Detect == m_nReadThread_type) + { + // // 取路径线程没有开始, 处理线程也停止。 + // if (IsStatus(Status_Type_PullPath, Thread_Status_IDE)) + // { + // continue; + // } + + // mtx_DetImgQueue.lock(); + // if (m_DetImgQueue.size() <= 0) + // { + // mtx_DetImgQueue.unlock(); + // continue; + // } + // ReadImgInfo tem = m_DetImgQueue.front(); // 获取队首数据 + // m_DetImgQueue.pop(); // 弹出队首数据 + // kkd++; + // if (tem.idx > maxidx) + // { + // maxidx = tem.idx; + // /* code */ + // } + + // mtx_DetImgQueue.unlock(); + // SetStatus_List(id, ReadImg_Status_Read); + // test_ZF(tem, id); + // SetStatus_List(id, ReadImg_Status_COMMPLET); + } + } +} +void deal::testimg(cv::Mat img) +{ +} + +int deal::updataResltInfo(std::shared_ptr result) +{ + + mutex_DetResult_.lock(); + std::string productID = result->in_shareImage->strImgProductID; + std::string imgName = result->in_shareImage->strChannel; + // printf("add productID %s imgName %s %d\n", productID.c_str(), imgName.c_str(), result->nresult); + long t1 = getcurTime(); + m_DetResult.updata(productID, imgName, result->nresult, t1); + for (int i = 0; i < ERROR_TYPE_COUNT; i++) + { + if (result->defectResultList[i].nresult == 1) + { + m_DetResult.update_qx(result->defectResultList[i].keyName, result->defectResultList[i].num); + } + } + mutex_DetResult_.unlock(); + return 0; +} +// 滑动窗口二值化函数 +void deal::slidingWindowAutoThreshold(const cv::Mat &src, cv::Mat &dst, int windowSize, int step, double C) +{ + // 确保窗口大小为奇数 + // if (windowSize % 2 == 0) + // { + // windowSize++; + // } + + // 创建目标图像 + dst = cv::Mat::zeros(src.size(), CV_8UC1); + + // 获取源图像的尺寸 + int rows = src.rows; + int cols = src.cols; + int xs = 0; + int xe = windowSize; + int ys = 0; + int ye = windowSize; + for (int y = ye; y < rows;) + { + int xs = 0; + int xe = windowSize; + for (int x = xe; x < cols;) + { + + cv::Rect roi; + roi.x = xs; + roi.width = windowSize; + roi.y = ys; + roi.height = windowSize; + + cv::Mat window = src(roi); + + // 计算窗口中的平均值和标准差 + cv::Scalar mean, stdDev; + cv::meanStdDev(window, mean, stdDev); + // printf(" x %d %d y %d %d %f %f \n", xs, xe, ys, ye, mean[0], stdDev[0]); + int T = mean[0] + 20 * stdDev[0]; + cv::threshold(window, dst(roi), T, 255, cv::THRESH_BINARY); + + // cv::rectangle(src, roi, cv::Scalar(255, 0, 255)); + if (xe == cols) + { + break; + } + xs = xs + step; + xe = xs + windowSize; + if (xs < cols && xe > cols) + { + xe = cols; + xs = xe - windowSize; + } + } + if (ye == rows) + { + break; + } + ys = ys + step; + ye = ys + windowSize; + if (ys < rows && ye > rows) + { + ye = rows; + ys = ye - windowSize; + } + } + + // // 遍历图像的每个像素 + // for (int i = 0; i < rows; ++i) + // { + // for (int j = 0; j < cols; ++j) + // { + // // 计算窗口边界 + // int startRow = std::max(0, i - windowSize / 2); + // int endRow = std::min(rows - 1, i + windowSize / 2); + // int startCol = std::max(0, j - windowSize / 2); + // int endCol = std::min(cols - 1, j + windowSize / 2); + + // // 提取窗口中的图像块 + // cv::Mat window = src(cv::Range(startRow, endRow + 1), cv::Range(startCol, endCol + 1)); + + // // 计算窗口中的平均值和标准差 + // cv::Scalar mean, stdDev; + // cv::meanStdDev(window, mean, stdDev); + + // // 计算局部阈值 + // double threshold = mean[0] - C * stdDev[0]; + + // // 根据局部阈值进行二值化 + // if (src.at(i, j) >= threshold) + // { + // dst.at(i, j) = 255; + // } + // else + // { + // dst.at(i, j) = 0; + // } + // } + // } +} + +int deal::testimgUP(cv::Mat img) +{ + + cv::Mat dst; + slidingWindowAutoThreshold(img, dst, 200, 180, 10); + cv::imwrite("up_dst.png", dst); + cv::imwrite("up.png", img); + printf("1111\n"); + getchar(); + return 0; +} +int deal::test_ZF(ReadImgInfo tem, int id) +{ + std::string ressss = "**"; + for (int i = 0; i < id; i++) + { + ressss += "*******"; + } + + // printf("%s %d start redimg img idx %d ID %s ch %s tem.imglist %zu\n ", ressss.c_str(), id, tem.idx, tem.strImgSN.c_str(), tem.strChannel.c_str(), tem.imglist.size()); + long t1 = getcurTime(); + cv::Mat L255Img = cv::imread(tem.strPath, 0); + long t2 = getcurTime(); + mtx_DetImgQueue_com.lock(); + m_read_ImgNum++; + + long useTime = t2 - m_readImgStarttime; + // printf("read Img mean time %ld -- m_read_ImgNum %d use time %ld \n", useTime / m_read_ImgNum, m_read_ImgNum, useTime / 1000); + mtx_DetImgQueue_com.unlock(); + printf("---------------------ThreadID %d readimg %d / %d use time %ld %s \n", id, tem.idx, tem.sumNUm, t2 - t1, tem.strPath.c_str()); + // printf("tem.strPath %s *\n", tem.strPath.c_str()); + // printf("%s %d End redimg use time %ld \n ", ressss.c_str(), id, t2 - t1); + cv::Mat mask; + if (L255Img.empty()) + { + printf("error:No L255 Img -------------- \n"); + InsertDetResult(tem); + return 1; + } + tem.status = 1; + int re = 0; + std::shared_ptr result; + // 多线程 互斥 作用域 + // if (false) + { + std::lock_guard lock(mtx_DetImgQueue_edge); + { + + if (tem.strChannel == "L255") + { + std::shared_ptr temdet = std::make_shared(); + if (m_nSaveDetprocessImg == 1) + { + temdet->otherValue = 9; + } + temdet->strImgName = "test"; + temdet->strImgProductID = tem.strImgSN; + temdet->strChannel = tem.strChannel; + + // if (m_nReadThread_type == READ_THREAD_TYPE_EDGE) + { + temdet->Det_Mode = DET_MODE_EDGE; + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + temdet->ninstruct = 999; + } + } + temdet->img = L255Img; + printf(">>>>>>>>>>>m_nReadThread_type %d m_nRunType %d temdet->ninstruct %d >>>>>>>>> ThreadID %d start Check readimg %d / %d ID %s ch %s \n ", m_nReadThread_type, m_nRunType, temdet->ninstruct, id, tem.idx, tem.sumNUm, tem.strImgSN.c_str(), tem.strChannel.c_str()); + m_pALLImgCheckAnalysisy->CheckImg(temdet, result); + // 结果异常 + if (result->nresult != 0) + { + printf("preCheck Img edge error..... %s \n", tem.strPath.c_str()); + InsertDetResult(tem); + return ERROR_PRECHECK_IMG_NULL; + } + + tem.status = 2; + InsertDetResult(tem); + } + } + } + + return 0; +} +int deal::SetStatus(int type, int status) +{ + std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); + m_DetStatusList[type] = status; + + return 0; +} +int deal::GetStatus(int type) +{ + std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); + + return m_DetStatusList[type]; +} +bool deal::IsStatus(int type, int status) +{ + std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); + if (m_DetStatusList[type] == status) + { + return true; + } + + return false; +} +int deal::SetStatus_List(int idx, Thread_Status_ status) +{ + std::lock_guard lock(mtx_List[Mutex_Type_ReadImgThread]); + m_nReadStausList[idx] = status; + return 0; +} +int deal::GetStatus_List(int idx) +{ + std::lock_guard lock(mtx_List[Mutex_Type_ReadImgThread]); + return m_nReadStausList[idx]; +} +bool deal::IsStatus_List(int idx, Thread_Status_ status) +{ + std::lock_guard lock(mtx_List[Mutex_Type_ReadImgThread]); + if (idx < 0 || idx >= READ_IMG_THREAD_NUM) + { + } + else + { + if (m_nReadStausList[idx] == status) + { + return true; + } + } + + return false; +} + +int deal::setReadThreadStart() +{ + for (int i = 0; i < READ_IMG_THREAD_NUM; i++) + { + SetStatus_List(i, Thread_Status_READY); + } + return 0; +} + +int deal::GetReadImgCompleteThreadIdx() +{ + for (int i = 0; i < READ_IMG_THREAD_NUM; i++) + { + if (IsStatus_List(i, Thread_Status_COMMPLET)) + { + return i; + } + } + return -1; +} + +bool deal::IsALLComplete() +{ + std::lock_guard lock(mtx_List[Mutex_Type_DetStatus]); + + for (size_t i = 0; i < READ_IMG_THREAD_NUM; i++) + { + if (m_nReadStausList[i] == ReadImg_Status_COMMPLET) + { + return false; + } + } + return true; +} + +int deal::InitCPUIDX() +{ + int start = 3; + m_CPUInfo[THREAD_CPU_Main_Det].set(start, 4); + start += 4; + m_CPUInfo[THREAD_CPU_Main_readImg].set(start, READ_IMG_THREAD_NUM); + start += READ_IMG_THREAD_NUM; + m_CPUInfo[THREAD_CPU_Main_saveImg].set(start, Save_IMG_THREAD_NUM); + start += Save_IMG_THREAD_NUM; + m_CPUInfo[THREAD_CPU_CheckSo].set(start, 15); + return 0; +} + +void deal::Thread_ReadImg(int id) +{ + if (!IsStatus_List(id, Thread_Status_READY)) + { + return; + } + + int re = 0; + std::shared_ptr pImageInfo = nullptr; + re = GetReadImgInfo(pImageInfo); + if (pImageInfo == nullptr) + { + printf("pImageInfo == nullptr=================id %d=============\n", id); + return; + } + bool read_16Img = true; + + if (true) + { + cv::Mat img16 = cv::imread(pImageInfo->strPath, cv::IMREAD_UNCHANGED); + + if (!img16.empty()) + { + + if (img16.type() != CV_8U) + { + cv::Mat img8; + cv::normalize(img16, img8, 0, 255, cv::NORM_MINMAX); + img8.convertTo(img8, CV_8U); + pImageInfo->img = img8; + } + else if (img16.type() == CV_8U) + { + pImageInfo->img = img16; + } + } + } + else + { + pImageInfo->img = cv::imread(pImageInfo->strPath, 0); + } + + m_ReadImgThread_Result[id] = pImageInfo; + + // 线程完成读图,设置现场状态为 完成 + SetStatus_List(id, Thread_Status_COMMPLET); + + // printf("Thread_ReadImg=================id %d %s=============\n", id, pImageInfo->strPath.c_str()); +} + +int deal::InsertReadImgInfo(std::shared_ptr pImageInfo) +{ + std::lock_guard lock(mutex_ReadImgList); + m_ReadImg_queue.push(pImageInfo); + cv_ReadImgList.notify_one(); // 唤醒等待的线程 + return 0; +} + +int deal::GetReadImgInfo(std::shared_ptr &pImageInfo) +{ + // printf("===============waite img info ===============\n"); + std::unique_lock lock(mutex_ReadImgList); + + cv_ReadImgList.wait(lock, [this]() + { return !m_ReadImg_queue.empty(); }); + + pImageInfo = m_ReadImg_queue.front(); // 获取队首数据 + if (pImageInfo == NULL) + { + return 1; + } + m_ReadImg_queue.pop(); // 弹出队首数据 + return 0; +} + +int deal::LoadOfflineCheckImg(std::string strImgPath) +{ + std::vector img_paths; + cv::glob(strImgPath, img_paths, true); + m_OffLineCheckImgList.erase(m_OffLineCheckImgList.begin(), m_OffLineCheckImgList.end()); + m_OffLineCheckImgNameList.erase(m_OffLineCheckImgNameList.begin(), m_OffLineCheckImgNameList.end()); + for (int i = 0; i < img_paths.size(); i++) + { + + size_t found = img_paths[i].find_last_of("/\\"); + + // std::cout << img_paths[i] << std::endl; + std::string str = img_paths[i]; + m_OffLineCheckImgNameList.push_back(str); + } + return 0; +} +int deal::LoadImgPath_JCSN(std::string strImgPath) +{ + + std::cout << strImgPath << std::endl; + std::vector img_paths; + + cv::glob(strImgPath, img_paths, true); + + m_OffImageSNPathList.erase(m_OffImageSNPathList.begin(), m_OffImageSNPathList.end()); + + for (int i = 0; i < img_paths.size(); i++) + { + + std::string path = img_paths[i]; + // std::cout << img_paths[i] << std::endl; + + // 提取所有文件夹名称 + std::vector allDirectories = extractAllDirectories(path); + std::string strSN = ""; + // 输出所有文件夹名称 + std::string strAllPath = "/"; + + for (const auto &dir : allDirectories) + { + strAllPath += dir; + if (isValidString(dir)) + { + strSN = dir; + // std::cout << strSN << std::endl; + break; + } + strAllPath += "/"; + } + + bool bh = false; + for (int j = 0; j < m_OffImageSNPathList.size(); j++) + { + if (m_OffImageSNPathList.at(j) == strAllPath) + { + bh = true; + break; + } + } + if (!bh) + { + if (m_OffImageSNPathList.size() < m_nTestNum) + { + m_OffImageSNPathList.push_back(strAllPath); + std::cout << strAllPath << std::endl; + } + + // std::cout << strSN << std::endl; + } + } + + return 0; +} + +bool deal::isValidString(const std::string &str) +{ + // 检查字符串长度是否为10 + if (str.length() < 14 || str.length() > 19) + { + return false; + } + + // 检查字符串中的每个字符是否都是字母或数字 + for (char c : str) + { + if (!std::isalnum(c)) + { // 如果字符不是字母或数字 + return false; + } + } + + // 字符串满足条件 + return true; +} +int deal::LoadProductID(std::string strImgPath) +{ + Read_Image dfe; + dfe.pimage_ReadChannel = &m_image_ReadChannel; + dfe.Read_Image_List(strImgPath); + + m_product_Camera_List.clear(); + m_product_Camera_List.assign(dfe.m_product_Camera_List.begin(), dfe.m_product_Camera_List.end()); + + return 0; +} +int deal::DelImg_Cell_ET() +{ + + size_t totalSize = m_product_Camera_List.size(); + if (totalSize > 0) + { + m_DetResult.Init(); + /* code */ + } + + for (size_t idx = 0; idx < totalSize; idx++) + { + printf(">>> %zu / %zu %s----start \n", idx, totalSize, m_product_Camera_List.at(idx)->strProductID.c_str()); + long t1, t2; + t1 = getcurTime(); + Det_OneProduct_Cell_ET(m_product_Camera_List.at(idx), idx); + t2 = getcurTime(); + printf(">>> %zu / %zu %s----End use time %ld\n", idx, totalSize, m_product_Camera_List.at(idx)->strProductID.c_str(), t2 - t1); + } + if (totalSize > 0) + { + // 等待所有检测都完成 + while (true) + { + usleep(1000 * 1000 * 15); + printf("len %zu \n", m_Result_list.size()); + if (m_Result_list.size() <= 0) + { + break; + } + } + } + m_product_Camera_List.erase(m_product_Camera_List.begin(), m_product_Camera_List.end()); + m_product_Camera_List.clear(); + return RESULT_OK; +} +int deal::Det_OneProduct_Cell_ET(std::shared_ptr product, int Idx) +{ + + std::string strProductID = product->strProductID; + + // 获取图片路径 + std::vector detImgInfoList; + + // 没有图片 + + // 读图现场都开启 + setReadThreadStart(); + int AllImgNum = product->getImgNum(); + if (AllImgNum <= 0) + { + return 1; + } + // 遍历所有图片 开始读图处理 + for (const auto pcam : product->camera_list) + { + for (const auto pimage : pcam->image_list) + { + std::shared_ptr tem = std::make_shared(); + tem->strCamID = pcam->strCamName; + tem->strchannelName = pimage->strchannelName; + tem->strName = pimage->strName; + tem->strProductID = pimage->strProductID; + tem->strPath = pimage->strPath; + InsertReadImgInfo(tem); + } + } + + IN_IMG_Status_ temstatus = IN_IMG_Status_Start; + + std::shared_ptr tempDetImageInfo = nullptr; + + Det_One_Result_Info tem_one; + tem_one.Product_ID = strProductID; + tem_one.result = 0; + long ts = getcurTime(); + tem_one.time_s = ts; + + int GetImgNum = 0; + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程 + int ThreadIdx = GetReadImgCompleteThreadIdx(); + if (ThreadIdx < 0) + { + continue; + } + std::shared_ptr pDetImageInfo = nullptr; + pDetImageInfo = m_ReadImgThread_Result[ThreadIdx]; + + // 开始送到检测进行处理 + if (pDetImageInfo != nullptr) + { + // printf(">>> %s----start \n", pDetImageInfo->strName.c_str()); + tempDetImageInfo = pDetImageInfo; + int re = SendImgToCheck(pDetImageInfo, temstatus); + if (re != 0) + { + continue; + } + Det_single_img_Result_Info tem_single; + tem_single.name = pDetImageInfo->strchannelName; + tem_single.result = -1; + tem_one.img_result_list.push_back(tem_single); + } + SetStatus_List(ThreadIdx, Thread_Status_READY); + GetImgNum++; + + if (IN_IMG_Status_Start == temstatus) + { + temstatus = IN_IMG_Status_Other; + } + + // 图是否都读取完了。 + bool bReadCompleted = false; + + if (GetImgNum >= AllImgNum) + { + bReadCompleted = true; + } + + // 退出 + if (bReadCompleted) + { + SendImgToCheck(tempDetImageInfo, IN_IMG_Status_End); + break; + } + } + + m_DetResult.one_result_list.push_back(tem_one); + m_DetResult.det_num_all++; + if (m_DetResult.det_num_all == 1) + { + m_DetResult.startTime_S = getcurTime(); + } + // printf("startTime_S==== %ld \n", m_DetResult.startTime_S); + // getchar(); + return 0; +} +int deal::Det_Edge_Test_OneImg() +{ + + int imgNum = 0; + std::string strchannel = "L255"; + std::string str = m_strCheckFilePath + "/*" + strchannel + ".tif"; + { + std::cout << str << std::endl; + m_OffImageSNPathList.erase(m_OffImageSNPathList.begin(), m_OffImageSNPathList.end()); + + cv::glob(str, m_OffImageSNPathList, true); + } + + imgNum = m_OffImageSNPathList.size(); + if (imgNum > m_nTestNum && m_nTestNum > 0) + { + imgNum = m_nTestNum; + } + + printf("Img Num %d \n", imgNum); + if (imgNum <= 0) + { + return 0; + } + + for (int i = 0; i < m_OffImageSNPathList.size(); i++) + { + printf(">>> %d / %zu --start \n", i, m_OffImageSNPathList.size()); + long t1, t2; + cv::Mat detimg = cv::imread(m_OffImageSNPathList.at(i)); + { + std::shared_ptr result; + + std::shared_ptr temdet = std::make_shared(); + if (m_nSaveDetprocessImg == 1) + { + temdet->otherValue = 9; + } + temdet->strImgName = "test"; + temdet->strImgProductID = "test"; + temdet->strChannel = "L255"; + + if (m_nRunType == RUNTYPE_RUN_Align) + { + temdet->ninstruct = 898; + } + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_TEST || + m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + temdet->Det_Mode = DET_MODE_EDGE; + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + temdet->ninstruct = 999; + } + } + + temdet->img = detimg; + + m_pALLImgCheckAnalysisy->CheckImg(temdet, result); + // 结果异常 + } + } + + return 0; +} +int deal::Det_Funtion_Test() +{ + int re = 0; + + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_TEST || + m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + + Det_Funtion_Edge(); + return 0; + } + if (m_nRunType == RUNTYPE_RUN_File_MarkLine_Test) + { + Det_Funtion_MarkLine(); + return 0; + } + + // 获取图片 + + return 0; +} +int deal::Det_Funtion_Edge() +{ + + int imgNum = 0; + std::string strchannel = "L127"; + std::string str = m_strCheckFilePath + "/*" + strchannel + ".tif"; + + if (m_check_Work_Type == Check_Work_POL_ET) + { + str = m_strCheckFilePath + "/*" + strchannel + ".tif"; + // str = m_strCheckFilePath + "/*" + strchannel + "_Org.tif"; + strchannel = "L255"; + } + + { + std::cout << str << std::endl; + m_OffImageSNPathList.erase(m_OffImageSNPathList.begin(), m_OffImageSNPathList.end()); + + cv::glob(str, m_OffImageSNPathList, true); + } + + imgNum = m_OffImageSNPathList.size(); + if (imgNum > m_nTestNum && m_nTestNum > 0) + { + imgNum = m_nTestNum; + } + printf("Img Num %d \n", imgNum); + if (imgNum <= 0) + { + return 0; + } + + // 读图现场都开启 + setReadThreadStart(); + int AllImgNum = imgNum; + + // 遍历所有图片 开始读图处理 + for (int i = 0; i < imgNum; i++) + { + std::shared_ptr tem = std::make_shared(); + tem->strPath = m_OffImageSNPathList.at(i); + tem->strchannelName = strchannel; + InsertReadImgInfo(tem); + } + int GetImgNum = 0; + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程 + int ThreadIdx = GetReadImgCompleteThreadIdx(); + if (ThreadIdx < 0) + { + continue; + } + + std::shared_ptr pDetImageInfo = nullptr; + pDetImageInfo = m_ReadImgThread_Result[ThreadIdx]; + + SetStatus_List(ThreadIdx, Thread_Status_READY); + GetImgNum++; + + // 开始送到检测进行处理 + if (pDetImageInfo == nullptr) + { + continue; + } + // printf("GetImgNum:111111111111111 %d\n", GetImgNum); + { + std::shared_ptr result; + + std::shared_ptr temdet = std::make_shared(); + if (m_nSaveDetprocessImg == 1) + { + temdet->otherValue = 9; + } + temdet->strImgName = "test"; + temdet->strImgProductID = "test"; + temdet->strChannel = strchannel; + + if (m_nRunType == RUNTYPE_RUN_Align) + { + temdet->ninstruct = 898; + } + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_TEST || + m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + temdet->Det_Mode = DET_MODE_EDGE; + if (m_nRunType == RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST) + { + temdet->ninstruct = 999; + } + } + + temdet->img = pDetImageInfo->img; + + m_pALLImgCheckAnalysisy->CheckImg(temdet, result); + // 结果异常 + } + + // 图是否都读取完了。 + if (GetImgNum >= AllImgNum) + { + break; + } + } + + return 0; +} +int deal::Det_Funtion_MarkLine() +{ + int imgNum = 0; + std::string strchannel = "L255"; + std::string str = m_strCheckFilePath + "/*" + strchannel + ".tif"; + + LoadSingleImgList(m_strCheckFilePath, strchannel, m_OffImageSNPathList); + + { + for (int i = 0; i < m_OffImageSNPathList.size(); i++) + { + printf(" %d/ %d %s \n", i, m_OffImageSNPathList.size(), m_OffImageSNPathList.at(i).c_str()); + } + // return 0 ; + } + + imgNum = m_OffImageSNPathList.size(); + if (imgNum > m_nTestNum && m_nTestNum > 0) + { + imgNum = m_nTestNum; + } + printf("Img Num %d \n", imgNum); + if (imgNum <= 0) + { + return 0; + } + + // 读图现场都开启 + setReadThreadStart(); + int AllImgNum = imgNum; + + // 遍历所有图片 开始读图处理 + for (int i = 0; i < imgNum; i++) + { + std::shared_ptr tem = std::make_shared(); + tem->strPath = m_OffImageSNPathList.at(i); + tem->strchannelName = strchannel; + InsertReadImgInfo(tem); + } + int GetImgNum = 0; + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费过程 + int ThreadIdx = GetReadImgCompleteThreadIdx(); + if (ThreadIdx < 0) + { + continue; + } + + std::shared_ptr pDetImageInfo = nullptr; + pDetImageInfo = m_ReadImgThread_Result[ThreadIdx]; + + SetStatus_List(ThreadIdx, Thread_Status_READY); + GetImgNum++; + + // 开始送到检测进行处理 + if (pDetImageInfo == nullptr) + { + continue; + } + + // if (GetImgNum < 95) + // { + // continue; + // /* code */ + // } + + // printf("GetImgNum:111111111111111 %d\n", GetImgNum); + { + std::shared_ptr result; + + std::shared_ptr temdet = std::make_shared(); + if (m_nSaveDetprocessImg == 1) + { + temdet->otherValue = 9; + } + temdet->strImgName = "test"; + temdet->strImgProductID = "test"; + temdet->strChannel = strchannel; + + temdet->Det_Mode = DET_MODE_MarkLine; + + temdet->img = pDetImageInfo->img; + + printf(" %d/ %d %s \n", GetImgNum, m_OffImageSNPathList.size(), pDetImageInfo->strPath.c_str()); + m_pALLImgCheckAnalysisy->CheckImg(temdet, result); + + // 结果异常 + } + + // 图是否都读取完了。 + if (GetImgNum >= AllImgNum) + { + break; + } + } + + return 0; + return 0; +} +int deal::LoadSingleImgList(std::string strSearchPath, std::string strChannle, std::vector &imgList) +{ + // POL ET + + imgList.erase(imgList.begin(), imgList.end()); + imgList.clear(); + + // tif 格式 + { + std::string str_tif = strSearchPath + "/*" + strChannle + "_Org.tif"; + std::cout << str_tif << std::endl; + + cv::glob(str_tif, imgList, true); + } + + // png 格式 + { + + std::string str_png = strSearchPath + "/*" + strChannle + ".png"; + std::cout << str_png << std::endl; + std::vector img_paths123; + cv::glob(str_png, img_paths123, true); + for (int i = 0; i < img_paths123.size(); i++) + { + + std::string path = img_paths123[i]; + + if (path.find("OriginalImage_out") != std::string::npos) + { + continue; + } + if (path.find("OriginalImage") != std::string::npos) + { + // std::cout << "路径包含 'OriginalImage'" << std::endl; + } + else + { + continue; + } + imgList.push_back(path); + } + } + + return 0; +} +int deal::RandDrawImg(cv::Mat srcimg, cv::Mat &randErrorImg) +{ + + randErrorImg = srcimg.clone(); + cv::Rect roi; + roi.x = (rand() % (srcimg.cols - 20 - 20)) + 20; + roi.y = (rand() % (srcimg.rows - 20 - 20)) + 20; + roi.width = (rand() % (100 - 5)) + 5; + roi.height = roi.width; + + if (roi.x + roi.width >= srcimg.cols) + { + roi.x = srcimg.cols - roi.width - 1; + /* code */ + } + if (roi.y + roi.height >= srcimg.rows) + { + roi.y = srcimg.rows - roi.height - 1; + /* code */ + } + randErrorImg(roi).setTo(30); + return 0; +} +void deal::DealImg() +{ + // 线程送图处理: + std::vector vi; + int startidx = m_CPUInfo[THREAD_CPU_Main_Det].startIdx; + int cpunum = m_CPUInfo[THREAD_CPU_Main_Det].num; + for (int i = 0; i < cpunum; i++) + { + vi.push_back(startidx + i); + } + auto nRet = set_cpu_id(vi); + printf("THREAD_CPU_Main_Det bind cpu ret %d startidx %d num %d\n", nRet, startidx, cpunum); + int re = 0; + while (!m_bExit) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟消费过程 + re = DelImg_Cell_ET(); + } +} +// 提取所有文件夹名称函数 +std::vector deal::extractAllDirectories(const std::string &path) +{ + std::vector directories; + std::string directory; + + // 遍历路径中的每个字符 + for (char c : path) + { + // 如果遇到路径分隔符,则将当前文件夹名称存储起来 + if (c == '/' || c == '\\') + { + if (!directory.empty()) + { // 确保文件夹名称不为空 + directories.push_back(directory); + directory.clear(); // 清空当前文件夹名称 + } + } + else + { + directory += c; // 将字符添加到当前文件夹名称中 + } + } + + // 将最后一个文件夹名称添加到列表中 + if (!directory.empty()) + { + directories.push_back(directory); + } + + return directories; +} \ No newline at end of file diff --git a/AlgorithmModule/example/deal.h b/AlgorithmModule/example/deal.h new file mode 100644 index 0000000..0ac6b54 --- /dev/null +++ b/AlgorithmModule/example/deal.h @@ -0,0 +1,704 @@ + +#ifndef _deal_HPP_ +#define _deal_HPP_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ImgBasicDeal.h" +#include "SystemCommonDefine.h" +#include "ImgCheckBase.h" +#include "ImgCheckConfig.h" +#include "ImgBasicDeal.h" +#include "ConfigBase.h" +#include +#include +#include +#include "Image_ReadAndChange.h" + +#include + +#include "Read_Image.h" + +namespace fs = std::filesystem; + +enum Thread_Status_ +{ + Thread_Status_IDE, + Thread_Status_READY, + Thread_Status_BUSY, + Thread_Status_COMMPLET, +}; +enum Thread_ReadImg_Status_ +{ + ReadImg_Status_IDE, + ReadImg_Status_Read, + ReadImg_Status_COMMPLET, +}; + +// 各种线程处理状态信息 +enum DET_Status_Type_ +{ + Status_Type_ReadAndDet, // 读取图和处理 + Status_Type_PullPath, // 读取图片路径 + Status_Type_Count, +}; + +enum Mutex_Type_ +{ + Mutex_Type_ReadImgThread, // 读图线程 + Mutex_Type_DetStatus, + Mutex_Type_DetResult, + Mutex_Type_Count, +}; +// 读线程,处理类型。 +enum READ_THREAD_TYPE_ +{ + READ_THREAD_TYPE_NULL, + READ_THREAD_TYPE_READIMG, // 读图 + READ_THREAD_Detect, // 检测模式 + READ_THREAD_TYPE_COUNT, +}; + +// 线程运行模式 +enum THREAD_RUN_TYPE +{ + THREAD_RUN_Only_ReadImg, // 仅读图 + THREAD_RUN_ALL, // 所有 +}; + +#define READ_IMG_THREAD_NUM 12 +#define Save_IMG_THREAD_NUM 5 + +using namespace std; +enum RUNTYPE_ +{ + RUNTYPE_RUN_Pre_BigImg, + RUNTYPE_RUN_Pre_BigImg_Cam2, + RUNTYPE_RUN_File_BigImg, + RUNTYPE_RUN_File_CEEL_ET, + RUNTYPE_RUN_File_BigImg_WHJC_Date, + RUNTYPE_RUN_File_BigImg_WHJC_EDGE_TEST, + RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST, + RUNTYPE_RUN_Ong_BigImg_WHJC_EDGE_TEST, + RUNTYPE_RUN_File_BigImg_WHJC_ZF_TEST, + RUNTYPE_RUN_File_MarkLine_Test, + RUNTYPE_RUN_Align, +}; + +struct JC_IMAGE_INFO_ +{ + enum Status_ + { + STATUS_Image_IDE, + STATUS_Image_READ, + STATUS_Image_COMMPLET, + STATUS_Det_Start, + }; + std::string strProductID; // 产品ID + std::string strCamID; // 相机名称 + std::string strchannelName; // 通道名称 + std::string strPath; // 完整路径 + std::string strName; // 图片名称 + cv::Mat img; // 图像数据 + Status_ status; // 状态 + long readImg_start; // 读取开始时间 + long readImg_end; // 读取结束时间 + + // 构造函数,调用 Init 初始化 + JC_IMAGE_INFO_() + { + Init(); + } + + // 初始化函数,重置所有成员变量 + void Init() + { + strProductID = ""; + strCamID = ""; + strchannelName = ""; + strPath = ""; + strName = ""; + img.release(); // 释放图像内存 + status = STATUS_Image_IDE; + readImg_start = 0; + readImg_end = 0; + } + + // 拷贝函数,将传入的结构体内容复制到当前对象 + void copy(JC_IMAGE_INFO_ tem) + { + this->strProductID = tem.strProductID; + this->strCamID = tem.strCamID; + this->strchannelName = tem.strchannelName; + this->strPath = tem.strPath; + this->strName = tem.strName; + if (!tem.img.empty()) + { + this->img = tem.img.clone(); // 深拷贝图像数据 + } + this->status = tem.status; + this->readImg_start = tem.readImg_start; + this->readImg_end = tem.readImg_end; + } + + // 打印信息函数(可选) + void print() + { + std::cout << "Product ID: " << strProductID << std::endl; + std::cout << "Camera ID: " << strCamID << std::endl; + std::cout << "Channel Name: " << strchannelName << std::endl; + std::cout << "Image Path: " << strPath << std::endl; + std::cout << "Image Name: " << strName << std::endl; + std::cout << "Status: " << status << std::endl; + std::cout << "Read Start Time: " << readImg_start << std::endl; + std::cout << "Read End Time: " << readImg_end << std::endl; + } +}; +struct Det_single_img_Result_Info +{ + int result; + std::string name; + std::string qx_name; + Det_single_img_Result_Info() + { + Init(); + } + void Init() + { + name = ""; + result = 0; + qx_name = "NO"; + } +}; +struct Det_One_Result_Info +{ + int result; + long time_s; + long time_e; + std::string Product_ID; + std::vector img_result_list; + Det_One_Result_Info() + { + Init(); + } + void Init() + { + Product_ID = ""; + time_s = 0; + time_e = 0; + result = 0; + img_result_list.erase(img_result_list.begin(), img_result_list.end()); + img_result_list.clear(); + } + std::string print() + { + std::string str = ""; + // printf("%s:result %d | ", Product_ID.c_str(), result); + char buffer[64]; + sprintf(buffer, "%s:result %d time %ld | ", Product_ID.c_str(), result, time_e - time_s); + std::string st1 = buffer; + str += st1; + for (size_t i = 0; i < img_result_list.size(); i++) + { + str += img_result_list.at(i).name + " " + img_result_list.at(i).qx_name + " | "; + } + // str += str; + + return str; + // printf("%s\n", str.c_str()); + } +}; +struct Det_File_qx_Info +{ + std::string qx_name; + int num; + Det_File_qx_Info() + { + Init(); + } + void Init() + { + qx_name = ""; + num = 0; + } +}; +// 套图检测 统计结果信息 +struct Det_File_Result_Info +{ + int det_num_all; + int det_num_ok; + int det_num_ng; + int det_num_error; + float sumtime_S; + long startTime_S; + float mean_time; + std::vector one_result_list; + std::vector strlist; + std::vector qx_result_list; + Det_File_Result_Info() + { + Init(); + } + void Init() + { + det_num_all = 0; + det_num_ok = 0; + det_num_ng = 0; + det_num_error = 0; + sumtime_S = 0; + startTime_S = 0; + mean_time = 0; + one_result_list.erase(one_result_list.begin(), one_result_list.end()); + one_result_list.clear(); + strlist.erase(strlist.begin(), strlist.end()); + strlist.clear(); + qx_result_list.erase(qx_result_list.begin(), qx_result_list.end()); + qx_result_list.clear(); + } + void updata(std::string productid, std::string imgname, int nresult, long t) + { + sumtime_S = t - startTime_S; + sumtime_S /= 1000; + if (det_num_all > 0) + { + mean_time = sumtime_S / det_num_all; + } + + for (int i = 0; i < one_result_list.size(); i++) + { + if (one_result_list.at(i).Product_ID == productid) + { + // if (one_result_list.at(i).result < 0) + // { + // one_result_list.at(i).result = 0; + // } + one_result_list.at(i).time_e = t; + + for (size_t j = 0; j < one_result_list.at(i).img_result_list.size(); j++) + { + if (one_result_list.at(i).img_result_list.at(j).name == imgname) + { + one_result_list.at(i).img_result_list.at(j).result = nresult; + if (nresult == 0) + { + one_result_list.at(i).img_result_list.at(j).qx_name = "OK"; + } + else if (nresult > 0) + { + one_result_list.at(i).img_result_list.at(j).qx_name = "NG"; + if (one_result_list.at(i).result == 0) + { + one_result_list.at(i).result = 1; + } + } + else + { + one_result_list.at(i).img_result_list.at(j).qx_name = "ER"; + one_result_list.at(i).result = -1; + } + } + } + } + } + } + void update_qx(std::string qx_name, int num) + { + for (int i = 0; i < qx_result_list.size(); i++) + { + if (qx_result_list.at(i).qx_name == qx_name) + { + qx_result_list.at(i).num += num; + return; + } + } + Det_File_qx_Info tem; + tem.qx_name = qx_name; + tem.num = num; + qx_result_list.push_back(tem); + } + void print(bool show = true) + { + + strlist.erase(strlist.begin(), strlist.end()); + strlist.clear(); + det_num_ok = 0; + det_num_ng = 0; + det_num_error = 0; + std::string str = ""; + str = "*****************************************************************************"; + strlist.push_back(str); + + str = "*****************************detect result***********************************"; + strlist.push_back(str); + + float fok = 0; + float fng = 0; + float ferror = 0; + // printf("one_result_list.size() %d \n", one_result_list.size()); + for (int i = 0; i < one_result_list.size(); i++) + { + if (one_result_list.at(i).result == 0) + { + det_num_ok++; + } + else if (one_result_list.at(i).result > 0) + { + det_num_ng++; + } + else + { + det_num_error++; + } + } + if (det_num_all > 0) + { + fok = det_num_ok * 1.0f / det_num_all * 100; + fng = det_num_ng * 1.0f / det_num_all * 100; + ferror = det_num_error * 1.0f / det_num_all * 100; + } + char buffer[64]; + sprintf(buffer, "ALL:%d OK:%d %.1f%% NG:%d %.1f%% Error:%d %.1f%%", det_num_all, det_num_ok, fok, det_num_ng, fng, det_num_error, ferror); + std::string st1 = buffer; + strlist.push_back(st1); + sprintf(buffer, "Use time %f s mean time %f s", sumtime_S, mean_time); + std::string st2 = buffer; + + strlist.push_back(st2); + // printf("%s\n", st1.c_str()); + // printf("------------------------------------------------------------------------------\n"); + str = "------------------------------------------------------------------------------"; + strlist.push_back(str); + + { + int qx_all_num = 0; + for (size_t i = 0; i < qx_result_list.size(); i++) + { + qx_all_num += qx_result_list.at(i).num; + } + for (size_t i = 0; i < qx_result_list.size(); i++) + { + float fr = qx_result_list.at(i).num * 1.0 / qx_all_num * 100; + std::string str_qx = ""; + // printf("len %d \n", qx_result_list.at(i).qx_name.length()); + for (int k = 0; k < (20 - qx_result_list.at(i).qx_name.length()); k++) + { + str_qx += " "; + } + str_qx += qx_result_list.at(i).qx_name; + char buffer123[64]; + sprintf(buffer123, ":%d %.1f%% ", qx_result_list.at(i).num, fr); + std::string st1 = buffer123; + str_qx += st1; + int nlen = fr; + + for (int j = 0; j < nlen; j++) + { + str_qx += "|"; + } + strlist.push_back(str_qx); + } + } + + str = "------------------------------------------------------------------------------"; + strlist.push_back(str); + + for (int i = 0; i < one_result_list.size(); i++) + { + st1 = one_result_list.at(i).print(); + strlist.push_back(st1); + } + str = "*****************************************************************************"; + strlist.push_back(str); + // printf("*****************************************************************************\n"); + if (show) + { + for (size_t i = 0; i < strlist.size(); i++) + { + printf("%s\n", strlist.at(i).c_str()); + } + } + } +}; +struct IMG_BASE_INFO_ +{ + std::string strPath; + std::string strChannel; + std::string strImgSN; + IMG_BASE_INFO_() + { + strPath = ""; + strImgSN = ""; + strChannel = ""; + } +}; +struct ReadImgInfo +{ + std::string strPath; + std::string strChannel; + int stype; + int status; + std::string strImgSN; + int idx; + int sumNUm; + cv::Rect cutRoi; + std::vector imglist; + ReadImgInfo() + { + strPath = ""; + strImgSN = ""; + stype = 0; + status = 0; + idx = 0; + imglist.clear(); + cutRoi = cv::Rect(0, 0, 0, 0); + sumNUm = 0; + } +}; + +struct AI_Det_Path +{ + std::string strPath_CutImg; + std::string strPath_AIMask; + /* data */ +}; +struct AI_Det_Channel_ +{ + std::string strChannel; + AI_Det_Path path; + /* data */ +}; +struct Json_Det_Path +{ + std::string strPath_CutImg; + std::string strPath_Json; + /* data */ +}; +struct READ_IMG_INFO +{ + std::string strpath= ""; + std::string strproduct = ""; +}; +class deal +{ +public: + // 构造函数 + deal(); + ~deal(); + int start(); + +private: + // 检测参数 + int LoadCheckImgConfig(); + + // 初始化检测分析线程类 + int InitCheckAnalysisy(); + int InitConfig(); + // 初始化 检查存图路径 + int InitSaveImgPath(); + + int LoadCheckConfig(); + // 分析参数 + int LoadAnalysisConfig(); + // 开启线程 + int StartThread(THREAD_RUN_TYPE type); + // 停止线程 + int StopThread(); + + int preCheck(); + std::string readTestImg(); + int readTestImg(READ_IMG_INFO& read); + // 重复检测 + int repeatCheck(); + int saveImg(std::string strpath, std::shared_ptr result); + int writeLog(std::string strSavePath, std::vector logList); + int WriteJsonString(std::string strSavePath, std::string strjson); + + int DelImg_Cell_ET(); + int Det_OneProduct_Cell_ET(std::shared_ptr product, int Idx); + + // 获取图片路径 + int GetDetImageInfo(std::string strProductID, std::string strSearchImg, std::vector &jcImageInfoList); + // 解析图片的信息 -- cell et + int GetImgInfo_POL_ET(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo); + + int GetImgInfo_POL_ET_PNG(std::string strImgPath, JC_IMAGE_INFO_ *pImageInfo); + + int Det_Edge_Test_OneImg(); + + // 功能测试 + int Det_Funtion_Test(); + // 边缘测试 + int Det_Funtion_Edge(); + + // 测试mark线 + int Det_Funtion_MarkLine(); + + int LoadSingleImgList(std::string strSearchPath, std::string strChannle, std::vector &imgList); + + // 随机绘制错误 + int RandDrawImg(cv::Mat srcimg, cv::Mat &randErrorImg); + + int LoadOfflineCheckImg(std::string strImgPath); + int LoadImgPath_JCSN(std::string strImgPath); + bool isValidString(const std::string &str); + + int LoadProductID(std::string strImgPath); + + int set_cpu_id(const std::vector &cpu_set_vec); + void GetDealResultToQueu(); + // 加载系统配置文件 + bool ReadSystemConfig(const std::string &strPath); + int GetJcImageInfo(std::string strpath, std::vector &jcImageInfoList); + + int ReadTestImgaData(); + // 处理前,初始化部分数据 + int InitDetData(); + // 检测结果 插入结果队列 + int InsertDetResult(ReadImgInfo tem); + int GetUpMaskImg(cv::Mat inImg, cv::Rect roi, cv::Mat &maskimg); + + // 送图去检测 + int SendImgToCheck(std::shared_ptr pDetImageInfo, IN_IMG_Status_ status); + +private: + // 处理调度线程 + std::shared_ptr ptr_DealImgthread; + + void DealImg(); + + std::vector extractAllDirectories(const std::string &path); + + // 结果处理线程 + // std::shared_ptr ptr_Resultthread; + std::vector> ptr_ResultthreadList; + void ResultThread(int id); + + // 结果拷贝线程 + std::shared_ptr ptr_GetResultthread; + + void GetResultThread(); + + std::vector> threadArray; + + void ReadImgThread(int id); + + void testimg(cv::Mat img); + + int updataResltInfo(std::shared_ptr result); + + void slidingWindowAutoThreshold(const cv::Mat &src, cv::Mat &dst, int windowSize, int step, double C); + + int testimgUP(cv::Mat img); + int test_ZF(ReadImgInfo tem, int id); + int SetStatus(int type, int status); + int GetStatus(int type); + bool IsStatus(int type, int status); + + int SetStatus_List(int idx, Thread_Status_ status); + int GetStatus_List(int idx); + bool IsStatus_List(int idx, Thread_Status_ status); + int setReadThreadStart(); + int GetReadImgCompleteThreadIdx(); // 获取读取完成后的idx + bool IsALLComplete(); + int InitCPUIDX(); + + // 线程读图 + void Thread_ReadImg(int id); + + int InsertReadImgInfo(std::shared_ptr pImageInfo); + int GetReadImgInfo(std::shared_ptr &pImageInfo); + +public: + std::vector m_OffLineCheckImgList; // 离线检测图片列表 + std::vector m_OffLineCheckImgNameList; // 离线检测图片列表 + std::vector m_OffImageSNPathList; // 离线检测图片列表 + // std::vector m_product_ID_List; // 离线检测图片列表 + + vector> m_product_Camera_List; // 产品相机列表 + + ALLImgCheckBase *m_pALLImgCheckAnalysisy; + // ALLImgCheckBase *m_pResultJsonCheckAnalysisy; + // ImgCheckAnalysisy m_ImgCheckAnalysisy[IMGCHECKANALYSISY_NUM]; + + std::vector m_TestJC_ImageDate; // 离线检测图片列表 + std::string m_strCurDate; + int m_nSystemCheckType; + bool m_bExit; + int nLastCheckAnalysisyThreadIdx; + + RunInfoST m_RunConfig; // 检测基本参数 + + ImgBasicDeal m_imgBasicDeal; + + std::mutex mutex_Result_list; + std::queue> m_Result_list; + + // 检测区域list + std::vector m_DetRoiMaskPointList; + // 检测区域list + std::vector m_CoreMaskPointList; + + int m_nTestAI; + int m_nRunType; + int m_nTestNum; + std::string m_strCheckFilePath; + std::string m_strSaveImgPath; + + ConfigBase *m_pConfig; + ConfigBase *m_pConfig_Cam2; + SystemConfigParam m_system_param; + int m_nCurUseCPUIDX; + int m_nCamIdx; + ImageInfo m_ImgInfo_src; + ImageInfo m_ImgInfo_result; + + int m_nSaveDetprocessImg; + cv::Rect m_CutRoi; + + int nn; + int nddd; + int kkd; + int maxidx; + + Det_File_Result_Info m_DetResult; + std::vector m_ImageInfoList; + + std::queue> m_ReadImg_queue; // 读图队列 + + std::mutex mutex_ReadImgList; + std::condition_variable cv_ReadImgList; + + int m_nReadStausList[READ_IMG_THREAD_NUM]; + // 读图线程状态 + std::shared_ptr m_ReadImgThread_Result[READ_IMG_THREAD_NUM]; + + READ_THREAD_TYPE_ m_nReadThread_type; + bool m_nreadImg_Stop; + std::mutex mutex_DetResult_; + + std::queue m_DetImgQueue; // 存储生产者生产的数据 + std::mutex mtx_DetImgQueue; // 互斥量,保护共享资源 + std::mutex mtx_DetImgQueue_edge; // 互斥量,保护共享资源 + std::condition_variable cv; // 条件变量,用于线程间通信 + + std::mutex mtx_DetImgQueue_com; // + int m_read_ImgNum; + long m_readImgStarttime; + + int m_DetStatusList[Status_Type_Count]; // 各种需要线程同步的状态信息 + std::mutex mtx_List[Mutex_Type_Count]; // 互斥量 + std::vector m_DetResultList; + + CPU_ID_INFO_ m_CPUInfo[THREAD_CPU_Count]; + + Check_Work_Type m_check_Work_Type; // 系统运行模式 + Image_ReadChannel m_image_ReadChannel; +}; + +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/example/json/json-forwards.h b/AlgorithmModule/example/json/json-forwards.h new file mode 100644 index 0000000..45d2e46 --- /dev/null +++ b/AlgorithmModule/example/json/json-forwards.h @@ -0,0 +1,346 @@ +/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json-forwards.h" +/// This header provides forward declaration for all JsonCpp types. + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and +The JsonCpp Authors, and is released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED +# define JSON_FORWARD_AMALGAMATED_H_INCLUDED +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED +#include +#include //typedef int64_t, uint64_t +#include //typedef String + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgamated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) // MSVC +#if _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // MSVC 6 + +#if _MSC_VER >= 1500 // MSVC 2008 + /// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#endif // defined(_MSC_VER) + +// In c++11 the override keyword allows you to explicitly define that a function +// is intended to override the base-class version. This makes the code more +// manageable and fixes a set of common hard-to-find bugs. +#if __cplusplus >= 201103L +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT throw() +#if _MSC_VER >= 1800 // MSVC 2013 +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OP_EXPLICIT +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OVERRIDE +#define JSONCPP_NOEXCEPT throw() +#define JSONCPP_OP_EXPLICIT +#endif + +#ifndef JSON_HAS_RVALUE_REFERENCES + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // MSVC >= 2010 + +#ifdef __clang__ +#if __has_feature(cxx_rvalue_references) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // has_feature + +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // GXX_EXPERIMENTAL + +#endif // __clang__ || __GNUC__ + +#endif // not defined JSON_HAS_RVALUE_REFERENCES + +#ifndef JSON_HAS_RVALUE_REFERENCES +#define JSON_HAS_RVALUE_REFERENCES 0 +#endif + +#ifdef __clang__ +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#endif // __clang__ || __GNUC__ + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +#if __GNUC__ >= 6 +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif + +#if !defined(JSON_IS_AMALGAMATION) + +#include "version.h" + +#if JSONCPP_USING_SECURE_MEMORY +#include "allocator.h" //typedef Allocator +#endif + +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef int64_t Int64; +typedef uint64_t UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +#if JSONCPP_USING_SECURE_MEMORY +#define JSONCPP_STRING \ + std::basic_string, Json::SecureAllocator > +#define JSONCPP_OSTRINGSTREAM \ + std::basic_ostringstream, \ + Json::SecureAllocator > +#define JSONCPP_OSTREAM std::basic_ostream > +#define JSONCPP_ISTRINGSTREAM \ + std::basic_istringstream, \ + Json::SecureAllocator > +#define JSONCPP_ISTREAM std::istream +#else +#define JSONCPP_STRING std::string +#define JSONCPP_OSTRINGSTREAM std::ostringstream +#define JSONCPP_OSTREAM std::ostream +#define JSONCPP_ISTRINGSTREAM std::istringstream +#define JSONCPP_ISTREAM std::istream +#endif // if JSONCPP_USING_SECURE_MEMORY +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED diff --git a/AlgorithmModule/example/json/json.h b/AlgorithmModule/example/json/json.h new file mode 100644 index 0000000..6d9a0bc --- /dev/null +++ b/AlgorithmModule/example/json/json.h @@ -0,0 +1,2268 @@ +/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json.h" + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and +The JsonCpp Authors, and is released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_AMALGAMATED_H_INCLUDED +# define JSON_AMALGAMATED_H_INCLUDED +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + +// DO NOT EDIT. This file (and "version") is generated by CMake. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +#define JSON_VERSION_H_INCLUDED + +#define JSONCPP_VERSION_STRING "1.8.4" +#define JSONCPP_VERSION_MAJOR 1 +#define JSONCPP_VERSION_MINOR 8 +#define JSONCPP_VERSION_PATCH 4 +#define JSONCPP_VERSION_QUALIFIER +#define JSONCPP_VERSION_HEXA \ + ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ + (JSONCPP_VERSION_PATCH << 8)) + +#ifdef JSONCPP_USING_SECURE_MEMORY +#undef JSONCPP_USING_SECURE_MEMORY +#endif +#define JSONCPP_USING_SECURE_MEMORY 0 +// If non-zero, the library zeroes any memory that it has allocated before +// it frees its memory. + +#endif // JSON_VERSION_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED +#include +#include //typedef int64_t, uint64_t +#include //typedef String + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgamated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) // MSVC +#if _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // MSVC 6 + +#if _MSC_VER >= 1500 // MSVC 2008 + /// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#endif // defined(_MSC_VER) + +// In c++11 the override keyword allows you to explicitly define that a function +// is intended to override the base-class version. This makes the code more +// manageable and fixes a set of common hard-to-find bugs. +#if __cplusplus >= 201103L +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT throw() +#if _MSC_VER >= 1800 // MSVC 2013 +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OP_EXPLICIT +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OVERRIDE +#define JSONCPP_NOEXCEPT throw() +#define JSONCPP_OP_EXPLICIT +#endif + +#ifndef JSON_HAS_RVALUE_REFERENCES + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // MSVC >= 2010 + +#ifdef __clang__ +#if __has_feature(cxx_rvalue_references) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // has_feature + +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // GXX_EXPERIMENTAL + +#endif // __clang__ || __GNUC__ + +#endif // not defined JSON_HAS_RVALUE_REFERENCES + +#ifndef JSON_HAS_RVALUE_REFERENCES +#define JSON_HAS_RVALUE_REFERENCES 0 +#endif + +#ifdef __clang__ +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#endif // __clang__ || __GNUC__ + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +#if __GNUC__ >= 6 +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif + +#if !defined(JSON_IS_AMALGAMATION) + +#include "version.h" + +#if JSONCPP_USING_SECURE_MEMORY +#include "allocator.h" //typedef Allocator +#endif + +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef int64_t Int64; +typedef uint64_t UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +#if JSONCPP_USING_SECURE_MEMORY +#define JSONCPP_STRING \ + std::basic_string, Json::SecureAllocator > +#define JSONCPP_OSTRINGSTREAM \ + std::basic_ostringstream, \ + Json::SecureAllocator > +#define JSONCPP_OSTREAM std::basic_ostream > +#define JSONCPP_ISTRINGSTREAM \ + std::basic_istringstream, \ + Json::SecureAllocator > +#define JSONCPP_ISTREAM std::istream +#else +#define JSONCPP_STRING std::string +#define JSONCPP_OSTRINGSTREAM std::ostringstream +#define JSONCPP_OSTREAM std::ostream +#define JSONCPP_ISTRINGSTREAM std::istringstream +#define JSONCPP_ISTREAM std::istream +#endif // if JSONCPP_USING_SECURE_MEMORY +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +#define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_; +}; + +} // namespace Json + +#pragma pack(pop) + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +#define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +#ifndef JSON_USE_CPPTL_SMALLMAP +#include +#else +#include +#endif +#ifdef JSON_USE_CPPTL +#include +#endif + +// Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +#if defined(_MSC_VER) +#define JSONCPP_NORETURN __declspec(noreturn) +#elif defined(__GNUC__) +#define JSONCPP_NORETURN __attribute__((__noreturn__)) +#else +#define JSONCPP_NORETURN +#endif +#endif + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +/** Base class for all exceptions we throw. + * + * We use nothing but these internally. Of course, STL can throw others. + */ +class JSON_API Exception : public std::exception { +public: + Exception(JSONCPP_STRING const& msg); + ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; + char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; + +protected: + JSONCPP_STRING msg_; +}; + +/** Exceptions which the user cannot easily avoid. + * + * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input + * + * \remark derived from Json::Exception + */ +class JSON_API RuntimeError : public Exception { +public: + RuntimeError(JSONCPP_STRING const& msg); +}; + +/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. + * + * These are precondition-violations (user bugs) and internal errors (our bugs). + * + * \remark derived from Json::Exception + */ +class JSON_API LogicError : public Exception { +public: + LogicError(JSONCPP_STRING const& msg); +}; + +/// used internally +JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg); +/// used internally +JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg); + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignment takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : c_str_(czstring) {} + + operator const char*() const { return c_str_; } + + const char* c_str() const { return c_str_; } + +private: + const char* c_str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * Values of an #objectValue or #arrayValue can be accessed using operator[]() + * methods. + * Non-const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resized and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtain default value in the case the + * required element does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + * + * \note #Value string-length fit in size_t, but keys must be < 2^30. + * (The reason is an implementation detail.) A #CharReader will raise an + * exception if a bound is exceeded to avoid security holes in your app, + * but the Value API does *not* check bounds. That is the responsibility + * of the caller. + */ +class JSON_API Value { + friend class ValueIteratorBase; + +public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +#if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + // Required for boost integration, e. g. BOOST_TEST + typedef std::string value_type; + + static const Value& null; ///< We regret this reference to a global instance; + ///< prefer the simpler Value(). + static const Value& nullRef; ///< just a kludge for binary-compatibility; same + ///< as null + static Value const& nullSingleton(); ///< Prefer this to null or nullRef. + + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; +#endif // defined(JSON_HAS_INT64) + + /// Default precision for real value for string representation. + static const UInt defaultRealPrecision; + +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else +private: +#endif +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + class CZString { + public: + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; + CZString(ArrayIndex index); + CZString(char const* str, unsigned length, DuplicationPolicy allocate); + CZString(CZString const& other); +#if JSON_HAS_RVALUE_REFERENCES + CZString(CZString&& other); +#endif + ~CZString(); + CZString& operator=(const CZString& other); + +#if JSON_HAS_RVALUE_REFERENCES + CZString& operator=(CZString&& other); +#endif + + bool operator<(CZString const& other) const; + bool operator==(CZString const& other) const; + ArrayIndex index() const; + // const char* c_str() const; ///< \deprecated + char const* data() const; + unsigned length() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + + struct StringStorage { + unsigned policy_ : 2; + unsigned length_ : 30; // 1GB max + }; + + char const* cstr_; // actually, a prefixed string, unless policy is noDup + union { + ArrayIndex index_; + StringStorage storage_; + }; + }; + +public: +#ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +#else + typedef CppTL::SmallMap ObjectValues; +#endif // ifndef JSON_USE_CPPTL_SMALLMAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. +This is useful since clear() and resize() will not alter types. + + Examples: +\code +Json::Value null_value; // null +Json::Value arr_value(Json::arrayValue); // [] +Json::Value obj_value(Json::objectValue); // {} +\endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) + Value(const char* begin, const char* end); ///< Copy all, incl zeroes. + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * \note This works only for null-terminated strings. (We cannot change the + * size of this class, so we have nowhere to store the length, + * which might be computed later for various operations.) + * + * Example of usage: + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode + */ + Value(const StaticString& value); + Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded + ///< zeroes too. +#ifdef JSON_USE_CPPTL + Value(const CppTL::ConstString& value); +#endif + Value(bool value); + /// Deep copy. + Value(const Value& other); +#if JSON_HAS_RVALUE_REFERENCES + /// Move constructor + Value(Value&& other); +#endif + ~Value(); + + /// Deep copy, then swap(other). + /// \note Over-write existing comments. To preserve comments, use + /// #swapPayload(). + Value& operator=(Value other); + + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + /// copy everything. + void copy(const Value& other); + /// copy values but leave comments and source offsets in place. + void copyPayload(const Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; ///< Embedded zeroes could cause you trouble! +#if JSONCPP_USING_SECURE_MEMORY + unsigned getCStringLength() const; // Allows you to understand the length of + // the CString +#endif + JSONCPP_STRING asString() const; ///< Embedded zeroes are possible. + /** Get raw char* of string-value. + * \return false if !string. (Seg-fault if str or end are NULL.) + */ + bool getString(char const** begin, char const** end) const; +#ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +#endif + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return !isNull() + JSONCPP_OP_EXPLICIT operator bool() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to newSize elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex newSize); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](int index); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](int index) const; + + /// If the array contains at least index+1 elements, returns the element + /// value, + /// otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + +#if JSON_HAS_RVALUE_REFERENCES + Value& append(Value&& value); +#endif + + /// Access an object value by name, create a null member if it does not exist. + /// \note Because of our implementation, keys are limited to 2^30 -1 chars. + /// Exceeding that will cause an exception. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + /// \param key may contain embedded nulls. + Value& operator[](const JSONCPP_STRING& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + /// \param key may contain embedded nulls. + const Value& operator[](const JSONCPP_STRING& key) const; + /** \brief Access an object value by name, create a null member if it does not + exist. + + * If the object has no entry for that name, then the member name used to + store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); +#ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const CppTL::ConstString& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const CppTL::ConstString& key) const; +#endif + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \note key may contain embedded nulls. + Value + get(const char* begin, const char* end, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \param key may contain embedded nulls. + Value get(const JSONCPP_STRING& key, const Value& defaultValue) const; +#ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const CppTL::ConstString& key, const Value& defaultValue) const; +#endif + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of object-mutators. + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. + Value const* demand(char const* begin, char const* end); + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + /// \deprecated + void removeMember(const char* key); + /// Same as removeMember(const char*) + /// \param key may contain embedded nulls. + /// \deprecated + void removeMember(const JSONCPP_STRING& key); + /// Same as removeMember(const char* begin, const char* end, Value* removed), + /// but 'key' is null-terminated. + bool removeMember(const char* key, Value* removed); + /** \brief Remove the named map member. + + Update 'removed' iff removed. + \param key may contain embedded nulls. + \return true iff removed (no exceptions) + */ + bool removeMember(JSONCPP_STRING const& key, Value* removed); + /// Same as removeMember(JSONCPP_STRING const& key, Value* removed) + bool removeMember(const char* begin, const char* end, Value* removed); + /** \brief Remove the indexed array element. + + O(n) expensive operations. + Update 'removed' iff removed. + \return true if removed (no exceptions) + */ + bool removeIndex(ArrayIndex index, Value* removed); + + /// Return true if the object has a member named key. + /// \note 'key' must be null-terminated. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + /// \param key may contain embedded nulls. + bool isMember(const JSONCPP_STRING& key) const; + /// Same as isMember(JSONCPP_STRING const& key)const + bool isMember(const char* begin, const char* end) const; +#ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString& key) const; +#endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif + + /// \deprecated Always pass len. + JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.") + void setComment(const char* comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const char* comment, size_t len, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const JSONCPP_STRING& comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + JSONCPP_STRING getComment(CommentPlacement placement) const; + + JSONCPP_STRING toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(ptrdiff_t start); + void setOffsetLimit(ptrdiff_t limit); + ptrdiff_t getOffsetStart() const; + ptrdiff_t getOffsetLimit() const; + +private: + void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); + + Value& resolveReference(const char* key); + Value& resolveReference(const char* key, const char* end); + + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); + + void setComment(const char* text, size_t len); + + char* comment_; + }; + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; // actually ptr to unsigned, followed by str, unless + // !allocated_ + ObjectValues* map_; + } value_; + ValueType type_ : 8; + unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is + // useless. If not allocated_, string_ must be + // null-terminated. + CommentInfo* comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + ptrdiff_t start_; + ptrdiff_t limit_; +}; + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(const JSONCPP_STRING& key); + +private: + enum Kind { kindNone = 0, kindIndex, kindKey }; + JSONCPP_STRING key_; + ArrayIndex index_; + Kind kind_; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ +class JSON_API Path { +public: + Path(const JSONCPP_STRING& path, + const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const JSONCPP_STRING& path, const InArgs& in); + void addPathInArg(const JSONCPP_STRING& path, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind); + static void invalidPath(const JSONCPP_STRING& path, int location); + + Args args_; +}; + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return other.computeDistance(*this); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value, or -1 if it is not an + /// arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value, or "" if it is not an + /// objectValue. + /// \note Avoid `c_str()` on result, as embedded zeroes are possible. + JSONCPP_STRING name() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + /// \deprecated This cannot be used for UTF-8 strings, since there can be + /// embedded nulls. + JSONCPP_DEPRECATED("Use `key = name();` instead.") + char const* memberName() const; + /// Return the member name of the referenced Value, or NULL if it is not an + /// objectValue. + /// \note Better version than memberName(). Allows embedded nulls. + char const* memberName(char const** end) const; + +protected: + Value& deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; + +public: + // For some reason, BORLAND needs these at the end, rather + // than earlier. No idea why. + ValueIteratorBase(); + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef const Value value_type; + // typedef unsigned int size_t; + // typedef int difference_type; + typedef const Value& reference; + typedef const Value* pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + ValueConstIterator(ValueIterator const& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef Value& reference; + typedef Value* pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + explicit ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +inline void swap(Value& a, Value& b) { a.swap(b); } + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +#define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Unserialize a JSON document into a + *Value. + * + * \deprecated Use CharReader and CharReaderBuilder. + */ +class JSON_API Reader { +public: + typedef char Char; + typedef const Char* Location; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + * + */ + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + JSONCPP_STRING message; + }; + + /** \brief Constructs a Reader allowing all features + * for parsing. + */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set + * for parsing. + */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * \param document UTF-8 encoded string containing the document to read. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + * back during + * serialization, \c false to discard comments. + * This parameter is ignored if + * Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool + parse(const std::string& document, Value& root, bool collectComments = true); + + /** \brief Read a Value from a JSON + document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + back during + * serialization, \c false to discard comments. + * This parameter is ignored if + Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") + JSONCPP_STRING getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + */ + JSONCPP_STRING getFormattedErrorMessages() const; + + /** \brief Returns a vector of structured erros encounted while parsing. + * \return A (possibly empty) vector of StructuredError objects. Currently + * only one error can be returned, but the caller should tolerate + * multiple + * errors. This can occur if the parser recovers from a non-fatal + * parse error and then encounters additional errors. + */ + std::vector getStructuredErrors() const; + + /** \brief Add a semantic error message. + * \param value JSON Value location associated with the error + * \param message The error message. + * \return \c true if the error was successfully added, \c false if the + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const JSONCPP_STRING& message); + + /** \brief Add a semantic error message with extra context. + * \param value JSON Value location associated with the error + * \param message The error message. + * \param extra Additional JSON Value location to contextualize the error + * \return \c true if the error was successfully added, \c false if either + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra); + + /** \brief Return whether there are any errors. + * \return \c true if there are no errors to report \c false if + * errors have occurred. + */ + bool good() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + JSONCPP_STRING message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool + addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static bool containsNewLine(Location begin, Location end); + static JSONCPP_STRING normalizeEOL(Location begin, Location end); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + JSONCPP_STRING document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + JSONCPP_STRING commentsBefore_; + Features features_; + bool collectComments_; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() {} + /** \brief Read a Value from a JSON + document. + * The document must be a UTF-8 encoded string containing the document to + read. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param errs [out] Formatted error messages (if not NULL) + * a user friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + virtual bool parse(char const* beginDoc, + char const* endDoc, + Value* root, + JSONCPP_STRING* errs) = 0; + + class JSON_API Factory { + public: + virtual ~Factory() {} + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + +Usage: +\code + using namespace Json; + CharReaderBuilder builder; + builder["collectComments"] = false; + Value value; + JSONCPP_STRING errs; + bool ok = parseFromStream(builder, std::cin, &value, &errs); +\endcode +*/ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + These are case-sensitive. + Available settings (case-sensitive): + - `"collectComments": false or true` + - true to collect comment and allow writing them + back during serialization, false to discard comments. + This parameter is ignored if allowComments is false. + - `"allowComments": false or true` + - true if comments are allowed. + - `"strictRoot": false or true` + - true if root must be either an array or an object value + - `"allowDroppedNullPlaceholders": false or true` + - true if dropped null placeholders are allowed. (See + StreamWriterBuilder.) + - `"allowNumericKeys": false or true` + - true if numeric object keys are allowed. + - `"allowSingleQuotes": false or true` + - true if '' are allowed for strings (both keys and values) + - `"stackLimit": integer` + - Exceeding stackLimit (recursive depth of `readValue()`) will + cause an exception. + - This is a security issue (seg-faults caused by deeply nested JSON), + so the default is low. + - `"failIfExtra": false or true` + - If true, `parse()` returns false when extra non-whitespace trails + the JSON value in the input string. + - `"rejectDupKeys": false or true` + - If true, `parse()` returns false when a key is duplicated within an + object. + - `"allowSpecialFloats": false or true` + - If true, special float values (NaNs and infinities) are allowed + and their values are lossfree restorable. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + ~CharReaderBuilder() JSONCPP_OVERRIDE; + + CharReader* newCharReader() const JSONCPP_OVERRIDE; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](JSONCPP_STRING key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); +}; + +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream(CharReader::Factory const&, + JSONCPP_ISTREAM&, + Value* root, + std::string* errs); + +/** \brief Read from 'sin' into 'root'. + + Always keep comments from the input JSON. + + This can be used to read a file into a particular sub-object. + For example: + \code + Json::Value root; + cin >> root["dir"]["file"]; + cout << root; + \endcode + Result: + \verbatim + { + "dir": { + "file": { + // The input stream JSON would be nested here. + } + } + } + \endverbatim + \throw std::exception on parse error. + \see Json::operator<<() +*/ +JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_READER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +class Value; + +/** + +Usage: +\code + using namespace Json; + void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { + std::unique_ptr const writer( + factory.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush + } +\endcode +*/ +class JSON_API StreamWriter { +protected: + JSONCPP_OSTREAM* sout_; // not owned; will not delete +public: + StreamWriter(); + virtual ~StreamWriter(); + /** Write Value into document as configured in sub-class. + Do not take ownership of sout, but maintain a reference during function. + \pre sout != NULL + \return zero on success (For now, we always return zero, so check the + stream instead.) \throw std::exception possibly, depending on configuration + */ + virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0; + + /** \brief A simple abstract factory. + */ + class JSON_API Factory { + public: + virtual ~Factory(); + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const = 0; + }; // Factory +}; // StreamWriter + +/** \brief Write into stringstream, then return string, for convenience. + * A StreamWriter will be created from the factory, used, and then deleted. + */ +JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, + Value const& root); + +/** \brief Build a StreamWriter implementation. + +Usage: +\code + using namespace Json; + Value value = ...; + StreamWriterBuilder builder; + builder["commentStyle"] = "None"; + builder["indentation"] = " "; // or whatever you like + std::unique_ptr writer( + builder.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush +\endcode +*/ +class JSON_API StreamWriterBuilder : public StreamWriter::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + Available settings (case-sensitive): + - "commentStyle": "None" or "All" + - "indentation": "". + - Setting this to an empty string also omits newline characters. + - "enableYAMLCompatibility": false or true + - slightly change the whitespace around colons + - "dropNullPlaceholders": false or true + - Drop the "null" string from the writer's output for nullValues. + Strictly speaking, this is not valid JSON. But when the output is being + fed to a browser's JavaScript, it makes for smaller output and the + browser can handle the output just fine. + - "useSpecialFloats": false or true + - If true, outputs non-finite floating point values in the following way: + NaN values as "NaN", positive infinity as "Infinity", and negative + infinity as "-Infinity". + - "precision": int + - Number of precision digits for formatting of real values. + - "precisionType": "significant"(default) or "decimal" + - Type of precision for formatting of real values. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + StreamWriterBuilder(); + ~StreamWriterBuilder() JSONCPP_OVERRIDE; + + /** + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + /** A simple way to update a specific setting. + */ + Value& operator[](JSONCPP_STRING key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults + */ + static void setDefaults(Json::Value* settings); +}; + +/** \brief Abstract class for writers. + * \deprecated Use StreamWriter. (And really, this is an implementation detail.) + */ +class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { +public: + virtual ~Writer(); + + virtual JSONCPP_STRING write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be useful to support feature such as RPC where bandwidth is limited. + * \sa Reader, Value + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter + : public Writer { +public: + FastWriter(); + ~FastWriter() JSONCPP_OVERRIDE {} + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + +private: + void writeValue(const Value& value); + + JSONCPP_STRING document_; + bool yamlCompatibilityEnabled_; + bool dropNullPlaceholders_; + bool omitEndingLineFeed_; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledWriter : public Writer { +public: + StyledWriter(); + ~StyledWriter() JSONCPP_OVERRIDE {} + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const JSONCPP_STRING& value); + void writeIndent(); + void writeWithIndent(const JSONCPP_STRING& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + JSONCPP_STRING document_; + JSONCPP_STRING indentString_; + unsigned int rightMargin_; + unsigned int indentSize_; + bool addChildValues_; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledStreamWriter { +public: + /** + * \param indentation Each level will be indented by this amount extra. + */ + StyledStreamWriter(const JSONCPP_STRING& indentation = "\t"); + ~StyledStreamWriter() {} + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(JSONCPP_OSTREAM& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const JSONCPP_STRING& value); + void writeIndent(); + void writeWithIndent(const JSONCPP_STRING& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + JSONCPP_OSTREAM* document_; + JSONCPP_STRING indentString_; + unsigned int rightMargin_; + JSONCPP_STRING indentation_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(JSON_HAS_INT64) +JSONCPP_STRING JSON_API valueToString(Int value); +JSONCPP_STRING JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +JSONCPP_STRING JSON_API valueToString(LargestInt value); +JSONCPP_STRING JSON_API valueToString(LargestUInt value); +JSONCPP_STRING JSON_API +valueToString(double value, + unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); +JSONCPP_STRING JSON_API valueToString(bool value); +JSONCPP_STRING JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +/** It should not be possible for a maliciously designed file to + * cause an abort() or seg-fault, so these macros are used only + * for pre-condition violations and internal logic errors. + */ +#if JSON_USE_EXCEPTION + +// @todo <= add detail about condition in exception +#define JSON_ASSERT(condition) \ + { \ + if (!(condition)) { \ + Json::throwLogicError("assert json failed"); \ + } \ + } + +#define JSON_FAIL_MESSAGE(message) \ + { \ + JSONCPP_OSTRINGSTREAM oss; \ + oss << message; \ + Json::throwLogicError(oss.str()); \ + abort(); \ + } + +#else // JSON_USE_EXCEPTION + +#define JSON_ASSERT(condition) assert(condition) + +// The call to assert() will show the failure message in debug builds. In +// release builds we abort, for a core-dump or debugger. +#define JSON_FAIL_MESSAGE(message) \ + { \ + JSONCPP_OSTRINGSTREAM oss; \ + oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } + +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_AMALGAMATED_H_INCLUDED diff --git a/AlgorithmModule/example/jsoncpp.cpp b/AlgorithmModule/example/jsoncpp.cpp new file mode 100644 index 0000000..ebd3aa5 --- /dev/null +++ b/AlgorithmModule/example/jsoncpp.cpp @@ -0,0 +1,5467 @@ +/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json.h" + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and +The JsonCpp Authors, and is released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + + +#include "json/json.h" +#ifndef JSON_IS_AMALGAMATION +#error "Compile with -I PATH_TO_JSON_DIRECTORY" +#endif + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include +#endif + +// Also support old flag NO_LOCALE_SUPPORT +#ifdef NO_LOCALE_SUPPORT +#define JSONCPP_NO_LOCALE_SUPPORT +#endif + +#ifndef JSONCPP_NO_LOCALE_SUPPORT +#include +#endif + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { +static inline char getDecimalPoint() { +#ifdef JSONCPP_NO_LOCALE_SUPPORT + return '\0'; +#else + struct lconv* lc = localeconv(); + return lc ? *(lc->decimal_point) : '\0'; +#endif +} + +/// Converts a unicode code-point to UTF-8. +static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) { + JSONCPP_STRING result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + // printf("-----------------111--cp %d-------\n",cp); + if ((cp >= 0x4E00 && cp <= 0x9FA5) || (cp >= 0xF00 && cp <= 0xFA2D) ) + { + + wchar_t src[2] = { 0 }; + char dest[5] = { 0 }; + src[0] = static_cast(cp); + std::string curLocale = setlocale(LC_ALL,NULL); + setlocale(LC_ALL,"chs"); + wcstombs(dest, src, 5); + result = dest; + setlocale(LC_ALL, curLocale.c_str()); + } + + + return result; +} + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned integer to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = static_cast(value % 10U + static_cast('0')); + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +template Iter fixNumericLocale(Iter begin, Iter end) { + for (; begin != end; ++begin) { + if (*begin == ',') { + *begin = '.'; + } + } + return begin; +} + +template void fixNumericLocaleInput(Iter begin, Iter end) { + char decimalPoint = getDecimalPoint(); + if (decimalPoint == '\0' || decimalPoint == '.') { + return; + } + for (; begin != end; ++begin) { + if (*begin == '.') { + *begin = decimalPoint; + } + } +} + +/** + * Return iterator that would be the new end of the range [begin,end), if we + * were to delete zeros in the end of string, but not the last zero before '.'. + */ +template Iter fixZerosInTheEnd(Iter begin, Iter end) { + for (; begin != end; --end) { + if (*(end - 1) != '0') { + return end; + } + // Don't delete the last zero before the decimal point. + if (begin != (end - 1) && *(end - 2) == '.') { + return end; + } + } + return end; +} + +} // namespace Json + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors +// Copyright (C) 2016 InfoTeCS JSC. All rights reserved. +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include + +#if !defined(snprintf) +#define snprintf std::snprintf +#endif + +#if !defined(sscanf) +#define sscanf std::sscanf +#endif +#else +#include + +#if defined(_MSC_VER) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#if !defined(snprintf) +#define snprintf _snprintf +#endif +#endif +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile +// time to change the stack limit +#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) +#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 +#endif + +static size_t const stackLimit_g = + JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() + +namespace Json { + +#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) +typedef std::unique_ptr CharReaderPtr; +#else +typedef std::auto_ptr CharReaderPtr; +#endif + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_(true), strictRoot_(false), + allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} + +Features Features::all() { return Features(); } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + features.allowDroppedNullPlaceholders_ = false; + features.allowNumericKeys_ = false; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} + +Reader::Reader(const Features& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool Reader::parse(const std::string& document, + Value& root, + bool collectComments) { + document_.assign(document.begin(), document.end()); + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& is, Value& root, bool collectComments) { + // std::istream_iterator begin(is); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since JSONCPP_STRING is reference-counted, this at least does not + // create an extra copy. + JSONCPP_STRING doc; + std::getline(is, doc, (char)EOF); + return parse(doc.data(), doc.data() + doc.size(), root, collectComments); +} + +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + // readValue() may call itself only if it calls readObject() or ReadArray(). + // These methods execute nodes_.push() just before and nodes_.pop)() just + // after calling readValue(). parse() executes one nodes_.push(), so > instead + // of >=. + if (nodes_.size() > stackLimit_g) + throwRuntimeError("Exceeded stackLimit in readValue()."); + + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenFalse: { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNull: { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, + Reader::Location end) { + JSONCPP_STRING normalized; + normalized.reserve(static_cast(end - begin)); + Reader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void Reader::addComment(Location begin, + Location end, + CommentPlacement placement) { + assert(collectComments_); + const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool Reader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void Reader::readNumber() { + const char* p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : '\0'; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } +} + +bool Reader::readString() { + Char c = '\0'; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& token) { + Token tokenName; + JSONCPP_STRING name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name.clear(); + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = JSONCPP_STRING(numberName.asCString()); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); +} + +bool Reader::readArray(Token& token) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token currentToken; + // Accept Comment after last item in the array. + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); + } + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); + } + if (currentToken.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(static_cast(c - '0')); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative && value == maxIntegerValue) + decoded = Value::minLargestInt; + else if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + JSONCPP_STRING buffer(token.start_, token.end_); + JSONCPP_ISTRINGSTREAM is(buffer); + if (!(is >> value)) + return addError("'" + JSONCPP_STRING(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + JSONCPP_STRING decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { + decoded.reserve(static_cast(token.end_ - token.start_ - 2)); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + + //printf("-->>>>>>>>>>>>>>>>>>>1>>>>>>\n"); + + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, current); + if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& ret_unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", token, + current); + int unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, current); + } + ret_unicode = static_cast(unicode); + return true; +} + +bool Reader::addError(const JSONCPP_STRING& message, + Token& token, + Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + size_t const errorCount = errors_.size(); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +// Deprecated. Preserved for backward compatibility +JSONCPP_STRING Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +JSONCPP_STRING Reader::getFormattedErrorMessages() const { + JSONCPP_STRING formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector Reader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + Reader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) { + ptrdiff_t const length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool Reader::pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra) { + ptrdiff_t const length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool Reader::good() const { return !errors_.size(); } + +// exact copy of Features +class OurFeatures { +public: + static OurFeatures all(); + bool allowComments_; + bool strictRoot_; + bool allowDroppedNullPlaceholders_; + bool allowNumericKeys_; + bool allowSingleQuotes_; + bool failIfExtra_; + bool rejectDupKeys_; + bool allowSpecialFloats_; + int stackLimit_; +}; // OurFeatures + +// exact copy of Implementation of class Features +// //////////////////////////////// + +OurFeatures OurFeatures::all() { return OurFeatures(); } + +// Implementation of class Reader +// //////////////////////////////// + +// exact copy of Reader, renamed to OurReader +class OurReader { +public: + typedef char Char; + typedef const Char* Location; + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + JSONCPP_STRING message; + }; + + OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + JSONCPP_STRING getFormattedErrorMessages() const; + std::vector getStructuredErrors() const; + bool pushError(const Value& value, const JSONCPP_STRING& message); + bool pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra); + bool good() const; + +private: + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl + + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenNaN, + tokenPosInf, + tokenNegInf, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + JSONCPP_STRING message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + bool readStringSingleQuote(); + bool readNumber(bool checkInf); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool + addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static JSONCPP_STRING normalizeEOL(Location begin, Location end); + static bool containsNewLine(Location begin, Location end); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + JSONCPP_STRING document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + JSONCPP_STRING commentsBefore_; + + OurFeatures const features_; + bool collectComments_; +}; // OurReader + +// complete copy of Read impl, for OurReader + +bool OurReader::containsNewLine(OurReader::Location begin, + OurReader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +OurReader::OurReader(OurFeatures const& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool OurReader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (features_.failIfExtra_) { + if ((features_.strictRoot_ || token.type_ != tokenError) && + token.type_ != tokenEndOfStream) { + addError("Extra non-whitespace after JSON value.", token); + return false; + } + } + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool OurReader::readValue() { + // To preserve the old behaviour we cast size_t to int. + if (static_cast(nodes_.size()) > features_.stackLimit_) + throwRuntimeError("Exceeded stackLimit in readValue()."); + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenFalse: { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNull: { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNaN: { + Value v(std::numeric_limits::quiet_NaN()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenPosInf: { + Value v(std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNegInf: { + Value v(-std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // else, fall through ... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void OurReader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool OurReader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + break; + } // else fall through + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token.type_ = tokenNumber; + readNumber(false); + break; + case '-': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenNegInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case 'N': + if (features_.allowSpecialFloats_) { + token.type_ = tokenNaN; + ok = match("aN", 2); + } else { + ok = false; + } + break; + case 'I': + if (features_.allowSpecialFloats_) { + token.type_ = tokenPosInf; + ok = match("nfinity", 7); + } else { + ok = false; + } + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void OurReader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool OurReader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool OurReader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, + OurReader::Location end) { + JSONCPP_STRING normalized; + normalized.reserve(static_cast(end - begin)); + OurReader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void OurReader::addComment(Location begin, + Location end, + CommentPlacement placement) { + assert(collectComments_); + const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool OurReader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool OurReader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +bool OurReader::readNumber(bool checkInf) { + const char* p = current_; + if (checkInf && p != end_ && *p == 'I') { + current_ = ++p; + return false; + } + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : '\0'; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + return true; +} +bool OurReader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool OurReader::readStringSingleQuote() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '\'') + break; + } + return c == '\''; +} + +bool OurReader::readObject(Token& token) { + Token tokenName; + JSONCPP_STRING name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name.clear(); + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); + } + if (name.length() >= (1U << 30)) + throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + JSONCPP_STRING msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover(msg, tokenName, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); +} + +bool OurReader::readArray(Token& token) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token currentToken; + // Accept Comment after last item in the array. + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); + } + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); + } + if (currentToken.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool OurReader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(static_cast(c - '0')); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool OurReader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + const int bufferSize = 32; + int count; + ptrdiff_t const length = token.end_ - token.start_; + + // Sanity check to avoid buffer overflow exploits. + if (length < 0) { + return addError("Unable to parse token length", token); + } + size_t const ulength = static_cast(length); + + // Avoid using a string constant for the format control string given to + // sscanf, as this can cause hard to debug crashes on OS X. See here for more + // info: + // + // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html + char format[] = "%lf"; + + if (length <= bufferSize) { + Char buffer[bufferSize + 1]; + memcpy(buffer, token.start_, ulength); + buffer[length] = 0; + fixNumericLocaleInput(buffer, buffer + length); + count = sscanf(buffer, format, &value); + } else { + JSONCPP_STRING buffer(token.start_, token.end_); + count = sscanf(buffer.c_str(), format, &value); + } + + if (count != 1) + return addError("'" + JSONCPP_STRING(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool OurReader::decodeString(Token& token) { + JSONCPP_STRING decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { + decoded.reserve(static_cast(token.end_ - token.start_ - 2)); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + //printf("-->>>>>>>>>>>>>>>>>>2>>>>>>\n"); + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool OurReader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, current); + if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, current); + } + return true; +} + +bool OurReader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& ret_unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", token, + current); + int unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, current); + } + ret_unicode = static_cast(unicode); + return true; +} + +bool OurReader::addError(const JSONCPP_STRING& message, + Token& token, + Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool OurReader::recoverFromError(TokenType skipUntilToken) { + size_t errorCount = errors_.size(); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& OurReader::currentValue() { return *(nodes_.top()); } + +OurReader::Char OurReader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void OurReader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +JSONCPP_STRING OurReader::getFormattedErrorMessages() const { + JSONCPP_STRING formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector OurReader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + OurReader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) { + ptrdiff_t length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool OurReader::pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra) { + ptrdiff_t length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool OurReader::good() const { return !errors_.size(); } + +class OurCharReader : public CharReader { + bool const collectComments_; + OurReader reader_; + +public: + OurCharReader(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + bool parse(char const* beginDoc, + char const* endDoc, + Value* root, + JSONCPP_STRING* errs) JSONCPP_OVERRIDE { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; + } +}; + +CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } +CharReaderBuilder::~CharReaderBuilder() {} +CharReader* CharReaderBuilder::newCharReader() const { + bool collectComments = settings_["collectComments"].asBool(); + OurFeatures features = OurFeatures::all(); + features.allowComments_ = settings_["allowComments"].asBool(); + features.strictRoot_ = settings_["strictRoot"].asBool(); + features.allowDroppedNullPlaceholders_ = + settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); + features.stackLimit_ = settings_["stackLimit"].asInt(); + features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); + features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); + return new OurCharReader(collectComments, features); +} +static void getValidReaderKeys(std::set* valid_keys) { + valid_keys->clear(); + valid_keys->insert("collectComments"); + valid_keys->insert("allowComments"); + valid_keys->insert("strictRoot"); + valid_keys->insert("allowDroppedNullPlaceholders"); + valid_keys->insert("allowNumericKeys"); + valid_keys->insert("allowSingleQuotes"); + valid_keys->insert("stackLimit"); + valid_keys->insert("failIfExtra"); + valid_keys->insert("rejectDupKeys"); + valid_keys->insert("allowSpecialFloats"); +} +bool CharReaderBuilder::validate(Json::Value* invalid) const { + Json::Value my_invalid; + if (!invalid) + invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidReaderKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + JSONCPP_STRING const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& CharReaderBuilder::operator[](JSONCPP_STRING key) { + return settings_[key]; +} +// static +void CharReaderBuilder::strictMode(Json::Value* settings) { + //! [CharReaderBuilderStrictMode] + (*settings)["allowComments"] = false; + (*settings)["strictRoot"] = true; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = true; + (*settings)["allowSpecialFloats"] = false; + //! [CharReaderBuilderStrictMode] +} +// static +void CharReaderBuilder::setDefaults(Json::Value* settings) { + //! [CharReaderBuilderDefaults] + (*settings)["collectComments"] = true; + (*settings)["allowComments"] = true; + (*settings)["strictRoot"] = false; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = false; + (*settings)["rejectDupKeys"] = false; + (*settings)["allowSpecialFloats"] = false; + //! [CharReaderBuilderDefaults] +} + +////////////////////////////////// +// global functions + +bool parseFromStream(CharReader::Factory const& fact, + JSONCPP_ISTREAM& sin, + Value* root, + JSONCPP_STRING* errs) { + JSONCPP_OSTRINGSTREAM ssin; + ssin << sin.rdbuf(); + JSONCPP_STRING doc = ssin.str(); + char const* begin = doc.data(); + char const* end = begin + doc.size(); + // Note that we do not actually need a null-terminator. + CharReaderPtr const reader(fact.newCharReader()); + return reader->parse(begin, end, root, errs); +} + +JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) { + CharReaderBuilder b; + JSONCPP_STRING errs; + bool ok = parseFromStream(b, sin, &root, &errs); + if (!ok) { + throwRuntimeError(errs); + } + return sin; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() + : current_(), isNull_(true) { +} + +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} + +Value& ValueIteratorBase::deref() const { + return current_->second; +} + +void ValueIteratorBase::increment() { + ++current_; +} + +void ValueIteratorBase::decrement() { + --current_; +} + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { +#ifdef JSON_USE_CPPTL_SMALLMAP + return other.current_ - current_; +#else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +#endif +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +} + +void ValueIteratorBase::copy(const SelfType& other) { + current_ = other.current_; + isNull_ = other.isNull_; +} + +Value ValueIteratorBase::key() const { + const Value::CZString czstring = (*current_).first; + if (czstring.data()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.data())); + return Value(czstring.data(), czstring.data() + czstring.length()); + } + return Value(czstring.index()); +} + +UInt ValueIteratorBase::index() const { + const Value::CZString czstring = (*current_).first; + if (!czstring.data()) + return czstring.index(); + return Value::UInt(-1); +} + +JSONCPP_STRING ValueIteratorBase::name() const { + char const* keey; + char const* end; + keey = memberName(&end); + if (!keey) return JSONCPP_STRING(); + return JSONCPP_STRING(keey, end); +} + +char const* ValueIteratorBase::memberName() const { + const char* cname = (*current_).first.data(); + return cname ? cname : ""; +} + +char const* ValueIteratorBase::memberName(char const** end) const { + const char* cname = (*current_).first.data(); + if (!cname) { + *end = NULL; + return NULL; + } + *end = cname + (*current_).first.length(); + return cname; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() {} + +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueConstIterator::ValueConstIterator(ValueIterator const& other) + : ValueIteratorBase(other) {} + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() {} + +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) { + throwRuntimeError("ConstIterator to Iterator should never be allowed."); +} + +ValueIterator::ValueIterator(const ValueIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +#include +#endif +#include // min() +#include // size_t + +// Disable warning C4702 : unreachable code +#if defined(_MSC_VER) && _MSC_VER >= 1800 // VC++ 12.0 and above +#pragma warning(disable : 4702) +#endif + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +#define ALIGNAS(byte_alignment) +#endif +// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +// const unsigned char& kNullRef = kNull[0]; +// const Value& Value::null = reinterpret_cast(kNullRef); +// const Value& Value::nullRef = null; + +// static +Value const& Value::nullSingleton() { + static Value const nullStatic; + return nullStatic; +} + +// for backwards compatibility, we'll leave these global references around, but +// DO NOT use them in JSONCPP library code any more! +Value const& Value::null = Value::nullSingleton(); +Value const& Value::nullRef = Value::nullSingleton(); + +const Int Value::minInt = Int(~(UInt(-1) / 2)); +const Int Value::maxInt = Int(UInt(-1) / 2); +const UInt Value::maxUInt = UInt(-1); +#if defined(JSON_HAS_INT64) +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); +const UInt64 Value::maxUInt64 = UInt64(-1); +// The constant is hard-coded because some compiler have trouble +// converting Value::maxUInt64 to a double correctly (AIX/xlC). +// Assumes that UInt64 is a 64 bits integer. +static const double maxUInt64AsDouble = 18446744073709551615.0; +#endif // defined(JSON_HAS_INT64) +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + +const UInt Value::defaultRealPrecision = 17; + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + // The casts can lose precision, but we are looking only for + // an approximate range. Might fail on edge cases though. ~cdunn + // return d >= static_cast(min) && d <= static_cast(max); + return d >= min && d <= max; +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + + static_cast(Int64(value & 1)); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, size_t length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= static_cast(Value::maxInt)) + length = Value::maxInt - 1; + + char* newString = static_cast(malloc(length + 1)); + if (newString == NULL) { + throwRuntimeError("in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + } + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/* Record the length as a prefix. + */ +static inline char* duplicateAndPrefixStringValue(const char* value, + unsigned int length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + JSON_ASSERT_MESSAGE(length <= static_cast(Value::maxInt) - + sizeof(unsigned) - 1U, + "in Json::Value::duplicateAndPrefixStringValue(): " + "length too big for prefixing"); + unsigned actualLength = length + static_cast(sizeof(unsigned)) + 1U; + char* newString = static_cast(malloc(actualLength)); + if (newString == 0) { + throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); + } + *reinterpret_cast(newString) = length; + memcpy(newString + sizeof(unsigned), value, length); + newString[actualLength - 1U] = + 0; // to avoid buffer over-run accidents by users later + return newString; +} +inline static void decodePrefixedString(bool isPrefixed, + char const* prefixed, + unsigned* length, + char const** value) { + if (!isPrefixed) { + *length = static_cast(strlen(prefixed)); + *value = prefixed; + } else { + *length = *reinterpret_cast(prefixed); + *value = prefixed + sizeof(unsigned); + } +} +/** Free the string duplicated by + * duplicateStringValue()/duplicateAndPrefixStringValue(). + */ +#if JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { + unsigned length = 0; + char const* valueDecoded; + decodePrefixedString(true, value, &length, &valueDecoded); + size_t const size = sizeof(unsigned) + length + 1U; + memset(value, 0, size); + free(value); +} +static inline void releaseStringValue(char* value, unsigned length) { + // length==0 => we allocated the strings memory + size_t size = (length == 0) ? strlen(value) : length; + memset(value, 0, size); + free(value); +} +#else // !JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { free(value); } +static inline void releaseStringValue(char* value, unsigned) { free(value); } +#endif // JSONCPP_USING_SECURE_MEMORY + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +Exception::Exception(JSONCPP_STRING const& msg) : msg_(msg) {} +Exception::~Exception() JSONCPP_NOEXCEPT {} +char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); } +RuntimeError::RuntimeError(JSONCPP_STRING const& msg) : Exception(msg) {} +LogicError::LogicError(JSONCPP_STRING const& msg) : Exception(msg) {} +JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg) { + throw RuntimeError(msg); +} +JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg) { + throw LogicError(msg); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Value::CommentInfo::CommentInfo() : comment_(0) {} + +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_, 0u); +} + +void Value::CommentInfo::setComment(const char* text, size_t len) { + if (comment_) { + releaseStringValue(comment_, 0u); + comment_ = 0; + } + JSON_ASSERT(text != 0); + JSON_ASSERT_MESSAGE( + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue(text, len); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +// Notes: policy_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} + +Value::CZString::CZString(char const* str, + unsigned length, + DuplicationPolicy allocate) + : cstr_(str) { + // allocate != duplicate + storage_.policy_ = allocate & 0x3; + storage_.length_ = length & 0x3FFFFFFF; +} + +Value::CZString::CZString(const CZString& other) { + cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_); + storage_.policy_ = + static_cast( + other.cstr_ + ? (static_cast(other.storage_.policy_) == + noDuplication + ? noDuplication + : duplicate) + : static_cast(other.storage_.policy_)) & + 3U; + storage_.length_ = other.storage_.length_; +} + +#if JSON_HAS_RVALUE_REFERENCES +Value::CZString::CZString(CZString&& other) + : cstr_(other.cstr_), index_(other.index_) { + other.cstr_ = nullptr; +} +#endif + +Value::CZString::~CZString() { + if (cstr_ && storage_.policy_ == duplicate) { + releaseStringValue(const_cast(cstr_), + storage_.length_ + 1u); // +1 for null terminating + // character for sake of + // completeness but not actually + // necessary + } +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(const CZString& other) { + cstr_ = other.cstr_; + index_ = other.index_; + return *this; +} + +#if JSON_HAS_RVALUE_REFERENCES +Value::CZString& Value::CZString::operator=(CZString&& other) { + cstr_ = other.cstr_; + index_ = other.index_; + other.cstr_ = nullptr; + return *this; +} +#endif + +bool Value::CZString::operator<(const CZString& other) const { + if (!cstr_) + return index_ < other.index_; + // return strcmp(cstr_, other.cstr_) < 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this->cstr_ && other.cstr_); + int comp = memcmp(this->cstr_, other.cstr_, min_len); + if (comp < 0) + return true; + if (comp > 0) + return false; + return (this_len < other_len); +} + +bool Value::CZString::operator==(const CZString& other) const { + if (!cstr_) + return index_ == other.index_; + // return strcmp(cstr_, other.cstr_) == 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + if (this_len != other_len) + return false; + JSON_ASSERT(this->cstr_ && other.cstr_); + int comp = memcmp(this->cstr_, other.cstr_, this_len); + return comp == 0; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +// const char* Value::CZString::c_str() const { return cstr_; } +const char* Value::CZString::data() const { return cstr_; } +unsigned Value::CZString::length() const { return storage_.length_; } +bool Value::CZString::isStaticString() const { + return storage_.policy_ == noDuplication; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType type) { + static char const emptyString[] = ""; + initBasic(type); + switch (type) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + // allocated_ == false, so this is safe. + value_.string_ = const_cast(static_cast(emptyString)); + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; +} + +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; +} +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; +} +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; +} + +Value::Value(const char* value) { + initBasic(stringValue, true); + JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor"); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast(strlen(value))); +} + +Value::Value(const char* begin, const char* end) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(begin, static_cast(end - begin)); +} + +Value::Value(const JSONCPP_STRING& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue( + value.data(), static_cast(value.length())); +} + +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value::Value(const CppTL::ConstString& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast(value.length())); +} +#endif + +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; +} + +Value::Value(const Value& other) { + dupPayload(other); + dupMeta(other); +} + +#if JSON_HAS_RVALUE_REFERENCES +// Move constructor +Value::Value(Value&& other) { + initBasic(nullValue); + swap(other); +} +#endif + +Value::~Value() { + releasePayload(); + + delete[] comments_; + + value_.uint_ = 0; +} + +Value& Value::operator=(Value other) { + swap(other); + return *this; +} + +void Value::swapPayload(Value& other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2 & 0x1; +} + +void Value::copyPayload(const Value& other) { + releasePayload(); + dupPayload(other); +} + +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); +} + +void Value::copy(const Value& other) { + copyPayload(other); + delete[] comments_; + dupMeta(other); +} + +ValueType Value::type() const { return type_; } + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + if (other.value_.string_) + return true; + else + return false; + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, + &other_str); + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, min_len); + if (comp < 0) + return true; + if (comp > 0) + return false; + return (this_len < other_len); + } + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + // if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + return (value_.string_ == other.value_.string_); + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, + &other_str); + if (this_len != other_len) + return false; + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, this_len); + return comp == 0; + } + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + return this_str; +} + +#if JSONCPP_USING_SECURE_MEMORY +unsigned Value::getCStringLength() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + return this_len; +} +#endif + +bool Value::getString(char const** begin, char const** end) const { + if (type_ != stringValue) + return false; + if (value_.string_ == 0) + return false; + unsigned length; + decodePrefixedString(this->allocated_, this->value_.string_, &length, begin); + *end = *begin + length; + return true; +} + +JSONCPP_STRING Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: { + if (value_.string_ == 0) + return ""; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + return JSONCPP_STRING(this_str, this_len); + } + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +#ifdef JSON_USE_CPPTL +CppTL::ConstString Value::asConstString() const { + unsigned len; + char const* str; + decodePrefixedString(allocated_, value_.string_, &len, &str); + return CppTL::ConstString(str, len); +} +#endif + +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + // This can fail (silently?) if the value is bigger than MAX_FLOAT. + return static_cast(integerToDouble(value_.uint_)); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + // This is kind of strange. Not recommended. + return (value_.real_ != 0.0) ? true : false; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString().empty()) || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; +} + +Value::operator bool() const { return !isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || + type_ == objectValue, + "in Json::Value::clear(): requires complex value"); + start_ = 0; + limit_ = 0; + switch (type_) { + case arrayValue: + case objectValue: + value_.map_->clear(); + break; + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + this->operator[](newSize - 1); + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + JSON_ASSERT(size() == newSize); + } +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) + return nullSingleton(); + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return nullSingleton(); + return (*it).second; +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +void Value::initBasic(ValueType type, bool allocated) { + type_ = type; + allocated_ = allocated; + comments_ = 0; + start_ = 0; + limit_ = 0; +} + +void Value::dupPayload(const Value& other) { + type_ = other.type_; + allocated_ = false; + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::releasePayload() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::dupMeta(const Value& other) { + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment(otherComment.comment_, + strlen(otherComment.comment_)); + } + } else { + comments_ = 0; + } + start_ = other.start_; + limit_ = other.limit_; +} + +// Access an object value by name, create a null member if it does not exist. +// @pre Type of '*this' is object or null. +// @param key is null-terminated. +Value& Value::resolveReference(const char* key) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey(key, static_cast(strlen(key)), + CZString::noDuplication); // NOTE! + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +// @param key is not null-terminated. +Value& Value::resolveReference(char const* key, char const* end) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(key, end): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey(key, static_cast(end - key), + CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &nullSingleton() ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +Value const* Value::find(char const* begin, char const* end) const { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::find(key, end, found): requires " + "objectValue or nullValue"); + if (type_ == nullValue) + return NULL; + CZString actualKey(begin, static_cast(end - begin), + CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return NULL; + return &(*it).second; +} +const Value& Value::operator[](const char* key) const { + Value const* found = find(key, key + strlen(key)); + if (!found) + return nullSingleton(); + return *found; +} +Value const& Value::operator[](JSONCPP_STRING const& key) const { + Value const* found = find(key.data(), key.data() + key.length()); + if (!found) + return nullSingleton(); + return *found; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, key + strlen(key)); +} + +Value& Value::operator[](const JSONCPP_STRING& key) { + return resolveReference(key.data(), key.data() + key.length()); +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value& Value::operator[](const CppTL::ConstString& key) { + return resolveReference(key.c_str(), key.end_c_str()); +} +Value const& Value::operator[](CppTL::ConstString const& key) const { + Value const* found = find(key.c_str(), key.end_c_str()); + if (!found) + return nullSingleton(); + return *found; +} +#endif + +Value& Value::append(const Value& value) { return (*this)[size()] = value; } + +#if JSON_HAS_RVALUE_REFERENCES +Value& Value::append(Value&& value) { + return (*this)[size()] = std::move(value); +} +#endif + +Value Value::get(char const* begin, + char const* end, + Value const& defaultValue) const { + Value const* found = find(begin, end); + return !found ? defaultValue : *found; +} +Value Value::get(char const* key, Value const& defaultValue) const { + return get(key, key + strlen(key), defaultValue); +} +Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const { + return get(key.data(), key.data() + key.length(), defaultValue); +} + +bool Value::removeMember(const char* begin, const char* end, Value* removed) { + if (type_ != objectValue) { + return false; + } + CZString actualKey(begin, static_cast(end - begin), + CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return false; + if (removed) +#if JSON_HAS_RVALUE_REFERENCES + *removed = std::move(it->second); +#else + *removed = it->second; +#endif + value_.map_->erase(it); + return true; +} +bool Value::removeMember(const char* key, Value* removed) { + return removeMember(key, key + strlen(key), removed); +} +bool Value::removeMember(JSONCPP_STRING const& key, Value* removed) { + return removeMember(key.data(), key.data() + key.length(), removed); +} +void Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type_ == nullValue) + return; + + CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); + value_.map_->erase(actualKey); +} +void Value::removeMember(const JSONCPP_STRING& key) { + removeMember(key.c_str()); +} + +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type_ != arrayValue) { + return false; + } + CZString key(index); + ObjectValues::iterator it = value_.map_->find(key); + if (it == value_.map_->end()) { + return false; + } + if (removed) + *removed = it->second; + ArrayIndex oldSize = size(); + // shift left all items left, into the place of the "removed" + for (ArrayIndex i = index; i < (oldSize - 1); ++i) { + CZString keey(i); + (*value_.map_)[keey] = (*this)[i + 1]; + } + // erase the last one ("leftover") + CZString keyLast(oldSize - 1); + ObjectValues::iterator itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); + return true; +} + +#ifdef JSON_USE_CPPTL +Value Value::get(const CppTL::ConstString& key, + const Value& defaultValue) const { + return get(key.c_str(), key.end_c_str(), defaultValue); +} +#endif + +bool Value::isMember(char const* begin, char const* end) const { + Value const* value = find(begin, end); + return NULL != value; +} +bool Value::isMember(char const* key) const { + return isMember(key, key + strlen(key)); +} +bool Value::isMember(JSONCPP_STRING const& key) const { + return isMember(key.data(), key.data() + key.length()); +} + +#ifdef JSON_USE_CPPTL +bool Value::isMember(const CppTL::ConstString& key) const { + return isMember(key.c_str(), key.end_c_str()); +} +#endif + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) { + members.push_back(JSONCPP_STRING((*it).first.data(), (*it).first.length())); + } + return members; +} +// +//# ifdef JSON_USE_CPPTL +// EnumMemberNames +// Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +// EnumValues +// Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type_ == nullValue; } + +bool Value::isBool() const { return type_ == booleanValue; } + +bool Value::isInt() const { + switch (type_) { + case intValue: +#if defined(JSON_HAS_INT64) + return value_.int_ >= minInt && value_.int_ <= maxInt; +#else + return true; +#endif + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type_) { + case intValue: +#if defined(JSON_HAS_INT64) + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); +#else + return value_.int_ >= 0; +#endif + case uintValue: +#if defined(JSON_HAS_INT64) + return value_.uint_ <= maxUInt; +#else + return true; +#endif + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { + switch (type_) { + case intValue: + case uintValue: + return true; + case realValue: +#if defined(JSON_HAS_INT64) + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); +#else + return value_.real_ >= minInt && value_.real_ <= maxUInt && + IsIntegral(value_.real_); +#endif // JSON_HAS_INT64 + default: + break; + } + return false; +} + +bool Value::isDouble() const { + return type_ == intValue || type_ == uintValue || type_ == realValue; +} + +bool Value::isNumeric() const { return isDouble(); } + +bool Value::isString() const { return type_ == stringValue; } + +bool Value::isArray() const { return type_ == arrayValue; } + +bool Value::isObject() const { return type_ == objectValue; } + +void Value::setComment(const char* comment, + size_t len, + CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + if ((len > 0) && (comment[len - 1] == '\n')) { + // Always discard trailing newline, to aid indentation. + len -= 1; + } + comments_[placement].setComment(comment, len); +} + +void Value::setComment(const char* comment, CommentPlacement placement) { + setComment(comment, strlen(comment), placement); +} + +void Value::setComment(const JSONCPP_STRING& comment, + CommentPlacement placement) { + setComment(comment.c_str(), comment.length(), placement); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +JSONCPP_STRING Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; +} + +void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } + +void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } + +ptrdiff_t Value::getOffsetStart() const { return start_; } + +ptrdiff_t Value::getOffsetLimit() const { return limit_; } + +JSONCPP_STRING Value::toStyledString() const { + StreamWriterBuilder builder; + + JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : ""; + out += Json::writeString(builder, *this); + out += '\n'; + + return out; +} + +Value::const_iterator Value::begin() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; + default: + break; + } + return const_iterator(); +} + +Value::const_iterator Value::end() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; + default: + break; + } + return const_iterator(); +} + +Value::iterator Value::begin() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} + +PathArgument::PathArgument(ArrayIndex index) + : key_(), index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) + : key_(key), index_(), kind_(kindKey) {} + +PathArgument::PathArgument(const JSONCPP_STRING& key) + : key_(key.c_str()), index_(), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const JSONCPP_STRING& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.reserve(5); + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *++current != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.' || *current == ']') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(JSONCPP_STRING(beginName, current)); + } + } +} + +void Path::addPathInArg(const JSONCPP_STRING& /*path*/, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg++); + } +} + +void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + return Value::null; + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + return Value::null; + } + node = &((*node)[arg.key_]); + if (node == &Value::nullSingleton()) { + // Error: unable to resolve path (object has no member named '' at + // position...) + return Value::null; + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::nullSingleton()) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include + +#if !defined(isnan) +#define isnan std::isnan +#endif + +#if !defined(isfinite) +#define isfinite std::isfinite +#endif + +#if !defined(snprintf) +#define snprintf std::snprintf +#endif +#else +#include +#include + +#if defined(_MSC_VER) +#if !defined(isnan) +#include +#define isnan _isnan +#endif + +#if !defined(isfinite) +#include +#define isfinite _finite +#endif + +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#if !defined(snprintf) +#define snprintf _snprintf +#endif +#endif + +#if defined(__sun) && defined(__SVR4) // Solaris +#if !defined(isfinite) +#include +#define isfinite finite +#endif +#endif + +#if defined(__hpux) +#if !defined(isfinite) +#if defined(__ia64) && !defined(finite) +#define isfinite(x) \ + ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) +#endif +#endif +#endif + +#if !defined(isnan) +// IEEE standard states that NaN values will not compare to themselves +#define isnan(x) (x != x) +#endif + +#if !defined(isfinite) +#define isfinite finite +#endif +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) +typedef std::unique_ptr StreamWriterPtr; +#else +typedef std::auto_ptr StreamWriterPtr; +#endif + +JSONCPP_STRING valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + if (value == Value::minLargestInt) { + uintToString(LargestUInt(Value::maxLargestInt) + 1, current); + *--current = '-'; + } else if (value < 0) { + uintToString(LargestUInt(-value), current); + *--current = '-'; + } else { + uintToString(LargestUInt(value), current); + } + assert(current >= buffer); + return current; +} + +JSONCPP_STRING valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +JSONCPP_STRING valueToString(Int value) { + return valueToString(LargestInt(value)); +} + +JSONCPP_STRING valueToString(UInt value) { + return valueToString(LargestUInt(value)); +} + +#endif // # if defined(JSON_HAS_INT64) + +namespace { +JSONCPP_STRING valueToString(double value, + bool useSpecialFloats, + unsigned int precision, + PrecisionType precisionType) { + // Print into the buffer. We need not request the alternative representation + // that always has a decimal point because JSON doesn't distinguish the + // concepts of reals and integers. + if (!isfinite(value)) { + static const char* const reps[2][3] = { { "NaN", "-Infinity", "Infinity" }, + { "null", "-1e+9999", "1e+9999" } }; + return reps[useSpecialFloats ? 0 : 1] + [isnan(value) ? 0 : (value < 0) ? 1 : 2]; + } + + JSONCPP_STRING buffer(size_t(36), '\0'); + while (true) { + int len = snprintf( + &*buffer.begin(), buffer.size(), + (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", + precision, value); + assert(len >= 0); + size_t wouldPrint = static_cast(len); + if (wouldPrint >= buffer.size()) { + buffer.resize(wouldPrint + 1); + continue; + } + buffer.resize(wouldPrint); + break; + } + + buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); + + // strip the zero padding from the right + if (precisionType == PrecisionType::decimalPlaces) { + buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end()); + } + + // try to ensure we preserve the fact that this was given to us as a double on + // input + if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { + buffer += ".0"; + } + return buffer; +} +} // namespace + +JSONCPP_STRING valueToString(double value, + unsigned int precision, + PrecisionType precisionType) { + return valueToString(value, false, precision, precisionType); +} + +JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; } + +static bool isAnyCharRequiredQuoting(char const* s, size_t n) { + assert(s || !n); + + char const* const end = s + n; + for (char const* cur = s; cur < end; ++cur) { + if (*cur == '\\' || *cur == '\"' || *cur < ' ' || + static_cast(*cur) < 0x80) + return true; + } + return false; +} + +static unsigned int utf8ToCodepoint(const char*& s, const char* e) { + const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; + + unsigned int firstByte = static_cast(*s); + + if (firstByte < 0x80) + return firstByte; + + if (firstByte < 0xE0) { + if (e - s < 2) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = + ((firstByte & 0x1F) << 6) | (static_cast(s[1]) & 0x3F); + s += 1; + // oversized encoded characters are invalid + return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF0) { + if (e - s < 3) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x0F) << 12) | + ((static_cast(s[1]) & 0x3F) << 6) | + (static_cast(s[2]) & 0x3F); + s += 2; + // surrogates aren't valid codepoints itself + // shouldn't be UTF-8 encoded + if (calculated >= 0xD800 && calculated <= 0xDFFF) + return REPLACEMENT_CHARACTER; + // oversized encoded characters are invalid + return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF8) { + if (e - s < 4) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x07) << 18) | + ((static_cast(s[1]) & 0x3F) << 12) | + ((static_cast(s[2]) & 0x3F) << 6) | + (static_cast(s[3]) & 0x3F); + s += 3; + // oversized encoded characters are invalid + return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; + } + + return REPLACEMENT_CHARACTER; +} + +static const char hex2[] = "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + +static JSONCPP_STRING toHex16Bit(unsigned int x) { + const unsigned int hi = (x >> 8) & 0xff; + const unsigned int lo = x & 0xff; + JSONCPP_STRING result(4, ' '); + result[0] = hex2[2 * hi]; + result[1] = hex2[2 * hi + 1]; + result[2] = hex2[2 * lo]; + result[3] = hex2[2 * lo + 1]; + return result; +} + +static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { + if (value == NULL) + return ""; + + if (!isAnyCharRequiredQuoting(value, length)) + return JSONCPP_STRING("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to JSONCPP_STRING is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL + JSONCPP_STRING result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + char const* end = value + length; + for (const char* c = value; c != end; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something.) + // blep notes: actually escaping \/ may be useful in javascript to avoid = 0x20) + result += static_cast(cp); + else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane + result += "\\u"; + result += toHex16Bit(cp); + } else { // codepoint is not in Basic Multilingual Plane + // convert to surrogate pair first + cp -= 0x10000; + result += "\\u"; + result += toHex16Bit((cp >> 10) + 0xD800); + result += "\\u"; + result += toHex16Bit((cp & 0x3FF) + 0xDC00); + } + } break; + //default: { + // result += *c; + //}break; + //xwj --------------- + } + } + result += "\""; + return result; +} + +JSONCPP_STRING valueToQuotedString(const char* value) { + return valueToQuotedStringN(value, static_cast(strlen(value))); +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() {} + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false), + omitEndingLineFeed_(false) {} + +void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } + +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } + +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } + +JSONCPP_STRING FastWriter::write(const Value& root) { + document_.clear(); + writeValue(root); + if (!omitEndingLineFeed_) + document_ += '\n'; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + document_ += valueToQuotedStringN(str, static_cast(end - str)); + break; + } + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + ArrayIndex size = value.size(); + for (ArrayIndex index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); + } + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const JSONCPP_STRING& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedStringN(name.data(), + static_cast(name.length())); + document_ += yamlCompatibilityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_(74), indentSize_(3), addChildValues_() {} + +JSONCPP_STRING StyledWriter::write(const Value& root) { + document_.clear(); + addChildValues_ = false; + indentString_.clear(); + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += '\n'; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const JSONCPP_STRING& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultilineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultilineArray(const Value& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const JSONCPP_STRING& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { + indentString_ += JSONCPP_STRING(indentSize_, ' '); +} + +void StyledWriter::unindent() { + assert(indentString_.size() >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += '\n'; + writeIndent(); + const JSONCPP_STRING& comment = root.getComment(commentBefore); + JSONCPP_STRING::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + document_ += *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + writeIndent(); + ++iter; + } + + // Comments are stripped of trailing newlines, so add one here + document_ += '\n'; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + document_ += '\n'; + document_ += root.getComment(commentAfter); + document_ += '\n'; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(const JSONCPP_STRING& indentation) + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_(), indented_(false) {} + +void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_.clear(); + indented_ = true; + writeCommentBeforeValue(root); + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const JSONCPP_STRING& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultilineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultilineArray(const Value& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) { + if (!indented_) + writeIndent(); + *document_ << value; + indented_ = false; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) + writeIndent(); + const JSONCPP_STRING& comment = root.getComment(commentBefore); + JSONCPP_STRING::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *document_ << *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would include newline + *document_ << indentString_; + ++iter; + } + indented_ = false; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << ' ' << root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *document_ << root.getComment(commentAfter); + } + indented_ = false; +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +////////////////////////// +// BuiltStyledStreamWriter + +/// Scoped enums are not available until C++11. +struct CommentStyle { + /// Decide whether to write comments. + enum Enum { + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. + }; +}; + +struct BuiltStyledStreamWriter : public StreamWriter { + BuiltStyledStreamWriter(JSONCPP_STRING const& indentation, + CommentStyle::Enum cs, + JSONCPP_STRING const& colonSymbol, + JSONCPP_STRING const& nullSymbol, + JSONCPP_STRING const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision, + PrecisionType precisionType); + int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE; + +private: + void writeValue(Value const& value); + void writeArrayValue(Value const& value); + bool isMultilineArray(Value const& value); + void pushValue(JSONCPP_STRING const& value); + void writeIndent(); + void writeWithIndent(JSONCPP_STRING const& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(Value const& root); + void writeCommentAfterValueOnSameLine(Value const& root); + static bool hasCommentForValue(const Value& value); + + typedef std::vector ChildValues; + + ChildValues childValues_; + JSONCPP_STRING indentString_; + unsigned int rightMargin_; + JSONCPP_STRING indentation_; + CommentStyle::Enum cs_; + JSONCPP_STRING colonSymbol_; + JSONCPP_STRING nullSymbol_; + JSONCPP_STRING endingLineFeedSymbol_; + bool addChildValues_ : 1; + bool indented_ : 1; + bool useSpecialFloats_ : 1; + unsigned int precision_; + PrecisionType precisionType_; +}; +BuiltStyledStreamWriter::BuiltStyledStreamWriter( + JSONCPP_STRING const& indentation, + CommentStyle::Enum cs, + JSONCPP_STRING const& colonSymbol, + JSONCPP_STRING const& nullSymbol, + JSONCPP_STRING const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision, + PrecisionType precisionType) + : rightMargin_(74), indentation_(indentation), cs_(cs), + colonSymbol_(colonSymbol), nullSymbol_(nullSymbol), + endingLineFeedSymbol_(endingLineFeedSymbol), addChildValues_(false), + indented_(false), useSpecialFloats_(useSpecialFloats), + precision_(precision), precisionType_(precisionType) {} +int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout) { + sout_ = sout; + addChildValues_ = false; + indented_ = true; + indentString_.clear(); + writeCommentBeforeValue(root); + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *sout_ << endingLineFeedSymbol_; + sout_ = NULL; + return 0; +} +void BuiltStyledStreamWriter::writeValue(Value const& value) { + switch (value.type()) { + case nullValue: + pushValue(nullSymbol_); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, + precisionType_)); + break; + case stringValue: { + // Is NULL is possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + JSONCPP_STRING const& name = *it; + Value const& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedStringN( + name.data(), static_cast(name.length()))); + *sout_ << colonSymbol_; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); + if (isMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + Value const& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *sout_ << "["; + if (!indentation_.empty()) + *sout_ << " "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *sout_ << ((!indentation_.empty()) ? ", " : ","); + *sout_ << childValues_[index]; + } + if (!indentation_.empty()) + *sout_ << " "; + *sout_ << "]"; + } + } +} + +bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + Value const& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *sout_ << value; +} + +void BuiltStyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + + if (!indentation_.empty()) { + // In this case, drop newlines too. + *sout_ << '\n' << indentString_; + } +} + +void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) { + if (!indented_) + writeIndent(); + *sout_ << value; + indented_ = false; +} + +void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } + +void BuiltStyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { + if (cs_ == CommentStyle::None) + return; + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) + writeIndent(); + const JSONCPP_STRING& comment = root.getComment(commentBefore); + JSONCPP_STRING::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *sout_ << *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would write extra newline + *sout_ << indentString_; + ++iter; + } + indented_ = false; +} + +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( + Value const& root) { + if (cs_ == CommentStyle::None) + return; + if (root.hasComment(commentAfterOnSameLine)) + *sout_ << " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *sout_ << root.getComment(commentAfter); + } +} + +// static +bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +/////////////// +// StreamWriter + +StreamWriter::StreamWriter() : sout_(NULL) {} +StreamWriter::~StreamWriter() {} +StreamWriter::Factory::~Factory() {} +StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } +StreamWriterBuilder::~StreamWriterBuilder() {} +StreamWriter* StreamWriterBuilder::newStreamWriter() const { + JSONCPP_STRING indentation = settings_["indentation"].asString(); + JSONCPP_STRING cs_str = settings_["commentStyle"].asString(); + JSONCPP_STRING pt_str = settings_["precisionType"].asString(); + bool eyc = settings_["enableYAMLCompatibility"].asBool(); + bool dnp = settings_["dropNullPlaceholders"].asBool(); + bool usf = settings_["useSpecialFloats"].asBool(); + unsigned int pre = settings_["precision"].asUInt(); + CommentStyle::Enum cs = CommentStyle::All; + if (cs_str == "All") { + cs = CommentStyle::All; + } else if (cs_str == "None") { + cs = CommentStyle::None; + } else { + throwRuntimeError("commentStyle must be 'All' or 'None'"); + } + PrecisionType precisionType(significantDigits); + if (pt_str == "significant") { + precisionType = PrecisionType::significantDigits; + } else if (pt_str == "decimal") { + precisionType = PrecisionType::decimalPlaces; + } else { + throwRuntimeError("precisionType must be 'significant' or 'decimal'"); + } + JSONCPP_STRING colonSymbol = " : "; + if (eyc) { + colonSymbol = ": "; + } else if (indentation.empty()) { + colonSymbol = ":"; + } + JSONCPP_STRING nullSymbol = "null"; + if (dnp) { + nullSymbol.clear(); + } + if (pre > 17) + pre = 17; + JSONCPP_STRING endingLineFeedSymbol; + return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, + endingLineFeedSymbol, usf, pre, + precisionType); +} +static void getValidWriterKeys(std::set* valid_keys) { + valid_keys->clear(); + valid_keys->insert("indentation"); + valid_keys->insert("commentStyle"); + valid_keys->insert("enableYAMLCompatibility"); + valid_keys->insert("dropNullPlaceholders"); + valid_keys->insert("useSpecialFloats"); + valid_keys->insert("precision"); + valid_keys->insert("precisionType"); +} +bool StreamWriterBuilder::validate(Json::Value* invalid) const { + Json::Value my_invalid; + if (!invalid) + invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidWriterKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + JSONCPP_STRING const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& StreamWriterBuilder::operator[](JSONCPP_STRING key) { + return settings_[key]; +} +// static +void StreamWriterBuilder::setDefaults(Json::Value* settings) { + //! [StreamWriterBuilderDefaults] + (*settings)["commentStyle"] = "All"; + (*settings)["indentation"] = "\t"; + (*settings)["enableYAMLCompatibility"] = false; + (*settings)["dropNullPlaceholders"] = false; + (*settings)["useSpecialFloats"] = false; + (*settings)["precision"] = 17; + (*settings)["precisionType"] = "significant"; + //! [StreamWriterBuilderDefaults] +} + +JSONCPP_STRING writeString(StreamWriter::Factory const& factory, + Value const& root) { + JSONCPP_OSTRINGSTREAM sout; + StreamWriterPtr const writer(factory.newStreamWriter()); + writer->write(root, &sout); + return sout.str(); +} + +JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) { + StreamWriterBuilder builder; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + diff --git a/AlgorithmModule/example/test_example.cpp b/AlgorithmModule/example/test_example.cpp new file mode 100644 index 0000000..f5b44ca --- /dev/null +++ b/AlgorithmModule/example/test_example.cpp @@ -0,0 +1,357 @@ +#include +#include +#include +#include "deal.h" +#include +#include +#include +#include +#include "Read_Image.h" +void handler(int sig) +{ + printf("Get handler sig"); + string strcmd = "ps -ef | grep test_JBL_Check| awk '{print $2}' | xargs kill -9 "; + const char *cmd = strcmd.c_str(); + printf("delete test_JBL_Check success"); + if (-1 == system(cmd)) + { + std::cout << "error" << std::endl; + } + + // delete UnderCarriageCoreLogic::GetInstance(); + exit(0); +} + +int _sysmkdir(const std::string &dir) +{ + int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (ret && errno == EEXIST) + { + printf("dir[%s] already exist.\n", dir.c_str()); + } + else if (ret) + { + printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno)); + return -1; + } + else + { + printf("create dir[%s] success.\n", dir.c_str()); + } + return 0; +} +std::string __getParentDir(const std::string &dir) +{ + std::string pdir = dir; + if (pdir.length() < 1 || (pdir[0] != '/')) + { + return ""; + } + while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/')) + pdir = pdir.substr(0, pdir.length() - 1); + + pdir = pdir.substr(0, pdir.find_last_of('/')); + return pdir; +} +int _sysmkdirs(const std::string &dir) +{ + int ret = 0; + if (dir.empty()) + return -1; + std::string pdir; + if ((ret = _sysmkdir(dir)) == -1) + { + pdir = __getParentDir(dir); + if ((ret = _sysmkdirs(pdir)) == 0) + { + ret = _sysmkdirs(dir); + } + } + + return ret; +} +int redimg_16() +{ + + std::string strImgPath = "/home/aidlux/BOE_CELL_ET/Image/20250718/left/__DB__6LQR560030C6BBA/*.tif"; + // std::cout << strImgPath << std::endl; + std::vector img_paths; + + cv::glob(strImgPath, img_paths, true); + for (int i = 0; i < img_paths.size(); i++) + { + std::string filename = img_paths[i]; + std::cout << filename << std::endl; + size_t pos1 = filename.find('^'); + size_t pos2 = filename.rfind(".tif"); // 或 ".tif" 的起始位置 + std::string result; + + if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1) + { + result = filename.substr(pos1 + 1, pos2 - pos1 - 1); + std::cout << "提取的内容: " << result << std::endl; + } + else + { + std::cerr << "格式不匹配,无法提取" << std::endl; + } + + cv::Mat img16 = cv::imread(filename, cv::IMREAD_UNCHANGED); + + if (img16.empty()) + { + std::cerr << "无法读取图像: " << filename << std::endl; + return -1; + } + + cv::Mat img8; + if (img16.type() == CV_16U) + { + cv::normalize(img16, img8, 0, 255, cv::NORM_MINMAX); + img8.convertTo(img8, CV_8U); + } + else if (img16.type() == CV_8U) + { + + img8 = img16; + } + else + { + std::cerr << "图像不是 16 / 8位灰度图,type = " << img16.type() << std::endl; + continue; + } + + std::cout << "读取成功: " << img16.cols << " x " << img16.rows << ",类型: CV_16U" << std::endl; + + // 方式一:线性映射(缩放到0~255) + // double minVal, maxVal; + // cv::minMaxLoc(img16, &minVal, &maxVal); + // std::cout << "图像值范围: [" << minVal << ", " << maxVal << "]" << std::endl; + + // cv::Mat img8; + // img16.convertTo(img8, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); + + // 方式二(如果你知道最大值就是 65535,也可以直接缩放): + // img16.convertTo(img8, CV_8U, 1.0 / 256.0); // 65536 -> 256 缩放 + + // 保存或显示结果 + cv::imwrite(result + "o11utput_8bit_gray.png", img8); + } + getchar(); + std::string filename = "/home/aidlux/BOE_CELL_ET/Image/20250718/left/__DB__6LQR560030C6BBA/6LQR560030C6BBA^L127.tif"; + + // 使用 IMREAD_UNCHANGED 保留原始位深 + cv::Mat img16 = cv::imread(filename, cv::IMREAD_UNCHANGED); + if (img16.empty()) + { + std::cerr << "无法读取图像: " << filename << std::endl; + return -1; + } + + // 检查是否是 16 位灰度图 + if (img16.type() != CV_16U) + { + std::cerr << "图像不是 16 位灰度图,type = " << img16.type() << std::endl; + return -1; + } + + std::cout << "读取成功: " << img16.cols << " x " << img16.rows << ",类型: CV_16U" << std::endl; + + // 方式一:线性映射(缩放到0~255) + double minVal, maxVal; + cv::minMaxLoc(img16, &minVal, &maxVal); + std::cout << "图像值范围: [" << minVal << ", " << maxVal << "]" << std::endl; + + cv::Mat img8; + img16.convertTo(img8, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); + + // 方式二(如果你知道最大值就是 65535,也可以直接缩放): + // img16.convertTo(img8, CV_8U, 1.0 / 256.0); // 65536 -> 256 缩放 + + // 保存或显示结果 + cv::imwrite("output_8bit_gray.png", img8); + // cv::imshow("8-bit Gray", img8); + // cv::waitKey(0); + return 0; +} +int main(int argc, char *argv[]) +{ + std::cout << "CHECK_WORK: " << CHECK_WORK << std::endl; + deal test; + + for (int i = 0; i < Check_Work_COUNT; i++) + { + if (CHECK_WORK == Check_Work_Name[i]) + { + test.m_check_Work_Type = static_cast(i); + break; + } + } + if (test.m_check_Work_Type == Check_Work_NULL) + { + + cout << "***********************work type Error *******************************" << endl; + return 0; + } + + if (argc > 1 && string(argv[1]) == "-h") + { + cout << "******************************************************" << endl; + cout << "*** 1、./test_JBL_Check: 默认处理一套图 图片文件夹位于 ../data/img/t1,结果位于/home/aidlux/BOE/testresult" << endl; + cout << "*** 2、./test_JBL_Check -s: 1 的基础上增加 过程存图,包括edge 和字符检测的中间结果存图,图片位于 当前文件夹。" << endl; + cout << "*** 3、./test_JBL_Check -fjc filepath: 处理精测套图大图 结果位于/home/aidlux/BOE/ResultImg" << endl; + cout << "*** 4、./test_JBL_Check -feai filepath num: 批量测试边缘检测算法,num 至多处理张数,结果:/home/aidlux/BOE/Edge" << endl; + cout << "*** 5、./test_JBL_Check -falign filepath num : 批量测试定位算法,num 至多处理张数,结果:/home/aidlux/BOE/Align" << endl; + cout << "*** 6、./test_JBL_Check -rjson filepath: 单张复测,filepath xx/xx/3A3K380001B1DK_20240408_152157_Main_0_2_L255" << endl; + cout << "*** 6、./test_JBL_Check -rjsonall filepath: 一套图复测,filepath xx/xx/" << endl; + cout << "******************************************************" << endl; + return 0; + } + + // redimg_16(); + // Read_Image dfe; + // dfe.Read_Image_List("../data/img/pre"); + // //dfe.Read_Image_List("/home/aidlux/BD_AOI/Data/SmallImage/60HW"); + // getchar(); + printf("argc = %d\n", argc); + for (int i = 0; i < argc; i++) + { + printf("argv[%d]=%s\n", i, argv[i]); + } + + test.m_nRunType = RUNTYPE_RUN_Pre_BigImg; // 大图 + test.m_strCheckFilePath = ""; + if (argc > 1 && string(argv[1]) != "-h") + { + { + if (string(argv[1]) == "-f") // 遍历检查武汉精测图片 + { + test.m_nRunType = RUNTYPE_RUN_File_BigImg; // 大图 + if (argc == 3) + { + test.m_strCheckFilePath = string(argv[2]); + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + else if (string(argv[1]) == "-fai") // 遍历检查武汉精测图片 + { + test.m_nRunType = RUNTYPE_RUN_File_BigImg; // 大图 + test.m_nTestAI = 1; + if (argc == 3) + { + test.m_strCheckFilePath = string(argv[2]); + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + else if (string(argv[1]) == "-fc2") + { + test.m_nRunType = RUNTYPE_RUN_Pre_BigImg_Cam2; // + + if (argc == 3) + { + if (string(argv[1]) == "-s") + { + test.m_nSaveDetprocessImg = 1; + } + } + } + else if (string(argv[1]) == "-fmark") + { + test.m_nRunType = RUNTYPE_RUN_File_MarkLine_Test; // + if (argc == 3) + { + test.m_strCheckFilePath = string(argv[2]); + test.m_nTestNum == 9999999; + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + else if (string(argv[1]) == "-fe") + { + test.m_nRunType = RUNTYPE_RUN_File_BigImg_WHJC_EDGE_TEST; // + if (argc == 3) + { + test.m_strCheckFilePath = string(argv[2]); + test.m_nTestNum == 9999999; + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + else if (string(argv[1]) == "-fcell") + { + test.m_nRunType = RUNTYPE_RUN_File_CEEL_ET; // + if (argc == 3) + { + test.m_strCheckFilePath = string(argv[2]); + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + else if (string(argv[1]) == "-feai") + { + test.m_nRunType = RUNTYPE_RUN_File_BigImg_WHJC_EDGE_AI_TEST; // + if (argc == 3) + { + test.m_strCheckFilePath = string(argv[2]); + test.m_nTestNum == 9999999; + } + else if (argc == 4) + { + test.m_strCheckFilePath = string(argv[2]); + std::string strnum = string(argv[3]); + test.m_nTestNum = atoi(strnum.c_str()); + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + else + { + if (string(argv[1]) == "-s") + { + test.m_nSaveDetprocessImg = 1; + } + else + { + cout << "参数错误 ------- " << endl; + return 0; + } + } + } + } + + for (int i = 0; i < argc; ++i) + { + std::cout << "Argument #" << i << ": " << argv[i] << std::endl; + } + printf("m_nRunType %d m_nSaveDetprocessImg %d path %s\n", test.m_nRunType, test.m_nSaveDetprocessImg, test.m_strCheckFilePath.c_str()); + // getchar(); + signal(SIGINT, handler); + test.start(); + + while (true) + { + usleep(10 * 1000); + } + + return 0; +} diff --git a/AlgorithmModule/include/AICheck.h b/AlgorithmModule/include/AICheck.h new file mode 100644 index 0000000..2ec878f --- /dev/null +++ b/AlgorithmModule/include/AICheck.h @@ -0,0 +1,216 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef AICheck_H_ +#define AICheck_H_ + +// #define USE_TERNSORRT10_BIGMODEL + +#define CUDA_API_PER_THREAD_DEFAULT_STREAM 1 + +#include +#include +#include +#ifdef USE_TERNSORRT10_BIGMODEL + +#include "NvInfer.h" +#include "cuda_runtime_api.h" +using namespace nvinfer1; +#else +#include "argsParser.h" +#include "buffers.h" +#include "common.h" +#include "logger.h" +#include "NvCaffeParser.h" +#include "NvInfer.h" +#include "cuda_runtime_api.h" +#endif +using namespace std; + +#define MAX_AI_BUFFER_SIZE 5 + +enum AIBufferType_ +{ + AIBufferType_NULL, // default + AIBufferType_IN, // 输入 + AIBufferType_OUT, // 输出 +}; +struct AIBuffer +{ + int ntype; // 数据类型 AIBufferType_ + int ndatalength; // 数据长度 + int ndataSize; // 数据字节大小 ndatalength*sizeof(float) + int nuchardataSize; // 数据字节大小 ndatalength*sizeof(char) + std::string strName; // 名称 + AIBuffer() + { + ntype = AIBufferType_NULL; + ndatalength = 0; + ndataSize = 0; + nuchardataSize = 0; + strName = ""; + } + void copy(AIBuffer tem) + { + this->ntype = tem.ntype; + this->ndatalength = tem.ndatalength; + this->ndataSize = tem.ndataSize; + this->nuchardataSize = tem.nuchardataSize; + this->strName = tem.strName; + } + void print(std::string str = "") + { + printf("ntype %d strName %s ndatalength %d ndataSize %d nuchardataSize %d\n", ntype, strName.c_str(), ndatalength, ndataSize, nuchardataSize); + } +}; + +struct AIInitConfig +{ + int nGpuIdx; + AIBuffer bufferList[MAX_AI_BUFFER_SIZE]; + std::string engine_file_path; + AIInitConfig() + { + nGpuIdx = -1; + engine_file_path = ""; + } + void copy(AIInitConfig tem) + { + this->nGpuIdx = tem.nGpuIdx; + this->engine_file_path = tem.engine_file_path; + for (int i = 0; i < MAX_AI_BUFFER_SIZE; i++) + { + this->bufferList[i].copy(tem.bufferList[i]); + } + } + bool Checking() + { + if (nGpuIdx < 0 || nGpuIdx > 4) + { + return false; + } + if (engine_file_path.empty()) + { + return false; + } + + // 第一个不是 输入 + if (bufferList[0].ntype != AIBufferType_IN) + { + return false; + } + // 第二个是 空 + if (bufferList[1].ntype == AIBufferType_NULL) + { + return false; + } + + bool bhaveout = false; + int npretype = AIBufferType_IN; + for (int i = 1; i < MAX_AI_BUFFER_SIZE; i++) + { + // 前序是in + if (npretype == AIBufferType_IN) + { + if (bufferList[i].ntype == AIBufferType_IN) + { + continue; + } + else if (bufferList[i].ntype == AIBufferType_OUT) + { + npretype = AIBufferType_OUT; + bhaveout = true; + } + else + { + return false; + } + } + else if (npretype == AIBufferType_OUT) + { + if (bufferList[i].ntype == AIBufferType_IN) + { + return false; + } + else if (bufferList[i].ntype == AIBufferType_OUT) + { + continue; + } + else + { + npretype = AIBufferType_NULL; + } + } + else + { + if (bufferList[i].ntype == AIBufferType_IN) + { + return false; + } + else if (bufferList[i].ntype == AIBufferType_OUT) + { + return false; + } + else + { + npretype = AIBufferType_NULL; + } + } + } + + if (!bhaveout) + { + return false; + } + + return true; + } + void CalSize(int mulSzie) + { + for (int i = 0; i < MAX_AI_BUFFER_SIZE; i++) + { + if (bufferList[i].ntype == AIBufferType_NULL) + { + continue; + } + bufferList[i].ndataSize = bufferList[i].ndatalength * mulSzie; + bufferList[i].nuchardataSize = bufferList[i].ndatalength * sizeof(unsigned char); + } + } +}; +class AI_defect +{ +public: + AI_defect(); + ~AI_defect(); + int model_init(AIInitConfig config); + + int model_Cuda_AI_In_1_Out_1(unsigned char *p_indata_0, unsigned char *p_outdata_1); + int model_Cuda_AI_In_1_Out_1_float(unsigned char *p_indata_0, float *p_outdata_1); + +private: + void destroy(); + +private: + IRuntime *runtime; + ICudaEngine *engine; + IExecutionContext *context; + void *buffers[MAX_AI_BUFFER_SIZE]; + void *ImgData[MAX_AI_BUFFER_SIZE]; // uchar + const int BATCH_SIZE = 1; + + bool m_bInitialized; + + std::mutex g_mutex; + AIInitConfig m_config; + float* floatData[MAX_AI_BUFFER_SIZE]; + + int kk = 0; +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/AIClassify.h b/AlgorithmModule/include/AIClassify.h new file mode 100644 index 0000000..25431bc --- /dev/null +++ b/AlgorithmModule/include/AIClassify.h @@ -0,0 +1,66 @@ +/* +//图片基本处理 + */ +#ifndef AIClassify_H_ +#define AIClassify_H_ +#include +using namespace std; + +struct AI_PIECE_INFO +{ + int num; + int len; + int abs_L; + int long_num; + int short_num; + AI_PIECE_INFO() + { + num = 0; + len = 0; + abs_L = 0; + long_num = 0; + short_num = 0; + } + void print(std::string str) + { + printf("%s>> num %d len %d abs_L %d long_num %d short_num %d\n", str.c_str(), num, len, abs_L, long_num, short_num); + } +}; +struct AI_Classify_Info +{ + int num; // 数量 + float score; // 得分 + float avgScore; // 平均得分 + AI_Classify_Info() + { + Init(); + } + void Init() + { + num = 0; + score = 0; + avgScore = 0; + } + void print(std::string str) + { + printf("%s==== num %d score %f avgScore %f\n", str.c_str(), num, score, avgScore); + } +}; + +class AIClassify +{ + +public: + AIClassify(); + ~AIClassify(); + // 分类 + int GetDetRoiList(const cv::Mat &src_Img, cv::Rect qx_roi, std::vector &samllRoiList); + +private: + cv::Rect GetCutRoi(cv::Rect roi, const cv::Mat &img); + // 获取检测roi list + +private: +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/AICommonDefine.h b/AlgorithmModule/include/AICommonDefine.h new file mode 100644 index 0000000..d575f4f --- /dev/null +++ b/AlgorithmModule/include/AICommonDefine.h @@ -0,0 +1,231 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef AICommonDefine_H_ +#define AICommonDefine_H_ + +// nf 输入图片尺寸 +#define AI_NF_IN_0_IMAGE_WIDTH 1024 +#define AI_NF_IN_0_IMAGE_HEIGHT 1024 +#define AI_NF_IN_0_IMAGE_CHANNEL 1 +#define AI_NF_IN_0_DATA_LENGTH AI_NF_IN_0_IMAGE_WIDTH *AI_NF_IN_0_IMAGE_HEIGHT *AI_NF_IN_0_IMAGE_CHANNEL +#define AI_NF_IN_0_IMAGE_Name "0" +// nf 输入图片尺寸 +#define AI_NF_out_0_IMAGE_WIDTH 512 +#define AI_NF_out_0_IMAGE_HEIGHT 512 +#define AI_NF_out_0_IMAGE_CHANNEL 1 +#define AI_NF_out_0_DATA_LENGTH AI_NF_out_0_IMAGE_WIDTH *AI_NF_out_0_IMAGE_HEIGHT *AI_NF_out_0_IMAGE_CHANNEL +#define AI_NF_out_0_IMAGE_Name "491" +// nf 输入图片尺寸 +#define AI_NF_out_1_IMAGE_WIDTH 512 +#define AI_NF_out_1_IMAGE_HEIGHT 512 +#define AI_NF_out_1_IMAGE_CHANNEL 1 +#define AI_NF_out_1_DATA_LENGTH AI_NF_out_1_IMAGE_WIDTH *AI_NF_out_1_IMAGE_HEIGHT *AI_NF_out_1_IMAGE_CHANNEL + +// YS 输入图片尺寸 +#define AI_YX_IN_0_IMAGE_WIDTH 1024 +#define AI_YX_IN_0_IMAGE_HEIGHT 640 +#define AI_YX_IN_0_IMAGE_CHANNEL 1 +#define AI_YX_IN_0_DATA_LENGTH AI_YX_IN_0_IMAGE_WIDTH *AI_YX_IN_0_IMAGE_HEIGHT *AI_YX_IN_0_IMAGE_CHANNEL +#define AI_YX_IN_0_IMAGE_Name "0" +// nf 输入图片尺寸 +#define AI_YX_out_0_IMAGE_WIDTH 1024 +#define AI_YX_out_0_IMAGE_HEIGHT 640 +#define AI_YX_out_0_IMAGE_CHANNEL 1 +#define AI_YX_out_0_DATA_LENGTH AI_YX_out_0_IMAGE_WIDTH *AI_YX_out_0_IMAGE_HEIGHT *AI_YX_out_0_IMAGE_CHANNEL +#define AI_YX_out_0_IMAGE_Name "480" +#define USE_WHITEBACK_CLASS 1 +// 1023 +#define AI_Cls_IN_0_IMAGE_WIDTH 160 +#define AI_Cls_IN_0_IMAGE_HEIGHT 160 +#define AICls_IN_0_IMAGE_CHANNEL 3 +#define AI_Cls_IN_0_IMAGE_DATA_LENGTH AI_Cls_IN_0_IMAGE_WIDTH *AI_Cls_IN_0_IMAGE_HEIGHT *AICls_IN_0_IMAGE_CHANNEL +#define AI_Cls_IN_0_IMAGE_Name "0" +// #define AI_Cls_out_0_IMAGE_WIDTH 5 //5---9---20231118 +// #define AI_Cls_out_0_IMAGE_WIDTH 9 //5---9---20231118 +#define AI_Cls_out_0_IMAGE_WIDTH 16 // 9---10---20231126 +#define AI_Cls_out_0_IMAGE_HEIGHT 1 +#define AI_Cls_out_0_IMAGE_CHANNEL 1 +#define AI_Cls_out_0_IMAGE_DATA_LENGTH AI_Cls_out_0_IMAGE_WIDTH *AI_Cls_out_0_IMAGE_HEIGHT *AI_Cls_out_0_IMAGE_CHANNEL +#define AI_Cls_out_0_IMAGE_Name "570" + +#define AI_Cls_14_out_0_IMAGE_WIDTH 14 // 9---10---20231126 +#define AI_Cls_14_out_0_IMAGE_HEIGHT 1 +#define AI_Cls_14_out_0_IMAGE_CHANNEL 1 +#define AI_Cls_14_out_0_IMAGE_DATA_LENGTH AI_Cls_14_out_0_IMAGE_WIDTH *AI_Cls_14_out_0_IMAGE_HEIGHT *AI_Cls_14_out_0_IMAGE_CHANNEL +#define AI_Cls_14_out_0_IMAGE_Name "570" +// 1023 + +// YS 输入图片尺寸 +#define AI_ZF_IN_0_IMAGE_WIDTH 1280 +#define AI_ZF_IN_0_IMAGE_HEIGHT 800 +#define AI_ZF_IN_0_IMAGE_CHANNEL 1 +#define AI_ZF_IN_0_DATA_LENGTH AI_ZF_IN_0_IMAGE_WIDTH *AI_ZF_IN_0_IMAGE_HEIGHT *AI_ZF_IN_0_IMAGE_CHANNEL +#define AI_ZF_IN_0_IMAGE_Name "0" +// nf 输入ZF片尺寸 +#define AI_ZF_out_0_IMAGE_WIDTH 1280 +#define AI_ZF_out_0_IMAGE_HEIGHT 800 +#define AI_ZF_out_0_IMAGE_CHANNEL 1 +#define AI_ZF_out_0_DATA_LENGTH AI_ZF_out_0_IMAGE_WIDTH *AI_ZF_out_0_IMAGE_HEIGHT *AI_ZF_out_0_IMAGE_CHANNEL +#define AI_ZF_out_0_IMAGE_Name "491" + +#define str_AI_127Cell_Model_Path "/home/aidlux/BOE/UseModel/defect_L127.engine" +// 127Cell 输入图片尺寸 +#define AI_127Cell_IN_0_IMAGE_WIDTH 1024 +#define AI_127Cell_IN_0_IMAGE_HEIGHT 1024 +#define AI_127Cell_IN_0_IMAGE_CHANNEL 1 +#define AI_127Cell_IN_0_DATA_LENGTH AI_127Cell_IN_0_IMAGE_WIDTH *AI_127Cell_IN_0_IMAGE_HEIGHT *AI_127Cell_IN_0_IMAGE_CHANNEL +#define AI_127Cell_IN_0_IMAGE_Name "0" +// nf 输入图片尺寸 +#define AI_127Cell_out_0_IMAGE_WIDTH 512 +#define AI_127Cell_out_0_IMAGE_HEIGHT 512 +#define AI_127Cell_out_0_IMAGE_CHANNEL 1 +#define AI_127Cell_out_0_DATA_LENGTH AI_127Cell_out_0_IMAGE_WIDTH *AI_127Cell_out_0_IMAGE_HEIGHT *AI_127Cell_out_0_IMAGE_CHANNEL +#define AI_127Cell_out_0_IMAGE_Name "491" + +#define str_AI_RE_POL_Model_Path "/home/aidlux/BOE/UseModel/BOE_POL_128x128.engine" +#define str_AI_RE_AD_Model_Path "/home/aidlux/BOE/UseModel/BOE_AD_128x128.engine" +// POL 二次计算面积 输入图片尺寸 +#define str_AI_RE_POL_IN_0_IMAGE_WIDTH 128 +#define str_AI_RE_POL_IN_0_IMAGE_HEIGHT 128 +#define str_AI_RE_POL_IN_0_IMAGE_CHANNEL 1 +#define str_AI_RE_POL_IN_0_DATA_LENGTH str_AI_RE_POL_IN_0_IMAGE_WIDTH *str_AI_RE_POL_IN_0_IMAGE_HEIGHT *str_AI_RE_POL_IN_0_IMAGE_CHANNEL +#define str_AI_RE_POL_IN_0_IMAGE_Name "0" +// nf 输入图片尺寸 +#define str_AI_RE_POL_out_0_IMAGE_WIDTH 128 +#define str_AI_RE_POL_out_0_IMAGE_HEIGHT 128 +#define str_AI_RE_POL_out_0_IMAGE_CHANNEL 1 +#define str_AI_RE_POL_out_0_DATA_LENGTH str_AI_RE_POL_out_0_IMAGE_WIDTH *str_AI_RE_POL_out_0_IMAGE_HEIGHT *str_AI_RE_POL_out_0_IMAGE_CHANNEL +#define str_AI_RE_POL_out_0_IMAGE_Name "491" + +// POL 二次计算面积 输入图片尺寸 +#define str_AI_RE_AD_IN_0_IMAGE_WIDTH 128 +#define str_AI_RE_AD_IN_0_IMAGE_HEIGHT 128 +#define str_AI_RE_AD_IN_0_IMAGE_CHANNEL 1 +#define str_AI_RE_AD_IN_0_DATA_LENGTH str_AI_RE_AD_IN_0_IMAGE_WIDTH *str_AI_RE_AD_IN_0_IMAGE_HEIGHT *str_AI_RE_AD_IN_0_IMAGE_CHANNEL +#define str_AI_RE_AD_IN_0_IMAGE_Name "0" +// nf 输入图片尺寸 +#define str_AI_RE_AD_out_0_IMAGE_WIDTH 128 +#define str_AI_RE_AD_out_0_IMAGE_HEIGHT 128 +#define str_AI_RE_AD_out_0_IMAGE_CHANNEL 1 +#define str_AI_RE_AD_out_0_DATA_LENGTH str_AI_RE_AD_out_0_IMAGE_WIDTH *str_AI_RE_AD_out_0_IMAGE_HEIGHT *str_AI_RE_AD_out_0_IMAGE_CHANNEL +#define str_AI_RE_AD_out_0_IMAGE_Name "491" + +// Edge 定位 +#define str_AI_EDGE_Big_Model_Path "/home/aidlux/BOE/UseModel/Edge_Big.engine" +#define str_AI_EDGE_Small_Model_Path "/home/aidlux/BOE/UseModel/Edge_Small.engine" +// POL 二次计算面积 输入图片尺寸 +#define str_AI_EDGE_Big_IN_0_IMAGE_WIDTH 1024 +#define str_AI_EDGE_Big_IN_0_IMAGE_HEIGHT 736 +#define str_AI_EDGE_Big_IN_0_IMAGE_CHANNEL 1 +#define str_AI_EDGE_Big_IN_0_DATA_LENGTH str_AI_EDGE_Big_IN_0_IMAGE_WIDTH *str_AI_EDGE_Big_IN_0_IMAGE_HEIGHT *str_AI_EDGE_Big_IN_0_IMAGE_CHANNEL +#define str_AI_EDGE_Big_IN_0_IMAGE_Name "image" +// nf 输入图片尺寸 +#define str_AI_EDGE_Big_out_0_IMAGE_WIDTH 1024 +#define str_AI_EDGE_Big_out_0_IMAGE_HEIGHT 736 +#define str_AI_EDGE_Big_out_0_IMAGE_CHANNEL 1 +#define str_AI_EDGE_Big_out_0_DATA_LENGTH str_AI_EDGE_Big_out_0_IMAGE_WIDTH *str_AI_EDGE_Big_out_0_IMAGE_HEIGHT *str_AI_EDGE_Big_out_0_IMAGE_CHANNEL +#define str_AI_EDGE_Big_out_0_IMAGE_Name "mask" + +// POL 二次计算面积 输入图片尺寸 +#define str_AI_EDGE_Small_IN_0_IMAGE_WIDTH 320 +#define str_AI_EDGE_Small_IN_0_IMAGE_HEIGHT 320 +#define str_AI_EDGE_Small_IN_0_IMAGE_CHANNEL 1 +#define str_AI_EDGE_Small_IN_0_DATA_LENGTH str_AI_EDGE_Small_IN_0_IMAGE_WIDTH *str_AI_EDGE_Small_IN_0_IMAGE_HEIGHT *str_AI_EDGE_Small_IN_0_IMAGE_CHANNEL +#define str_AI_EDGE_Small_IN_0_IMAGE_Name "image" +// nf 输入图片尺寸 +#define str_AI_EDGE_Small_out_0_IMAGE_WIDTH 320 +#define str_AI_EDGE_Small_out_0_IMAGE_HEIGHT 320 +#define str_AI_EDGE_Small_out_0_IMAGE_CHANNEL 1 +#define str_AI_EDGE_Small_out_0_DATA_LENGTH str_AI_EDGE_Small_out_0_IMAGE_WIDTH *str_AI_EDGE_Small_out_0_IMAGE_HEIGHT *str_AI_EDGE_Small_out_0_IMAGE_CHANNEL +#define str_AI_EDGE_Small_out_0_IMAGE_Name "mask" + + + +// 缺pol 检测 +#define str_AI_LOSSPOL_Model_Path "/home/aidlux/BOE/UseModel/BOE_LOSSPOL.engine" +// 输入图片尺寸 +#define str_AI_LOSSPOL_IN_0_IMAGE_WIDTH 1024 +#define str_AI_LOSSPOL_IN_0_IMAGE_HEIGHT 640 +#define str_AI_LOSSPOL_IN_0_IMAGE_CHANNEL 1 +#define str_AI_LOSSPOL_IN_0_DATA_LENGTH str_AI_LOSSPOL_IN_0_IMAGE_WIDTH *str_AI_LOSSPOL_IN_0_IMAGE_HEIGHT *str_AI_LOSSPOL_IN_0_IMAGE_CHANNEL + +// nf 输入图片尺寸 +#define str_AI_LOSSPOL_out_0_IMAGE_WIDTH 1024 +#define str_AI_LOSSPOL_out_0_IMAGE_HEIGHT 640 +#define str_AI_LOSSPOL_out_0_IMAGE_CHANNEL 1 +#define str_AI_LOSSPOL_out_0_DATA_LENGTH str_AI_LOSSPOL_out_0_IMAGE_WIDTH *str_AI_LOSSPOL_out_0_IMAGE_HEIGHT *str_AI_LOSSPOL_out_0_IMAGE_CHANNEL + + +// Mark 检测 +#define str_AI_Mark_Model_Path "/home/aidlux/BOE/UseModel/defect_MARK_LINE.engine" +// 输入图片尺寸 +#define str_AI_Mark_IN_0_IMAGE_WIDTH 512 +#define str_AI_Mark_IN_0_IMAGE_HEIGHT 512 +#define str_AI_Mark_IN_0_IMAGE_CHANNEL 1 +#define str_AI_Mark_IN_0_DATA_LENGTH str_AI_Mark_IN_0_IMAGE_WIDTH *str_AI_Mark_IN_0_IMAGE_HEIGHT *str_AI_Mark_IN_0_IMAGE_CHANNEL + +// nf 输入图片尺寸 +#define str_AI_Mark_out_0_IMAGE_WIDTH 512 +#define str_AI_Mark_out_0_IMAGE_HEIGHT 512 +#define str_AI_Mark_out_0_IMAGE_CHANNEL 1 +#define str_AI_Mark_out_0_DATA_LENGTH str_AI_Mark_out_0_IMAGE_WIDTH *str_AI_Mark_out_0_IMAGE_HEIGHT *str_AI_Mark_out_0_IMAGE_CHANNEL + + + + + + +#define QX_SAMLLIMG_WIDTH 160 +#define QX_SAMLLIMG_HEIGHT 160 + +// AI缺陷分类缺陷的种类 +enum AI_CLass_QX_NAME_ +{ + + AI_CLass_QX_NAME_ok_yisi, // 疑似 + AI_CLass_QX_NAME_yixian, // 异显 + AI_CLass_QX_NAME_POL_CEL, // 亮点 + AI_CLass_QX_NAME_zara, // ZARA + AI_CLass_QX_NAME_ps, // PS + AI_CLass_QX_NAME_line, // 线 + AI_CLass_QX_NAME_fangge_line, // 方格线 + AI_CLass_QX_NAME_qipao, // 气泡 + AI_CLass_QX_NAME_qing_huashang, // 轻划伤 + AI_CLass_QX_NAME_mtx, // MTX + AI_CLass_QX_NAME_yisi_qianzangwu, // 疑似浅层脏污 + AI_CLass_QX_NAME_qing_zangwu, // 轻脏污 + AI_CLass_QX_NAME_zhong_zangwu, // 严重脏污 + AI_CLass_QX_NAME_andian, // 暗点 + AI_CLass_QX_NAME_huashang, // 划伤 + AI_CLass_QX_NAME_zf, // zf + AI_CLass_QX_NAME_other, // 其他 + AI_CLass_QX_NAME_count, +}; +// 缺陷项对应在参数中的名称 +static const std::string AI_CLass_QX_NAME_Names[] = + { + "ok_yisi", + "yixian", + "liangdian", + "zara", + "ps", + "line", + "fangge_line", + "qipao", + "qing_huashang", + "mtx", + "yisi_qianzangwu", + "qing_zangwu", + "zhong_zangwu", + "andian", + "huashang", + "zf", + "other"}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/AIImgDeal.h b/AlgorithmModule/include/AIImgDeal.h new file mode 100644 index 0000000..fbaa038 --- /dev/null +++ b/AlgorithmModule/include/AIImgDeal.h @@ -0,0 +1,98 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef AIIMGDeal_H_ +#define AIIMGDeal_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "SingleGPU.h" +#include "AICommonDefine.h" + +using namespace std; + +class AI_IMG_deal +{ +public: + AI_IMG_deal(); + ~AI_IMG_deal(); + + int Init(int nGpuIdx); + +private: + int m_nGpuIdx; + +private: + // new Data + int NewData(); + + // Delete Data + int DelteData(); + +public: + // 初始化 + int Init_BOE(AIInitConfig config); + int Init_127Cell(AIInitConfig config); + int Init_BOE_Type2(AIInitConfig config); + int Init_BOE_UP(AIInitConfig config); + int Init_BOE_Chess(AIInitConfig config); + int Init_YX_1(AIInitConfig config); + int Init_YX_2(AIInitConfig config); + int Init_Cls(AIInitConfig config, int ntype); // 1023 + int Init_zf(AIInitConfig config); // 1023 + int Init_RE_POL(AIInitConfig config); // 1023 + int Init_RE_AD(AIInitConfig config); // 1023 + int Init_Edge_Big(AIInitConfig config); // 1023 + int Init_Edge_Small(AIInitConfig config); // 1023 + int Init_LackPol(AIInitConfig config); + int Init_MarkLine(AIInitConfig config); + + // 检测 + int AICheck_BOE(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_BOE_Type2(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_BOE_Chess(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_BOE_UP(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_YX_1(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_YX_2(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_Cls(cv::Mat inImg, int ntype, float *fmaxScore); // 1023 + int AICheck_zf(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_127Cell(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_RE_POL(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_RE_AD(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_Edge_Big(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_Edge_Small(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_LackPol(cv::Mat inImg, cv::Mat &outImg_1); + int AICheck_MarkLine(cv::Mat inImg, cv::Mat &outImg_1); + +private: + cv::Mat F2M(float *data, int clannel, int w, int h); + + cv::Mat InitMat(int channel, int w, int h); + int F2softmaxId(float *data, int class_num, float *fmaxScore); // 1024dyy-add +private: + AI_SingleGPU *m_pAI_SingleGPU; + + float *AI_DATA_Cls_OUT_0; + float *AI_DATA_Cls_L0_OUT_0; + + bool bInitSucc_127Cell; + bool bInitSucc_re_Pol; + bool bInitSucc_re_AD; + bool bInitSucc_MarkLine; + + bool bInitSucc_Edge_big; + bool bInitSucc_Edge_Samll; + bool bInitSucc_LackPol; +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/AI_Edge_Algin.h b/AlgorithmModule/include/AI_Edge_Algin.h new file mode 100644 index 0000000..2894841 --- /dev/null +++ b/AlgorithmModule/include/AI_Edge_Algin.h @@ -0,0 +1,178 @@ +/* +//实现对部分缺陷 需要进行 数量 和距离上分析的 + */ +#ifndef AI_Edge_Algin_H_ +#define AI_Edge_Algin_H_ +#include +#include "CheckUtil.hpp" +#include "OtherDetBaseDefine.h" +#include "CheckErrorCodeDefine.hpp" +#include "ImageDetConfig.h" +using namespace std; + +using namespace std; +using namespace cv; + +// 边缘搜索定位结果 +struct Edge_AI_Result +{ + int nresult; + cv::Mat mask; + cv::Rect roi; + cv::Mat DetMask_src; // 原图上产品区域 + + Edge_AI_Result() + { + Init(); + } + void Init() + { + nresult = 0; + roi = cv::Rect(0, 0, 0, 0); + if (!mask.empty()) + { + mask.release(); + } + if (!DetMask_src.empty()) + { + DetMask_src.release(); + } + } +}; +class AI_Edge_Algin +{ +public: + enum SaveProcessType + { + Save_Close, // 不保存 + Save_Filter, // 过滤的 + Save_ALL, // 全部 + }; + + /// @brief 检测过程的参数 + struct DetConfig + { + int ncamId; // 相机ID + std::string strCamName; // 相机ID + int nthresholdvalue; // 背景阈值 + int nAIErodesize; // 边缘腐蚀强度 + bool bSaveResultImg; // 保存结果图片 + SaveProcessType saveProcessImg; // 保存过程图片 + bool bUseDrawRoi_Check; // 是否用绘制的ROI进行校验 + cv::Rect drawRoi; // 绘制的 ROi; + cv::Mat drawMask; // 绘制的maksk + DetConfig() + { + Init(); + } + void Init() + { + ncamId = 0; + strCamName = ""; + nthresholdvalue = 1; + nAIErodesize = 7; + bSaveResultImg = false; + saveProcessImg = Save_Close; + bUseDrawRoi_Check = false; + drawRoi = cv::Rect(0, 0, 0, 0); + if (!drawMask.empty()) + { + drawMask.release(); + /* code */ + } + } + void Print() + { + printf("nthresholdvalue:%d;nAIErodesize %d;bSaveResultImg %s SaveProcessImg %d\n", + nthresholdvalue, nAIErodesize, BOOL_TO_STR(bSaveResultImg), saveProcessImg); + + printf("bUseDrawRoi_Check %s roi %s \n", + BOOL_TO_STR(bUseDrawRoi_Check), CheckUtil::GetRectString(drawRoi).c_str()); + } + bool IsSaveProcessImg() + { + if (saveProcessImg != Save_Close) + { + return true; + } + + return false; + } + }; + +public: + AI_Edge_Algin(/* args */); + ~AI_Edge_Algin(); + // 初始化检测模型 + int Init(OtherDet_Config *pOtherDet_Config); + int InitModel_ALL(); + int Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared_ptr &pCheckResult_Aling); + int SaveSmallImg(const cv::Mat &img, const cv::Mat &mask, cv::Rect roi); + +private: + int InitModel_Big(); + int InitModel_Small(); + int Det_big(const cv::Mat &img, vector &smallRoiList, cv::Rect &bigRoi, cv::Mat &big_mask); + +private: + bool m_bInitSucc; // 是否初始化成功 + + // 检测结果 + // std::shared_ptr m_pCheckResult_Aling; + + OtherDet_Config *m_pOtherDet_Config; + DetConfig *m_pDetConfig; + + AI_IMG_deal *m_pAIDeal; + bool m_bInitialized; + bool m_bModelSucc; + +private: + /* data */ +}; + +// 图片特征定位 +class Image_Feature_Algin +{ +public: + struct DetConfig + { + bool bSaveImg; + bool bSave_Process; // 存储过程图片 + + float fscore; + cv::Mat TemplateImg; // 模版图片 + cv::Mat DetImg; // 检测图片 + + cv::Rect Search_Roi; // 搜索 范围 + cv::Rect feature_Roi; // 特征区域 + cv::Rect param_CropRoi; // 裁剪区域,在参数图片上 + cv::Rect DetImg_CropROi; // 裁剪区域,在检测图片上 + DetConfig() + { + bSaveImg = false; + bSave_Process = false; + fscore = 0.9; + Search_Roi = cv::Rect(0, 0, 0, 0); + feature_Roi = cv::Rect(0, 0, 0, 0); + param_CropRoi = cv::Rect(0, 0, 0, 0); + DetImg_CropROi = cv::Rect(0, 0, 0, 0); + } + }; + +public: + Image_Feature_Algin(/* args */); + ~Image_Feature_Algin(); + int Detect(DetConfig *pDetConfig, Align_Result *pResult, std::vector &LogList); + +private: + cv::Point findBestTemplateMatch(const cv::Mat &detectionImage, const cv::Mat &templateImage, double &bestScore, int method = cv::TM_CCOEFF_NORMED); + +private: + PRINT_LOG_ m_PrintLog; + +private: + /* data */ +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/AI_Mark_Det.h b/AlgorithmModule/include/AI_Mark_Det.h new file mode 100644 index 0000000..4c71c14 --- /dev/null +++ b/AlgorithmModule/include/AI_Mark_Det.h @@ -0,0 +1,79 @@ +/* +//实现对部分缺陷 需要进行 数量 和距离上分析的 + */ +#ifndef AI_Mark_Det_H_ +#define AI_Mark_Det_H_ +#include +#include "CheckUtil.hpp" +#include "OtherDetect.h" +#include "OtherDetBaseDefine.h" +#include "CheckErrorCodeDefine.hpp" +#include "ImageDetConfig.h" +#include "CheckConfigDefine.h" +#include "ImageStorage.h" + +using namespace std; +using namespace cv; + +// 二次分割求面积 +class AI_Mark_Det : public AIDetectBase +{ +public: + // 检测参数和结果 + struct DetConfigResult + { + + int ncamID; + int nresult; + cv::Rect searchroi; + std::string strChannel; + bool bsaveprocessimg; + + cv::Rect markRoi; + + DetConfigResult() + { + + nresult = -1; + ncamID = 0; + strChannel = ""; + searchroi = cv::Rect(0, 0, 0, 0); + bsaveprocessimg = false; + markRoi = cv::Rect(0, 0, 0, 0); + } + }; + +public: + AI_Mark_Det(/* args */); + ~AI_Mark_Det(); + int InitModel_ALL(); + int Detect(const cv::Mat &img, DetConfigResult *pDetConfig); + +private: + int InitModel(); + + cv::Rect GetCutRoi(cv::Rect &roi, const cv::Mat &img); + + int Det_img(const cv::Mat &img, DetConfigResult *pDetConfig); + + // 分析结果 + int Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig); + + // 存储过程图片 + int SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig); + +private: + bool m_bModelSucc; + cv::Mat detimg123; + ImageStorage *m_pImageStorage; + + int m_Show_Area; + float m_Show_Len; + cv::Point m_Len_P1; + cv::Point m_Len_P2; + +private: + /* data */ +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/AI_Second_Det.h b/AlgorithmModule/include/AI_Second_Det.h new file mode 100644 index 0000000..70fabee --- /dev/null +++ b/AlgorithmModule/include/AI_Second_Det.h @@ -0,0 +1,100 @@ +/* +//实现对部分缺陷 需要进行 数量 和距离上分析的 + */ +#ifndef AI_Second_Det_H_ +#define AI_Second_Det_H_ +#include +#include "CheckUtil.hpp" +#include "OtherDetect.h" +#include "OtherDetBaseDefine.h" +#include "CheckErrorCodeDefine.hpp" +#include "ImageDetConfig.h" +#include "CheckConfigDefine.h" +#include "ImageStorage.h" + +using namespace std; +using namespace cv; + +// 二次分割求面积 +class AI_SecondDet : public AIDetectBase +{ +public: + // 检测参数和结果 + struct DetConfigResult + { + Function_SecondDet *pfunction_secondDet; + float fImgage_Scale_X; + float fImgage_Scale_Y; + float min_DetArea; + cv::Rect qx_roi; + int qx_type; + std::string qx_name; + int old_Area; + float old_len; + int new_Area; + float new_len; + int nresult; + std::string strChannel; + + DetConfigResult() + { + qx_roi = cv::Rect(0, 0, 0, 0); + qx_type = 0; + min_DetArea = 0; + qx_name = ""; + old_Area = 0; + old_len = 0; + new_Area = 0; + new_len = 0; + nresult = 0; + pfunction_secondDet = NULL; + strChannel = ""; + fImgage_Scale_X = 0.0333; + fImgage_Scale_Y = 0.0333; + } + void SetAreaAndLen(int oldArea, float oldLen) + { + old_Area = oldArea; + old_len = oldLen; + new_Area = old_Area; + new_len = old_len; + } + }; + +public: + AI_SecondDet(/* args */); + ~AI_SecondDet(); + int InitModel_ALL(); + int Detect(const cv::Mat &img, const cv::Mat &mask, DetConfigResult *pDetConfig); + +private: + int InitModel_Re_POL(); + int InitModel_Re_AD(); + + cv::Rect GetCutRoi(cv::Rect &roi, const cv::Mat &img); + + int Det_Pol(const cv::Mat &img, DetConfigResult *pDetConfig); + int Det_AD(const cv::Mat &img, DetConfigResult *pDetConfig); + + // 分析结果 + int Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig); + + // 存储过程图片 + int SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig); + +private: + bool m_bModelSucc_AD; + bool m_bModelSucc_POL; + cv::Mat detimg123; + ImageStorage *m_pImageStorage; + + int m_Show_Area; + float m_Show_Len; + cv::Point m_Len_P1; + cv::Point m_Len_P2; + +private: + /* data */ +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/ALLImgCheckAnalysisy.hpp b/AlgorithmModule/include/ALLImgCheckAnalysisy.hpp new file mode 100644 index 0000000..204f222 --- /dev/null +++ b/AlgorithmModule/include/ALLImgCheckAnalysisy.hpp @@ -0,0 +1,196 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2025-07-26 11:23:45 + * @LastEditors: xiewenji 527774126@qq.com + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef ALLImgCheckAnalysisy_H_ +#define ALLImgCheckAnalysisy_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "BlobBase.h" +#include "AICheck.h" +#include "ImgCheckBase.h" +#include "ImageDetBase.h" +#include "ImgCheckConfig.h" +#include "CheckErrorCodeDefine.hpp" +#include "ConfigBase.h" +#include "CheckSODefine.hpp" +#include "CheckConfigDefine.h" +#include "EdgeDet.h" +#include "ImageDetConfig.h" +#include "Define_Product.hpp" +#include "CameraCheckAnalysisy.hpp" + +using namespace std; +using namespace cv; + +class ALLImgCheckAnalysisy : public ALLImgCheckBase +{ + +public: + ALLImgCheckAnalysisy(); + ~ALLImgCheckAnalysisy(); + + // 初始化参数 pconfig 参数指针 返回:0 成功 其他异常 + int RunStart(void *pconfig1); + + // 设置检测数据,并开启检测 返回:0 成AT_THRESHOLD_TYPE_READY功 其他异常 + int SetDataRun_SharePtr(std::shared_ptr p); + + // 获取结果信息 返回:0 成功 其他异常 + int GetCheckReuslt(std::shared_ptr &pResult); + + int CheckImg(std::shared_ptr p, std::shared_ptr &pResult); + + // 获取检测库 状态信息 返回:CHECK_THREAD_RUN_STATUS + int GetStatus(); + + // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 + int UpdateConfig(void *pconfig, int nConfigType); + + std::string GetVersion(); + + std::string GetErrorInfo(); + +private: + // 加载运行参数 + int LoadRunConfig(void *p); + + // 加载分析参数 + int LoadCheckConfig(void *p); + + /// @brief 初始化并且启动程序 + /// @return + int InitRun(); + + /// @brief 开启检测 + /// @return + int StartCheck(); + + /// @brief 设置空闲 + /// @return + int SetIDLE(); + +private: + // 开启线程 + int StartThread(); + // 停止线程 + int StopThread(); + + // 退出系统 + int ExitSystem(); + + // 初始化相机检测分析类 + int InitCameraCheckAnalysisy(); + // 设置相机图片并开始检测分析 + int SetCameraImgAndStartDet(std::string strcameraName, std::shared_ptr pCamera); + + // 初始化 + int InitData(); + + // 处理产品 + int Det_Product(); + + // 联合分析 + int AnalysiyAll(int productIdx); + // 暗点联合分析 + int AD_AllChannelAnalysisy(int productIdx, std::shared_ptr &pProduct); + int AD_AllChannelAnalysisy_New(); + int POL_AllChannelAnalysisy_New(); + // 设置最终结果 + int SetProductResult(); + // 设置检测完成 + int SetSetComplet(int productIdx, int result, int nerror); + int SetSetComplet_New(int result, int nerror); + + // 处理数量 + int DetListNum(); + + // 加载图片 队列 + int PushInImg_New(std::shared_ptr p); + + // 当前检查环境判断 + int CurCheckListStatus(); + + // 异常返回 + int ErrorReturn(std::shared_ptr p); + + float CalImgScorl(cv::Mat det_img, cv::Mat up_img); + + int AddStrToLog(int productIdx, std::string str); + int AddStrToLog_New(std::string str); + // 设置新的检测参数 + int SetNewConfig(); + ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能 + +private: + // 图片处理线程 + std::shared_ptr ptr_thread_Run; + int Run(); // 运行; + int set_cpu_id(const std::vector &cpu_set_vec); + +private: + RunInfoST m_RunConfig; + // 检测参数模块 + ConfigBase *m_pConfig; + ConfigBase *m_pConfig_Cam2; + // 图片处理线程 + + // 相机处理模块,负责完成对应相机图片的处理功能。 + CameraCheckAnalysisy *m_pCameraCheckAnalysisy[MAX_Camera_NUM]; + + PRINT_LOG_ m_PrintLog; + // 互斥锁定义 +private: + // 产品的所有信息 + std::shared_ptr m_ProductImgDetResult_New; + + std::vector> m_ProductImgDetResultList; + + std::mutex mtx_ProductImgDetResultList; // 互斥锁,用于保护数据队列 + + std::mutex mtx_DetSingle; // 互斥量 + + std::queue> m_CheckResultList; // 检测结果 + std::mutex mtx_CheckResult; // 互斥锁,用于保护数据队列 + std::condition_variable CheckResult_cond; // 条件变量,用于同步生产者和消费者线程 + + std::vector Last_det_LogList; // 上一个产品的检测日志 + + std::mutex mtx_Last_det_LogList; // 互斥量 + +private: + int m_nErrorCode; // 错误代码 + bool m_bInitSucc; // 初始化状态 + bool m_bExit; // 是否退出检测 + + std::shared_ptr m_OneImg_Result_shareP; + std::shared_ptr DetImgInfo_shareP; + + std::string m_strTest; + + // 检测分析参数 + AnalysisyConfigST m_AnalysisyConfig; + ALLChannelCheckFunction *m_pChannelFuntion; // 画面检测功能 + // 当前检测产品的个数 + int m_CurProductIdx; + + ReJson_Status m_reJsonStatus_push; // 复测状态;送图 + ReJson_Status m_reJsonStatus_Det; // 复测状态;复测 +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/BlobBase.h b/AlgorithmModule/include/BlobBase.h new file mode 100644 index 0000000..d3e2674 --- /dev/null +++ b/AlgorithmModule/include/BlobBase.h @@ -0,0 +1,127 @@ +#pragma once + +enum ERR_DOT_TYPE_ENUM +{ + ERR_TYPE_1, + ERR_TYPE_2, + ERR_TYPE_3, + ERR_TYPE_4, + ERR_TYPE_5, + ERR_TYPE_6, + ERR_TYPE_COUNT, +}; + +//-----------------------sxg added +#define _MAX_ERROR_SCAN_LINE_PER_ROW 200 +#define _MAX_ERROR_DOT_BLOB 1000 +#define _MAX_MACRO_COUNT 4 + +#define _MAX_ERR_CLASS ERR_TYPE_COUNT +// #define _CAM_WIDTH 640 +#define _MAX_MIN_VALUE_NUM 10 +typedef struct ERROR_DOTS_SCAN_DATA +{ + unsigned short x, count; + unsigned short minx, miny; + unsigned short maxx, maxy; + int area, energy; + int xposSum, yposSum; + int macro; + int type; + int ErrClass[_MAX_ERR_CLASS]; +} ERROR_DOTS_SCAN_DATA; + +typedef struct ERROR_DOTS_SCAN_ROW +{ + int scanCount; + ERROR_DOTS_SCAN_DATA errorScanLineTab[_MAX_ERROR_SCAN_LINE_PER_ROW]; + int macro[_MAX_MACRO_COUNT]; + int ErrClass[_MAX_ERR_CLASS]; + int minValue[_MAX_MIN_VALUE_NUM]; +} ERROR_DOTS_SCAN_ROW; + +typedef struct ERROR_DOTS_BLOB_DATA +{ + unsigned short x, y; + unsigned short minx, miny; + unsigned short maxx, maxy; + int area; + int energy; + float JudgArea; + float len; + int macro[_MAX_MACRO_COUNT]; + int ErrClass[_MAX_ERR_CLASS]; + int ErrDesc; + int ErrType; + int UserErrorType; + int maxValue; + float grayDis; + int AIclasstype; + float density; + unsigned short badd; +} ERROR_DOTS_BLOB_DATA; + +typedef struct ERROR_DOTS_BLOBS +{ + int blobCount; + int totalArea; + int totalEnergy; + ERROR_DOTS_BLOB_DATA blobTab[_MAX_ERROR_DOT_BLOB]; + int ErrClass[_MAX_ERR_CLASS]; + int Pass[_MAX_ERROR_DOT_BLOB]; +} ERROR_DOTS_BLOBS; + +typedef struct ERROR_DOTS_BLOB_PARAM +{ + int minArea; // ²ÐµãÇøÓòÃæ»ý×îСֵ£¬µ¥Î»ÎªÏñËØµã£¬Èç¹ûСÓÚ´ËÖµ£¬ÔòºöÂÔ + int minEnergy; // ²ÐµãÇøÓòÄÜÁ¿×îСֵ£¬Èç¹ûСÓÚ´ËÖµ£¬ÔòºöÂÔ + + int maxErrorBlobCount; // ×î´óÔÊÐíµÄÂú×ãÉÏÊöÌõ¼þºóµÄ²ÐµãÇøÓòÊýÁ¿£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í + int maxTotalArea; // ×î´óÔÊÐíµÄÂú×ãÉÏÊöÌõ¼þºóµÄ²ÐµãÇøÓò×ÜÃæ»ý£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í + int maxTotalEnergy; // ×î´óÔÊÐíµÄÂú×ãÉÏÊöÌõ¼þºóµÄ²ÐµãÇøÓò×ÜÄÜÁ¿£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í + + int maxRegionArea; // ×î´óÔÊÐíµÄµ¥¸ö²ÐµãÇøÓòÃæ»ý£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í + int maxRegionEnergy; // ×î´óÔÊÐíµÄµ¥¸ö²ÐµãÇøÓòÄÜÁ¿£¬Èç¹û´óÓÚ´ËÖµ£¬ Ôò±¨´í + int Hthold[4]; // ѧϰģ°æºóµÄÀ©Õ¹ãÐÖµ + int Lthold[4]; // ѧϰģ°æºóµÄÀ©Õ¹ãÐÖµ + int Level[2]; // ÑÏÖØµÈ¼¶ + int mergeDistance; // ²ÐµãºÏ²¢×îС¾àÀë £¬¡¡ÈôÁ½¸ö²Ðµã¾àÀëСÓÚ´ËÖµÔòºÏ²¢ÎªÒ»¸ö + int isUseMacro; +} ERROR_DOTS_BLOB_PARAM; + +typedef struct ERROR_BLOBS_PARAM +{ + int id; + unsigned char *pb; + unsigned char *pr; + unsigned char *pc; + int width; + int height; + int obj; + ERROR_DOTS_BLOBS *blobs; + +} ERROR_BLOBS_PARAM; +#ifdef __cplusplus +extern "C" +{ +#endif + void pretest(double x); + extern void AddErrorScan(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int mdx, int *pErrClass); + extern void LinkScanLineToBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width); + extern void SortBlob(ERROR_DOTS_BLOBS *blobs); + extern void MergeBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOB_PARAM *param); + extern void AddErrorScan_New(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int errorType); + extern void LinkScanLineToBlob_New(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width); + + extern int GetBlobsFromImg(ERROR_DOTS_BLOBS *blobs_0, ERROR_DOTS_BLOBS *blobs_1, ERROR_DOTS_BLOBS *blobs_2, unsigned char *pb, unsigned char *pr, unsigned char *pc, int width, int height, int obj); + extern int GetBlobsFromIm_1(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pGrayErrordata, unsigned char *pRGBErrordata, int width, int height); + extern int GetBlobsFromIm_2(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pGrayErrordata, unsigned char *pRGBErrordata, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT); + extern int GetBlobsFromIm_All(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pGrayErrordata, unsigned char *pRGBErrordata, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT); + extern int GetBlobsFromIm_single(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pErrordata, int nstartPos, int nstep, int npitch, int nErrorType, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT); + extern int GetBlobsFromIm_All_onemask(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pRGBErrordata, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT); + extern int GetBlobsFromIm_single_onemask(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pErrordata, int AndValue, int npitch, int nErrorType, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT); + extern int GetBlobs_V2(ERROR_DOTS_BLOBS *blobs, unsigned char *pImgdata, unsigned char *pErrordata, int width, int height, int basev, int minArea); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/CUDA_Det.cuh b/AlgorithmModule/include/CUDA_Det.cuh new file mode 100644 index 0000000..a5e5666 --- /dev/null +++ b/AlgorithmModule/include/CUDA_Det.cuh @@ -0,0 +1,21 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef CUDA_Det_H_ +#define CUDA_Det_H_ +#include "cuda_runtime.h" +#include "cublas_v2.h" +#include "device_launch_parameters.h" +#include +#include + +void wrap_test_print(); +void Cuda_ucharToFloat(const unsigned char* input, float* output, int size); +void Cuda_FloatTouchar(const float* input, unsigned char* output, int size); + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/CameraCheckAnalysisy.hpp b/AlgorithmModule/include/CameraCheckAnalysisy.hpp new file mode 100644 index 0000000..53eac08 --- /dev/null +++ b/AlgorithmModule/include/CameraCheckAnalysisy.hpp @@ -0,0 +1,154 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef CameraCheckAnalysisy_H_ +#define CameraCheckAnalysisy_H_ + +#include +#include +#include +#include +#include +#include +#include "Define_Base.h" +#include "AICheck.h" +#include "ImgCheckBase.h" +#include "ImageDetBase.h" +#include "ImgCheckConfig.h" +#include "CheckErrorCodeDefine.hpp" +#include "ConfigBase.h" +#include "CheckSODefine.hpp" +#include "CheckConfigDefine.h" +#include "EdgeDet.h" +#include "ImageDetConfig.h" +#include "Define_Product.hpp" +#include "AI_Mark_Det.h" + +using namespace std; +using namespace cv; +// 相机处理类 +class CameraCheckAnalysisy +{ + +public: + CameraCheckAnalysisy(); + ~CameraCheckAnalysisy(); + + // 相机处理类 初始化 + int Init(Camera_IDX camera_ID); + int StartCheck(std::shared_ptr pCamera_Check_Result); + +private: + // 开启线程 + int StartThread(); + // 停止线程 + int StopThread(); + + // 初始化检测分析线程类 + int InitCheckAnalysisy(); + // 初始化其他 + int InitRun(); + // 设置新的检测参数 + int SetNewConfig(); + + int InitMarkLine(); + + // 处理每张图片 + int CheckImgRun(); + + int Run(); // 运行; + int set_cpu_id(const std::vector &cpu_set_vec); + // 等待处理图片 + int WaitDetImg(); + // 增加日志 + int AddStrToLog_New(std::string str); + + // 预处理图片 + int Detect_Pre(); + + // 处理每张图片 + int Detect_Images(); + + // 边缘处理 + int ImgEdge(cv::Mat img, bool bUseDraw, const cv::Mat ¶MaskImg, int thresholdvalue, int AIErodesize, bool bUseAIDet, cv::Mat &detMaskImg, cv::Rect &roi, int productIdx); + + // 插入相机日志 + int InsertCameraLog(); + + ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能 + + // 特征主定位 + int Feature_Align(const cv::Mat &detSrcImg, int nproductIdx, cv::Rect Det_CropRoi, ChannelCheckFunction *pFuntion_L255, const cv::Mat &detImg_mask, bool bsave = false, bool bsaveprocessimg = false); + // 预处理 字符检测 + int preDet_ZF(std::shared_ptr p, std::shared_ptr &pResult); + + // 检测MarkLine + int Det_MarkLine(const cv::Mat &detSrcImg, cv::Rect Det_CropRoi, Base_Function_MarkLine *pFuntion, cv::Mat &detImg_mask, cv::Rect &markRoi_x, cv::Rect &markRoi_y, bool bsaveprocessimg = false); + + // 获取 检测核心库 + ImgCheckBase *GetDealResult(int idx = -1); + + int GetAndAnalysisyCheckResult(std::shared_ptr &pResult); + +public: + // 运行的基本参数 + RunInfoST m_RunConfig; + // 检测参数模块 + ConfigBase *m_pConfig; + PRINT_LOG_ m_PrintLog; + + AI_Edge_Algin::DetConfig AI_detConfig; + Align_Result m_align_Result; + // 图片特征定位 + Image_Feature_Algin m_Image_Feature_Algin; + // 检测分析参数 + AnalysisyConfigST m_AnalysisyConfig; + ALLChannelCheckFunction *m_pChannelFuntion; // 画面检测功能 + BaseCheckFunction *m_pbaseCheckFunction; // 基础检测 + + std::shared_ptr m_OneImg_Result_shareP; + std::shared_ptr DetImgInfo_shareP; + std::string m_strCameraName; + +private: + // 相机ID + Camera_IDX m_camera_ID; + int m_ncamera_idx; + + int m_nErrorCode; // 错误代码 + bool m_bInitSucc; // 初始化状态 + bool m_bExit; // 是否退出检测 + int nLastCheckAnalysisyThreadIdx; + // 图片处理线程 + std::shared_ptr ptr_thread_Run; + + // 单相机的相关结果信息 + std::shared_ptr m_pCamera_Check_Result; + + bool m_bHaveImgeDet; // 是否有图片需要检查 + std::mutex mtx_WaiteImg; // 等待图片的锁 + std::condition_variable cond_WaiteImg; // 条件变量,是否有图片需要检查 + +private: + // 检测核心库 + ImgCheckBase *m_pImgCheckAnalysisy[IMGCHECKANALYSISY_NUM]; + + AI_IMG_deal m_AIDeal; + OtherDet_Config m_OtherDet_Config; + // 边缘检测 + EdgeDet_New m_DetEdge; + + AI_Mark_Det m_MarkDet; // Mark检测 + + CHECK_TEM_RESULT m_TemCheck; + +private: +private: +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/CheckErrorCodeDefine.hpp b/AlgorithmModule/include/CheckErrorCodeDefine.hpp new file mode 100644 index 0000000..af430e3 --- /dev/null +++ b/AlgorithmModule/include/CheckErrorCodeDefine.hpp @@ -0,0 +1,512 @@ + + +#ifndef _CheckErrorDefine_HPP_ +#define _CheckErrorDefine_HPP_ +#include +#include +#include "CheckUtil.hpp" +#include "Base_Define.h" +#include "Define_Base.h" +#include "Define_Error.h" + + +#define BOOL_TO_STR(bool_expr) (bool_expr) ? "true" : "false" +#define BOOL_TO_STROK(bool_expr) (bool_expr) ? "OK" : "NG" +#define BOOL_TO_ThanLess(bool_expr) (bool_expr) ? ">" : "<" +#define BOOL_TO_LessThan(bool_expr) (bool_expr) ? "<" : ">" +#define BOOL_TO_STR_Error(bool_expr) ((bool_expr) ? "Succ" : "Error") +#define Re_TO_STR_Error(num) ((num) == 0 ? "Succ" : "Error") +#define Re_TO_STR_False(num) ((num) == 0 ? "Succ" : "false") +#define Re_TO_STR_Pass_1(num) ((num) == 1 ? "Pass" : "fail") +#define Re_TO_STR_NG(num) ((num) == 0 ? "OK" : "NG") +#define SRC_IMG_WIDTH 14192 +#define SRC_IMG_HEIGHT 10640 + +// 输入模型图片尺寸 +#define SRC_AI_In_IMAGE_WIDTH 1024 +#define SRC_AI_In_IMAGE_HEIGHT 1024 + +// resize 图片的 宽度 +#define RESIZE_IMAGE_WIDTH 1280 + +enum PrintLevel_ +{ + PrintLevel_0, + PrintLevel_1, + PrintLevel_2, + PrintLevel_3, + PrintLevel_4, +}; +enum TEM_IMG_IDX_ +{ + TEM_IMG_IDX_SrcCrop, + TEM_IMG_IDX_AImask, + TEM_IMG_IDX_DrawSrc, + TEM_IMG_IDX_Result, + TEM_IMG_IDX_Count, +}; +static const std::string TEM_IMG_IDX_Names[] = + { + "SrcCrop", + "AImask", + "Drawmask", + "result"}; +// 检测过程临结果 +struct CHECK_TEM_RESULT +{ + cv::Mat temImgList[TEM_IMG_IDX_Count]; + std::vector timeInfoList; + std::vector analysisInfoList; + std::vector temlogList; + bool bPrintStr; // 是否打印日志 + int addLogLevel; + bool bInTemList; + CHECK_TEM_RESULT() + { + Init(); + } + void Init() + { + timeInfoList.clear(); + timeInfoList.shrink_to_fit(); + + analysisInfoList.clear(); + analysisInfoList.shrink_to_fit(); + + temlogList.clear(); + temlogList.shrink_to_fit(); + + for (int i = 0; i < TEM_IMG_IDX_Count; i++) + { + if (!temImgList[i].empty()) + { + temImgList[i].release(); + } + } + bPrintStr = false; + addLogLevel = 0; + bInTemList = false; + } + void temLogListInit() + { + temlogList.erase(temlogList.begin(), temlogList.end()); + temlogList.clear(); + } + void AddTimeStr(std::string str, long start, long end) + { + char text[1024] = {0}; + double t = end - start; + sprintf(text, "%s : use Time :%.2f", str.c_str(), t); + std::string temstr = text; + printf("%s\n", temstr.c_str()); + timeInfoList.push_back(temstr); + } + + template + void AddCheckstr(int step, int LogLevel, std::string stepStr, const std::string &format, Args... args) + { + std::string str = ""; + + if (step <= PrintLevel_0) + { + str += ".. "; + } + else if (step == PrintLevel_1) + { + str += "..... "; + } + else if (step == PrintLevel_2) + { + str += "........ "; + } + else if (step == PrintLevel_3) + { + str += "........... "; + } + else if (step >= PrintLevel_4) + { + str += ".............. "; + } + str += stepStr + ": "; + str += str_Format(format, args...); + if (bPrintStr) + { + printf("%s\n", str.c_str()); + } + if (bInTemList) + { + temlogList.push_back(str); + } + else + { + if (LogLevel <= addLogLevel) + { + analysisInfoList.push_back(str); + } + } + } + void AddCheckstr(std::string str) + { + if (str == "") + { + return; + } + printf("%s\n", str.c_str()); + analysisInfoList.push_back(str); + } + void AddCheckstr(std::string str, std::string str1) + { + str = str + ":" + str1; + printf("%s\n", str.c_str()); + analysisInfoList.push_back(str); + } + void AddCheckstr(std::string str, int value) + { + str = str + ":" + std::to_string(value); + printf("%s\n", str.c_str()); + analysisInfoList.push_back(str); + } + void AddCheckstr(std::string str, float value) + { + str = str + ":" + std::to_string(value); + printf("%s\n", str.c_str()); + analysisInfoList.push_back(str); + } + void saveImg() + { + for (int i = 0; i < TEM_IMG_IDX_Count; i++) + { + if (!temImgList[i].empty()) + { + std::string str = TEM_IMG_IDX_Names[i] + ".png"; + cv::imwrite(str, temImgList[i]); + } + } + } +}; +enum Print_Level_ +{ + Print_Level_Info, + Print_Level_Key, + Print_Level_Error, +}; +// 大于日志 +struct PRINT_LOG_ +{ + bool bprint; + bool bshow_Info; + bool bshow_Key; + bool bshow_Error; + + PRINT_LOG_() + { + Init(); + } + void Init() + { + bprint = true; + bshow_Info = true; + bshow_Key = true; + bshow_Error = true; + } + + template + std::string printstr(int LogLevel, std::string stepStr, const std::string &format, Args... args) + { + std::string str = ""; + if (!bprint) + { + return str; + } + switch (LogLevel) + { + case Print_Level_Info: + if (!bshow_Info) + { + return str; + } + str = "info-> "; + break; + case Print_Level_Key: + if (!bshow_Key) + { + return str; + } + str = "key-> "; + break; + case Print_Level_Error: + if (!bshow_Error) + { + return str; + } + str = "Error-> "; + break; + default: + return str; + break; + } + + str += stepStr + ": "; + str += str_Format(format, args...); + printf("%s\n", str.c_str()); + + return str; + } +}; + +#define MAX_THREAD_AIDET_NUM 2 + +struct SMALLIMGINFO +{ + int nDetType; + int nidx; + cv::Mat img; + cv::Mat outimg; + cv::Rect Roi; + int flag; + int start_x; + int start_y; + int nresult; + int x_idx; + int y_idx; + SMALLIMGINFO() + { + + Init(); + } + ~SMALLIMGINFO() + { + release(); + } + void Init() + { + if (!img.empty()) + { + img.release(); + } + if (!outimg.empty()) + { + outimg.release(); + } + nDetType = 0; + flag = 0; + start_x = 0; + start_y = 0; + nidx = 0; + nresult = 0; + x_idx = 0; + y_idx = 0; + } + void release() + { + if (!img.empty()) + { + img.release(); + } + if (!outimg.empty()) + { + outimg.release(); + } + } +}; +struct YX_CheckResult_ +{ + int nresult; // 检测结果 + YX_CheckResult_() + { + Init(); + } + void Init() + { + + nresult = 0; + } +}; +// 缺失POl 检测 +struct LackPol_CheckResult_ +{ + int nresult; // 检测结果 + LackPol_CheckResult_() + { + Init(); + } + void Init() + { + + nresult = 0; + } +}; +struct WTB_Check_Result_ +{ + cv::Rect roi_src; + cv::Rect roi_show; + WTB_Check_Result_() + { + Init(); + } + void Init() + { + roi_src = cv::Rect(0, 0, 0, 0); + roi_show = cv::Rect(0, 0, 0, 0); + } +}; +// 其他检测结果 +struct OtherCheckResult +{ + YX_CheckResult_ result_YX; + WTB_Check_Result_ WTB_Check_Result; + LackPol_CheckResult_ result_LackPol; + OtherCheckResult() + { + Init(); + } + void Init() + { + result_YX.Init(); + WTB_Check_Result.Init(); + result_LackPol.Init(); + } +}; +// 检测指令 +struct CHECK_INSTRUCT_ +{ + + bool bWhiteAndBlack; // 使用另外一个 检测模型。 + + CHECK_INSTRUCT_() + { + Init(); + } + void Init() + { + + bWhiteAndBlack = false; + } +}; + +// 亮点的判断参数 +struct LD_ConfigT_ +{ + bool buse; + float minArea; + float maxArea; + float hj; + LD_ConfigT_() + { + buse = false; + minArea = 0; + maxArea = 0; + hj = 0; + } + void print(std::string str) + { + printf("%s buse %d minArea %f maxArea %f hj %f\n", str.c_str(), buse, minArea, maxArea, hj); + } +}; + +// 检测区域参数 +struct Detect_ROI_Config +{ + bool bdraw; // 是否绘制 + std::vector> roiList_Src; + std::vector> roiList_Show; + Detect_ROI_Config() + { + Init(); + } + void Init() + { + bdraw = false; + for (auto &innerVec : roiList_Src) + { + innerVec.clear(); + } + roiList_Src.clear(); // 清空外层vector + + for (auto &innerVec : roiList_Show) + { + innerVec.clear(); + } + roiList_Show.clear(); // 清空外层vector + } + void Update(const std::vector &list, const cv::Rect &roi, float fScale_x, float fScale_y) + { + + std::vector adjustedPolygon; + std::vector adjustedPolygon_size; + // 遍历多边形中的每个点,并根据roi调整位置 + for (const auto &point : list) + { + // 调整每个点的位置,平移到roi的位置 + cv::Point adjustedPoint(point.x - roi.x, point.y - roi.y); + cv::Point sizep; + sizep.x = adjustedPoint.x * fScale_x; + sizep.y = adjustedPoint.y * fScale_y; + adjustedPolygon.push_back(adjustedPoint); + adjustedPolygon_size.push_back(sizep); + } + + // 将调整后的多边形添加到roiList_Src + roiList_Src.push_back(adjustedPolygon); + roiList_Show.push_back(adjustedPolygon_size); + } + // 判断点是否在指定idx的ROI内 + bool isPointInROI(int idx, const cv::Point &point) + { + // 判断索引是否有效 + if (idx < 0 || idx >= roiList_Src.size()) + { + printf("Invalid idx: %d\n", idx); + return false; + } + + // 获取第 idx 个多边形 + const std::vector &polygon = roiList_Src[idx]; + + // 使用 pointPolygonTest 来判断点是否在多边形内 + double result = cv::pointPolygonTest(polygon, point, false); + + // 如果结果大于 0,则点在多边形内 + if (result > 0) + { + return true; + } + // 如果结果等于 0,点在边界上 + else if (result == 0) + { + return true; // 你可以根据需求调整边界情况 + } + + // 如果结果小于 0,点在多边形外 + return false; + } + + void print(std::string str) + { + printf("%s bdraw %d roi num %ld\n", str.c_str(), bdraw, roiList_Src.size()); + } +}; +// 复测的状态 +enum ReJson_Status +{ + ReJson_Status_Idel, + ReJson_Status_start, + ReJson_Status_Run, + ReJson_Status_end, +}; +struct AD_Channel_Info_ +{ + cv::Rect roi; + int num; + float fdis; + AD_Channel_Info_() + { + roi = cv::Rect(0, 0, 0, 0); + num = 0; + fdis = 999999999999; + } +}; + +extern std::string GetErrorCodeInfo(int nErrorCode); + +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/include/CheckSODefine.hpp b/AlgorithmModule/include/CheckSODefine.hpp new file mode 100644 index 0000000..e69de29 diff --git a/AlgorithmModule/include/CheckUtil.hpp b/AlgorithmModule/include/CheckUtil.hpp new file mode 100644 index 0000000..8cb6bfe --- /dev/null +++ b/AlgorithmModule/include/CheckUtil.hpp @@ -0,0 +1,76 @@ +/* + * @Descripttion: + * @version: + * @Author: sueRimn + * @Date: 2022-04-28 10:41:42 + * @LastEditors: sueRimn + * @LastEditTime: 2022-04-28 15:32:49 + */ +/* + * FileName:CoreLogicFactory.hpp + * Version:V1.0 + * Description: + * Created On:Mon Sep 10 11:13:13 UTC 2018 + * Modified date: + * Author:Sky + */ +#ifndef _CheckUtil_HPP_ +#define _CheckUtil_HPP_ +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +class CheckUtil +{ +public: + static long getcurTime(); + static std::string Op_float2String(float nvalue); + static int64_t getSnowId(); + static bool JudgRect(cv::Rect roi, int img_w, int img_h); + static bool JudgRect_SZ(cv::Rect roi, int w, int h); + static bool compareIgnoreCase(const std::string &str1, const std::string &str2); + static bool RoiInImg(cv::Rect roi, cv::Mat img); + static int printROI(cv::Rect roi, std::string str = ""); + static float CalIoU(cv::Rect rect1, cv::Rect rect2); + static float CalRoi2RoiPre(cv::Rect rect1, cv::Rect rect2); + static float CalIoU_t(cv::Rect rect1, cv::Rect rect2); + static int CheckRect(cv::Rect &roi, int img_w, int img_h); + static int SizeRect(cv::Rect &roi, int img_w, int img_h, int addw, int addh); + + // 计算平均灰度 + static float CalImgBrightness(cv::Mat imgRoi); + // 计算角度 + static float Cal2PointAngle(cv::Point p_left, cv::Point p_right); + + // 找图片的最大外轮廓 + static cv::Rect getLargestContourROI(const cv::Mat &binaryImg, bool &found); + + static std::string GetRectString(cv::Rect rect); + //创建目录 + static int CreateDir(const std::string &dir); + + // 点的距离是否过小 + static bool bcalDis(cv::Point p1, cv::Point p2, int disT); + static double calDis(cv::Point p1, cv::Point p2); + static void PrintRect(cv::Rect roi, std::string str = ""); + static int cutSmallImg(cv::Mat img, std::vector &samllRoiList, cv::Rect config_roi, int config_SmallImg_Width, int config_SmallImg_Height, int config_MinOverlap_Width, int config_MinOverlap_Height); +}; +template +static std::string str_Format(const std::string &format, Args... args) +{ + auto size_buf = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; + std::unique_ptr buf(new (std::nothrow) char[size_buf]); + + if (!buf) + return std::string(""); + + std::snprintf(buf.get(), size_buf, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size_buf - 1); + +} +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/include/Define_Base.h b/AlgorithmModule/include/Define_Base.h new file mode 100644 index 0000000..79be90f --- /dev/null +++ b/AlgorithmModule/include/Define_Base.h @@ -0,0 +1,46 @@ +/* +//定义整个系统基础的 定义 信息 + */ +#ifndef Define_Base_H_ +#define Define_Base_H_ +#include +#include +#include "CheckUtil.hpp" +#include "ImgCheckConfig.h" +#include "ImageDetConfig.h" +#include "Define_Error.h" + +// 检测分析线程类数目 +#define IMGCHECKANALYSISY_NUM 4 +// 最大 GPU 个数 +#define MAX_GPU_NUM 2 + +// 单个产品有几个相机拍摄 +#define MAX_Camera_NUM 2 + +// 相机ID 的相关定义 +enum Camera_IDX +{ + Camera_IDX_0 = 0, + Camera_IDX_1 = 1, +}; +static const std::string strCameraName[] = + { + "left", + "right"}; +struct Camera_Info +{ + Camera_IDX camera_ID; + std::string camera_name; + Camera_Info() + { + Init(); + } + void Init() + { + camera_ID = Camera_IDX_0; + camera_name = strCameraName[camera_ID]; + } +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/Define_Error.h b/AlgorithmModule/include/Define_Error.h new file mode 100644 index 0000000..a4e7586 --- /dev/null +++ b/AlgorithmModule/include/Define_Error.h @@ -0,0 +1,67 @@ +/* +//定义整个系统基础的 定义 信息 + */ +#ifndef Define_Error_H_ +#define Define_Error_H_ +#include +using namespace std; + +enum ERRORCODEDEFINE +{ + CHECK_OK, + CHECK_ERROR_VERSION, // 参数或接口版本问题 + CHECK_ERROR_Config_Null, // 参数指针为空 + CHECK_ERROR_Config_Value, // 参数值错误 + CHECK_ERROR_Path_NULL, // 路径为空 + CHECK_ERROR_Mask_Empty, // mask 图片为空 + CHECK_ERROR_Config_cutRoi, // 参数的 roi 错误 + CHECK_ERROR_CheckImg_Empty, // 检测 图片为空 + CHECK_ERROR_PushImg_ListSize, // 送图错误 队列太长 + CHECK_ERROR_PushImg_NoDetChannel, // 不检测通道 + CHECK_ERROR_PushImg_Existing_ID, // ID 已存在 + CHECK_ERROR_PushImg_ID_Error, // ID 错误 + CHECK_ERROR_ID_Error, // ID 错误 + CHECK_ERROR_L255_Empty, // L255 为空 + CHECK_ERROR_L255_Edge_Fail, // L255 边界搜索失败 + CHECK_ERROR_PRODUCT_ID_EXIST, // 产品 ID 已存在 + CHECK_ERROR_Camear_ID_Error, // 相机ID 错误 + INIT_CameraCheck_Error, // 初始化 相机处理类错误 +}; +static const std::string str_ErrorName[] = + { + "ok", + "ERROR_VERSION", + "Config_Null", + "Config_Value", + "Path_NULL", + "Mask_Empty", + "Config_cutRoi", + "CheckImg_Empty", + "PushImg_ListSize", + "PushImg_NoDetChannel", + "PushImg_Existing_ID", + "PushImg_ID_Error", + "ID_Error", + "L255_Empty", + "L255_Edge_Fail", + "L255_Empty", + "L255_Empty", + "PRODUCT_ID_EXIST", + "Camear_ID_Error", + "INIT_CameraCheck_Error"}; +struct ErrorInfo +{ + int nerror_code; // 错误代码 + string strerror_msg; // 错误信息 + ErrorInfo() + { + Init(); + } + void Init() + { + nerror_code = CHECK_OK; + strerror_msg = str_ErrorName[CHECK_OK]; + } +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/Define_Product.hpp b/AlgorithmModule/include/Define_Product.hpp new file mode 100644 index 0000000..21f05ed --- /dev/null +++ b/AlgorithmModule/include/Define_Product.hpp @@ -0,0 +1,281 @@ + + +#ifndef Define_Product_HPP_ +#define Define_Product_HPP_ +#include "Define_Base.h" +#include "ImgCheckConfig.h" + +// 相机的一些状态情况 +struct CameraImage_Status +{ + bool bImgComplete; /// 图片送完成了 + bool bHaveImg; // 是否有图片 + bool bHave_L255; // 是否有L55图片 + bool bHave_DP; // 是否有DP图片 + bool bhave_UP; // 是否有UP图片 + bool bDetCutRoi; // 是否完成边缘检测 + CameraImage_Status() + { + Init(); + } + void Init() + { + bImgComplete = false; + bHaveImg = false; + bHave_L255 = false; + bHave_DP = false; + bhave_UP = false; + bDetCutRoi = false; + } +}; +// 处理状态 +enum Check_Step +{ + Check_Step_NODet = 0, // 未处理 + Check_Step_PreDet, // 预处理 + Check_Step_ImgeDet, // 图片处理 + Check_Step_ImgeDet_End, // 图片检测完成 + Check_Step_Complete, // 处理完成 + Check_Step_COUNT, +}; +// 检测结果状态 +enum Check_Result_Status +{ + Check_Result_Status_NoDet = -1, // 未检测 + Check_Result_Status_PreError = -2, // 预处理错误 + Check_Result_Status_DetError = -3, // 检测错误 + Check_Result_Status_OK = 0, // 检测成功 结果OK + Check_Result_Status_NG = 1, // 检测成功 检测结果NG +}; + +// 产品检测结果 +struct PRODUCT_DET_RESULT_ +{ + int nresult; // 检测结果 + int nError; // 错误情况 + std::string strSN; // 产品SN号。 + int AddImgStatus; // 检测图片状态 + int detImgStatus; // 检测状态 1:表检测全部完成 + int L255ImgStatus; // l255 图片状态 1 有了 + bool bDet_Edge; + bool bDet_Zf; + bool bDet_Up; + int nDet_DP; + bool bhaveDPImg; // 是否有DP的图片 + bool bHaveUPImg; // 是否有UP的图片 + cv::Rect CutRoi; + std::shared_ptr> pZF_roiList; // 字符的区域 + cv::Mat Edge_maskImg; + cv::Mat Up_MaskImg; + cv::Mat DP_MaskImg; + std::vector> DetImageList; // 每个通道的检测结果 ,返回的结果。 + std::vector> pImageDetResultList; // 检测结果的完整信息 + + std::vector LogList; + int nNotDetCount; // 未检测计数。 当计算超过阈值时,直接不检测,返回结果。 + PRODUCT_DET_RESULT_() + { + Init(); + } + void Init() + { + nresult = 0; + nError = 0; + strSN = ""; + AddImgStatus = 0; + detImgStatus = 0; + L255ImgStatus = 0; + bDet_Edge = false; + bDet_Zf = false; + bDet_Up = false; + bhaveDPImg = false; + bHaveUPImg = false; + nDet_DP = 0; + CutRoi = cv::Rect(0, 0, 0, 0); + if (!Edge_maskImg.empty()) + { + Edge_maskImg.release(); + } + if (!Up_MaskImg.empty()) + { + Up_MaskImg.release(); + } + if (!DP_MaskImg.empty()) + { + DP_MaskImg.release(); + } + LogList.clear(); + LogList.shrink_to_fit(); + + nNotDetCount = 0; + } +}; + +// 相机检测结果 +struct Camera_Check_Result +{ + + int detMode; // 检测模式 + + Camera_Info camera_info; // 相机信息 + Check_Result_Status checkResultStatus; // 检测结果状态 + int nresult; // 检测结果 + Check_Step checkStep; // 检测步骤 + CameraImage_Status cameraImage_Status; // 图片状态 + ErrorInfo errorInfo; // 错误情况 + + std::string strSN; // 产品SN号。 + int AddImgStatus; // 检测图片状态 + int detImgStatus; // 检测状态 1:表检测全部完成 + int L255ImgStatus; // l255 图片状态 1 有了 + bool bDet_Edge; + bool bDet_Zf; + bool bDet_Up; + int nDet_DP; + bool bhaveDPImg; // 是否有DP的图片 + bool bHaveUPImg; // 是否有UP的图片 + cv::Rect CutRoi; + std::shared_ptr> pZF_roiList; // 字符的区域 + cv::Mat sheildImg; // 屏蔽图片 + cv::Mat edge_SheildImg; // 边缘屏蔽图片 + cv::Mat Edge_maskImg; + cv::Mat Up_MaskImg; + cv::Mat DP_MaskImg; + std::vector> DetImageList; // 每个通道的检测结果 ,返回的结果。 + std::vector> pImageDetResultList; // 检测结果的完整信息 + + std::vector LogList; + int nNotDetCount; // 未检测计数。 当计算超过阈值时,直接不检测,返回结果。 + cv::Rect markLine_Roi_X; + cv::Rect markLine_Roi_Y; + std::mutex mtx_Det; // 互斥量 + Camera_Check_Result() + { + Init(); + } + void Init() + { + camera_info.Init(); + checkResultStatus = Check_Result_Status_NoDet; + nresult = 0; + + checkStep = Check_Step_NODet; + cameraImage_Status.Init(); + + errorInfo.Init(); + strSN = ""; + AddImgStatus = 0; + detImgStatus = 0; + L255ImgStatus = 0; + bDet_Edge = false; + bDet_Zf = false; + bDet_Up = false; + bhaveDPImg = false; + bHaveUPImg = false; + nDet_DP = 0; + detMode = DET_MODE_Det; + CutRoi = cv::Rect(0, 0, 0, 0); + if (!Edge_maskImg.empty()) + { + Edge_maskImg.release(); + } + if (!Up_MaskImg.empty()) + { + Up_MaskImg.release(); + } + if (!DP_MaskImg.empty()) + { + DP_MaskImg.release(); + } + if (!sheildImg.empty()) + { + sheildImg.release(); + } + if (!edge_SheildImg.empty()) + { + edge_SheildImg.release(); + } + LogList.clear(); + LogList.shrink_to_fit(); + markLine_Roi_X = cv::Rect(0, 0, 0, 0); + markLine_Roi_Y = cv::Rect(0, 0, 0, 0); + nNotDetCount = 0; + } + // 设置状态和结果 + void Set_Det_Step_Result(Check_Step checkStatus, Check_Result_Status checkResultStatus) + { + this->checkStep = checkStatus; + this->checkResultStatus = checkResultStatus; + } + void AddLog(std::string str) + { + LogList.push_back(str); + } +}; +// 产品检测结果 +struct Product_Check_Result +{ + int nresult; // 检测结果 + Check_Step checkStatus; // 检测状态 + + std::string strSN; // 产品SN号。 + ErrorInfo errorInfo; // 错误情况 + + std::vector> cameraCheckResults; // 每个通道的检测结果 ,返回的结果。 + + std::vector LogList; + + bool bIsImgComplete; // 图片是否都送完了。 + + Product_Check_Result() + { + Init(); + } + void Init() + { + checkStatus = Check_Step_NODet; + nresult = 0; + strSN = ""; + errorInfo.Init(); + cameraCheckResults.erase(cameraCheckResults.begin(), cameraCheckResults.end()); + cameraCheckResults.clear(); + LogList.clear(); + LogList.shrink_to_fit(); + bIsImgComplete = false; + } + // 创建相应的相机检测结果 + std::shared_ptr CreateCameraCheckResult(std::string strcameraName) + { + std::shared_ptr tem; + tem = GetCameraCheckResult(strcameraName); + if (tem == nullptr) + { + tem = std::make_shared(); + tem->camera_info.camera_name = strcameraName; + cameraCheckResults.push_back(tem); + } + return tem; + } + std::shared_ptr GetCameraCheckResult(std::string strcameraName) + { + if (cameraCheckResults.size() <= 0) + { + return nullptr; + } + for (int i = 0; i < cameraCheckResults.size(); i++) + { + if (cameraCheckResults[i]->camera_info.camera_name == strcameraName) + { + return cameraCheckResults[i]; + } + } + return nullptr; + } + + void AddLog(std::string str) + { + LogList.push_back(str); + } +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/DrawImg.h b/AlgorithmModule/include/DrawImg.h new file mode 100644 index 0000000..9794c84 --- /dev/null +++ b/AlgorithmModule/include/DrawImg.h @@ -0,0 +1,68 @@ +/* +//图片基本处理 + */ +#ifndef DrawImgl_H_ +#define DrawImg_H_ + +#include +#include +#include "ImgCheckConfig.h" +#include "JsonCoversion.h" +#include +#include "ImageDetConfig.h" + +using namespace std; + +class DrawImg +{ +public: + enum Draw_Type + { + Draw_Type_YS, + Draw_Type_NG, + Draw_Type_Other, + }; + +public: + DrawImg(); + ~DrawImg(); + + int DrawResult(std::shared_ptr &result); + int DrawInfoImg(cv::Mat &img, cv::Rect roi, int blobidx, int type, float fArea, float fenerge, float fmaxv, float fhj, float flen, Draw_Type drayType, std::string strqx_error, std::string strqx_code, int qx_type, int qx_num, float mindis, bool bqxroi = false); + int DrawInfoImg_Src(cv::Mat &img, cv::Rect roi, int blobidx, int type, float fArea, float fenerge, float fmaxv, float fhj, float flen, Draw_Type drayType, std::string strqx_error, std::string strqx_code, int qx_type, int qx_num, float mindis, bool bqxroi = false); + int preDealImg(cv::Mat &srcimg, cv::Mat &image_resize, bool bfilpSrcImg = true); + int DrawPointList(cv::Mat &image_draw, std::vector plist); + + bool bdraw(cv::Rect roi); + +public: + int font_face = cv::FONT_HERSHEY_SIMPLEX; + double font_scale = 0.5; + int thickness = 1; + bool m_bstatus_ReJson; + + cv::Scalar Color_Brightness_roi = cv::Scalar(0, 255, 0); + cv::Scalar Color_Brightness_text = cv::Scalar(0, 255, 0); + cv::Scalar DrawBlobErrorCorleList[ERROR_TYPE_COUNT]; + + std::vector m_drawList; + +private: +}; +class CheckResultJson : public JsonCoversion +{ +public: + CheckResultJson() {} + virtual ~CheckResultJson() {} + +public: + virtual Json::Value toJsonValue(); + virtual void toObjectFromValue(Json::Value root); + int GetConfig(std::string strJson, std::shared_ptr &pOneImgDetResult); + std::string GetResultString(std::shared_ptr &pOneImgDetResult); + +private: + std::shared_ptr m_pOneImgDetResult; +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/EdgeDet.h b/AlgorithmModule/include/EdgeDet.h new file mode 100644 index 0000000..57cd0dc --- /dev/null +++ b/AlgorithmModule/include/EdgeDet.h @@ -0,0 +1,60 @@ +/* +//图片基本处理 + */ +#ifndef EdgeDet_H_ +#define EdgeDet_H_ +#include +#include "AI_Edge_Algin.h" + +using namespace std; + +enum LINE_SEARCH_DIRECTION_CONST +{ + DIRECTION_POSITIVE = 1, + DIRECTION_NEGATIVE = -1, +}; +class EdgeDet_New +{ + +public: + EdgeDet_New(); + ~EdgeDet_New(); + int InitRun(); + int InitModel(); + int GetImgEdge(cv::Mat img, cv::Rect &roi); + int AIEdgeDete(const cv::Mat &img, AI_Edge_Algin::DetConfig *pdetConfig, cv::Mat &detMaskImg, cv::Rect &roi); + + cv::Mat showimg; + bool bshowimg; + AI_IMG_deal m_AIDeal; + OtherDet_Config m_OtherDet_Config; + // std::shared_ptr m_pAI_Edge_Algin; // 边缘定位 + AI_Edge_Algin m_pAI_Edge_Algin; + + cv::Mat detmask; + +private: + /// @brief + /// @param img 搜到图片 单通道 + /// @param DirectSign 搜索方向 >0 正向,< 0 反向 + /// @param Gate 阈值 + /// @param BorW 搜索黑点 = 0还是白点 = 1 + /// @param roi 搜索范围 + /// @param StepCount 搜索点数 + /// @param Limit 最小满是阈值点个数算上搜索成功 + /// @return <0 搜索错误, >=0表示 搜索位置 + int UDNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit); + /// @brief + /// @param img 搜到图片 单通道 + /// @param DirectSign 搜索方向 >0 正向,< 0 反向 + /// @param Gate 阈值 + /// @param BorW 搜索黑点 = 0还是白点 = 1 + /// @param roi 搜索范围 + /// @param StepCount 搜索点数 + /// @param Limit 最小满是阈值点个数算上搜索成功 + /// @return <0 搜索错误, >=0表示 搜索位置 + int LRNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit); + // int LRNoiseEdgeDetect(cv::Mat img,int DirectSign, int Gate,int BorW, int StartSearchSite, int Step, int StepCount, int top, int bottom, int Limit, int Depth, int MaxLimit); +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/ImageDetBase.h b/AlgorithmModule/include/ImageDetBase.h new file mode 100644 index 0000000..49bd933 --- /dev/null +++ b/AlgorithmModule/include/ImageDetBase.h @@ -0,0 +1,46 @@ +#ifndef ImageDetBase_H_ +#define ImageDetBase_H_ +#include +#include +#define INTERFACE_Det_VERSION 4 + +/*******************一般调用流程*************************************************************************************************************************/ +/*******************1、初始化 UpdateConfig*************************************************************************************************************************/ +/*******************2、初始化 Init 并开启 *************************************************************************************************************************/ +/*******************3、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_IDLE 可以设置检测数据并开启检测 SetDataRun***************************************************/ +/*******************4、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_COMPLETE 检测完成,可以获取检测结果 GetCheckReuslt 拷贝检测结果 自动把状态设为 CHECK_THREAD_STATUS_IDLE*****************************/ +struct ImageDetconfig; +struct ImageDetResult; +class ImgCheckBase +{ +protected: + ImgCheckBase() {} + +public: + // delete camera interface + ~ImgCheckBase() {} + static ImgCheckBase *GetInstance(); + // 初始化参数 pconfig 参数指针 返回:0 成功 其他异常 + virtual int RunStart(void *pconfig1 = NULL) = 0; + + // 设置检测数据,并开启检测 返回:0 成功 其他异常 + virtual int SetDataRun_SharePtr(std::shared_ptr p) = 0; + + // 获取结果信息 返回:0 成功 其他异常 + virtual int GetCheckReuslt(std::shared_ptr &pResult) = 0; + + virtual int CheckImg(std::shared_ptr p, std::shared_ptr &pResult) = 0; + virtual int ReJsonResul(std::shared_ptr p, std::shared_ptr &pResult) = 0; + + // 获取检测库 状态信息 返回:CHECK_THREAD_RUN_STATUS + virtual int GetStatus() = 0; + + // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 + virtual int UpdateConfig(void *pconfig, int nConfigType) = 0; + + // 返回检测版本信息 + virtual std::string GetVersion() = 0; + // 返回错误信息 + virtual std::string GetErrorInfo() = 0; +}; +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/ImageDetConfig.h b/AlgorithmModule/include/ImageDetConfig.h new file mode 100644 index 0000000..5b2564e --- /dev/null +++ b/AlgorithmModule/include/ImageDetConfig.h @@ -0,0 +1,344 @@ + + +#ifndef _ImageDetConfig_HPP_ +#define _ImageDetConfig_HPP_ +#include +#include +#include "ImgCheckConfig.h" + +// 缺陷结果信息 +struct QX_ERROR_INFO_ +{ + int Idx; + int result; + std::string result_name; + cv::Rect roi; + int area; + int energy; + float JudgArea; + float JudgArea_second; + float flen; + int nconfig_qx_type; + std::string qx_name; + int maxValue; + float grayDis; + float fUpIou; + float density; // Blob- 密度 + bool bIsStandardLD; // 是否通过LD标准判定(跳过UP/DP的IOU检查) + std::vector detLogList; // 检测日志 + QX_ERROR_INFO_() + { + Init(); + } + ~QX_ERROR_INFO_() + { + } + void Init() + { + Idx = 0; + area = 0; + energy = 0; + JudgArea = 0; + JudgArea_second = 0; + flen = 0; + nconfig_qx_type = 0; + qx_name = ""; + maxValue = 0; + grayDis = 0; + fUpIou = 0; + result = 0; + result_name = "OK"; + density = 0; + bIsStandardLD = false; + cv::Rect roi = cv::Rect(0, 0, 0, 0); + detLogList.erase(detLogList.begin(), detLogList.end()); + detLogList.clear(); + } + void print(std::string str = "") + { + std::cout << str << ": " + << "Idx: " << Idx + << ", Result: " << result << " " << result_name + << ", ROI: (" << roi.x << ", " << roi.y << ", " << roi.width << ", " << roi.height << ")" + << ", Area: " << area + << ", Energy: " << energy + << ", JudgArea: " << JudgArea + << ", JudgArea second: " << JudgArea_second + << ", density: " << density + << ", Flen: " << flen + << ", nconfig_qx_type: " << nconfig_qx_type + << ", QX Name: " << qx_name + << ", Max Value: " << maxValue + << ", Gray Dis: " << grayDis + << ", fUpIou: " << fUpIou + << std::endl; + } +}; +struct One_Image_CheckResult_ +{ + cv::Rect CutRoi; // 当前检测图片 对应的裁切区域 + cv::Rect Param_CropRoi; // 参数模版 对应的裁切区域 + std::shared_ptr> pQx_ErrorList; // 缺陷错误信息 + void print(std::string str = "") + { + std::cout << str << ": " + << " CutRoi: (" << CutRoi.x << ", " << CutRoi.y << ", " << CutRoi.width << ", " << CutRoi.height << ")" + << std::endl; + + std::cout << str << ": " + << " Param_CropRoi: (" << Param_CropRoi.x << ", " << Param_CropRoi.y << ", " << Param_CropRoi.width << ", " << Param_CropRoi.height << ")" + << std::endl; + + for (int i = 0; i < pQx_ErrorList->size(); i++) + { + pQx_ErrorList->at(i).print(std::to_string(i)); + } + } +}; +// 定位结果 +struct Align_Result +{ + bool bDet; // 检测状态 true 成功,false 失败。 + bool bUse; // 是否要使用。 + bool bDraw; // 是否绘制 + + cv::Point bestMatch; + int offt_x; // 偏移值 + int offt_y; // 偏移值 + float fCropROI_Scale_ParmToDet_X; // 裁剪区域的缩放 + float fCropROI_Scale_ParmToDet_Y; // 裁剪区域的缩放 + + std::vector feature_PointList_DetImg; // 特征区域点 检查图上的特征点 + cv::Rect Crop_Roi_DetImg; // 检测图片上的 裁切区域 + cv::Rect Crop_Roi_ParmImg; // 参数图片上的 裁切区域 + + Align_Result() + { + Init(); + } + void Init() + { + bDet = false; + bUse = false; + offt_x = 0; + offt_y = 0; + bestMatch = cv::Point(0, 0); + fCropROI_Scale_ParmToDet_X = 1; + fCropROI_Scale_ParmToDet_Y = 1; + feature_PointList_DetImg.clear(); + Crop_Roi_DetImg = cv::Rect(0, 0, 0, 0); + Crop_Roi_ParmImg = cv::Rect(0, 0, 0, 0); + bDraw = false; + } + void copy(Align_Result tem) + { + this->bDet = tem.bDet; + this->bUse = tem.bUse; + this->offt_x = tem.offt_x; + this->offt_y = tem.offt_y; + this->fCropROI_Scale_ParmToDet_X = tem.fCropROI_Scale_ParmToDet_X; + this->fCropROI_Scale_ParmToDet_Y = tem.fCropROI_Scale_ParmToDet_Y; + this->bDraw = tem.bDraw; + this->bestMatch = tem.bestMatch; + this->Crop_Roi_DetImg = tem.Crop_Roi_DetImg; + this->Crop_Roi_ParmImg = tem.Crop_Roi_ParmImg; + this->feature_PointList_DetImg.assign(tem.feature_PointList_DetImg.begin(), tem.feature_PointList_DetImg.end()); + } + // 从检测图的原始图片 映射到 参数的原始图 + cv::Point Det_srcToParm_src_Point(cv::Point &p) + { + cv::Point dst_p; + dst_p.x = (p.x - offt_x) / fCropROI_Scale_ParmToDet_X; + dst_p.y = (p.y - offt_y) / fCropROI_Scale_ParmToDet_Y; + return dst_p; + } + cv::Rect Det_srcToParm_src_Rect(cv::Rect &roi) + { + cv::Rect dst_roi; + cv::Point src_pl = cv::Point(roi.x, roi.y); + cv::Point src_rb = cv::Point(roi.x + roi.width, roi.y + roi.height); + cv::Point p_lt = Det_srcToParm_src_Point(src_pl); + cv::Point p_rb = Det_srcToParm_src_Point(src_rb); + dst_roi.x = p_lt.x; + dst_roi.y = p_lt.y; + dst_roi.width = p_rb.x - p_lt.x; + dst_roi.height = p_rb.y - p_lt.y; + + return dst_roi; + } + // 参数的原始图 映射到 检测图的原始图片 + cv::Point Parm_srcToDet_src_Point(cv::Point &p) + { + cv::Point dst_p; + dst_p.x = p.x * fCropROI_Scale_ParmToDet_X + offt_x; + dst_p.y = p.y * fCropROI_Scale_ParmToDet_Y + offt_y; + return dst_p; + } + cv::Rect Parm_srcToDet_src_Rect(cv::Rect &roi) + { + cv::Rect dst_roi; + cv::Point src_pl = cv::Point(roi.x, roi.y); + cv::Point src_rb = cv::Point(roi.x + roi.width, roi.y + roi.height); + cv::Point p_lt = Parm_srcToDet_src_Point(src_pl); + cv::Point p_rb = Parm_srcToDet_src_Point(src_rb); + dst_roi.x = p_lt.x; + dst_roi.y = p_lt.y; + dst_roi.width = p_rb.x - p_lt.x; + dst_roi.height = p_rb.y - p_lt.y; + + return dst_roi; + } + // 参数图片上的点 对应到 检测裁切后上的点 + cv::Point Parm_srcToDet_Crop_Point(cv::Point &p) + { + cv::Point dst_p = Parm_srcToDet_src_Point(p); + dst_p.x -= Crop_Roi_DetImg.x; + dst_p.y -= Crop_Roi_DetImg.y; + return dst_p; + } + // 参数图片上的点 对应到 检测裁切后上的点 + cv::Rect Parm_srcToDet_Crop_Rect(cv::Rect &roi) + { + cv::Rect dst_roi; + cv::Point src_pl = cv::Point(roi.x, roi.y); + cv::Point src_rb = cv::Point(roi.x + roi.width, roi.y + roi.height); + cv::Point p_lt = Parm_srcToDet_Crop_Point(src_pl); + cv::Point p_rb = Parm_srcToDet_Crop_Point(src_rb); + dst_roi.x = p_lt.x; + dst_roi.y = p_lt.y; + dst_roi.width = p_rb.x - p_lt.x; + dst_roi.height = p_rb.y - p_lt.y; + + return dst_roi; + } + void CalOfftScal() + { + cv::Point src_pl = cv::Point(Crop_Roi_DetImg.x, Crop_Roi_DetImg.y); + cv::Point src_rb = cv::Point(Crop_Roi_DetImg.x + Crop_Roi_DetImg.width, Crop_Roi_DetImg.y + Crop_Roi_DetImg.height); + + cv::Point param_pl = cv::Point(Crop_Roi_ParmImg.x, Crop_Roi_ParmImg.y); + cv::Point param_rb = cv::Point(Crop_Roi_ParmImg.x + Crop_Roi_ParmImg.width, Crop_Roi_ParmImg.y + Crop_Roi_ParmImg.height); + + int a_x_1 = src_pl.x; + int a_x_2 = src_rb.x; + + int b_x_1 = param_pl.x; + int b_x_2 = param_rb.x; + + int diff_a_x = a_x_1 - a_x_2; + int diff_b_x = b_x_1 - b_x_2; + float fscale_x = 1; + if (diff_b_x != 0) + { + fscale_x = diff_a_x * 1.0f / diff_b_x; + } + int ofx = a_x_1 - fscale_x * b_x_1; + + // printf("a_x_1 %d a_x_2 %d\n", a_x_1, a_x_2); + // printf("b_x_1 %d b_x_2 %d\n", b_x_1, b_x_2); + // printf("fscale_x %f ofx %d \n", fscale_x, ofx); + + int a_y_1 = src_pl.y; + int a_y_2 = src_rb.y; + + int b_y_1 = param_pl.y; + int b_y_2 = param_rb.y; + + int diff_a_y = a_y_1 - a_y_2; + int diff_b_y = b_y_1 - b_y_2; + float fscale_y = 1; + if (diff_b_y != 0) + { + fscale_y = diff_a_y * 1.0f / diff_b_y; + } + int ofy = a_y_1 - fscale_y * b_y_1; + + // printf("a_y_1 %d a_y_2 %d\n", a_y_1, a_y_2); + // printf("b_y_1 %d b_y_2 %d\n", b_y_1, b_y_2); + // printf("fscale_y %f ofy %d \n", fscale_y, ofy); + + offt_x = ofx; + offt_y = ofy; + fCropROI_Scale_ParmToDet_X = fscale_x; + fCropROI_Scale_ParmToDet_Y = fscale_y; + } + void print() + { + printf("scale x %f y %f ,offt x %d y %d\n", fCropROI_Scale_ParmToDet_X, fCropROI_Scale_ParmToDet_Y, offt_x, offt_y); + } +}; + +struct ImageDetconfig +{ + cv::Mat ShieldMaskImg; // 屏蔽mask + cv::Mat UpMaskImg; // Up 画面 mask图片 + cv::Mat DPMaskImg; + cv::Mat edge_maskImg; + bool bUseUpMaskImg; + std::shared_ptr> pZF_roiList; // 字符的区域 + cv::Rect markLine_Roi_X; + cv::Rect markLine_Roi_Y; + std::shared_ptr pBaseImgCheckConfig; + Align_Result alignResult; // 定位结果 + ImageDetconfig() + { + Init(); + } + ~ImageDetconfig() + { + } + void Init() + { + bUseUpMaskImg = false; + if (!ShieldMaskImg.empty()) + { + ShieldMaskImg.release(); + } + if (!UpMaskImg.empty()) + { + UpMaskImg.release(); + } + if (!DPMaskImg.empty()) + { + DPMaskImg.release(); + } + if (!edge_maskImg.empty()) + { + edge_maskImg.release(); + } + alignResult.Init(); + markLine_Roi_X = cv::Rect(0, 0, 0, 0); + markLine_Roi_Y = cv::Rect(0, 0, 0, 0); + } +}; + +struct ImageDetResult +{ + bool bShield_ZF; // 是否要屏蔽字符区域 + bool bUseUpImg; // 是否要使用 up img 进行过滤 + cv::Mat AI_maskImg; + int Yx_result; // 异显检测状态 + float fUP_IOU; // UP 画面 使用的 iou + std::shared_ptr> pZF_roiList; // 字符的区域 + std::shared_ptr pOneImgDetResult; // 单图检测结果 + std::shared_ptr pBaseImgCheckResult; + ImageDetResult() + { + Init(); + } + ~ImageDetResult() + { + } + void Init() + { + bShield_ZF = false; + if (!AI_maskImg.empty()) + { + AI_maskImg.release(); + } + Yx_result = 0; + fUP_IOU = 0; + bUseUpImg = false; + } +}; +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/include/ImageStorage.h b/AlgorithmModule/include/ImageStorage.h new file mode 100644 index 0000000..5b62c6d --- /dev/null +++ b/AlgorithmModule/include/ImageStorage.h @@ -0,0 +1,44 @@ +#ifndef IMAGE_STORAGE_H +#define IMAGE_STORAGE_H + +#include +#include +#include +#include +#include +#include + +class ImageStorage { +private: + std::queue> imageQueue; + std::mutex queueMutex; + std::condition_variable cv; + std::thread storageThread; + + static ImageStorage* instance; // 静态成员指针,存储单例对象 + + bool stopFlag; + + // 私有构造函数和析构函数,防止外部创建实例 + ImageStorage(); + ~ImageStorage(); + + // 存储线程的工作函数 + void storeImages(); + +public: + // 获取单例实例 + static ImageStorage* getInstance(); + + // 禁止拷贝构造和赋值 + ImageStorage(const ImageStorage&) = delete; + ImageStorage& operator=(const ImageStorage&) = delete; + + // 添加图片到队列 + int addImage(const std::string &path,const cv::Mat &image,bool badd = false); + + // 停止存储线程 + void stop(); +}; + +#endif // IMAGE_STORAGE_H diff --git a/AlgorithmModule/include/ImgCheckAnalysisy.hpp b/AlgorithmModule/include/ImgCheckAnalysisy.hpp new file mode 100644 index 0000000..f357b17 --- /dev/null +++ b/AlgorithmModule/include/ImgCheckAnalysisy.hpp @@ -0,0 +1,379 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef ImgCheckAnalysisy_H_ +#define ImgCheckAnalysisy_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "BlobBase.h" +#include "AICheck.h" +#include "ImgCheckBase.h" +#include "ImageDetBase.h" +#include "ImgCheckConfig.h" +#include "CheckErrorCodeDefine.hpp" +#include "AIImgDeal.h" +#include "DrawImg.h" +#include "CheckConfigDefine.h" +#include "ConfigBase.h" +#include "ImageDetConfig.h" +#include "QX_Analysis.h" +#include "AIClassify.h" +#include "OtherDetect.h" +#include "AI_Second_Det.h" +#include "Define_Error.h" + +using namespace std; +using namespace cv; + +enum AT_THRESHOLD_TYPE_ +{ + AT_THRESHOLD_TYPE_NULL, + AT_THRESHOLD_TYPE_READY, + AT_THRESHOLD_TYPE_BUSY, + AT_THRESHOLD_TYPE_COMPLETE, +}; + +// 全局静态变量, 记录图像灰度值异常累计数量 +static int g_nImgBrightnessErrorCount = 0; +class ImgCheckAnalysisy : public ImgCheckBase +{ + +public: + ImgCheckAnalysisy(); + ~ImgCheckAnalysisy(); + + // 初始化参数 pconfig 参数指针 返回:0 成功 其他异常 + int RunStart(void *pconfig1); + + // 设置检测数据,并开启检测 返回:0 成AT_THRESHOLD_TYPE_READY功 其他异常 + int SetDataRun_SharePtr(std::shared_ptr p); + + // 获取结果信息 返回:0 成功 其他异常 + int GetCheckReuslt(std::shared_ptr &pResult); + + int CheckImg(std::shared_ptr p, std::shared_ptr &pResult); + int ReJsonResul(std::shared_ptr p, std::shared_ptr &pResult); + // 获取检测库 状态信息 返回:CHECK_THREAD_RUN_STATUS + int GetStatus(); + + // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 + int UpdateConfig(void *pconfig, int nConfigType); + + std::string GetVersion(); + + std::string GetErrorInfo(); + +private: + // 加载运行参数 + int LoadRunConfig(void *p); + + // 加载分析参数 + int LoadCheckConfig(void *p); + + /// @brief 初始化并且启动程序 + /// @return + int InitRun(int nId); + + /// @brief 开启检测 + /// @return + int StartCheck(); + + /// @brief 设置空闲 + /// @return + int SetIDLE(); + +private: + // 开启线程 + int StartThread(int nId); + // 停止线程 + int StopThread(); + + // 退出系统 + int ExitSystem(); + + // 初始化模型 + int InitModel(); + int InitModel_NF(); + int InitModel_YX(); + int InitModel_Clas(); + int InitModel_ZF(); + int InitModel_Up(); + int InitModel_127Cell(); + // 检测 + int CheckRun(); + + // 设置新的检测参数 + int SetNewConfig(); + int GetParamidx(); + // 增加检测日志 + int AddCheckLog(int nlevel, std::string str); + + int GetRegionIdx(int x, int y); + + ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能 + +private: + // 图片处理线程 + std::shared_ptr ptr_thread_Run; + int Run(int nId); // 运行; + + // 图片处理线程 + std::shared_ptr ptr_thread_AI; + + int set_cpu_id(const std::vector &cpu_set_vec); + + int saveAIImg(); + int AnalysisResult_New(); + int AnalysisResult_Qx(); + int AnalysisResult_Param_Judge(); + int AnalysisResult_Pre(QX_ERROR_INFO_ *pQX_info, std::string strChannel); // 弱化处理 + int AI_Det(cv::Mat inImg, cv::Mat &outimg); + + // 利用Up 画面过滤 + float UseUpMaskAnalysis(cv::Rect teroi, cv::Mat AIMaskImg); + float CalImgScorl(cv::Mat det_img, cv::Mat up_img); + float CalImgScorl_t(cv::Mat det_img, cv::Mat up_img); + // 分类 + int AI_Classify(cv::Mat img, cv::Rect qx_roi, float fjustarea, float *fmaxScore); + // 多区域分类 + int AI_Classify_New(const cv::Mat &src_Img, cv::Rect qx_roi, float fjustarea, float *fmaxScore); + // 计算缺陷长度 + float Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y); + // 启动AI处理 + int StartAIDeal(); + // 等待AIdeal完成 + int waitImgAIDealEnd(); + void waitAIData(); + // 二次计算缺陷面积 + int ReCalQX_AreaAndLen(AI_SecondDet::DetConfigResult *pdetConfig); + + // 检测结果分析 + int CheckAnalysisResult(); + + // BLob分析 + int BlobAnalysis_new(); + + int CalBLobMean_GrayDis(); + int CalBLobMean_GrayDis_127Cell(); + + // 计算blob的密度 + int CalBlobDensity(); + int CalBlobDensity_QX(); + + // 轮廓处理 + int Contours(); + // 轮廓处理 + int Contours_New(cv::Mat mask); + + cv::Rect GetCutRoi(cv::Rect roi, cv::Mat img); + cv::Rect GetREAIRoi(cv::Rect roi, cv::Mat img); + // 异显检测 + int AI_Det_YX(cv::Mat cropImg); + // 检测初始化 + int CheckImgInit(); + // 参数 核对 + int ConfigCheck(cv::Mat img); + // 多线程方式处理 + int AI_Detect_Thread(cv::Mat img, cv::Mat &ResultImg); + // 多线程处理,获取小图 序号。 + int Multi_Thread_GetSmallImgIdx(int ntype); + // 多线程处理,设置资源状态 + int Multi_Thread_SetSmallType(int idx, int ntype); + // AI 后处理 + int Multi_Thread_AIResultDet(cv::Mat &resultImg, int idx); + // AI预处理图片 + int AI_PreImg(cv::Mat img, cv::Mat &AI_DealImg); + + int ThreadAI(int nId); // 运行; + // resize 图片 + int ResizeImg(); + + // 更新 检测区域 + int Update_DetRoiList(); + // 绘制结果 + int DrawResult(); + + // 对127重复检测 + int ReCheck127Cell(const cv::Mat &DetImage); + + // 把检查结果转成json + int DetResultToJson(); + + int DrawOther(); + // 创建mask + int CreateMaskImg(); + + int SetInDetConfig(); + // 更新亮点参数 + int UPdateLDConfig(); + // 添加检测结果 + int AddQXResult(cv::Rect qx_roi_src, cv::Rect qx_roi_resize, int qx_type, float fJudgArea, float fenergy, float fgrayDis, cv::Mat YX_AI_InImg, cv::Mat YX_AI_OUTImg); + + // 参数缺陷类型转 结果参数类型 + int AIClassTypeToConfigType(int nAIQXType, cv::Rect qx_roi); + // 参数缺陷类型转 结果参数类型 + int ConfigTypeToResultType(int nconfigType); + int ConfigTypeToQXAnalysis(int nconfigType); + // 判断是否是点状缺陷 + bool IsPointQX(int config_qx_tpe); + // 解析 指令 + int GetInstruct(int nInstruct); + + int GetZfCropMask(cv::Rect roi); + + int ZF_Check(cv::Mat img, cv::Mat &inImg, cv::Mat &maskimg); + int YX_Check_L255(cv::Mat cropImg, cv::Mat &inImg, cv::Mat &outmaskimg); + + // 使用 DP mask 进行二次判断 + int UseDPMask(int L0, int nconfigtype, cv::Rect roi, float JudgeArea, int maxV, int hj); + // 检测有效区域mask图片 + int GetDetMaskImg(cv::Mat img, cv::Rect cutroi); + + // 亮的判断 + int LDJudge(int nconfigtype, cv::Rect roi, float JudgeArea, int maxV, int hj); + + // 获取缺陷 对应的AI输入 输出图片, + int GetAIDetImg(cv::Rect Qx_roi, cv::Mat &AI_InImg, cv::Mat &AI_OutImg); + int GetUpMaskImg(cv::Mat inImg, cv::Mat &maskimg); + // 更新成像精度 + int UpdateImgageScale(const cv::Mat &srcimg); + // 更新屏蔽区域 + int UpdateSheildMask(std::string strChannel, cv::Rect roi); + + // 缺陷是否要进行检测分析 缺陷是参数类型的缺陷 + bool JudgeQXAnalysis(int nqx_configType); + + // 缺陷是否要进行检测分析 缺陷是参数类型的缺陷 + bool Judge_MarkLine_QX(int nqx_configType,cv::Rect detqx_Roi); + + // AI 检测的缺陷类型,转换成 web 控制 是否要分析检测的缺陷类型 + std::string ConfigTypeToWebDetType(int nconfigType); + + // 增加到 绘制区域 + int addInDrawBlob(int errortype, int blobidx, ERROR_DOTS_BLOB_DATA *blob, float fs_resize_x, float fs_resize_y); + int addInDrawBlob_New(int errortype, int blobidx, QX_ERROR_INFO_ *QX_info, float fs_resize_x, float fs_resize_y); + // 初始化其他检测类 + int InitOtherDet(); + + // 其他类的检测 + int OtherDetect(); + // 缺失pol检测 + int Detect_LackPol(const cv::Mat &DetImage); + + // 精确计算缺陷能量(基于像素灰度差) + cv::Scalar calc_blob_info_withstats(cv::Mat &img, const cv::Mat &mask, cv::Rect &stats, cv::Size k_size = cv::Size(5, 5), int expand = 10, double threshold = 0.7); + +private: + int m_nErrorCode; // 错误代码 + bool m_bInitSucc; // 初始化状态 + bool m_bExit; // 是否退出检测 + int m_nThreadIdx; // 线程序号 //相机处理的顺序号,该序号 程序运行就已经固定 + + std::shared_ptr DetImgInfo_shareP; + std::shared_ptr ImageDet_shareP; + // 检测结果 + std::shared_ptr m_CheckResult_shareP; + std::shared_ptr m_ImageDetResult_shareP; + // 检测参数模块 + ConfigBase *m_pConfig; + // 线程运行的一些参数 + RunInfoST m_RunConfig; + // 检测结果 + // CheckResult m_CheckResult; + // 基本信息和深度学习模型文件参数 + CheckConfigST m_CheckConfig; + + float m_fImgage_Scale_X; + float m_fImgage_Scale_Y; + + // 分析参数 + AnalysisyConfigST m_AnalysisyConfig; + ChannelCheckFunction *m_pFuntion; + BaseCheckFunction *m_pbaseCheckFunction; // 基础检测 + CommonConfigNodeST *m_pCommonAnalysisyConfig; + BasicConfig *m_pBasicConfig; + RegionConfigST *m_pRegionAnalysisyParam; // 分析参数 + int m_QxInParamListIdx[CONFIG_QX_NAME_count]; + + cv::Mat m_AnalysisyMaskImg; // 分析的mask + cv::Rect m_CutRoi; + cv::Rect m_Crop_Roi_paramImg; // 裁切在参数模板图上的 位置。 + bool m_bShield_ZF; // 屏蔽字符检测 + + // // 检测控制参数 + // CheckControlConfigSt *m_pcheckControlConfig; + int m_nRun_Status; // 运行状态:空闲,运行中,异常,。。。。。 + + int m_nCheckResultErrorCode; + + AI_IMG_deal m_AIDeal; + + CHECK_TEM_RESULT m_TemCheck; + + Detect_ROI_Config m_DetRoiList; // 检测区域roi List + + ERROR_DOTS_BLOBS blobs; + ERROR_DOTS_BLOBS blobs_127; + + std::mutex mutex_AIDeal; // AI处理互斥锁 + std::condition_variable condVar_AI; // 条件变量 + int m_nWaite_AIDeal_SmallImg_Num; // 等待AI处理多线程状态 小图数目 + int m_nWaite_AIComplete_SmallImg_Num; // AI处理完成 等待 后处理的小图数目 + + // 小图资源 + // SMALLIMGINFO Multi_Thread_DetSmallImgList[MAX_THREAD_AIDET_NUM]; + SMALLIMGINFO Multi_Thread_DetSmallImgList[MAX_THREAD_AIDET_NUM]; + std::vector AI_DetImgList; + std::mutex mutex_SmallImgList; // 小图资源锁 + + OtherCheckResult m_OtherResult; + DrawImg m_DrawImg; + CHECK_INSTRUCT_ m_CheckInstruct; // 检测指令 + + std::vector m_ZF_centerPoint; // 字符的中心点位置 + cv::Rect m_Cut_roi; // 裁剪区域 + int m_curLogLevel; // 当前日志等级 + cv::Mat m_DetImgMask; // 检测有效区域mask图片 + cv::Mat m_ShieldImg_resize; + + QX_Analysis m_qx_Analysis; + + LD_ConfigT_ m_LDConfig; + LD_ConfigT_ m_LD_WTBConfig; + LD_ConfigT_ m_LD_HSConfig; + + AIClassify m_AIClassify; // 缺陷分类 + + DetResultST m_DetResult; // 检测结果 + + OtherDet_Config m_OtherDet_Config; + LackPolDet m_LackPolDet; // 缺Pol 检测; + AI_SecondDet m_SecondDet; // 二次分割检测 + + std::vector m_Draw_qxImageResult; // 缺陷小图结果 + + std::vector SmallRoiList; + int det_SmallImgNum; + + cv::Mat m_127CellAIMask; + bool m_bstatus_ReJson; + CheckResultJson m_CheckResultJson; +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/ImgCheckBase.h b/AlgorithmModule/include/ImgCheckBase.h new file mode 100644 index 0000000..771dfd8 --- /dev/null +++ b/AlgorithmModule/include/ImgCheckBase.h @@ -0,0 +1,94 @@ +#ifndef ImgCheckBase_H_ +#define ImgCheckBase_H_ +#include +#include +#define ALL_INTERFACE_VERSION 4 + +enum CHECK_THREAD_RUN_STATUS +{ + CHECK_THREAD_STATUS_IDLE, // 空闲 0 + CHECK_THREAD_STATUS_READY, // 准备好了 1 + CHECK_THREAD_STATUS_BUSY, // 运行中 2 + CHECK_THREAD_STATUS_COMPLETE, // 检测完成 3 + CHECK_THREAD_STATUS_ERROR, // 运行错误 4 +}; +struct RunInfoST +{ + int nThreadIdx; // 线程号id + int nDeviceId; // GPU 设备 号 0 或 1 + int nCpu_start_Idx; // 绑定cpu 核号, + int nCpu_num; // 8 至少需要 8个 + bool bSaveCheckImg; // 是否存储 + bool bRetest; // 是否是复测标志,复测不需要加载模型 + int flag1; + int flag2; + std::string str1; + std::string str2; + RunInfoST() + { + nThreadIdx = 0; + nDeviceId = 0; + nCpu_start_Idx = 0; + nCpu_num = 8; + flag1 = 0; + flag2 = 0; + bRetest = false; + str1 = ""; + str2 = ""; + bSaveCheckImg = false; + } + void copy(RunInfoST tem) + { + this->nDeviceId = tem.nDeviceId; + this->nThreadIdx = tem.nThreadIdx; + this->nCpu_start_Idx = tem.nCpu_start_Idx; + this->nCpu_num = tem.nCpu_num; + this->bSaveCheckImg = tem.bSaveCheckImg; + this->flag1 = tem.flag1; + this->flag2 = tem.flag2; + this->bRetest = tem.bRetest; + this->str1 = tem.str1; + this->str2 = tem.str2; + } +}; +/*******************一般调用流程*************************************************************************************************************************/ +/*******************1、初始化 UpdateConfig*************************************************************************************************************************/ +/*******************2、初始化 Init 并开启 *************************************************************************************************************************/ +/*******************3、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_IDLE 可以设置检测数据并开启检测 SetDataRun***************************************************/ +/*******************4、GetStatus 获取状态 如果 =CHECK_THREAD_STATUS_COMPLETE 检测完成,可以获取检测结果 GetCheckReuslt 拷贝检测结果 自动把状态设为 CHECK_THREAD_STATUS_IDLE*****************************/ +struct shareImage; +struct CheckResult; +class ALLImgCheckBase +{ +protected: + ALLImgCheckBase() {} + +public: + // delete camera interface + ~ALLImgCheckBase() {} + static ALLImgCheckBase *GetInstance(); + // 初始化参数 pconfig 参数指针 返回:0 成功 其他异常 + virtual int RunStart(void *pconfig1 = NULL) = 0; + + // 设置检测数据,并开启检测 返回:0 成功 其他异常 + virtual int SetDataRun_SharePtr(std::shared_ptr p) = 0; + + // 获取结果信息 返回:0 成功 其他异常 + virtual int GetCheckReuslt(std::shared_ptr &pResult) = 0; + + virtual int CheckImg(std::shared_ptr p, std::shared_ptr &pResult) = 0; + + // 获取检测库 状态信息 返回:CHECK_THREAD_RUN_STATUS + virtual int GetStatus() = 0; + + // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 + virtual int UpdateConfig(void *pconfig, int nConfigType) = 0; + + // 返回检测版本信息 + virtual std::string GetVersion() = 0; + // 返回错误信息 + virtual std::string GetErrorInfo() = 0; + + static ALLImgCheckBase *instance; +}; +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/ImgCheckConfig.h b/AlgorithmModule/include/ImgCheckConfig.h new file mode 100644 index 0000000..61c148c --- /dev/null +++ b/AlgorithmModule/include/ImgCheckConfig.h @@ -0,0 +1,652 @@ +/* + * @Descripttion: + * @version: + * @Author: sueRimn + * @Date: 2022-03-16 17:09:11 + * @LastEditors: xiewenji 527774126@qq.com + * @LastEditTime: 2025-07-26 11:21:59 + */ +/***********************************************/ +/************ ***************/ +/************金佰利检测算法参数定义**************/ +/************ **************/ +/**********************************************/ +#ifndef _ImgCheckConfig_HPP_ +#define _ImgCheckConfig_HPP_ +#include +#include +#define RESULT_VERSION 26 +#define MAX_BLOB_NUM 200 + +// 输入模型图片尺寸 +#define SRCIMG_WIDTH 14200 +#define SRCIMG_HEIGHT 10640 + +#define CHECKIMG_HEIGHT 2000 +#define CHECKIMG_WIDTH 4000 + +#define MASK_IMG_STEP 16 +#define MASK_IMG_STARTVALUE 48 + +// 检测日志 等级 +enum DET_LOG_LEVEL_ +{ + DET_LOG_LEVEL_0, // 极简信息 + DET_LOG_LEVEL_1, // 包含检测关键信息 + DET_LOG_LEVEL_2, // 关键信息+ 一般节点信息 + DET_LOG_LEVEL_3, // 详细信息 +}; +struct VERSION_INFO +{ + int ConfigVersion = 0; + int ResultVersion = RESULT_VERSION; + int InterfaceVersion = 0; +}; +// 检测错误代码 +enum ERROR_TYPE_ +{ + ERROR_TYPE_OK, // 0 疑是 + ERROR_TYPE_AD_YX, // 1 AD-异常显示 + ERROR_TYPE_Line_X, // 2 x line + ERROR_TYPE_Line_Y, // 3 y line + ERROR_TYPE_Line_fangge, // 3 y line + ERROR_TYPE_Rubbing_Mura, // 4 + ERROR_TYPE_line_Broken, // 5 断线 + ERROR_TYPE_ZARA, // 6 ZARA + ERROR_TYPE_MTX, // 7 MTX + ERROR_TYPE_POL_Cell, // 8 异物 + ERROR_TYPE_LD, // 9 亮点 + ERROR_TYPE_AD, // 10 暗点 + ERROR_TYPE_BD, // 11 黑点 + ERROR_TYPE_WD, // 12 白点 + ERROR_TYPE_Scratch, // 13 划伤 + ERROR_TYPE_Weak_Bright_Mura, // 14 白GAP + ERROR_TYPE_No_Label, // 15 缺POL + ERROR_TYPE_PS, // 16 PS + ERROR_TYPE_GRID_LINE, // 17 方格线 + ERROR_TYPE_STEAM_POCKET, // 19 气泡 + ERROR_TYPE_Dirty, // 19 脏污 + ERROR_TYPE_Other, // 19 other + ERROR_TYPE_Cell_W, // 19 other + ERROR_TYPE_Cell_B, // 19 other + ERROR_TYPE_LackPol, // 缺失Pol + ERROR_TYPE_CHESS, + ERROR_TYPE_COUNT, +}; +static const std::string QX_Result_Names[] = + { + "OK", + "AD_YX", + "X_Line", + "Y_Line", + "fangge", + "Rubbing_Mura", + "Broken_line", + "ZARA", + "MTX", + "POL_Cell", + "Bright_Point", + "Dark_Point", + "BLack_Point", + "White_Point", + "Scratch", + "Weak_Bright_Mura", + "No_Label", + "Bright_Mura_Exe", + "Sweak_Line_Dark", + "STEAM_POCKET", + "Dirty", + "other", + "Cell_W", + "Cell_B", + "LackPol", + "Chess"}; +static const std::string QX_Result_Code[] = + { + "P1153", + "P6873", + "P3351", + "P3452", + "P3453", + "P1550", + "P3379", + "P1153", + "P1164", + "P1101", + "P1112", + "P1111", + "P1104", + "P1103", + "P1557", + "P1654", + "P2833", + "P1549", + "P1204", + "P2534", + "P2534", + "P1101", + "P1103", + "P1104", + "P8001", + "P8002", +}; +// 检测检测参数类型 +enum CHECK_CONFIG_TYPE_ +{ + CHECK_CONFIG_Run, // 运行参数 + CHECK_CONFIG_Module, // 参数模块 + CHECK_CONFIG_Module_Cam2, // 参数模块 相机2参数 + CHECK_CONFIG_COUNT, +}; +// 输入检测图片的 +enum IMG_INPUT_ +{ + IMG_INPUT_SRC, + IMG_INPUT_COUNT, +}; +// 输入检测缺陷小图 +enum IMG_OUTPUT_ +{ + IMG_OUTPUT_RESIZE, + IMG_OUTPUT_COUNT, +}; +// 输入图片的状态 +enum IN_IMG_Status_ +{ + IN_IMG_Status_Start, + IN_IMG_Status_Other, + IN_IMG_Status_End, + IN_IMG_Status_OneImg, +}; +// 检测模式 +enum DET_MODE_ +{ + DET_MODE_NULL, + DET_MODE_EDGE, + DET_MODE_ZF, + DET_MODE_YX, + DET_MODE_UP, + DET_MODE_Det, + DET_MODE_MarkLine, + DET_MODE_ReJson, +}; + +#define MAX_REGION_NUM 20 + +// 一个检测项基本信息,包括图片序号,图片、开始时间 +struct shareImage +{ + int Det_Mode; // 检测模式 + int Status; + int camera_ID; // 相机ID + std::string camera_Name; // 相机名称 + int img_id; + cv::Mat img; + cv::Mat other_channel_Result_mask; // 其他通道的mask图片 + cv::Mat AI_maskImg; // 推理图片 + std::string strSnowID; // 相机发古来的雪花码 + long getImgTimeMs; // 获取图片的时间点 + long readImg_start; + long readImg_end; + long time_PushIn; + long time_sendCheck; + long time_startCheck; + long time_EndCheck; + int imgtype; + cv::Rect cutRoi; + int img_channel; // 图片通道号 + int ninstruct; // 运行指令 + int nlogLevel; // 日志等级 + + std::string imgstr; + std::string strImgName; + std::string strImgProductID; + std::string strImgType; + std::string strChannel; + int nImgBigIdx; + int otherValue; + int otherValue_1; + std::string resultJson; + bool bsaveProcessImg; // 保存处理图片 + + + shareImage() + { + Init(); + } + ~shareImage() + { + } + void Init() + { + if (!img.empty()) + { + img.release(); + } + if (!other_channel_Result_mask.empty()) + { + other_channel_Result_mask.release(); + } + if (!AI_maskImg.empty()) + { + AI_maskImg.release(); + } + Det_Mode = 0; + Status = 0; + nlogLevel = DET_LOG_LEVEL_0; + img_id = -1; + getImgTimeMs = 0; + time_PushIn = 0; + time_sendCheck = 0; + time_startCheck = 0; + time_EndCheck = 0; + readImg_start = 0; + readImg_end = 0; + imgtype = 0; + imgstr = ""; + strSnowID = ""; + camera_ID = 0; + strImgName = ""; + strImgProductID = ""; + strChannel = ""; + strImgType = ""; + nImgBigIdx = 0; + cutRoi = cv::Rect(0, 0, 0, 0); + otherValue = 0; + ninstruct = 0; + img_channel = 0; + resultJson = ""; + camera_Name = ""; + bsaveProcessImg = false; + } + void InitImg(int ImgW, int imgH, bool Isgray = true) + { + if (Isgray) + { + img = cv::Mat(imgH, ImgW, CV_8UC1); + } + else + { + img = cv::Mat(imgH, ImgW, CV_8UC3); + } + } +}; + +// AI分析结果 +struct JudgeInfo +{ + int result = 0; + int positive = 0; + int smudgy = 0; + int abnormal = 0; + int black = 0; + int dot = 0; + int other = 0; + std::string RESULT = "OK"; + std::string POSITIVE = "OK"; // 正样本 4 + std::string SMUDGY = "OK"; // 脏污 3 R通道 + std::string ABNORMAL = "OK"; // zhansi 毛发 2 B通道 + std::string BLACK = "OK"; // 黑接头 1 + std::string DOT = "OK"; // 黑点 1 + std::string OTHER = "OK"; // 其他 1 + void Init() + { + result = 0; + positive = 0; + smudgy = 0; + abnormal = 0; + black = 0; + dot = 0; + other = 0; + RESULT = "OK"; + POSITIVE = "OK"; + SMUDGY = "OK"; + ABNORMAL = "OK"; + BLACK = "OK"; + DOT = "OK"; + OTHER = "OK"; + } + void copy(JudgeInfo tem) + { + this->result = tem.result; + this->positive = tem.positive; + this->smudgy = tem.smudgy; + this->abnormal = tem.abnormal; + this->black = tem.black; + this->dot = tem.dot; + this->RESULT = tem.RESULT; + this->POSITIVE = tem.POSITIVE; + this->SMUDGY = tem.SMUDGY; + this->ABNORMAL = tem.ABNORMAL; + this->BLACK = tem.BLACK; + this->DOT = tem.DOT; + } +}; + +// 检测结果基本信息 +struct BasicResult +{ + int img_id; + long checkUseTimeMs; // 所有时间 + int64_t snowId; // 雪花ID + int imgtype; + std::string imgstr; + std::string strChannel; + void Init() + { + img_id = 0; + checkUseTimeMs = 0; + snowId = 0; + imgtype = 0; + imgstr = ""; + strChannel = ""; + } + void copy(BasicResult tem) + { + this->img_id = tem.img_id; + this->checkUseTimeMs = tem.checkUseTimeMs; + this->snowId = tem.snowId; + this->imgtype = tem.imgtype; + this->imgstr = tem.imgstr; + this->strChannel = tem.strChannel; + } +}; + +// 缺陷blob信息 +struct BLobST +{ + cv::Rect blob; + cv::Rect blob_ResizeImg; + cv::Rect blob_SrcImg; + int energy; + int area; + float JudgArea; + int UserErrorType; + BLobST() + { + Init(); + } + void Init() + { + blob = cv::Rect(0, 0, 0, 0); + blob_ResizeImg = cv::Rect(0, 0, 0, 0); + blob_SrcImg = cv::Rect(0, 0, 0, 0); + energy = 0; + area = 0; + JudgArea = 0; + UserErrorType = ERROR_TYPE_OK; + } + void copy(BLobST tem) + { + this->blob = tem.blob; + this->blob_ResizeImg = tem.blob_ResizeImg; + this->blob_SrcImg = tem.blob_SrcImg; + this->energy = tem.energy; + this->area = tem.area; + this->JudgArea = tem.JudgArea; + this->UserErrorType = tem.UserErrorType; + } +}; + +// 缺陷blob信息 +struct BLobListST +{ + BLobST bloblist[MAX_BLOB_NUM]; + int blobNum; + BLobListST() + { + Init(); + } + void Init() + { + blobNum = 0; + for (int i = 0; i < MAX_BLOB_NUM; i++) + { + bloblist[i].Init(); + } + } + void copy(BLobListST tem) + { + this->blobNum = tem.blobNum; + for (int i = 0; i < MAX_BLOB_NUM; i++) + { + this->bloblist[i].copy(tem.bloblist[i]); + } + } +}; +struct DetectInfo +{ + int nresult; + std::string keyName; + std::string keyCode; + int num; + DetectInfo() + { + Init(); + } + void Init() + { + nresult = 0; + num = 0; + keyName = ""; + keyCode = ""; + } + void copy(DetectInfo tem) + { + this->nresult = tem.nresult; + this->num = tem.num; + this->keyName = tem.keyName; + this->keyCode = tem.keyCode; + } +}; +#define MAX_SamllImg_xcount 13 +#define MAX_SamllImg_ycount 10 + +struct QXImageResult +{ + int type; // 缺陷类型 + std::string qx_Code; // 缺陷code + std::string strTypeName; // 缺陷名称 + + cv::Mat srcImg; // 缺陷原始图片 + cv::Mat resizeImg; // 缺陷缩略图 + cv::Mat AI_in_Img; + cv::Mat AI_out_img; + + cv::Rect srcImgroi; // 相对原图的 框坐标; + cv::Rect CutImgroi; // 裁剪原图 框坐标; + cv::Rect resizeImgroi; // 相对相对小图 框坐标; + + float x_pixel; // 缺陷坐标 像素 + float y_pixel; // 缺陷坐标 像素 + + float x_mm; // 缺陷坐标 mm + float y_mm; // 缺陷坐标 mm + int idx; + float area; + float energy; + float hj; + float max_v; + float len; + float fScore; + int qx_type; // 缺陷的原因 + float minDis_mm; + int qx_num; + float density; // 密度 + + QXImageResult() + { + Init(); + } + void Init() + { + if (!srcImg.empty()) + { + srcImg.release(); + } + if (!resizeImg.empty()) + { + resizeImg.release(); + } + if (!AI_in_Img.empty()) + { + AI_in_Img.release(); + /* code */ + } + if (!AI_out_img.empty()) + { + AI_out_img.release(); + /* code */ + } + + x_pixel = 0; + y_pixel = 0; + x_mm = 0; + y_mm = 0; + type = 0; + area = 0; + energy = 0; + hj = 0; + max_v = 0; + strTypeName = ""; + qx_Code = ""; + len = 0; + idx = 0; + fScore = 0; + qx_type = 0; + minDis_mm = 0; + qx_num = 0; + density = 0; + srcImgroi = cv::Rect(0, 0, 0, 0); + CutImgroi = cv::Rect(0, 0, 0, 0); + resizeImgroi = cv::Rect(0, 0, 0, 0); + } +}; +// 结果信息 +struct CheckResult +{ + // 原始图片,输入检测的图片 + int checkStatus; + int nDetStep; // 处理步骤 + int nresult; + int nProductResult; // 产品结果 + int nYS_result; + float productWidht_mm; // 产品宽度 毫米 + float productHeight_mm; // 产品 高度 毫米 + cv::Mat cutSrcimg; + cv::Mat resultimg; + cv::Mat SrcResultImg; // 结果 + cv::Mat resultMaskImg; // AI mask Result + std::shared_ptr in_shareImage; // 输入图片信息 + DetectInfo defectResultList[ERROR_TYPE_COUNT]; // 缺陷检测结果list + BasicResult basicResult; // 基本检测结果信息 + std::vector qxImageResult; // 缺陷小图结果 + std::vector YS_ImageResult; // 疑似小图结果 + std::vector det_LogList; // 检测日志 + std::string strResultJson; // 缺陷结果 jason + bool bSaveALL; + int nflage1; + int nflage2; + CheckResult() + { + Init(); + } + ~CheckResult() + { + release(); + } + void Init() + { + nProductResult = 0; + checkStatus = 0; + nDetStep = 0; + nresult = ERROR_TYPE_OK; + nYS_result = ERROR_TYPE_OK; + bSaveALL = false; + nflage1 = 0; + nflage2 = 0; + productWidht_mm = 0; + productHeight_mm = 0; + basicResult.Init(); + strResultJson = ""; + if (!resultimg.empty()) + { + resultimg.release(); + } + if (!cutSrcimg.empty()) + { + cutSrcimg.release(); + } + if (!SrcResultImg.empty()) + { + SrcResultImg.release(); + } + if (!resultMaskImg.empty()) + { + resultMaskImg.release(); + } + for (int i = 0; i < ERROR_TYPE_COUNT; i++) + { + defectResultList[i].Init(); + } + std::vector tmp; + qxImageResult.swap(tmp); + YS_ImageResult.swap(tmp); + qxImageResult.erase(qxImageResult.begin(), qxImageResult.end()); + YS_ImageResult.erase(YS_ImageResult.begin(), YS_ImageResult.end()); + det_LogList.erase(det_LogList.begin(), det_LogList.end()); + } + + void release() + { + if (!resultimg.empty()) + { + resultimg.release(); + } + if (!cutSrcimg.empty()) + { + cutSrcimg.release(); + } + if (!SrcResultImg.empty()) + { + SrcResultImg.release(); + } + if (!resultMaskImg.empty()) + { + resultMaskImg.release(); + } + strResultJson = ""; + std::vector tmp; + qxImageResult.swap(tmp); + YS_ImageResult.swap(tmp); + det_LogList.erase(det_LogList.begin(), det_LogList.end()); + } +}; + +// AI处理后的 结果信息,上传到队列中,做后续风险 +struct AI_REUSLTIMG +{ + + cv::Mat defectImg; // 缺陷检测结果图片 + AI_REUSLTIMG() + { + if (!defectImg.empty()) + { + defectImg.release(); + } + } + ~AI_REUSLTIMG() + { + release(); + } + void release() + { + + if (!defectImg.empty()) + { + defectImg.release(); + } + } +}; + +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/AlgorithmModule/include/OtherDetBaseDefine.h b/AlgorithmModule/include/OtherDetBaseDefine.h new file mode 100644 index 0000000..b309eba --- /dev/null +++ b/AlgorithmModule/include/OtherDetBaseDefine.h @@ -0,0 +1,39 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef OtherDetBaseDefine_H_ +#define OtherDetBaseDefine_H_ +#include +#include +#include "CheckErrorCodeDefine.hpp" +#include "AIImgDeal.h" +#include "BlobBase.h" + +using namespace std; + +struct OtherDet_Config +{ + int nDeviceId; // GPU 号 + int nUserValue; + int nShowImg_Width; + int nShowImg_Height; + AI_IMG_deal *pAIDeal; + CHECK_TEM_RESULT *pTemCheck; + + OtherDet_Config() + { + pAIDeal = NULL; + pTemCheck = NULL; + nDeviceId = 0; + nUserValue = 0; + nShowImg_Width = 100; + nShowImg_Height = 100; + } +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/OtherDetect.h b/AlgorithmModule/include/OtherDetect.h new file mode 100644 index 0000000..7190a33 --- /dev/null +++ b/AlgorithmModule/include/OtherDetect.h @@ -0,0 +1,74 @@ +/* +//其他类的检测 + */ +#ifndef OtherDetect_H_ +#define OtherDetect_H_ +#include +#include "CheckUtil.hpp" +#include "OtherDetBaseDefine.h" +#include "CheckErrorCodeDefine.hpp" + +using namespace std; +using namespace cv; +// 基础类 +class AIDetectBase +{ + +public: + AIDetectBase(/* args */); + ~AIDetectBase(); + int Init(OtherDet_Config *pOtherDet_Config); + +protected: + OtherDet_Config *m_pOtherDet_Config; + AI_IMG_deal *m_pAIDeal; + CHECK_TEM_RESULT *m_pTemCheck; + bool m_bInitialized; + bool m_bModelSucc; +}; + +// 缺pol 检测 +class LackPolDet : public AIDetectBase +{ + +public: + /// @brief 检测过程的参数 + struct DetConfig + { + float fImgage_Scale_X; + float fImgage_Scale_Y; + bool bSaveResultImg; // 保存结果图片 + std::string strChannel; // 通道名称 + cv::Mat detMaskImg; // 检测区域图片 + DetConfig() + { + Init(); + } + void Init() + { + fImgage_Scale_X = 0.03f; + fImgage_Scale_Y = 0.03f; + bSaveResultImg = false; + strChannel = ""; + } + void Print() + { + printf("bSaveResultImg %s strChannel %s\n", + BOOL_TO_STR(bSaveResultImg), strChannel.c_str()); + } + }; + +public: + LackPolDet(/* args */); + ~LackPolDet(); + int InitModel_ALL(); + int Detect(const cv::Mat &img, DetConfig *pDetConfig, cv::Mat &outMask); + +private: + int Init_LackPol(); + +public: +private: +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/QX_Analysis.h b/AlgorithmModule/include/QX_Analysis.h new file mode 100644 index 0000000..910553d --- /dev/null +++ b/AlgorithmModule/include/QX_Analysis.h @@ -0,0 +1,214 @@ +/* +//实现对部分缺陷 需要进行 数量 和距离上分析的 + */ +#ifndef QX_Analysis_H_ +#define QX_Analysis_H_ +#include +#include "CheckUtil.hpp" +#include "CheckErrorCodeDefine.hpp" +using namespace std; + +enum QX_ANALYSIS_NAME +{ + QX_ANALYSIS_POL_CELL, // 异物 + QX_ANALYSIS_AD, // 暗点 + QX_ANALYSIS_Scratch, // 划伤 + QX_ANALYSIS_LINE, // 线类 + QX_ANALYSIS_MTX, // MTX + QX_ANALYSIS_ALL, // MTX&异物 + QX_ANALYSIS_COUNT, +}; +// 缺陷项对应在参数中的名称 +static const std::string QX_ANALYSIS_NAME_Names[] = + { + "POL_Cell", + "AD", + "Scratch", + "LINE", + "MTX", + "POL_Cell&MTX"}; +// 记录缺陷信息 +struct QX_Info +{ + float area; // 面积 + float energy; // 能量 + float hj; // 灰阶 + float length; // 长度 + float density; // 密度 + cv::Point plocatin_mm; // 位置,mm + cv::Point plocatin_pixel; // 位置 像素 + int blobIdx; // blob idx; + int result; + float fmindis; + int nmindis_BlobIdx; + cv::Point mindis_locatin_pixel; // 位置 像素 + int nstatus; + int nqx_type; + QX_Info() + { + Init(); + } + void Init() + { + area = 0; + energy = 0; + hj = 0; + length = 0; + plocatin_mm = cv::Point(0, 0); + plocatin_pixel = cv::Point(0, 0); + blobIdx = 0; + result = 0; + fmindis = 0; + mindis_locatin_pixel = cv::Point(0, 0); + nstatus = 0; + nqx_type = 0; + nmindis_BlobIdx = 0; + density = 0; + } + void print(std::string str) + { + printf("%s blobIdx %d,result %d area %f energy %f hj %f length %f md %f x %d y %d x %d y %d \n", + str.c_str(), blobIdx, result, area, energy, hj, length, density, plocatin_mm.x, plocatin_mm.y, plocatin_pixel.x, plocatin_pixel.y); + printf("%s blobIdx %d,fmindis %f mindis_locatin_pixel x %d y %d \n", + str.c_str(), blobIdx, fmindis, mindis_locatin_pixel.x, mindis_locatin_pixel.y); + } +}; +struct QX_ALL_List +{ + std::vector qxList; + QX_ALL_List() + { + Init(); + } + void Init() + { + qxList.erase(qxList.begin(), qxList.end()); + qxList.clear(); + // config.Init(); + } +}; + +struct QXAnalysis_Config +{ + bool bok; + int num; + float dis; + float len; + int hj; + float density; + float area; + float sum_area; + QXAnalysis_Config() + { + Init(); + } + void Init() + { + bok = false; + num = 0; + dis = 0; + len = 0; + area = 0; + hj = 0; + sum_area = 0; + density = 0; + } + void print(std::string str) + { + printf("%s bok %d num %d area %f dis %f len %f hj %d md %f\n", str.c_str(), bok, num, area, dis, len, hj,density); + } +}; + +struct QX_Config_List +{ + std::vector configlsit; + QX_Config_List() + { + Init(); + } + void Init() + { + configlsit.erase(configlsit.begin(), configlsit.end()); + configlsit.clear(); + // config.Init(); + } +}; +enum QX_ERROR_TYPE_ +{ + QX_ERROR_TYPE_OK, + QX_ERROR_TYPE_AREA, + QX_ERROR_TYPE_NUM, + QX_ERROR_TYPE_DIS, + QX_ERROR_TYPE_Len, + QX_ERROR_TYPE_NUM_RGB255, +}; +struct QX_RESULT +{ + int blobIdx; // blob idx; + int error_Type; // 错误原因 + int qx_Num; // 缺陷的数量 + float mindis; + float flen; + cv::Point qx_MisDis_point_pixel; // 缺陷 间的最小距离 + QX_RESULT() + { + Init(); + } + void Init() + { + blobIdx = -1; + error_Type = 0; + qx_Num = 0; + flen = 0; + mindis = 0; + qx_MisDis_point_pixel = cv::Point(0, 0); + } + void print(std::string str) + { + printf("%s blobIdx %d error_Type %d qx_Num %d min dis %f flen %f x %d y %d \n", + str.c_str(), blobIdx, error_Type, qx_Num, mindis, flen, qx_MisDis_point_pixel.x, qx_MisDis_point_pixel.y); + } +}; +struct QX_Analysis_Result_List +{ + std::vector resultList; + QX_Analysis_Result_List() + { + Init(); + } + void Init() + { + resultList.erase(resultList.begin(), resultList.end()); + resultList.clear(); + // config.Init(); + } +}; +class QX_Analysis +{ +private: + QX_ALL_List m_QXList[QX_ANALYSIS_COUNT]; + QX_Config_List m_ConfigList[QX_ANALYSIS_COUNT]; + + QX_Analysis_Result_List m_reultList; + +public: + CHECK_TEM_RESULT *m_pTemCheck; + +public: + QX_Analysis(); + ~QX_Analysis(); + void SetConfig(int qxidx, QXAnalysis_Config config); + void InitConfig(); + bool AddQxInfo(int qxidx, QX_Info qxinfo); + int Init(); + int GetReusult(QX_Analysis_Result_List *&presult); + +private: + bool Idx(int qxidx); + int Analysis(QX_Config_List *pconfigList, QX_ALL_List *pqxList,int qx_type); + int Analysis_s(QXAnalysis_Config *pconfig, QX_ALL_List *pqxList,int qx_type); + int Analysis_AD_Num(QXAnalysis_Config *pconfig, QX_ALL_List *pqxList,int qx_type); + int Analysis_POL_Num(QXAnalysis_Config *pconfig, QX_ALL_List *pqxList,int qx_type); +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/SingleGPU.h b/AlgorithmModule/include/SingleGPU.h new file mode 100644 index 0000000..075cbb6 --- /dev/null +++ b/AlgorithmModule/include/SingleGPU.h @@ -0,0 +1,76 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef SingleGPU_H_ +#define SingleGPU_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "AICheck.h" +using namespace std; +#define MAX_GPU_NUMBER 4 +class AI_SingleGPU +{ +public: + AI_SingleGPU(int nGpuIdx); + ~AI_SingleGPU(); + static AI_SingleGPU *GetInstance(int nGpuIdx); + static AI_SingleGPU *m_pInstance[MAX_GPU_NUMBER]; + +private: + // 定义一个内部类 + class CGarbo + { + public: + CGarbo() {}; + ~CGarbo() + { + for (int i = 0; i < MAX_GPU_NUMBER; i++) + { + if (nullptr != m_pInstance[i]) + { + delete m_pInstance[i]; + m_pInstance[i] = nullptr; + } + } + } + }; + // 定义一个内部类的静态对象 + // 当该对象销毁时,顺带就释放myInstance指向的堆区资源 + static CGarbo m_garbo; + +private: + int m_nGpuIdx; + +public: + AI_defect AI_defect_NF; // BOE测试 + AI_defect AI_defect_Type2; // 第二个检测模型 + AI_defect AI_defect_Cls; // 1023 + AI_defect AI_defect_Cls_L0; // + AI_defect AI_defect_YX_1; // L0 + AI_defect AI_defect_YX_2; // L127 L255 + AI_defect AI_defect_zf; // L127 L255 + AI_defect AI_defect_UP; // L127 L255 + AI_defect AI_defect_Chess; // L127 L255 + AI_defect AI_defect_127Cell; // L127 L255 + AI_defect AI_defect_RE_POL; // L127 L255 + AI_defect AI_defect_RE_AD; // L127 L255 + + AI_defect AI_defect_Edge_Big; // L127 L255 + AI_defect AI_defect_Edge_Samll; // L127 L255 + + AI_defect AI_defect_LackPol; // 缺pol检测 + AI_defect AI_defect_MarkLine; // MarkLine +}; + +#endif \ No newline at end of file diff --git a/AlgorithmModule/include/snowflake.hpp b/AlgorithmModule/include/snowflake.hpp new file mode 100644 index 0000000..9ea6a04 --- /dev/null +++ b/AlgorithmModule/include/snowflake.hpp @@ -0,0 +1,106 @@ +#pragma once +#include +#include +#include +#include + +class snowflake_nonlock +{ +public: + void lock() + { + } + void unlock() + { + } +}; + +template +class snowflake +{ + using lock_type = Lock; + static constexpr int64_t TWEPOCH = Twepoch; + static constexpr int64_t WORKER_ID_BITS = 5L; + static constexpr int64_t DATACENTER_ID_BITS = 5L; + static constexpr int64_t MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1; + static constexpr int64_t MAX_DATACENTER_ID = (1 << DATACENTER_ID_BITS) - 1; + static constexpr int64_t SEQUENCE_BITS = 12L; + static constexpr int64_t WORKER_ID_SHIFT = SEQUENCE_BITS; + static constexpr int64_t DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; + static constexpr int64_t TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS; + static constexpr int64_t SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1; + + using time_point = std::chrono::time_point; + + time_point start_time_point_ = std::chrono::steady_clock::now(); + int64_t start_millsecond_ = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + int64_t last_timestamp_ = -1; + int64_t workerid_ = 0; + int64_t datacenterid_ = 0; + int64_t sequence_ = 0; + lock_type lock_; +public: + snowflake() = default; + + snowflake(const snowflake&) = delete; + + snowflake& operator=(const snowflake&) = delete; + + void init(int64_t workerid, int64_t datacenterid) + { + if (workerid > MAX_WORKER_ID || workerid < 0) { + throw std::runtime_error("worker Id can't be greater than 31 or less than 0"); + } + + if (datacenterid > MAX_DATACENTER_ID || datacenterid < 0) { + throw std::runtime_error("datacenter Id can't be greater than 31 or less than 0"); + } + + workerid_ = workerid; + datacenterid_ = datacenterid; + } + + int64_t nextid() + { + std::lock_guard lock(lock_); + //std::chrono::steady_clock cannot decrease as physical time moves forward + auto timestamp = millsecond(); + if (last_timestamp_ == timestamp) + { + sequence_ = (sequence_ + 1)&SEQUENCE_MASK; + if (sequence_ == 0) + { + timestamp = wait_next_millis(last_timestamp_); + } + } + else + { + sequence_ = 0; + } + + last_timestamp_ = timestamp; + + return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) + | (datacenterid_ << DATACENTER_ID_SHIFT) + | (workerid_ << WORKER_ID_SHIFT) + | sequence_; + } + +private: + int64_t millsecond() const noexcept + { + auto diff = std::chrono::duration_cast(std::chrono::steady_clock::now() - start_time_point_); + return start_millsecond_ + diff.count(); + } + + int64_t wait_next_millis(int64_t last) const noexcept + { + auto timestamp = millsecond(); + while (timestamp <= last) + { + timestamp = millsecond(); + } + return timestamp; + } +}; diff --git a/AlgorithmModule/src/AICheck.cpp b/AlgorithmModule/src/AICheck.cpp new file mode 100644 index 0000000..f73cc21 --- /dev/null +++ b/AlgorithmModule/src/AICheck.cpp @@ -0,0 +1,515 @@ +/* + * FileName:CoreLogicFactory.cpp + * Version:V1.0 + * Description: + * Created On:Mon Sep 10 11:13:16 UTC 2018 + * Modified date: + * Author:Sky + */ +#include "AICheck.h" +#include "CUDA_Det.cuh" + +#ifdef USE_TERNSORRT10_BIGMODEL +#include // 添加头文件 +#include +#include +#include +#include +#include "CheckUtil.hpp" +#define CHECK(status) \ + do \ + { \ + auto ret = (status); \ + if (ret != 0) \ + { \ + std::cerr << "Cuda failure: " << ret << std::endl; \ + abort(); \ + } \ + } while (0) + +class Logger : public ILogger +{ + void log(Severity severity, const char *msg) noexcept override + { + // suppress info-level messages + if (severity <= Severity::kWARNING) + std::cout << msg << std::endl; + } +} logger; + +static Logger gLogger; +#else + +#endif +int g_falage = 0; +AI_defect::AI_defect() +{ + m_bInitialized = false; +} + +AI_defect::~AI_defect() +{ + destroy(); +} +void AI_defect::destroy() +{ + for (int i = 0; i < MAX_AI_BUFFER_SIZE; i++) + { + if (m_config.bufferList[i].ntype == AIBufferType_NULL) + { + break; + } + cudaFree(buffers[i]); + cudaFree(ImgData[i]); + if (floatData) + { + free(floatData); + } + } + +// Destroy the engine +#ifdef USE_TERNSORRT10_BIGMODEL +#else + context->destroy(); + engine->destroy(); + runtime->destroy(); +#endif +} +#ifdef USE_TERNSORRT10_BIGMODEL + +int AI_defect::model_init(AIInitConfig config) +{ + + if (m_bInitialized) + { + printf("AI_defect::model_init succ \n"); + return 0; + } + if (config.bufferList[0].strName == "") + { + // getchar(); + /* code */ + } + + m_bInitialized = false; + printf("-- AI Init nGpuIdx %d model file %s \n", config.nGpuIdx, config.engine_file_path.c_str()); + if (config.nGpuIdx < 0) + { + return 1; + } + + if (!config.Checking()) + { + printf("Checking error \n"); + return 1; + } + m_config.copy(config); + m_config.CalSize(sizeof(float)); + + cudaSetDevice(m_config.nGpuIdx); + char *trtModelStream{nullptr}; + size_t size{0}; + + std::ifstream file(m_config.engine_file_path, std::ios::binary); + if (!file) + { + std::cerr << "Error opening engine file!" << std::endl; + return 1; + } + if (file.good()) + { + std::cout << "load engine success" << std::endl; + file.seekg(0, file.end); + size = file.tellg(); + file.seekg(0, file.beg); + + trtModelStream = new char[size]; + assert(trtModelStream); + + file.read(trtModelStream, size); + file.close(); + } + else + { + printf("------------Model file open error--********* \n"); + return 1; + } + printf("model_init 1 \n"); + runtime = createInferRuntime(gLogger); + if (!runtime) + { + std::cerr << "Failed to create runtime!" << std::endl; + return 1; + } + printf("model_init 2 \n"); + engine = runtime->deserializeCudaEngine(trtModelStream, size); + if (!engine) + { + std::cerr << "Failed to create engine!" << std::endl; + return 1; + } + printf("model_init 3 \n"); + // // Create execution context + context = engine->createExecutionContext(); + if (!context) + { + std::cerr << "Failed to create execution context!" << std::endl; + return 1; + } + delete[] trtModelStream; + printf("model_init 4 \n"); + // 初始化buffer + for (int i = 0; i < MAX_AI_BUFFER_SIZE; i++) + { + if (m_config.bufferList[i].ntype == AIBufferType_NULL) + { + break; + } + floatData[i] = (float *)malloc(m_config.bufferList[i].ndatalength * sizeof(float)); + cudaMalloc(&buffers[i], m_config.bufferList[i].ndataSize); + { + int nsize = m_config.bufferList[i].ndatalength * sizeof(unsigned char); + cudaMalloc(&ImgData[i], nsize); + } + } + m_bInitialized = true; + return 0; +} +int AI_defect::model_Cuda_AI_In_1_Out_1(unsigned char *p_indata_0, unsigned char *p_outdata_1) +{ + + std::lock_guard lock(g_mutex); + cudaSetDevice(m_config.nGpuIdx); + cudaStream_t stream; + CHECK(cudaStreamCreate(&stream)); + + // printf(">>>>>>>>>>>>>>>>>CUDA test m_config.nGpuIdx %d \n", m_config.nGpuIdx); + + const ICudaEngine &engine_123 = context->getEngine(); + // printf("name %s \n", m_config.bufferList[0].strName.c_str()); + // auto s = engine_123.getTensorShape(m_config.bufferList[0].strName.c_str()); + // std::cout << "tensor dims: ["; + // for (int i = 0; i < s.nbDims; i++) + // { + // std::cout << s.d[i]; + // if (i < s.nbDims - 1) + // std::cout << ", "; + // } + // std::cout << "]" << std::endl; + + // { + // printf("name %s \n", m_config.bufferList[1].strName.c_str()); + // auto s = engine_123.getTensorShape(m_config.bufferList[1].strName.c_str()); + // std::cout << "tensor dims: ["; + // for (int i = 0; i < s.nbDims; i++) + // { + // std::cout << s.d[i]; + // if (i < s.nbDims - 1) + // std::cout << ", "; + // } + // std::cout << "]" << std::endl; + // } + long t1, t2, t3, t4, t5, t6, t7; + // t1 = CheckUtil::getcurTime(); + + for (int i = 0; i < m_config.bufferList[0].ndatalength; i++) + { + floatData[0][i] = p_indata_0[i]; + } + cudaMemcpyAsync(buffers[0], floatData[0], m_config.bufferList[0].ndataSize, cudaMemcpyHostToDevice, stream); + // wrap_test_print(); + + // 拷贝数据到显卡 + // if (kk == 0) + // { + // cudaMemcpyAsync(ImgData[0], p_indata_0, m_config.bufferList[0].nuchardataSize, cudaMemcpyHostToDevice, stream); + // printf("set img************************** m_config.bufferList[0].nuchardataSize %d\n", m_config.bufferList[0].nuchardataSize); + // kk++; + // } + + // t2 = CheckUtil::getcurTime(); + // // 在显存中 图片数据从 uchar 转到 float + // Cuda_ucharToFloat((unsigned char *)ImgData[0], (float *)buffers[0], m_config.bufferList[0].ndatalength); + // t3 = CheckUtil::getcurTime(); + // float *temsssssdata = new float[1024 * 1024]; + // cudaMemcpyAsync(temsssssdata, buffers[0], m_config.bufferList[0].ndataSize, cudaMemcpyDeviceToHost, stream); + // for (int i = 0; i < 1024*1024; i = i + 800) + // { + + // printf("%d %d %f %d ", i,m_config.bufferList[0].ndatalength, temsssssdata[i],p_indata_0[i]); + // } + // delete [] temsssssdata; + + std::string s1 = engine_123.getIOTensorName(0); + std::string s2 = engine_123.getIOTensorName(1); + context->setTensorAddress(s1.c_str(), buffers[0]); + context->setTensorAddress(s2.c_str(), buffers[1]); + + context->enqueueV3(stream); + // t4 = CheckUtil::getcurTime(); + + // Cuda_FloatTouchar((float *)buffers[1], (unsigned char *)ImgData[1], m_config.bufferList[1].ndatalength); + // cudaMemcpyAsync(p_outdata_1, ImgData[1], m_config.bufferList[1].nuchardataSize, cudaMemcpyDeviceToHost, stream); + + // float *temdata = new float[m_config.bufferList[1].nuchardataSize]; + cudaMemcpyAsync(floatData[1], buffers[1], m_config.bufferList[1].ndataSize, cudaMemcpyDeviceToHost, stream); + // printf("11m_config.bufferList[0].nuchardataSize %d\n", m_config.bufferList[1].nuchardataSize); + + for (int i = 0; i < m_config.bufferList[1].nuchardataSize; i++) + { + p_outdata_1[i] = floatData[1][i]; + } + // for (int i = 512 * 512 - 1000; i < 512 * 512; i++) + // { + // if (p_outdata_1[i] != 0) + // { + // printf("%d %d %f %d ", i, m_config.bufferList[1].nuchardataSize, temdata[i], p_outdata_1[i]); + // } + // } + + // delete temsssssdata; + // delete temdata; + + // t5 = CheckUtil::getcurTime(); + cudaStreamSynchronize(stream); + cudaStreamDestroy(stream); + // t6 = CheckUtil::getcurTime(); + + // printf("t2 -t1 %ld t3 -t2 %ld t4 -t3 %ld t5 -t4 %ld t6 -t5 %ld t6 -t1 %ld \n", t2 - t1, t3 - t2, t4 - t3, t5 - t4, t6 - t5, t6 - t1); + + // getchar(); + return 0; +} + +int AI_defect::model_Cuda_AI_In_1_Out_1_float(unsigned char *p_indata_0, float *p_outdata_1) +{ + std::lock_guard lock(g_mutex); + cudaSetDevice(m_config.nGpuIdx); + cudaStream_t stream; + CHECK(cudaStreamCreate(&stream)); + + // printf(">>>>>>>>>>>>>>>>>CUDA test \n"); + + const ICudaEngine &engine_123 = context->getEngine(); + + // auto s = engine_123.getTensorShape(m_config.bufferList[0].strName.c_str()); + // std::cout << "tensor dims: ["; + // for (int i = 0; i < s.nbDims; i++) + // { + // std::cout << s.d[i]; + // if (i < s.nbDims - 1) + // std::cout << ", "; + // } + // std::cout << "]" << std::endl; + + // { + // printf("name %s \n", m_config.bufferList[1].strName.c_str()); + // auto s = engine_123.getTensorShape(m_config.bufferList[1].strName.c_str()); + // std::cout << "tensor dims: ["; + // for (int i = 0; i < s.nbDims; i++) + // { + // std::cout << s.d[i]; + // if (i < s.nbDims - 1) + // std::cout << ", "; + // } + // std::cout << "]" << std::endl; + // } + + // wrap_test_print(); + long t1, t2, t3, t4, t5, t6, t7; + // t1 = CheckUtil::getcurTime(); + + for (int i = 0; i < m_config.bufferList[0].ndatalength; i++) + { + floatData[0][i] = p_indata_0[i]; + } + cudaMemcpyAsync(buffers[0], floatData[0], m_config.bufferList[0].ndataSize, cudaMemcpyHostToDevice, stream); + // 拷贝数据到显卡 + // cudaMemcpyAsync(ImgData[0], p_indata_0, m_config.bufferList[0].nuchardataSize, cudaMemcpyHostToDevice, stream); + // t2 = CheckUtil::getcurTime(); + // 在显存中 图片数据从 uchar 转到 float + // Cuda_ucharToFloat((unsigned char *)ImgData[0], (float *)buffers[0], m_config.bufferList[0].ndatalength); + // t3 = CheckUtil::getcurTime(); + + std::string s1 = engine_123.getIOTensorName(0); + std::string s2 = engine_123.getIOTensorName(1); + context->setTensorAddress(s1.c_str(), buffers[0]); + context->setTensorAddress(s2.c_str(), buffers[1]); + + context->enqueueV3(stream); + // t4 = CheckUtil::getcurTime(); + + cudaMemcpyAsync(p_outdata_1, buffers[1], m_config.bufferList[1].ndataSize, cudaMemcpyDeviceToHost, stream); + + // t5 = CheckUtil::getcurTime(); + cudaStreamSynchronize(stream); + cudaStreamDestroy(stream); + // t6 = CheckUtil::getcurTime(); + + // printf("t2 -t1 %ld t3 -t2 %ld t4 -t3 %ld t5 -t4 %ld t6 -t5 %ld t6 -t1 %ld \n", t2 - t1, t3 - t2, t4 - t3, t5 - t4, t6 - t5, t6 - t1); + + return 0; +} +#else + +int AI_defect::model_init(AIInitConfig config) +{ + if (m_bInitialized) + { + printf("AI_defect::model_init succ \n"); + return 0; + } + + m_bInitialized = false; + printf("-- AI Init nGpuIdx %d model file %s \n", config.nGpuIdx, config.engine_file_path.c_str()); + if (config.nGpuIdx < 0) + { + return 1; + } + + if (!config.Checking()) + { + return 1; + } + m_config.copy(config); + m_config.CalSize(sizeof(float)); + + cudaSetDevice(m_config.nGpuIdx); + char *trtModelStream{nullptr}; + size_t size{0}; + + std::ifstream file(m_config.engine_file_path, std::ios::binary); + if (file.good()) + { + file.seekg(0, file.end); + size = file.tellg(); + file.seekg(0, file.beg); + trtModelStream = new char[size]; + assert(trtModelStream); + file.read(trtModelStream, size); + file.close(); + } + else + { + printf("------------Model file open error--********* \n"); + return 1; + } + sample::Logger m_logger; + runtime = createInferRuntime(m_logger); + assert(runtime != nullptr); + + engine = runtime->deserializeCudaEngine(trtModelStream, size, nullptr); + assert(engine != nullptr); + + context = engine->createExecutionContext(); + assert(context != nullptr); + delete[] trtModelStream; + + for (int i = 0; i < MAX_AI_BUFFER_SIZE; i++) + { + if (m_config.bufferList[i].ntype == AIBufferType_NULL) + { + break; + } + floatData[i] = (float *)malloc(m_config.bufferList[i].ndatalength * sizeof(float)); + cudaMalloc(&buffers[i], m_config.bufferList[i].ndataSize); + { + int nsize = m_config.bufferList[i].ndatalength * sizeof(unsigned char); + cudaMalloc(&ImgData[i], nsize); + /* code */ + } + } + m_bInitialized = true; + return 0; +} + +int AI_defect::model_Cuda_AI_In_1_Out_1(unsigned char *p_indata_0, unsigned char *p_outdata_1) +{ + std::lock_guard lock(g_mutex); + cudaSetDevice(m_config.nGpuIdx); + cudaStream_t stream; + cudaStreamCreate(&stream); + + for (int i = 0; i < m_config.bufferList[0].ndatalength; i++) + { + floatData[0][i] = p_indata_0[i]; + } + cudaMemcpyAsync(buffers[0], floatData[0], m_config.bufferList[0].ndataSize, cudaMemcpyHostToDevice, stream); + + // // 拷贝数据到显卡 + // cudaMemcpyAsync(ImgData[0], p_indata_0, m_config.bufferList[0].nuchardataSize, cudaMemcpyHostToDevice, stream); + // // t2 = CheckUtil::getcurTime(); + // // 在显存中 图片数据从 uchar 转到 float + // Cuda_ucharToFloat((unsigned char *)ImgData[0], (float *)buffers[0], m_config.bufferList[0].ndatalength); + // t3 = CheckUtil::getcurTime(); + + context->enqueueV2(buffers, stream, nullptr); + // t4 = CheckUtil::getcurTime(); + + cudaMemcpyAsync(floatData[1], buffers[1], m_config.bufferList[1].ndataSize, cudaMemcpyDeviceToHost, stream); + // printf("11m_config.bufferList[0].nuchardataSize %d\n", m_config.bufferList[1].nuchardataSize); + + for (int i = 0; i < m_config.bufferList[1].nuchardataSize; i++) + { + p_outdata_1[i] = floatData[1][i]; + } + + // Cuda_FloatTouchar((float *)buffers[1], (unsigned char *)ImgData[1], m_config.bufferList[1].ndatalength); + // cudaMemcpyAsync(p_outdata_1, ImgData[1], m_config.bufferList[1].nuchardataSize, cudaMemcpyDeviceToHost, stream); + + // t5 = CheckUtil::getcurTime(); + cudaStreamSynchronize(stream); + cudaStreamDestroy(stream); + // t6 = CheckUtil::getcurTime(); + + // printf("t2 -t1 %ld t3 -t2 %ld t4 -t3 %ld t5 -t4 %ld t6 -t5 %ld t6 -t1 %ld \n", t2 - t1, t3 - t2, t4 - t3, t5 - t4, t6 - t5, t6 - t1); + + // getchar(); + return 0; +} + +int AI_defect::model_Cuda_AI_In_1_Out_1_float(unsigned char *p_indata_0, float *p_outdata_1) +{ + std::lock_guard lock(g_mutex); + cudaSetDevice(m_config.nGpuIdx); + cudaStream_t stream; + cudaStreamCreate(&stream); + + for (int i = 0; i < m_config.bufferList[0].ndatalength; i++) + { + floatData[0][i] = p_indata_0[i]; + } + cudaMemcpyAsync(buffers[0], floatData[0], m_config.bufferList[0].ndataSize, cudaMemcpyHostToDevice, stream); + + // // 拷贝数据到显卡 + // cudaMemcpyAsync(ImgData[0], p_indata_0, m_config.bufferList[0].nuchardataSize, cudaMemcpyHostToDevice, stream); + // // t2 = CheckUtil::getcurTime(); + // // 在显存中 图片数据从 uchar 转到 float + // Cuda_ucharToFloat((unsigned char *)ImgData[0], (float *)buffers[0], m_config.bufferList[0].ndatalength); + // t3 = CheckUtil::getcurTime(); + + context->enqueueV2(buffers, stream, nullptr); + + cudaMemcpyAsync(floatData[1], buffers[1], m_config.bufferList[1].ndataSize, cudaMemcpyDeviceToHost, stream); + // printf("11m_config.bufferList[0].nuchardataSize %d\n", m_config.bufferList[1].nuchardataSize); + + for (int i = 0; i < m_config.bufferList[1].nuchardataSize; i++) + { + p_outdata_1[i] = floatData[1][i]; + } + + // t4 = CheckUtil::getcurTime(); + // cudaMemcpyAsync(p_outdata_1, buffers[1], m_config.bufferList[1].ndataSize, cudaMemcpyDeviceToHost, stream); + + // t5 = CheckUtil::getcurTime(); + cudaStreamSynchronize(stream); + cudaStreamDestroy(stream); + // t6 = CheckUtil::getcurTime(); + + // printf("t2 -t1 %ld t3 -t2 %ld t4 -t3 %ld t5 -t4 %ld t6 -t5 %ld t6 -t1 %ld \n", t2 - t1, t3 - t2, t4 - t3, t5 - t4, t6 - t5, t6 - t1); + + // getchar(); + return 0; +} + +#endif \ No newline at end of file diff --git a/AlgorithmModule/src/AIClassify.cpp b/AlgorithmModule/src/AIClassify.cpp new file mode 100644 index 0000000..ee53eb5 --- /dev/null +++ b/AlgorithmModule/src/AIClassify.cpp @@ -0,0 +1,359 @@ + +#include "AIClassify.h" +#include "AICommonDefine.h" +bool compare_Piece(const AI_PIECE_INFO &a, const AI_PIECE_INFO &b) +{ + return a.abs_L < b.abs_L; +} +AIClassify::AIClassify() +{ +} + +AIClassify::~AIClassify() +{ +} + + +cv::Rect AIClassify::GetCutRoi(cv::Rect roi, const cv::Mat &img) +{ + + cv::Rect cutroi; + int pc_x = roi.x + roi.width * 0.5; + int pc_y = roi.y + roi.height * 0.5; + bool bresize = false; + if (roi.width < QX_SAMLLIMG_WIDTH && roi.height < QX_SAMLLIMG_HEIGHT) + { + cutroi.width = QX_SAMLLIMG_WIDTH; + cutroi.x = pc_x - QX_SAMLLIMG_WIDTH * 0.5; + cutroi.height = QX_SAMLLIMG_HEIGHT; + cutroi.y = pc_y - QX_SAMLLIMG_HEIGHT * 0.5; + } + else + { + // 宽 高 + if (roi.width > roi.height) + { + cutroi.width = roi.width + 20; + cutroi.x = roi.x - 10; + + float fsx = QX_SAMLLIMG_HEIGHT * 1.0f / QX_SAMLLIMG_WIDTH; + cutroi.height = cutroi.width * fsx; + cutroi.y = pc_y - cutroi.height * 0.5; + } + else + { + cutroi.height = roi.height + 20; + cutroi.y = roi.y - 10; + + float fsy = QX_SAMLLIMG_WIDTH * 1.0f / QX_SAMLLIMG_HEIGHT; + cutroi.width = cutroi.height * fsy; + cutroi.x = pc_x - cutroi.width * 0.5; + } + + bresize = true; + } + + if (cutroi.x < 0) + { + cutroi.x = 0; + } + if (cutroi.y < 0) + { + cutroi.y = 0; + } + if (cutroi.x + cutroi.width >= img.cols) + { + cutroi.x = img.cols - cutroi.width; + if (cutroi.x < 0) + { + cutroi.x = 0; + if (cutroi.x + cutroi.width >= img.cols) + { + cutroi.width = img.cols; + } + } + } + if (cutroi.y + cutroi.height >= img.rows) + { + cutroi.y = img.rows - cutroi.height; + if (cutroi.y < 0) + { + cutroi.y = 0; + if (cutroi.y + cutroi.height >= img.rows) + { + cutroi.height = img.rows; + } + } + } + + return cutroi; +} +int AIClassify::GetDetRoiList(const cv::Mat &src_Img, cv::Rect qx_roi, std::vector &samllRoiList) +{ + + // qx_roi.x = 10; + // qx_roi.y = src_Img.rows - 10; + // qx_roi.width = src_Img.rows - 150; + // qx_roi.height = 8; + + int Min_SizeWH = 160; + int Max_sizeWH = 400; + // 块之间重叠度 + int overlap = 100; + // 单边的块数最多 + int Edge_Piece_single_Num = 7; + // 总的块数最多支持 9个。 + int Edge_Piece_Sum_Num = 9; + + int qx_w = qx_roi.width; + int qx_h = qx_roi.height; + // 长边、短边 + int long_side = qx_w; + int short_side = qx_h; + if (qx_w >= qx_h) + { + long_side = qx_w; + short_side = qx_h; + } + else + { + long_side = qx_h; + short_side = qx_w; + } + //printf("img %d %d qx %d %d \n", src_Img.cols, src_Img.rows, long_side, short_side); + std::vector pieceList; + if (long_side <= Min_SizeWH) + { + AI_PIECE_INFO tem; + tem.len = long_side; + tem.num = 1; + tem.long_num = 1; + tem.short_num = 1; + tem.abs_L = 0; + + pieceList.push_back(tem); + } + else + { + + // 1、从长边开始计算 + for (int i = 1; i <= Edge_Piece_single_Num; i++) + { + int piece_len = std::ceil(long_side * 1.0f / i); + int piece_overlap_len = std::ceil(piece_len + (i - 1) / i * overlap); + int long_Piece_Num = i; + int short_Piece_Num = std::ceil(short_side * 1.0f / piece_overlap_len); + int sum_Piece_Num = long_Piece_Num * short_Piece_Num; + + //printf("piece size %d %d long Num %d short Num %d sum %d \n", piece_len, piece_overlap_len, long_Piece_Num, short_Piece_Num, sum_Piece_Num); + if (sum_Piece_Num > Edge_Piece_Sum_Num) + { + continue; + } + + AI_PIECE_INFO tem; + tem.len = piece_overlap_len; + tem.num = sum_Piece_Num; + tem.long_num = long_Piece_Num; + tem.short_num = short_Piece_Num; + tem.abs_L = std::abs(piece_overlap_len - Max_sizeWH); + + pieceList.push_back(tem); + } + } + std::sort(pieceList.begin(), pieceList.end(), compare_Piece); + + // for (int i = 0; i < pieceList.size(); i++) + // { + // pieceList.at(i).print(std::to_string(i)); + // } + if (pieceList.size() <= 0) + { + printf("Select Roi fail\n"); + return 1; + } + AI_PIECE_INFO selectPiece; + selectPiece.len = pieceList.at(0).len; + selectPiece.num = pieceList.at(0).num; + selectPiece.long_num = pieceList.at(0).long_num; + selectPiece.short_num = pieceList.at(0).short_num; + selectPiece.abs_L = pieceList.at(0).abs_L; + //selectPiece.print("select"); + + int W_Piece_Num = selectPiece.long_num; + int H_Piece_Num = selectPiece.short_num; + if (qx_w >= qx_h) + { + W_Piece_Num = selectPiece.long_num; + H_Piece_Num = selectPiece.short_num; + } + else + { + W_Piece_Num = selectPiece.short_num; + H_Piece_Num = selectPiece.long_num; + } + int Piece_len = selectPiece.len; + if (Piece_len < Min_SizeWH) + { + Piece_len = Min_SizeWH; + } + + /////////////////、计算宽度方向 块的个数 和 重叠 /////////////////////// + // 块的个数 + int nBlocknum_x = W_Piece_Num; + + int use_MinOverlap_Width = 0; + // 计算重叠率 + if (nBlocknum_x > 1) + { + // 有多个块,要判断 块的重叠是否满足要求 + int nSumLen_x = nBlocknum_x * Piece_len; // + float fOverlap_x = (nSumLen_x - qx_w) * 1.0f / (nBlocknum_x - 1); + use_MinOverlap_Width = int(fOverlap_x); + } + + /////////////////、计算高度方向 块的个数 和 重叠 /////////////////////// + + // 块的个数 + int nBlocknum_y = H_Piece_Num; + + int use_MinOverlap_Height = 0; + // 计算重叠率 + if (nBlocknum_y > 1) + { + // 有多个块,要判断 块的重叠是否满足要求 + int nSumLen_y = nBlocknum_y * Piece_len; // + float fOverlap_y = (nSumLen_y - qx_h) * 1.0f / (nBlocknum_y - 1); + use_MinOverlap_Height = int(fOverlap_y); + } + + int start_x = qx_roi.x; + int start_y = qx_roi.y; + + int end_x = qx_roi.width + qx_roi.x; + int end_y = qx_roi.height + qx_roi.y; + + // 有效图片 宽 高 + int det_width = qx_roi.width; + int det_height = qx_roi.height; + + int AI_Img_width = Piece_len; + int AI_Img_height = Piece_len; + + if (nBlocknum_x == 1) + { + int sx = AI_Img_width - det_width; + int sub_x = 0; + if (sx > 0) + { + sub_x = sx / 2; + } + start_x -= sub_x; + if (start_x < 0) + { + start_x = 0; + } + } + + int cut_sy = qx_roi.y; + int cut_ey = qx_roi.y + Piece_len; + + if (nBlocknum_y == 1) + { + int sy = AI_Img_width - det_height; + int sub_y = 0; + if (sy > 0) + { + sub_y = sy / 2; + } + start_y -= sub_y; + if (start_y < 0) + { + start_y = 0; + } + } + cut_sy = start_y; + cut_ey = start_y + AI_Img_height; + if (cut_ey >= src_Img.rows) + { + cut_ey = src_Img.rows; + cut_sy = cut_ey - AI_Img_height; + } + + for (int iy = 0; iy < nBlocknum_y; iy++) + { + int nleny = end_y - cut_ey; + int cut_sx = start_x; + int cut_ex = start_x + AI_Img_width; + if (cut_ex >= src_Img.cols) + { + cut_ex = src_Img.cols; + cut_sx = cut_ex - AI_Img_width; + } + + for (int ix = 0; ix < nBlocknum_x; ix++) + { + + cv::Rect roi; + roi.x = cut_sx; + roi.y = cut_sy; + roi.width = AI_Img_width; + roi.height = AI_Img_height; + + samllRoiList.push_back(roi); + + // 剩余长度 + int nlenx = end_x - cut_ex; + if (nlenx > AI_Img_width) + { + cut_sx = cut_sx + AI_Img_width - use_MinOverlap_Width; + cut_ex = cut_sx + AI_Img_width; + } + else + { + cut_sx = end_x - AI_Img_width; + cut_ex = cut_sx + AI_Img_width; + } + } + + if (nleny > AI_Img_height) + { + cut_sy = cut_sy + AI_Img_height - use_MinOverlap_Height; + cut_ey = cut_sy + AI_Img_height; + } + else + { + cut_sy = end_y - AI_Img_height; + cut_ey = cut_sy + AI_Img_height; + } + } + + // 如果是偶数个,则需要再加个一个。 + int sumblob = nBlocknum_y * nBlocknum_x; + if (sumblob % 2 == 0) + { + + cv::Rect temRoi = GetCutRoi(qx_roi, src_Img); + samllRoiList.push_back(temRoi); + } + + if (false) + { + cv::Mat showimg = src_Img.clone(); + if (showimg.channels() == 1) + { + cv::cvtColor(showimg, showimg, cv::COLOR_GRAY2BGR); + } + cv::rectangle(showimg, qx_roi, cv::Scalar(255, 255, 0), 5); + for (size_t i = 0; i < samllRoiList.size(); i++) + { + cv::rectangle(showimg, samllRoiList.at(i), cv::Scalar(255, 0, 0)); + } + static int idx = 0; + cv::imwrite(std::to_string(idx++) + "tem_piece.png", showimg); + } + + // getchar(); + + return 0; +} diff --git a/AlgorithmModule/src/AIImgDeal.cpp b/AlgorithmModule/src/AIImgDeal.cpp new file mode 100644 index 0000000..b04f9d2 --- /dev/null +++ b/AlgorithmModule/src/AIImgDeal.cpp @@ -0,0 +1,710 @@ +/* + * FileName:CoreLogicFactory.cpp + * Version:V1.0 + * Description: + * Created On:Mon Sep 10 11:13:16 UTC 2018 + * Modified date: + * Author:Sky + */ +#include "AIImgDeal.h" +#include "CheckUtil.hpp" +AI_IMG_deal::AI_IMG_deal() +{ + + m_pAI_SingleGPU = NULL; + + AI_DATA_Cls_OUT_0 = NULL; + AI_DATA_Cls_L0_OUT_0 = NULL; + bInitSucc_re_AD = false; + bInitSucc_re_Pol = false; + + bInitSucc_Edge_Samll = false; + bInitSucc_Edge_big = false; + bInitSucc_LackPol = false; + bInitSucc_MarkLine = false; + NewData(); +} + +AI_IMG_deal::~AI_IMG_deal() +{ + // cout << "单例对象销毁!" << endl; + DelteData(); +} + +// 根据gpu号初始化 +int AI_IMG_deal::Init(int nGpuIdx) +{ + if (nGpuIdx < 0 || nGpuIdx >= MAX_GPU_NUMBER) + { + return -1; + } + m_nGpuIdx = nGpuIdx; + + m_pAI_SingleGPU = AI_SingleGPU::GetInstance(nGpuIdx); + cout << "AI_IMG_deal GPU:" << m_nGpuIdx << " create succ " << m_pAI_SingleGPU << endl; + + return 0; +} + +int AI_IMG_deal::NewData() +{ + + if (AI_DATA_Cls_OUT_0 == NULL) + { + AI_DATA_Cls_OUT_0 = new float[AI_Cls_out_0_IMAGE_DATA_LENGTH]; + } + if (AI_DATA_Cls_L0_OUT_0 == NULL) + { + AI_DATA_Cls_L0_OUT_0 = new float[AI_Cls_14_out_0_IMAGE_DATA_LENGTH]; + } + + return 0; +} +int AI_IMG_deal::DelteData() +{ + + if (AI_DATA_Cls_OUT_0) + { + delete[] AI_DATA_Cls_OUT_0; + AI_DATA_Cls_OUT_0 = NULL; + } + if (AI_DATA_Cls_L0_OUT_0) + { + delete[] AI_DATA_Cls_L0_OUT_0; + AI_DATA_Cls_L0_OUT_0 = NULL; + } + + return 0; +} +int AI_IMG_deal::Init_BOE(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_NF.model_init(config); + if (0 != re) + { + printf("Init_NF error \n"); + } + printf("Init_NF succ----------------------------%d \n", config.nGpuIdx); + return re; +} +int AI_IMG_deal::Init_127Cell(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_127Cell.model_init(config); + if (0 != re) + { + printf("Init_127Cell error \n"); + bInitSucc_127Cell = false; + } + else + { + bInitSucc_127Cell = true; + } + printf("Init_127Cell succ----------------------------%d bInitSucc_127Cell %d\n", config.nGpuIdx, bInitSucc_127Cell); + + return 0; +} +int AI_IMG_deal::Init_BOE_Type2(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_Type2.model_init(config); + if (0 != re) + { + printf("Init_BOE_Type2 error \n"); + } + printf("Init_BOE_Type2 succ----------------------------%d \n", config.nGpuIdx); + return re; +} +int AI_IMG_deal::Init_BOE_UP(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_UP.model_init(config); + if (0 != re) + { + printf("Init_BOE_UP error \n"); + } + printf("Init_BOE_UP succ----------------------------%d \n", config.nGpuIdx); + return re; +} +int AI_IMG_deal::Init_BOE_Chess(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_Chess.model_init(config); + if (0 != re) + { + printf("Init_BOE_Chess error \n"); + } + printf("Init_BOE_Chess succ----------------------------%d \n", config.nGpuIdx); + return re; +} +int AI_IMG_deal::Init_YX_1(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_YX_1.model_init(config); + if (0 != re) + { + printf("Init_YX_1 error \n"); + } + printf("Init_YX_1 succ----------------------------%d \n", config.nGpuIdx); + return re; +} +int AI_IMG_deal::Init_YX_2(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_YX_2.model_init(config); + if (0 != re) + { + printf("Init_YX_2 error \n"); + } + printf("Init_YX_2 succ----------------------------%d \n", config.nGpuIdx); + return 0; +} +int AI_IMG_deal::Init_Cls(AIInitConfig config, int ntype) +{ + int re = 0; + if (ntype != 1 && ntype != 2) + { + re = m_pAI_SingleGPU->AI_defect_Cls.model_init(config); + if (0 != re) + { + printf("Init_Cls error \n"); + } + printf("Init_Cls succ------123---------------ntype%d-------%d \n", config.nGpuIdx, ntype); + } + + if (ntype == 1) + { + re = m_pAI_SingleGPU->AI_defect_Cls_L0.model_init(config); + if (0 != re) + { + printf("Init_Cls error \n"); + } + printf("Init_Cls succ-----------AI_defect_Cls_L0-----------------%d \n", config.nGpuIdx); + } + + return re; +} +int AI_IMG_deal::Init_zf(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_zf.model_init(config); + if (0 != re) + { + printf("Init_zf error \n"); + } + + printf("Init_zf succ----------------------------%d \n", config.nGpuIdx); + return re; +} +int AI_IMG_deal::Init_RE_POL(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_RE_POL.model_init(config); + if (0 != re) + { + printf("AI_defect_RE_POL error \n"); + bInitSucc_re_Pol = false; + } + else + { + bInitSucc_re_Pol = true; + } + printf("AI_defect_RE_POL succ----------------------------%d AI_defect_RE_POL %d\n", config.nGpuIdx, bInitSucc_re_Pol); + + return re; +} +int AI_IMG_deal::Init_RE_AD(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_RE_AD.model_init(config); + if (0 != re) + { + printf("AI_defect_RE_AD error \n"); + bInitSucc_re_AD = false; + } + else + { + bInitSucc_re_AD = true; + } + printf("AI_defect_RE_AD succ---------------------------%d AI_defect_RE_AD %d\n", config.nGpuIdx, bInitSucc_re_AD); + + return re; +} +int AI_IMG_deal::Init_Edge_Big(AIInitConfig config) +{ + printf("Init_Edge_Big gpu %d \n", config.nGpuIdx); + int re = m_pAI_SingleGPU->AI_defect_Edge_Big.model_init(config); + if (0 != re) + { + printf("AI_defect_Edge_Big error \n"); + bInitSucc_Edge_big = false; + } + else + { + bInitSucc_Edge_big = true; + } + printf("AI_defect_Edge_Big succ-------------------------gpu :%d reuslt : %d\n", config.nGpuIdx, bInitSucc_Edge_big); + return 0; +} +int AI_IMG_deal::Init_Edge_Small(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_Edge_Samll.model_init(config); + if (0 != re) + { + printf("AI_defect_Edge_Samll error \n"); + bInitSucc_Edge_Samll = false; + } + else + { + bInitSucc_Edge_Samll = true; + } + printf("AI_defect_Edge_Samll succ---------------------------gpu :%d reuslt : %d\n", config.nGpuIdx, bInitSucc_Edge_Samll); + return 0; +} +int AI_IMG_deal::Init_LackPol(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_LackPol.model_init(config); + if (0 != re) + { + printf("Init_LackPol error \n"); + bInitSucc_LackPol = false; + return re; + } + else + { + bInitSucc_LackPol = true; + } + printf("bInitSucc_LackPol succ---------------------------gpu :%d reuslt: %d\n", config.nGpuIdx, bInitSucc_LackPol); + return 0; +} +int AI_IMG_deal::Init_MarkLine(AIInitConfig config) +{ + int re = m_pAI_SingleGPU->AI_defect_MarkLine.model_init(config); + if (0 != re) + { + printf("AI_defect_MarkLine error \n"); + bInitSucc_MarkLine = false; + } + else + { + bInitSucc_MarkLine = true; + } + printf("AI_defect_MarkLine succ----------------------------%d AI_defect_RE_POL %d\n", config.nGpuIdx, bInitSucc_MarkLine); + + return 0; +} +int AI_IMG_deal::AICheck_BOE(cv::Mat inImg, cv::Mat &outImg_1) +{ + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_NF_out_0_IMAGE_CHANNEL, AI_NF_out_0_IMAGE_WIDTH, AI_NF_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_NF.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + + return 0; +} + +int AI_IMG_deal::AICheck_BOE_Type2(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_NF_out_0_IMAGE_CHANNEL, AI_NF_out_0_IMAGE_WIDTH, AI_NF_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_Type2.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + return 0; +} + +int AI_IMG_deal::AICheck_BOE_Chess(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_NF_out_0_IMAGE_CHANNEL, AI_NF_out_0_IMAGE_WIDTH, AI_NF_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_Chess.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + return 0; +} + +int AI_IMG_deal::AICheck_BOE_UP(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_NF_out_0_IMAGE_CHANNEL, AI_NF_out_0_IMAGE_WIDTH, AI_NF_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_UP.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + return 0; +} + +int AI_IMG_deal::AICheck_YX_1(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_YX_out_0_IMAGE_CHANNEL, AI_YX_out_0_IMAGE_WIDTH, AI_YX_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_YX_1.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + + return 0; +} + +int AI_IMG_deal::AICheck_YX_2(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_YX_out_0_IMAGE_CHANNEL, AI_YX_out_0_IMAGE_WIDTH, AI_YX_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_YX_2.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + return 0; +} + +int AI_IMG_deal::AICheck_Cls(cv::Mat inImg, int ntype, float *fmaxScore) +{ + + if (inImg.empty()) + { + return -1; + } + uchar *pindata = inImg.ptr(0); + + int cls_num = AI_Cls_out_0_IMAGE_DATA_LENGTH; + if (ntype == 1) + { + cls_num = AI_Cls_14_out_0_IMAGE_DATA_LENGTH; + } + + int max_id = 0; + if (ntype == 1) + { + m_pAI_SingleGPU->AI_defect_Cls_L0.model_Cuda_AI_In_1_Out_1_float(pindata, AI_DATA_Cls_L0_OUT_0); + max_id = F2softmaxId(AI_DATA_Cls_L0_OUT_0, cls_num, fmaxScore); + } + else + { + m_pAI_SingleGPU->AI_defect_Cls.model_Cuda_AI_In_1_Out_1_float(pindata, AI_DATA_Cls_OUT_0); + max_id = F2softmaxId(AI_DATA_Cls_OUT_0, cls_num, fmaxScore); + } + // printf("ccccccccc 2\n"); + // getchar(); + // std::cout<<"-----------------------------------------max_id="<(0); + + outImg_1 = InitMat(AI_ZF_out_0_IMAGE_CHANNEL, AI_ZF_out_0_IMAGE_WIDTH, AI_ZF_out_0_IMAGE_HEIGHT); + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_zf.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_defect_NF conver work sum %ld \n", t2 - t1); + return 0; +} + +int AI_IMG_deal::AICheck_127Cell(cv::Mat inImg, cv::Mat &outImg_1) +{ + if (inImg.empty()) + { + return -1; + } + + long t1, t2; + t1 = CheckUtil::getcurTime(); + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(AI_127Cell_out_0_IMAGE_CHANNEL, AI_127Cell_out_0_IMAGE_WIDTH, AI_127Cell_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_127Cell) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_127Cell.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + t2 = CheckUtil::getcurTime(); + + return 0; +} + +int AI_IMG_deal::AICheck_RE_POL(cv::Mat inImg, cv::Mat &outImg_1) +{ + if (inImg.empty()) + { + return -1; + } + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(str_AI_RE_POL_out_0_IMAGE_CHANNEL, str_AI_RE_POL_out_0_IMAGE_WIDTH, str_AI_RE_POL_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_re_Pol) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_RE_POL.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + return 0; +} + +int AI_IMG_deal::AICheck_RE_AD(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(str_AI_RE_AD_out_0_IMAGE_CHANNEL, str_AI_RE_AD_out_0_IMAGE_WIDTH, str_AI_RE_AD_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_re_AD) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_RE_AD.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + return 0; +} + +int AI_IMG_deal::AICheck_Edge_Big(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(str_AI_EDGE_Big_out_0_IMAGE_CHANNEL, str_AI_EDGE_Big_out_0_IMAGE_WIDTH, str_AI_EDGE_Big_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_Edge_big) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_Edge_Big.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + return 0; +} + +int AI_IMG_deal::AICheck_Edge_Small(cv::Mat inImg, cv::Mat &outImg_1) +{ + + if (inImg.empty()) + { + return -1; + } + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(str_AI_EDGE_Small_out_0_IMAGE_CHANNEL, str_AI_EDGE_Small_out_0_IMAGE_WIDTH, str_AI_EDGE_Small_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_Edge_Samll) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_Edge_Samll.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + return 0; +} + +int AI_IMG_deal::AICheck_LackPol(cv::Mat inImg, cv::Mat &outImg_1) +{ + if (inImg.empty()) + { + return -1; + } + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(str_AI_LOSSPOL_out_0_IMAGE_CHANNEL, str_AI_LOSSPOL_out_0_IMAGE_WIDTH, str_AI_LOSSPOL_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_LackPol) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_LackPol.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + + return 0; +} + +int AI_IMG_deal::AICheck_MarkLine(cv::Mat inImg, cv::Mat &outImg_1) +{ + if (inImg.empty()) + { + return -1; + } + + uchar *pindata = inImg.ptr(0); + + outImg_1 = InitMat(str_AI_Mark_out_0_IMAGE_CHANNEL, str_AI_Mark_out_0_IMAGE_WIDTH, str_AI_Mark_out_0_IMAGE_HEIGHT); + + if (!bInitSucc_MarkLine) + { + return 1; + } + uchar *poutImg_1 = outImg_1.ptr(0); + m_pAI_SingleGPU->AI_defect_MarkLine.model_Cuda_AI_In_1_Out_1(pindata, poutImg_1); + return 0; +} + +cv::Mat AI_IMG_deal::F2M(float *data, int clannel, int w, int h) +{ + cv::Mat dst(h, w, 8 * (clannel - 1)); + uint8_t *dstp = (uint8_t *)dst.data; + int length = w * h * clannel; + for (int i = 0; i < length; i++) + { + if (data[i] > 255) + { + dstp[i] = 256 - data[i] / 255; + } + else + { + dstp[i] = uint8_t(data[i]); + } + } + + return dst; +} +cv::Mat AI_IMG_deal::InitMat(int channel, int w, int h) +{ + if (w <= 0 || h <= 0 || channel <= 0 || channel > 3) + { + return cv::Mat(); + } + + cv::Mat dst; + if (channel == 1) + { + dst = cv::Mat(h, w, CV_8UC1, cv::Scalar(0)); + } + else + { + dst = cv::Mat(h, w, CV_8UC3, cv::Scalar(0, 0, 0)); + } + return dst; +} + +int AI_IMG_deal::F2softmaxId(float *data, int class_num, float *fmaxScore) +{ + + // std::cout<<"F2softmaxId()-class_num="<pAIDeal; + + m_bInitialized = true; + return 0; +} +int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared_ptr &pCheckResult_Aling) +{ + + printf("save type %d \n", pDetConfig->saveProcessImg); + m_pDetConfig = pDetConfig; + static int erridx = 0; + std::string str_error = ""; + + // 保存过程图片 + if (m_pDetConfig->IsSaveProcessImg()) + { + erridx++; + if (erridx > 9999999) + { + erridx = 0; + } + str_error = "/home/aidlux/BOE/Edge/Error/" + std::to_string(erridx) + "_src.png"; + } + cv::Mat showimg; + // 保存结果图片 + if (m_pDetConfig->bSaveResultImg) + { + cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR); + } + pCheckResult_Aling = std::make_shared(); + if (img.empty()) + { + return 1; + } + + // 1、初步定位 找到产品大致区域 + int re = 0; + vector rois; + cv::Rect Big_roi; + cv::Mat mask; + cv::Mat big_mask; + re = Det_big(img, rois, Big_roi, big_mask); + if (re != 0) + { + printf("AICheck_Edge_Big----error %d \n", re); + if (m_pDetConfig->IsSaveProcessImg()) + { + cv::imwrite(str_error, img); + } + return re; + } + + if (m_pDetConfig->bSaveResultImg) + { + for (const auto &roi : rois) + { + cv::rectangle(showimg, roi, cv::Scalar(0, 0, 255)); + } + cv::rectangle(showimg, Big_roi, cv::Scalar(255, 255, 255), 2); + cv::imwrite(pDetConfig->strCamName + " edge_Small_Det_ROI_0.png", showimg); + } + + // 2、对每个小区域进行处理 + cv::Mat Src_Mask = cv::Mat(img.rows, img.cols, CV_8U, cv::Scalar(0)); + cv::Mat Src_Masksss; + for (const auto &roi : rois) + { + cv::Mat smask; + cv::Rect detROI = roi; + if (detROI.x < 0) + detROI.x = 0; + if (detROI.y < 0) + detROI.y = 0; + if (detROI.x + detROI.width > img.cols) + detROI.x = img.cols - detROI.width; + if (detROI.y + detROI.height > img.rows) + detROI.y = img.rows - detROI.height; + + cv::Mat temDet = img(detROI).clone(); + + re = m_pAIDeal->AICheck_Edge_Small(temDet, smask); + if (re != 0) + { + printf("AICheck_Edge_small----error \n"); + return 6; + } + + // 保存过程小图 + SaveSmallImg(temDet, smask, detROI); + + smask.copyTo(Src_Mask(detROI), smask); + } + if (m_pDetConfig->bSaveResultImg) + { + cv::imwrite(pDetConfig->strCamName + " edge_Small_Out_Mask_1.png", Src_Mask); + } + cv::Rect result_roi; + Mat resultMask = Mat::zeros(img.size(), CV_8UC1); + { + vector> contours; + findContours(Src_Mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + // 找到最大轮廓 + double max_area = 0; + int max_contour_index = 0; + + for (int i = 0; i < contours.size(); i++) + { + double area = contourArea(contours[i]); + if (area > max_area) + { + max_area = area; + max_contour_index = i; + } + } + if (max_contour_index < 0) + { + cerr << "No contours found!" << endl; + return 7; + } + + if (max_contour_index >= 0) + { + result_roi = boundingRect(contours[max_contour_index]); + } + drawContours(resultMask, contours, max_contour_index, Scalar(255), FILLED); // -1表示填充所有轮廓 + } + + // 和原始big模型做比对 + { + + double widthDiff = std::abs(result_roi.width - Big_roi.width) * 1.0f / std::min(result_roi.width, Big_roi.width); + double heightDiff = std::abs(result_roi.height - Big_roi.height) * 1.0f / std::min(result_roi.height, Big_roi.height); + printf("big roi %s det %swidthDiff %f heightDiff %f\n", CheckUtil::GetRectString(Big_roi).c_str(), CheckUtil::GetRectString(result_roi).c_str(), widthDiff, heightDiff); + // 如果差异超过10%,抛出异常 + if (widthDiff > 0.10) + { + return 51; + } + if (heightDiff > 0.10) + { + return 52; + } + } + if (m_pDetConfig->bUseDrawRoi_Check) + { + double widthDiff = std::abs(result_roi.width - m_pDetConfig->drawRoi.width) * 1.0f / std::min(result_roi.width, m_pDetConfig->drawRoi.width); + double heightDiff = std::abs(result_roi.height - m_pDetConfig->drawRoi.height) * 1.0f / std::min(result_roi.height, m_pDetConfig->drawRoi.height); + printf("draw roi %s det %s widthDiff %f heightDiff %f\n", CheckUtil::GetRectString(m_pDetConfig->drawRoi).c_str(), CheckUtil::GetRectString(result_roi).c_str(), widthDiff, heightDiff); + // 如果差异超过10%,抛出异常 + if (widthDiff > 0.10) + { + return 53; + } + if (heightDiff > 0.10) + { + return 54; + } + } + // 用big 的来测试 + if (false) + { + cv::Size sz_big; + sz_big.width = big_mask.cols; + sz_big.height = big_mask.rows; + cv::Mat size_prodct; + cv::resize(resultMask, size_prodct, sz_big, 0, 0, cv::INTER_AREA); + + int va_big = countNonZero(big_mask); + int va_small = countNonZero(size_prodct); + if (va_big > 0) + { + int diff = std::abs(va_big - va_small); // 面积的差异值。 + float fs = diff * 1.0f / va_big; + printf("va_big %d va_small %d dff %d diffscale %f \n", va_big, va_small, diff, fs); + if (fs > 0.1) + { + // if (true) + // { + // cv::imwrite("big_mask.png",big_mask); + // cv::imwrite("size_prodct.png",size_prodct); + // getchar(); + // } + + return 55; + } + } + + /* code */ + } + if (m_pDetConfig->bUseDrawRoi_Check && !m_pDetConfig->drawMask.empty()) + { + cv::Size sz_big; + sz_big.width = big_mask.cols; + sz_big.height = big_mask.rows; + cv::Mat size_prodct; + cv::resize(resultMask, size_prodct, sz_big, 0, 0, cv::INTER_AREA); + + cv::Mat size_drawmask; + cv::resize(m_pDetConfig->drawMask, size_drawmask, sz_big, 0, 0, cv::INTER_AREA); + + int va_draw = countNonZero(size_drawmask); + int va_small = countNonZero(size_prodct); + if (va_draw > 0) + { + int diff = std::abs(va_draw - va_small); // 面积的差异值。 + float fs = diff * 1.0f / va_draw; + printf("va_draw %d va_small %d dff %d diffscale %f \n", va_draw, va_small, diff, fs); + if (fs > 0.1) + { + return 56; + } + } + } + + if (m_pDetConfig->bSaveResultImg) + { + cv::imwrite(pDetConfig->strCamName + " edge_product_det_mask.png", resultMask); + if (!m_pDetConfig->drawMask.empty()) + { + cv::imwrite(pDetConfig->strCamName + " edge_product_draw_mask.png", m_pDetConfig->drawMask); + } + } + + pCheckResult_Aling->DetMask_src = resultMask.clone(); + if (m_pDetConfig->bSaveResultImg) + { + cv::imwrite(std::to_string(m_pDetConfig->ncamId) + " edge_Small_mask_Filled_2.png", resultMask); + } + cv::Mat resultMask_erode_small; + // 膨胀腐蚀处理 + { + printf("m_pDetConfig->nAIErodesize %d\n", m_pDetConfig->nAIErodesize); + if (m_pDetConfig->nAIErodesize <= 0) + { + resultMask_erode_small = resultMask(result_roi).clone(); + } + else + { + // 定义膨胀核 + int dilation_size = 7; // 膨胀核的大小 + if (m_pDetConfig->nAIErodesize > 0 && m_pDetConfig->nAIErodesize < 101) + { + dilation_size = 2 * m_pDetConfig->nAIErodesize; + } + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(dilation_size, dilation_size)); + + // 进行膨胀操作 + + cv::erode(resultMask(result_roi), resultMask_erode_small, kernel); + } + + pCheckResult_Aling->mask = ~resultMask_erode_small; + } + + if (m_pDetConfig->bSaveResultImg) + { + // cv::imwrite("edge_result_src_roi_thresholdvalue.png", temimg); + cv::imwrite(pDetConfig->strCamName + " edge_result_src_3.png", img(result_roi)); + cv::imwrite(pDetConfig->strCamName + " edge_result_mask_4.png", pCheckResult_Aling->mask); + cv::Mat temAdd = img(result_roi).clone(); + + { + // 查找轮廓 + std::vector> contours; + std::vector hierarchy; + cv::findContours(resultMask_erode_small.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + // 创建一个空白图像用于绘制轮廓 + + // 绘制轮廓 + cv::drawContours(temAdd, contours, -1, cv::Scalar(255, 255, 0), 2); // 绿色,线宽2 + } + cv::imwrite(pDetConfig->strCamName + " edge_result_Merge_5.png", temAdd); + } + + // 存在中间结果 + if (m_pDetConfig->saveProcessImg != Save_Close) + { + static int svidx = 0; + svidx++; + if (svidx > 9999999) + { + svidx = 0; + /* code */ + } + std::string str1 = "/home/aidlux/BOE/Edge/Result/" + std::to_string(svidx) + "_mask.png"; + std::string str2 = "/home/aidlux/BOE/Edge/Result/" + std::to_string(svidx) + "_show.png"; + + int newWidth = 1280; + float aspectRatio = static_cast(resultMask_erode_small.rows) / resultMask_erode_small.cols; + int newHeight = static_cast(newWidth * aspectRatio); + + // 缩放图像 + cv::Mat resizedImage; + cv::resize(resultMask_erode_small, resizedImage, cv::Size(newWidth, newHeight)); + + cv::Mat temAdd = img(result_roi).clone(); + cv::resize(temAdd, temAdd, cv::Size(newWidth, newHeight)); + { + // 查找轮廓 + std::vector> contours; + std::vector hierarchy; + cv::findContours(resizedImage.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + // 创建一个空白图像用于绘制轮廓 + + // 绘制轮廓 + cv::drawContours(temAdd, contours, -1, cv::Scalar(255, 255, 0), 1); // 绿色,线宽2 + } + cv::imwrite(str1, resizedImage); + + cv::imwrite(str2, temAdd); + } + + pCheckResult_Aling->roi = result_roi; + + return 0; +} + +int AI_Edge_Algin::SaveSmallImg(const cv::Mat &img, const cv::Mat &mask, cv::Rect roi) +{ + // 是否要保存中间过程的小图 + if (m_pDetConfig->IsSaveProcessImg()) + { + static int svsmallidx = 0; + svsmallidx++; + if (svsmallidx > 9999999) + { + svsmallidx = 0; + /* code */ + } + bool bssss = false; + + if (m_pDetConfig->saveProcessImg == Save_Filter) + { + // 4. 查找轮廓 + vector> contours; + vector hierarchy; + findContours(mask.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + if (contours.size() > 1) + { + bssss = true; + } + else if (contours.size() == 1) + { + int pointNum = 0; + for (int i = 0; i < contours.size(); i++) + { + pointNum += contours[i].size(); + } + // printf("pointNum============== %d\n", pointNum); + if (pointNum > 30) + { + bssss = true; + } + } + } + else if (m_pDetConfig->saveProcessImg == Save_ALL) + { + bssss = true; + } + + if (bssss) + { + std::string str1 = "/home/aidlux/BOE/Edge/Smasll/" + std::to_string(svsmallidx) + "_in.png"; + std::string str2 = "/home/aidlux/BOE/Edge/Smasll/" + std::to_string(svsmallidx) + "_in_mask.png"; + // std::string st3 = "/home/aidlux/BOE/Edge/Smasll/" + std::to_string(svsmallidx) + "_in_show.png"; + cv::imwrite(str1, img); + cv::imwrite(str2, mask); + // cv::Mat showsss = temDet + smask * 0.4; + // cv::imwrite(st3, showsss); + } + } + return 0; +} + +int AI_Edge_Algin::InitModel_ALL() +{ + m_bModelSucc = false; + int re = InitModel_Big(); + if (re != 0) + { + printf("AI_Edge_Algin InitModel_Big Error \n"); + return re; + } + re = InitModel_Small(); + if (re != 0) + { + printf("AI_Edge_Algin InitModel_Small Error \n"); + + return re; + } + m_bModelSucc = true; + return 0; +} + +int AI_Edge_Algin::InitModel_Big() +{ + + AIInitConfig config_nf; + config_nf.nGpuIdx = EDGE_GPU; + config_nf.engine_file_path = str_AI_EDGE_Big_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = str_AI_EDGE_Big_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = str_AI_EDGE_Big_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = str_AI_EDGE_Big_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = str_AI_EDGE_Big_out_0_IMAGE_Name; + m_pAIDeal->Init_Edge_Big(config_nf); + + return 0; +} + +int AI_Edge_Algin::InitModel_Small() +{ + AIInitConfig config_nf; + config_nf.nGpuIdx = EDGE_GPU; + config_nf.engine_file_path = str_AI_EDGE_Small_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = str_AI_EDGE_Small_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = str_AI_EDGE_Big_out_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = str_AI_EDGE_Small_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = str_AI_EDGE_Small_out_0_IMAGE_Name; + m_pAIDeal->Init_Edge_Small(config_nf); + return 0; +} + +int AI_Edge_Algin::Det_big(const cv::Mat &img, vector &smallRoiList, cv::Rect &bigRoi, cv::Mat &big_mask) +{ + cv::Size sz; + sz.width = str_AI_EDGE_Big_IN_0_IMAGE_WIDTH; + sz.height = str_AI_EDGE_Big_IN_0_IMAGE_HEIGHT; + cv::Mat detImg; + cv::resize(img, detImg, sz); + int re = 0; + cv::Mat mask; + re = m_pAIDeal->AICheck_Edge_Big(detImg, mask); + big_mask = mask; + if (re != 0) + { + printf("AICheck_Edge_Big----error \n"); + int re123 = 100 + re; + return re123; + } + if (m_pDetConfig->bSaveResultImg) + { + cv::imwrite("edge_big_in.png", detImg); + cv::imwrite("edge_big_out_mask.png", mask); + } + if (m_pDetConfig->IsSaveProcessImg()) + { + static int bigidx = 0; + bigidx++; + if (bigidx > 9999999) + { + bigidx = 0; + /* code */ + } + std::string str1 = "/home/aidlux/BOE/Edge/Big/" + std::to_string(bigidx) + "_in.png"; + std::string str2 = "/home/aidlux/BOE/Edge/Big/" + std::to_string(bigidx) + "_in_mask.png"; + cv::imwrite(str1, detImg); + cv::imwrite(str2, mask); + } + + // 找到最大轮廓 + + bool found; + cv::Rect boundingBox = CheckUtil::getLargestContourROI(mask, found); + if (!found) + { + cerr << "No contours found!" << endl; + return 4; + } + + // 形成 小图分割的检测区域 + float fresize_x = img.cols * 1.0f / sz.width; + float fresize_y = img.rows * 1.0f / sz.height; + + bigRoi.x = boundingBox.x * fresize_x; + bigRoi.y = boundingBox.y * fresize_y; + bigRoi.width = boundingBox.width * fresize_x; + bigRoi.height = boundingBox.height * fresize_y; + + // 使用手动绘制的roi进行校验 + if (m_pDetConfig->bUseDrawRoi_Check) + { + double widthDiff = std::abs(bigRoi.width - m_pDetConfig->drawRoi.width) * 1.0f / std::min(bigRoi.width, m_pDetConfig->drawRoi.width); + double heightDiff = std::abs(bigRoi.height - m_pDetConfig->drawRoi.height) * 1.0f / std::min(bigRoi.height, m_pDetConfig->drawRoi.height); + printf("draw roi %s bigRoi %s widthDiff %f heightDiff %f\n", CheckUtil::GetRectString(m_pDetConfig->drawRoi).c_str(), CheckUtil::GetRectString(bigRoi).c_str(), widthDiff, heightDiff); + // 如果差异超过10%,抛出异常 + if (widthDiff > 0.10) + { + return 5; + } + if (heightDiff > 0.10) + { + return 5; + } + } + + float fresize_x_1 = sz.width * 1.0f / img.cols; + float fresize_y_1 = sz.height * 1.0f / img.rows; + + int resize_Small_Roi_width = 320 * fresize_x_1; + int resize_Small_Roi_height = 320 * fresize_y_1; + int haf_w = resize_Small_Roi_width / 2; + int haf_h = resize_Small_Roi_height / 2; + int step_w = resize_Small_Roi_width * 0.85; + int step_h = resize_Small_Roi_height * 0.85; + smallRoiList.clear(); + int sizeare = resize_Small_Roi_width * resize_Small_Roi_height; + for (int y = boundingBox.y; y < boundingBox.y + boundingBox.height + haf_h; y += step_h) + { + int roiY = y - haf_h; + for (int x = boundingBox.x; x < boundingBox.x + boundingBox.width + haf_w; x += step_w) + { + int roiX = x - haf_w; + if (roiX < 0) + roiX = 0; + if (roiY < 0) + roiY = 0; + if (roiX + resize_Small_Roi_width >= mask.cols) + roiX = mask.cols - resize_Small_Roi_width; + if (roiY + resize_Small_Roi_height > mask.rows) + roiY = mask.rows - resize_Small_Roi_height; + Rect rect(roiX, roiY, resize_Small_Roi_width, resize_Small_Roi_height); + if (!CheckUtil::RoiInImg(rect, mask)) + { + continue; + } + + if (roiX >= 0 && roiY >= 0) + { + + if (roiX == 0 || roiX + resize_Small_Roi_width == mask.cols) + { + cv::Rect src_Roi; + src_Roi.x = rect.x * fresize_x; + src_Roi.y = rect.y * fresize_y; + src_Roi.width = 320; + src_Roi.height = 320; + smallRoiList.push_back(src_Roi); // 存储ROI的矩形框 + + // printf("\n\n\n\n\n\n\n=================%d===============\n\n\n\n\n\n\n", smallRoiList.size()); + } + else + { + int va = countNonZero(mask(rect)); + if (va > 0 && va < sizeare) + { + cv::Rect src_Roi; + src_Roi.x = rect.x * fresize_x; + src_Roi.y = rect.y * fresize_y; + src_Roi.width = 320; + src_Roi.height = 320; + smallRoiList.push_back(src_Roi); // 存储ROI的矩形框 + } + } + } + } + } + + return 0; +} + +Image_Feature_Algin::Image_Feature_Algin() +{ +} + +Image_Feature_Algin::~Image_Feature_Algin() +{ +} + +int Image_Feature_Algin::Detect(DetConfig *pDetConfig, Align_Result *pResult, std::vector &LogList) +{ + // 检测目标:找到 参数模版图到 检测图的 映射关系。包括 缩放和移动。 + + // 先缩放 在 移动 + std::string strlog = ""; + if (!pDetConfig) + { + return 1; + } + if (pDetConfig->TemplateImg.empty()) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", "TemplateImg is empty "); + LogList.push_back(strlog); + return 1; + } + // 裁切位置; + pResult->Crop_Roi_DetImg = pDetConfig->DetImg_CropROi; + // 1、缩放尺度 + float fx = 1; + float fy = 1; + // 裁切尺寸 存在 并合理 + if (pDetConfig->param_CropRoi.width > 0 && pDetConfig->param_CropRoi.height > 0 && + pDetConfig->DetImg_CropROi.width > 0 && pDetConfig->DetImg_CropROi.height > 0) + { + fx = pDetConfig->DetImg_CropROi.width * 1.0f / pDetConfig->param_CropRoi.width; + fy = pDetConfig->DetImg_CropROi.height * 1.0f / pDetConfig->param_CropRoi.height; + if (fx > 0.5 && fx < 2 && fy > 0.5 && fy < 2) + { + pResult->fCropROI_Scale_ParmToDet_X = fx; + pResult->fCropROI_Scale_ParmToDet_Y = fy; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", "Scale out 0.5--2"); + LogList.push_back(strlog); + return 1; + } + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", "crop ROI Error"); + LogList.push_back(strlog); + return 1; + } + // strlog = m_PrintLog.printstr(Print_Level_Info, "Image_Align", "Scale x %f y %f\n", fx, fy); + // LogList.push_back(strlog); + + // 2、定位 + // 1)、模版特征图片的 缩放。 + cv::Mat TemplateFeature; + cv::Size sz; + // fx = 1; + // fy = 1; + sz.width = int(pDetConfig->TemplateImg.cols * fx); + sz.height = int(pDetConfig->TemplateImg.rows * fy); + cv::resize(pDetConfig->TemplateImg, TemplateFeature, sz); + + if (!CheckUtil::RoiInImg(pDetConfig->Search_Roi, pDetConfig->DetImg)) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", "Search_Roi ROI Error Not In img"); + LogList.push_back(strlog); + return 1; + } + + cv::Mat DetFeature = pDetConfig->DetImg(pDetConfig->Search_Roi).clone(); + + double confidence = 0; + + int kernel_size = 128; + int search_size = 1024; + int det_search_min_size = DetFeature.cols; + if (DetFeature.rows < det_search_min_size) + { + det_search_min_size = DetFeature.rows; + } + int template_kernel_min_size = TemplateFeature.cols; + if (TemplateFeature.rows < template_kernel_min_size) + { + template_kernel_min_size = TemplateFeature.rows; + } + float f_search = search_size * 1.0f / det_search_min_size; + float f_Kernel = kernel_size * 1.0f / template_kernel_min_size; + float falign = f_search; + if (f_Kernel > falign) + { + falign = f_Kernel; + } + cv::Size Search_sz; + Search_sz.width = int(DetFeature.cols * falign); + Search_sz.height = int(DetFeature.rows * falign); + cv::Mat Search_img; + cv::resize(DetFeature, Search_img, Search_sz); + cv::Size Kernel_sz; + Kernel_sz.width = int(TemplateFeature.cols * falign); + Kernel_sz.height = int(TemplateFeature.rows * falign); + cv::Mat Kernel_img; + cv::resize(TemplateFeature, Kernel_img, Kernel_sz); + + auto bestMatch = findBestTemplateMatch(Search_img, Kernel_img, confidence); + + bestMatch.x /= falign; + bestMatch.y /= falign; + + pResult->bestMatch = bestMatch; + if (pDetConfig->bSaveImg) + { + cv::imwrite("Align_template.png", TemplateFeature); + cv::imwrite("Align_Det.png", DetFeature); + } + + if (confidence != -1) + { + std::cout << "最佳匹配位置: (" << bestMatch.x << ", " << bestMatch.y + << "), 得分: " << confidence << std::endl; + if (confidence > pDetConfig->fscore) + { + + /* code */ + + int m_x = pDetConfig->feature_Roi.x * fx - pDetConfig->Search_Roi.x; + int m_y = pDetConfig->feature_Roi.y * fy - pDetConfig->Search_Roi.y; + pResult->offt_x = bestMatch.x - m_x; + pResult->offt_y = bestMatch.y - m_y; + printf("m_x %d bestMatch.x %d offt_x %d\n", m_x, bestMatch.x, pResult->offt_x); + printf("m_y %d bestMatch.y %d offt_y %d\n", m_y, bestMatch.y, pResult->offt_y); + + pResult->bDet = true; + + pResult->Crop_Roi_ParmImg = pResult->Det_srcToParm_src_Rect(pResult->Crop_Roi_DetImg); + + strlog = m_PrintLog.printstr(Print_Level_Info, "Image_Align", " -- Succ :Align score %f > %f offt x %d y %d Scale x %f y %f", + confidence, pDetConfig->fscore, pResult->offt_x, pResult->offt_y, pResult->fCropROI_Scale_ParmToDet_X, pResult->fCropROI_Scale_ParmToDet_Y); + + LogList.push_back(strlog); + } + else + { + + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", " error :Align score %f< 0.9", confidence); + pResult->fCropROI_Scale_ParmToDet_X = 1; + pResult->fCropROI_Scale_ParmToDet_Y = 1; + LogList.push_back(strlog); + } + } + else + { + pResult->fCropROI_Scale_ParmToDet_X = 1; + pResult->fCropROI_Scale_ParmToDet_Y = 1; + std::cout << "未找到有效匹配" << std::endl; + } + + return 0; +} + +cv::Point Image_Feature_Algin::findBestTemplateMatch( + const cv::Mat &detectionImage, + const cv::Mat &templateImage, + double &bestScore, + int method) +{ + // 输入验证 + if (detectionImage.empty() || templateImage.empty()) + { + throw std::invalid_argument("输入图像不能为空"); + } + if (detectionImage.channels() != 1 || templateImage.channels() != 1) + { + throw std::invalid_argument("必须输入灰度图像"); + } + if (templateImage.rows > detectionImage.rows || + templateImage.cols > detectionImage.cols) + { + throw std::invalid_argument("模板尺寸不能大于被检测图像"); + } + + // cv::imwrite("detectionImage.png", detectionImage); + // cv::imwrite("templateImage.png", templateImage); + // 执行模板匹配 + cv::Mat resultMatrix; + cv::matchTemplate(detectionImage, templateImage, resultMatrix, method); + + // 确定极值搜索方式 + const bool findMinima = (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED); + + // 查找极值位置 + cv::Point extremaLoc = cv::Point(0, 0); + double extremaVal; + cv::minMaxLoc(resultMatrix, + findMinima ? &extremaVal : nullptr, + findMinima ? nullptr : &extremaVal, + findMinima ? &extremaLoc : nullptr, + findMinima ? nullptr : &extremaLoc); + + // 设置有效性检查阈值(可根据方法动态调整) + double threshold = 0.0; + switch (method) + { + case cv::TM_CCOEFF_NORMED: + threshold = 0.6; + break; // [-1, 1] + case cv::TM_CCORR_NORMED: + threshold = 0.7; + break; // [0, 1] + case cv::TM_SQDIFF_NORMED: + threshold = 0.2; + break; // [0, 1] + default: + threshold = 0.0; + } + + // 验证匹配有效性 + const bool isValid = findMinima ? (extremaVal <= threshold) : (extremaVal >= threshold); + + if (isValid) + { + bestScore = extremaVal; + return extremaLoc; + } + bestScore = -1; // 无效时的默认值 + return extremaLoc; +} diff --git a/AlgorithmModule/src/AI_Mark_Det.cpp b/AlgorithmModule/src/AI_Mark_Det.cpp new file mode 100644 index 0000000..1db7bae --- /dev/null +++ b/AlgorithmModule/src/AI_Mark_Det.cpp @@ -0,0 +1,476 @@ + +#include "AI_Edge_Algin.h" +#include "CheckErrorCodeDefine.hpp" +#include "AI_Mark_Det.h" + +AI_Mark_Det::AI_Mark_Det() +{ + m_bModelSucc = false; + CheckUtil::CreateDir("/home/aidlux/BOE/MarkLine/"); + m_pImageStorage = ImageStorage::getInstance(); + m_Show_Area = 0; + m_Show_Len = 0; + m_Len_P1 = cv::Point(0, 0); + m_Len_P2 = cv::Point(0, 0); +} + +AI_Mark_Det::~AI_Mark_Det() +{ +} +int AI_Mark_Det::InitModel_ALL() +{ + if (!m_bInitialized) + { + printf("Initialized error \n"); + + return 1; + } + m_bModelSucc = false; + + int re = 0; + re = InitModel(); + if (re != 0) + { + printf("InitModel error \n"); + m_bModelSucc = false; + } + else + { + m_bModelSucc = true; + } + + return 0; +} +int AI_Mark_Det::Detect(const cv::Mat &img, DetConfigResult *pDetConfig) +{ + printf("AI_Mark_Det::Detect \n"); + cv::Rect searchroi = pDetConfig->searchroi; + + if (searchroi.x < 0) + { + searchroi.x = 0; + } + if (searchroi.y < 0) + { + searchroi.y = 0; + } + if (searchroi.x + searchroi.width > img.cols) + { + searchroi.width = img.cols - searchroi.x; + } + if (searchroi.y + searchroi.width > img.rows) + { + searchroi.height = img.rows - searchroi.y; + } + + // 每个小矩形的大小 + int rectWidth = 512; + int rectHeight = 512; + // 重叠区域大小 + int overlap = 50; + + // 计算步长 + int stepX = rectWidth - overlap; + int stepY = rectHeight - overlap; + + int x_start = searchroi.x; + int x_end = searchroi.x + searchroi.width; + int y_start = searchroi.y; + int y_end = searchroi.y + searchroi.height; + if (searchroi.width < 512) + { + int cx = searchroi.x + searchroi.width * 0.5; + x_start = cx - rectWidth * 0.5; + x_end = x_start + rectWidth; + } + if (searchroi.height < 512) + { + int cy = searchroi.y + searchroi.height * 0.5; + y_start = cy - rectHeight * 0.5; + y_end = y_start + rectHeight; + } + + if (x_start < 0) + { + x_start = 0; + } + if (y_start < 0) + { + y_start = 0; + } + if (y_start + searchroi.height > img.rows) + { + y_start = img.rows - searchroi.height; + } + if (x_start + searchroi.width > img.cols) + { + x_start = img.cols - searchroi.width; + } + + if (y_end > img.rows) + { + y_end = img.rows; + } + if (x_end > img.cols) + { + x_end = img.cols; + } + + // cv::Mat showImg; + + // if (true) + // { + // cv::cvtColor(detSrcImg, showImg, cv::COLOR_GRAY2BGR); + // } + + int cut_y_s = y_start; + int cut_y_e = cut_y_s + rectHeight; + int cut_x_s = x_start; + int cut_x_e = cut_x_s + rectWidth; + + bool bb_y = false; + bool bb_x = false; + + int w = x_end - x_start; + int h = y_end - y_start; + if (w < 512) + { + if (x_start == 0) + { + x_end = x_start + 512; + if (x_end > img.cols) + { + return 1; + } + } + else + { + x_start = x_end - 512; + if (x_start < 0) + { + return 1; + } + } + } + + if (h < 512) + { + if (y_start == 0) + { + y_end = y_start + 512; + if (y_end > img.rows) + { + return 1; + } + } + else + { + y_start = y_end - 512; + if (y_start < 0) + { + return 1; + } + } + } + + w = x_end - x_start; + h = y_end - y_start; + if (w < rectWidth) + { + return 1; + } + if (h < rectHeight) + { + return 1; + } + + cv::Rect allroi(x_start, y_start, w, h); + cv::Mat allmask = cv::Mat(h, w, CV_8UC1, cv::Scalar(0)); + + // printf("y_start %d y_end %d\n", y_start, y_end); + // printf("x_start %d x_end %d\n", x_start, x_end); + + static int ki = 0; + // + for (int y = y_start; y < y_end; y += stepY) + { + cut_y_s = y; + cut_y_e = cut_y_s + rectHeight; + if (cut_y_e > y_end) + { + cut_y_e = y_end; + cut_y_s = y_end - rectHeight; + bb_y = true; + } + bb_x = false; + for (int x = x_start; x < x_end; x += stepX) + { + cut_x_s = x; + cut_x_e = cut_x_s + rectWidth; + if (cut_x_e > x_end) + { + cut_x_e = x_end; + cut_x_s = x_end - rectWidth; + bb_x = true; + } + + // 定义小矩形 + cv::Rect smallRect(cut_x_s, cut_y_s, rectWidth, rectHeight); + cv::Rect maskrect = smallRect; + maskrect.x -= x_start; + maskrect.y -= y_start; + + if (!CheckUtil::RoiInImg(smallRect, img)) + { + // printf("img %d %d= \n", img.cols, img.rows); + // CheckUtil::printROI(smallRect, "smallRect"); + continue; + } + cv::Mat outmask; + + cv::Mat temdet = img(smallRect).clone(); + + if (m_bModelSucc) + { + int re = m_pAIDeal->AICheck_MarkLine(temdet, outmask); + + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "AI Model POL"); + // 推理是否成功 + if (re != 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Mark_Det ", "Error POL AI Model Error"); + continue; + } + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Mark_Det ", "Error POL AI Model Error"); + continue; + } + if (outmask.empty()) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Mark_Det ", "Error POL AI Error"); + continue; + } + // printf("AI_Mark_Det::Detect ========3333============ \n"); + + // printf("img %d %d= \n", allmask.cols, allmask.rows); + // CheckUtil::printROI(maskrect, "maskrect---"); + outmask.copyTo(allmask(maskrect), outmask); + + if (pDetConfig->bsaveprocessimg) + { + std::string str12 = "/home/aidlux/BOE/MarkLine/" + std::to_string(pDetConfig->ncamID) + "_" + std::to_string(ki) + "_in.png"; + std::string strmask = "/home/aidlux/BOE/MarkLine/" + std::to_string(pDetConfig->ncamID) + "_" + std::to_string(ki) + "_in_mask.png"; + ki++; + if (ki > 999999) + { + ki = 0; + } + cv::imwrite(str12, img(smallRect)); + cv::imwrite(strmask, outmask); + } + + if (bb_x) + { + break; + /* code */ + } + } + if (bb_y) + { + break; + } + } + + bool bf = false; + cv::Rect markroi = CheckUtil::getLargestContourROI(allmask, bf); + + if (bf) + { + pDetConfig->nresult = 0; + pDetConfig->markRoi = markroi; + + if (pDetConfig->bsaveprocessimg) + { + std::string str12 = "/home/aidlux/BOE/MarkLine/Check_big_" + std::to_string(pDetConfig->ncamID) + "_in.png"; + std::string strmask = "/home/aidlux/BOE/MarkLine/Check_big_" + std::to_string(pDetConfig->ncamID) + "_in_mask.png"; + // CheckUtil::printROI(allroi, "allroi"); + // printf("-------------------1111 33 img %d %d\n", img.cols, img.rows); + cv::Mat detimg = img(allroi).clone(); + // printf("-------------------1111 33 \n"); + cv::rectangle(detimg, pDetConfig->markRoi, cv::Scalar(180), 3); + // printf("-------------------1111 444\n"); + cv::imwrite(str12, detimg); + cv::imwrite(strmask, allmask); + } + + pDetConfig->markRoi.x += x_start; + pDetConfig->markRoi.y += y_start; + } + else + { + } + + return 0; +} + +int AI_Mark_Det::InitModel() +{ + AIInitConfig config_nf; + config_nf.nGpuIdx = m_pOtherDet_Config->nDeviceId; + config_nf.engine_file_path = str_AI_Mark_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = str_AI_Mark_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = "0"; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = str_AI_Mark_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = "0"; + + return m_pAIDeal->Init_MarkLine(config_nf); +} + +cv::Rect AI_Mark_Det::GetCutRoi(cv::Rect &roi, const cv::Mat &img) +{ + int Dst_Width = str_AI_RE_AD_IN_0_IMAGE_WIDTH; + int Dst_Height = str_AI_RE_AD_IN_0_IMAGE_HEIGHT; + cv::Rect cutroi = cv::Rect(0, 0, 0, 0); + if (Dst_Width >= img.cols || Dst_Height >= img.rows) + { + return cutroi; + } + if (roi.width >= Dst_Width || roi.height >= Dst_Height) + { + return cutroi; + } + + int centerX = roi.x + roi.width / 2; + int centerY = roi.y + roi.height / 2; + + // 构造一个以中心为中心的 128x128 矩形 + int halfSize = Dst_Width / 2; // 128 / 2 + int newX = centerX - halfSize; + int newY = centerY - halfSize; + int newWidth = Dst_Width; + int newHeight = Dst_Height; + + // 检查矩形是否越界 + if (newX < 0) + { + newX = 0; + } + if (newY < 0) + { + newY = 0; + } + if (newX + newWidth > img.cols) + { + newX = img.cols - newWidth; + } + if (newY + newHeight > img.rows) + { + newY = img.rows - newHeight; + } + + // 创建新的矩形 + cv::Rect newRect(newX, newY, newWidth, newHeight); + int add = 3; + // 重新计算 roi 在新的矩形中的位置 + int newRoiX = roi.x - newRect.x - add; + int newRoiY = roi.y - newRect.y - add; + int newRoiWidth = roi.width + 2 * add; + int newRoiHeight = roi.height + 2 * add; + + // 确保新的 roi 在新的矩形内 + if (newRoiX < 0) + { + newRoiX = 0; + } + if (newRoiY < 0) + { + newRoiY = 0; + } + if (newRoiX + newRoiWidth > newRect.width) + { + newRoiWidth = newRect.width - newRoiX; + } + if (newRoiY + newRoiHeight > newRect.height) + { + newRoiHeight = newRect.height - newRoiY; + } + + // 更新 roi + roi = cv::Rect(newRoiX, newRoiY, newRoiWidth, newRoiHeight); + + // 返回新的矩形 + return newRect; +} +int AI_Mark_Det::Det_img(const cv::Mat &img, DetConfigResult *pDetConfig) +{ + + return 0; +} + +int AI_Mark_Det::Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig) +{ + + return 0; +} + +int AI_Mark_Det::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig) +{ + + // if (inImg.empty() || outImg.empty()) + // { + // return 1; + // } + // static int saveimgIdx_pol = 0; + // static int saveimgIdx_ad = 0; + // // 循环存储 + + // std::string str_Root = "/home/aidlux/BOE/Second/"; + // if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) + // { + + // saveimgIdx_pol++; + // if (saveimgIdx_pol > 1000) + // { + // saveimgIdx_pol = 0; + // } + // str_Root += "POL/POl_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_pol); + // } + // if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + // { + + // saveimgIdx_ad++; + // if (saveimgIdx_ad > 1000) + // { + // saveimgIdx_ad = 0; + // } + // str_Root += "AD/AD_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_ad); + // } + // std::string strIn = str_Root + +"_in.png"; + // int re = 0; + // if (!inImg.empty()) + // { + // re = m_pImageStorage->addImage(strIn, inImg); + // } + + // if (re == 0) + // { + // std::string strmask = str_Root + "_in_mask.png"; + // if (!outImg.empty()) + // { + // m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储 + // } + + // std::string stroldmask = str_Root + "_old_mask.png"; + // if (!oldmask.empty()) + // { + // m_pImageStorage->addImage(stroldmask, oldmask, true); // 强制 存储 + // } + // } + + return 0; +} diff --git a/AlgorithmModule/src/AI_Second_Det.cpp b/AlgorithmModule/src/AI_Second_Det.cpp new file mode 100644 index 0000000..5941be8 --- /dev/null +++ b/AlgorithmModule/src/AI_Second_Det.cpp @@ -0,0 +1,649 @@ + +#include "AI_Edge_Algin.h" +#include "CheckErrorCodeDefine.hpp" +#include "AI_Second_Det.h" + +AI_SecondDet::AI_SecondDet() +{ + m_bModelSucc_AD = false; + m_bModelSucc_POL = false; + CheckUtil::CreateDir("/home/aidlux/BOE/Second/POL/"); + CheckUtil::CreateDir("/home/aidlux/BOE/Second/AD/"); + m_pImageStorage = ImageStorage::getInstance(); + m_Show_Area = 0; + m_Show_Len = 0; + m_Len_P1 = cv::Point(0, 0); + m_Len_P2 = cv::Point(0, 0); +} + +AI_SecondDet::~AI_SecondDet() +{ +} +int AI_SecondDet::InitModel_ALL() +{ + if (!m_bInitialized) + { + printf("Initialized error \n"); + + return 1; + } + m_bModelSucc_AD = false; + m_bModelSucc_POL = false; + int re = 0; + re = InitModel_Re_POL(); + if (re != 0) + { + printf("InitModel_Re_POL error \n"); + m_bModelSucc_POL = false; + } + else + { + m_bModelSucc_POL = true; + } + re = InitModel_Re_AD(); + if (re != 0) + { + printf("InitModel_Re_AD error \n"); + m_bModelSucc_AD = false; + } + else + { + m_bModelSucc_AD = true; + } + + return 0; +} +int AI_SecondDet::Detect(const cv::Mat &img, const cv::Mat &mask, DetConfigResult *pDetConfig) +{ + // 二次求面积长度 功能关闭 + if (!pDetConfig->pfunction_secondDet->bOpen) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "function colse"); + return 1; + } + // cv::Mat temimg = mask.clone(); + // cv::rectangle(temimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); + cv::Rect AIroi = GetCutRoi(pDetConfig->qx_roi, img); + + if (AIroi.width <= 0 || AIroi.height <= 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error Size"); + return 1; + } + if (!CheckUtil::RoiInImg(AIroi, img)) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error ROI"); + return 1; + } + float min_set_param_area = 0; + float max_set_param_area = 9999; + if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) + { + min_set_param_area = pDetConfig->pfunction_secondDet->pol_area_min; + max_set_param_area = pDetConfig->pfunction_secondDet->pol_area_max; + } + if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + { + min_set_param_area = pDetConfig->pfunction_secondDet->andian_area_min; + max_set_param_area = pDetConfig->pfunction_secondDet->andian_area_max; + } + float oldarea_mm2 = pDetConfig->old_Area * pDetConfig->fImgage_Scale_X * pDetConfig->fImgage_Scale_Y; + if (oldarea_mm2 < min_set_param_area || oldarea_mm2 > max_set_param_area) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "error Area %0.2f out[%0.2f %0.2f] ", oldarea_mm2, min_set_param_area, max_set_param_area); + return 1; + } + if (oldarea_mm2 < pDetConfig->min_DetArea) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Error Area %0.2f < det param %0.2f ", oldarea_mm2, pDetConfig->min_DetArea); + return 1; + } + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "succ Area %0.2f >= min det param %0.2f and in [%0.2f %0.2f] ", oldarea_mm2, pDetConfig->min_DetArea, min_set_param_area, max_set_param_area); + } + + cv::Mat detimg = img(AIroi).clone(); + + cv::Mat outimg; + int re12 = 0; + // + if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) + { + if (pDetConfig->pfunction_secondDet->pol_saveProcessImg) + { + detimg123 = mask(AIroi).clone(); + } + + re12 = Det_Pol(detimg, pDetConfig); + } + if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + { + if (pDetConfig->pfunction_secondDet->andian_saveProcessImg) + { + detimg123 = mask(AIroi).clone(); + } + re12 = Det_AD(detimg, pDetConfig); + } + if (re12 != 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE_POL /AD", "Error "); + return 1; + } + return 0; +} + +int AI_SecondDet::InitModel_Re_POL() +{ + AIInitConfig config_nf; + config_nf.nGpuIdx = m_pOtherDet_Config->nDeviceId; + config_nf.engine_file_path = str_AI_RE_POL_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = str_AI_RE_POL_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = str_AI_RE_POL_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = str_AI_RE_POL_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = str_AI_RE_POL_out_0_IMAGE_Name; + + return m_pAIDeal->Init_RE_POL(config_nf); +} +int AI_SecondDet::InitModel_Re_AD() +{ + AIInitConfig config_nf; + config_nf.nGpuIdx = m_pOtherDet_Config->nDeviceId; + config_nf.engine_file_path = str_AI_RE_AD_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = str_AI_RE_AD_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = str_AI_RE_POL_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = str_AI_RE_AD_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = str_AI_RE_POL_out_0_IMAGE_Name; + + return m_pAIDeal->Init_RE_AD(config_nf); +} + +cv::Rect AI_SecondDet::GetCutRoi(cv::Rect &roi, const cv::Mat &img) +{ + int Dst_Width = str_AI_RE_AD_IN_0_IMAGE_WIDTH; + int Dst_Height = str_AI_RE_AD_IN_0_IMAGE_HEIGHT; + cv::Rect cutroi = cv::Rect(0, 0, 0, 0); + if (Dst_Width >= img.cols || Dst_Height >= img.rows) + { + return cutroi; + } + if (roi.width >= Dst_Width || roi.height >= Dst_Height) + { + return cutroi; + } + + int centerX = roi.x + roi.width / 2; + int centerY = roi.y + roi.height / 2; + + // 构造一个以中心为中心的 128x128 矩形 + int halfSize = Dst_Width / 2; // 128 / 2 + int newX = centerX - halfSize; + int newY = centerY - halfSize; + int newWidth = Dst_Width; + int newHeight = Dst_Height; + + // 检查矩形是否越界 + if (newX < 0) + { + newX = 0; + } + if (newY < 0) + { + newY = 0; + } + if (newX + newWidth > img.cols) + { + newX = img.cols - newWidth; + } + if (newY + newHeight > img.rows) + { + newY = img.rows - newHeight; + } + + // 创建新的矩形 + cv::Rect newRect(newX, newY, newWidth, newHeight); + int add = 3; + // 重新计算 roi 在新的矩形中的位置 + int newRoiX = roi.x - newRect.x - add; + int newRoiY = roi.y - newRect.y - add; + int newRoiWidth = roi.width + 2 * add; + int newRoiHeight = roi.height + 2 * add; + + // 确保新的 roi 在新的矩形内 + if (newRoiX < 0) + { + newRoiX = 0; + } + if (newRoiY < 0) + { + newRoiY = 0; + } + if (newRoiX + newRoiWidth > newRect.width) + { + newRoiWidth = newRect.width - newRoiX; + } + if (newRoiY + newRoiHeight > newRect.height) + { + newRoiHeight = newRect.height - newRoiY; + } + + // 更新 roi + roi = cv::Rect(newRoiX, newRoiY, newRoiWidth, newRoiHeight); + + // 返回新的矩形 + return newRect; +} +int AI_SecondDet::Det_Pol(const cv::Mat &img, DetConfigResult *pDetConfig) +{ + int re = 0; + cv::Mat outimg; + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " POL start"); + // 如果 有面积或长度功能 开启,就进行推理 + // if (pDetConfig->pfunction_secondDet->pol_Open_len || pDetConfig->pfunction_secondDet->pol_Open_area) + { + // 模型初始化是否成功 + if (m_bModelSucc_POL) + { + re = m_pAIDeal->AICheck_RE_POL(img, outimg); + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "AI Model POL"); + // 推理是否成功 + if (re != 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Model Error"); + return 1; + } + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Model Error"); + return 1; + } + } + // else + // { + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "POL Param Close "); + // return 1; + // } + + if (outimg.empty()) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error POL AI Error"); + return 1; + } + cv::Mat AnalysisyImg = outimg(pDetConfig->qx_roi).clone(); + m_Show_Area = pDetConfig->old_Area; + m_Show_Len = pDetConfig->old_len; + // 开始分析mask; + re = Analysisy(AnalysisyImg, pDetConfig); + m_Len_P1.x += pDetConfig->qx_roi.x; + m_Len_P1.y += pDetConfig->qx_roi.y; + + m_Len_P2.x += pDetConfig->qx_roi.x; + m_Len_P2.y += pDetConfig->qx_roi.y; + + // 存储中间过程图片 + if (pDetConfig->pfunction_secondDet->pol_saveProcessImg) + { + if (true) + { + cv::rectangle(outimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); + cv::rectangle(detimg123, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); + + cv::line(outimg, m_Len_P1, m_Len_P2, cv::Scalar(128, 0, 0)); + + { + char buffer[128]; + sprintf(buffer, " oA %d -> nA %d ", + pDetConfig->old_Area, m_Show_Area); + std::string st1 = buffer; + cv::Point p(0, 10); + cv::putText(outimg, st1, p, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); + + sprintf(buffer, " oL %0.2f -> nL %0.2f ", + pDetConfig->old_len, m_Show_Len); + st1 = buffer; + cv::Point p2(0, 20); + cv::putText(outimg, st1, p2, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); + } + } + SaveProcessImg(img, outimg, detimg123, pDetConfig); + } + + return re; +} + +int AI_SecondDet::Det_AD(const cv::Mat &img, DetConfigResult *pDetConfig) +{ + + int re = 0; + cv::Mat outimg; + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " AD start"); + // 如果 有面积或长度功能 开启,就进行推理 + // if (pDetConfig->pfunction_secondDet->andian_Open_len || pDetConfig->pfunction_secondDet->andian_Open_area) + { + // 模型初始化是否成功 + if (m_bModelSucc_AD) + { + re = m_pAIDeal->AICheck_RE_AD(img, outimg); + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "AI Model AD"); + // 推理是否成功 + if (re != 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Model Error"); + return 1; + } + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Model Error"); + return 1; + } + } + // else + // { + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "AD Param Close "); + // return 1; + // } + + if (outimg.empty()) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE ", "Error AD AI Error"); + return 1; + } + if (!CheckUtil::RoiInImg(pDetConfig->qx_roi, outimg)) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "qx roi Error"); + return 1; + } + cv::Mat AnalysisyImg = outimg(pDetConfig->qx_roi).clone(); + + m_Show_Area = pDetConfig->old_Area; + m_Show_Len = pDetConfig->old_len; + // 开始分析mask; + re = Analysisy(AnalysisyImg, pDetConfig); + + m_Len_P1.x += pDetConfig->qx_roi.x; + m_Len_P1.y += pDetConfig->qx_roi.y; + + m_Len_P2.x += pDetConfig->qx_roi.x; + m_Len_P2.y += pDetConfig->qx_roi.y; + + if (pDetConfig->pfunction_secondDet->andian_saveProcessImg) + { + if (true) + { + cv::rectangle(outimg, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); + cv::rectangle(detimg123, pDetConfig->qx_roi, cv::Scalar(128, 0, 0)); + cv::line(outimg, m_Len_P1, m_Len_P2, cv::Scalar(128, 0, 0)); + { + char buffer[128]; + sprintf(buffer, " oA %d -> nA %d ", + pDetConfig->old_Area, m_Show_Area); + std::string st1 = buffer; + cv::Point p(0, 10); + cv::putText(outimg, st1, p, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); + + sprintf(buffer, " oL %0.2f -> nL %0.2f ", + pDetConfig->old_len, m_Show_Len); + st1 = buffer; + cv::Point p2(0, 20); + cv::putText(outimg, st1, p2, cv::FONT_HERSHEY_SIMPLEX, 0.35, cv::Scalar(200, 0, 255), 0.35, 1, 0); + } + } + + SaveProcessImg(img, outimg, detimg123, pDetConfig); + } + + return re; +} + +int AI_SecondDet::Analysisy(const cv::Mat &maskImg, DetConfigResult *pDetConfig) +{ + // 存储轮廓 + std::vector> contours; + // 存储每个轮廓的层级 + std::vector hierarchy; + + // 寻找轮廓 + cv::findContours(maskImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + double maxArea = 0; + int maxIndex = -1; + + // 遍历每个轮廓,计算面积并找出最大的面积 + for (size_t i = 0; i < contours.size(); i++) + { + double area = cv::contourArea(contours[i]); + if (area > maxArea) + { + maxArea = area; + maxIndex = i; + } + } + if (maxIndex < 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "second mask is error"); + return 1; + /* code */ + } + bool barea = false; + bool blen = false; + int oldArea = pDetConfig->old_Area; + float oldLen = pDetConfig->old_len; + if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) + { + barea = pDetConfig->pfunction_secondDet->pol_Open_area; + blen = pDetConfig->pfunction_secondDet->pol_Open_len; + } + if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + { + barea = pDetConfig->pfunction_secondDet->andian_Open_area; + blen = pDetConfig->pfunction_secondDet->andian_Open_len; + } + // 计算面积 + // if (barea) + { + int maxContourPixelCount = 0; + if (maxIndex >= 0) + { + cv::Mat mask = cv::Mat::zeros(maskImg.size(), CV_8UC1); + cv::drawContours(mask, contours, maxIndex, cv::Scalar(255), cv::FILLED); // 绘制轮廓填充区域 + maxContourPixelCount = cv::countNonZero(mask); // 计算填充区域的像素个数 + } + m_Show_Area = maxContourPixelCount; + + if (barea) + { + if (maxContourPixelCount > 0 && maxContourPixelCount < oldArea) + { + pDetConfig->new_Area = maxContourPixelCount; + } + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Use New Area :old area %d (pixel) new %d", oldArea, pDetConfig->new_Area); + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", " Not Use Area :old area %d (pixel) new %d", oldArea, maxContourPixelCount); + } + } + // else + // { + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Area", "Cal Area is Close"); + // } + + // 计算长度 + // if (blen) + { + cv::RotatedRect rect = cv::minAreaRect(contours[maxIndex]); + + // 获取最小外接矩形的尺寸 + float width = rect.size.width; + float height = rect.size.height; + + Point2f vertices[4]; + rect.points(vertices); + + if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + { + float len1 = sqrt((vertices[0].x - vertices[1].x) * (vertices[0].x - vertices[1].x) + + (vertices[0].y - vertices[1].y) * (vertices[0].y - vertices[1].y)); + + float len2 = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) + + (vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y)); + + if (len1 > len2) + { + m_Len_P1.x = vertices[0].x; + m_Len_P1.y = vertices[0].y; + + m_Len_P2.x = vertices[1].x; + m_Len_P2.y = vertices[1].y; + } + else + { + m_Len_P1.x = vertices[2].x; + m_Len_P1.y = vertices[2].y; + + m_Len_P2.x = vertices[1].x; + m_Len_P2.y = vertices[1].y; + } + } + else + { + m_Len_P1.x = vertices[2].x; + m_Len_P1.y = vertices[2].y; + + m_Len_P2.x = vertices[0].x; + m_Len_P2.y = vertices[0].y; + } + + vector newcont; + for (int i = 0; i < 4; ++i) + { + Point2f p; + p.x = vertices[i].x * pDetConfig->fImgage_Scale_X; + p.y = vertices[i].y * pDetConfig->fImgage_Scale_Y; + newcont.push_back(p); + } + vector> contours_New; + contours_New.push_back(newcont); + // Recreate the rotated rectangle with scaled vertices + RotatedRect scaledRect = minAreaRect(contours_New[0]); + + // Calculate scaled width and height + width = scaledRect.size.width; + height = scaledRect.size.height; + float new_len = width; + if (width > 0 && height > 0) + { + if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + { + if (width > height) + { + new_len = width; + } + else + { + new_len = height; + } + } + else + { + new_len = sqrt(width * width + height * height); + } + } + else + { + if (width > height) + { + new_len = width; + } + else + { + new_len = height; + } + } + + // printf("oldLen %f new_len %f \n", oldLen, new_len); + m_Show_Len = new_len; + if (blen) + { + if (new_len > 0 && new_len < oldLen) + { + pDetConfig->new_len = new_len; + } + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", "Use New Len :old Len %f (mm) new %f", oldLen, pDetConfig->new_len); + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", " Not Use Len :old Len %f (mm) new %f", oldLen, new_len); + } + } + // else + // { + // m_pTemCheck->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AICheck_RE Len", "Cal Len is Close"); + // } + + return 0; +} + +int AI_SecondDet::SaveProcessImg(const cv::Mat &inImg, const cv::Mat &outImg, const cv::Mat &oldmask, DetConfigResult *pDetConfig) +{ + + if (inImg.empty() || outImg.empty()) + { + return 1; + } + static int saveimgIdx_pol = 0; + static int saveimgIdx_ad = 0; + // 循环存储 + + std::string str_Root = "/home/aidlux/BOE/Second/"; + if (pDetConfig->qx_type == CONFIG_QX_NAME_POL_Cell) + { + + saveimgIdx_pol++; + if (saveimgIdx_pol > 1000) + { + saveimgIdx_pol = 0; + } + str_Root += "POL/POl_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_pol); + } + if (pDetConfig->qx_type == CONFIG_QX_NAME_AD) + { + + saveimgIdx_ad++; + if (saveimgIdx_ad > 1000) + { + saveimgIdx_ad = 0; + } + str_Root += "AD/AD_" + pDetConfig->strChannel + "_" + std::to_string(saveimgIdx_ad); + } + std::string strIn = str_Root + +"_in.png"; + int re = 0; + if (!inImg.empty()) + { + re = m_pImageStorage->addImage(strIn, inImg); + } + + if (re == 0) + { + std::string strmask = str_Root + "_in_mask.png"; + if (!outImg.empty()) + { + m_pImageStorage->addImage(strmask, outImg, true); // 强制 存储 + } + + std::string stroldmask = str_Root + "_old_mask.png"; + if (!oldmask.empty()) + { + m_pImageStorage->addImage(stroldmask, oldmask, true); // 强制 存储 + } + } + + return 0; +} diff --git a/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp b/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp new file mode 100644 index 0000000..d9e4277 --- /dev/null +++ b/AlgorithmModule/src/ALLImgCheckAnalysisy.cpp @@ -0,0 +1,1870 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2025-07-26 11:32:42 + * @LastEditors: xiewenji 527774126@qq.com + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ALLImgCheckAnalysisy.hpp" +#include "CheckUtil.hpp" +#include "Define.h" +#include "QX_Analysis.h" + +double calculateDistanceBetweenRectCenters(const cv::Rect &rect1, const cv::Rect &rect2, float fx, float fy) +{ + // 计算矩形1的中心点 + cv::Point center1(rect1.x + rect1.width / 2, rect1.y + rect1.height / 2); + + // 计算矩形2的中心点 + cv::Point center2(rect2.x + rect2.width / 2, rect2.y + rect2.height / 2); + center1.x *= fx; + center1.y *= fy; + + center2.x *= fx; + center2.y *= fy; + + // 计算中心点之间的欧几里得距离 + double distance = cv::norm(center1 - center2); + + return distance; +} + +ALLImgCheckAnalysisy::ALLImgCheckAnalysisy() +{ + + m_strTest = ""; + m_pChannelFuntion = &m_AnalysisyConfig.checkFunction; + m_CurProductIdx = 0; + m_reJsonStatus_push = ReJson_Status_Idel; + m_reJsonStatus_Det = ReJson_Status_Idel; + + m_ProductImgDetResult_New = nullptr; + for (int i = 0; i < MAX_Camera_NUM; i++) + { + m_pCameraCheckAnalysisy[i] = nullptr; + } +} + +ALLImgCheckAnalysisy::~ALLImgCheckAnalysisy() +{ + StopThread(); + for (int i = 0; i < MAX_Camera_NUM; i++) + { + if (m_pCameraCheckAnalysisy[i]) + { + delete m_pCameraCheckAnalysisy[i]; + } + } +} + +int ALLImgCheckAnalysisy::RunStart(void *pconfig1) +{ + VERSION_INFO *pVersionconfig = (VERSION_INFO *)pconfig1; + if (pVersionconfig == NULL) + { + printf("**************************** \n"); + m_nErrorCode = CHECK_ERROR_VERSION; // 参数或接口版本问题 + return m_nErrorCode; + } + + int v1 = ALL_INTERFACE_VERSION; + int v2 = CONFIGBASE_VERSION; + int v3 = RESULT_VERSION; + printf("**************************** ALL_INTERFACE_VERSION so: %d in:%d CONFIGBASE_VERSION so:%d in:%d RESULT_VERSION so:%d in:%d\n", + v1, pVersionconfig->InterfaceVersion, v2, pVersionconfig->ConfigVersion, v3, pVersionconfig->ResultVersion); + // 版本控制 + if (pVersionconfig->InterfaceVersion != ALL_INTERFACE_VERSION || + pVersionconfig->ConfigVersion != CONFIGBASE_VERSION || + pVersionconfig->ResultVersion != RESULT_VERSION) + { + m_nErrorCode = CHECK_ERROR_VERSION; // 参数或接口版本问题 + return m_nErrorCode; + } + printf("**************************** bRetest %d \n", m_RunConfig.bRetest); + if (IMGCHECKANALYSISY_NUM * 2 + 2 > m_RunConfig.nCpu_num && m_RunConfig.flag2 != 1) + { + printf("*************CPU num error config %d < %d*************** \n", m_RunConfig.nCpu_num, IMGCHECKANALYSISY_NUM * 2 + 2); + m_nErrorCode = CHECK_ERROR_Config_Value; // 参数或接口版本问题 + return m_nErrorCode; + } + + int re = InitCameraCheckAnalysisy(); + if (re != 0) + { + printf("*************InitCameraCheckAnalysisy error %d*************** \n", re); + m_nErrorCode = INIT_CameraCheck_Error; + return m_nErrorCode; + } + + re = InitRun(); + if (CHECK_OK != re) + { + m_nErrorCode = re; + return m_nErrorCode; + } + + // 更新参数 + SetNewConfig(); + + m_nErrorCode = CHECK_OK; + printf(">>>> ALLImgCheckAnalysisy Start Succ \n"); + DetImgInfo_shareP = std::make_shared(); + m_nErrorCode = CHECK_OK; + + return m_nErrorCode; +} + +int ALLImgCheckAnalysisy::SetDataRun_SharePtr(std::shared_ptr p) +{ + + int re = PushInImg_New(p); + + // printf("SetDataRun_SharePtr======================= re %d \n", re); + + return re; +} + +int ALLImgCheckAnalysisy::GetCheckReuslt(std::shared_ptr &pResult) +{ + std::unique_lock lk(mtx_CheckResult); // 使用 unique_lock + CheckResult_cond.wait(lk, [this] + { return !m_CheckResultList.empty(); }); // 等待直到数据队列非空 + pResult = m_CheckResultList.front(); // 从队列中取出数据 + m_CheckResultList.pop(); + lk.unlock(); + return 0; +} + +int ALLImgCheckAnalysisy::CheckImg(std::shared_ptr p, std::shared_ptr &pResult) +{ + + std::lock_guard lock(mtx_DetSingle); + p->Status = IN_IMG_Status_OneImg; + m_PrintLog.printstr(Print_Level_Info, "CheckImg", "start"); + + PushInImg_New(p); + + // 等待检测结果 + GetCheckReuslt(pResult); + + m_PrintLog.printstr(Print_Level_Info, "CheckImg", "End"); + + return 0; +} + +int ALLImgCheckAnalysisy::GetStatus() +{ + return 0; +} + +int ALLImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType) +{ + int re = 0; + RunInfoST *tempconfig; + switch (nConfigType) + { + case CHECK_CONFIG_Run: + tempconfig = (RunInfoST *)pconfig; + m_RunConfig.copy(*tempconfig); + break; + case CHECK_CONFIG_Module: + m_pConfig = (ConfigBase *)pconfig; + break; + case CHECK_CONFIG_Module_Cam2: + m_pConfig_Cam2 = (ConfigBase *)pconfig; + break; + default: + break; + } + + return 0; +} + +std::string ALLImgCheckAnalysisy::GetVersion() +{ + return std::string("BOE_2.0.5"); +} + +std::string ALLImgCheckAnalysisy::GetErrorInfo() +{ + std::string result = ""; + + return result; +} + +int ALLImgCheckAnalysisy::ErrorReturn(std::shared_ptr p) +{ + + std::shared_ptr result = std::make_shared(); + result->in_shareImage = p; + result->checkStatus = 1; + result->nresult = -CHECK_ERROR_PushImg_ID_Error; + result->basicResult.img_id = p->img_id; + result->basicResult.imgtype = p->imgtype; + result->basicResult.imgstr = p->imgstr; + result->basicResult.strChannel = p->strChannel; + // printf("ErrorReturn==== %s %s\n", p->strImgProductID.c_str(), p->strChannel.c_str()); + { + std::lock_guard lock(mtx_CheckResult); + m_CheckResultList.push(result); + } + CheckResult_cond.notify_all(); + + return 0; +} + +float ALLImgCheckAnalysisy::CalImgScorl(cv::Mat det_img, cv::Mat up_img) +{ + float fs = 0; + + unsigned char *det_img_data = (unsigned char *)det_img.data; + unsigned char *up_img_data = (unsigned char *)up_img.data; + int w = det_img.cols; + int h = det_img.rows; + int pitch = w; + int offset = 0; + int sum_jc = 0; // 交集 都有的 + int sum_bj = 0; // 并集 有一个有的 + int sum_up = 0; + int sum_det = 0; + for (int y = 0; y < h; y++) + { + offset = y * pitch - 1; + int kh = 0; + for (int x = 0; x < w; x++) + { + + if (det_img_data[offset] != 0 && up_img_data[offset] != 0) + { + sum_jc++; + sum_bj++; + sum_up++; + sum_det++; + } + else if (det_img_data[offset] != 0 || up_img_data[offset] != 0) + { + sum_bj++; + if (det_img_data[offset] != 0) + { + sum_det++; + } + if (up_img_data[offset] != 0) + { + sum_up++; + } + } + offset++; + } + } + if (sum_bj != 0) + { + fs = sum_jc * 1.0f / sum_bj; + } + if (sum_up > sum_det * 1.1) + { + fs = 0; + } + + return fs; +} + +int ALLImgCheckAnalysisy::AddStrToLog(int productIdx, std::string str) +{ + + m_ProductImgDetResult_New->LogList.push_back(str); + return 0; +} + +int ALLImgCheckAnalysisy::AddStrToLog_New(std::string str) +{ + if (m_ProductImgDetResult_New) + { + m_ProductImgDetResult_New->AddLog(str); + } + + return 0; +} + +int ALLImgCheckAnalysisy::SetNewConfig() +{ + if (m_pConfig == NULL) + { + return 1; + } + + if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, MAX_USER_COUNT - 1)) + { + m_pConfig->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig); + printf("*******ALLImgCheckAnalysisy m_pConfig*********************** Update GetConfig \n"); + // m_AnalysisyConfig.checkFunction.print("Update GetConfig"); + } + + if (m_pConfig_Cam2 == NULL) + { + return 1; + } + + if (m_pConfig_Cam2->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, MAX_USER_COUNT - 1)) + { + m_pConfig_Cam2->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig); + printf("**************ALLImgCheckAnalysisy m_pConfig_Cam2**************** Update GetConfig \n"); + // m_AnalysisyConfig.checkFunction.print("Update GetConfig"); + } + return 0; +} + +ChannelCheckFunction *ALLImgCheckAnalysisy::GetChannelFuntion(std::string strChannelName) +{ + ChannelCheckFunction *p = NULL; + for (int i = 0; i < m_pChannelFuntion->channelFunctionArr.size(); i++) + { + if (CheckUtil::compareIgnoreCase(m_pChannelFuntion->channelFunctionArr[i].strChannelName, strChannelName)) + { + p = &m_pChannelFuntion->channelFunctionArr[i]; + } + } + + return p; +} + +int ALLImgCheckAnalysisy::LoadRunConfig(void *p) +{ + return 0; +} + +int ALLImgCheckAnalysisy::LoadCheckConfig(void *p) +{ + return 0; +} + +int ALLImgCheckAnalysisy::InitRun() +{ + int re; + re = StartThread(); + if (CHECK_OK != re) + { + return re; + } + m_bInitSucc = true; + return 0; +} + +int ALLImgCheckAnalysisy::StartCheck() +{ + return 0; +} + +int ALLImgCheckAnalysisy::SetIDLE() +{ + return 0; +} + +int ALLImgCheckAnalysisy::StartThread() +{ + m_bExit = false; + // 开启检测线程 + ptr_thread_Run = std::make_shared(std::bind(&ALLImgCheckAnalysisy::Run, this)); + return 0; +} + +int ALLImgCheckAnalysisy::StopThread() +{ + m_bExit = true; + if (ptr_thread_Run != nullptr) + { + if (ptr_thread_Run->joinable()) + { + ptr_thread_Run->join(); + } + } + return 0; +} + +int ALLImgCheckAnalysisy::ExitSystem() +{ + return 0; +} + +int ALLImgCheckAnalysisy::InitCameraCheckAnalysisy() +{ + for (int i = 0; i < MAX_Camera_NUM; i++) + { + m_pCameraCheckAnalysisy[i] = new CameraCheckAnalysisy(); + Camera_IDX camidx = static_cast(i); + + m_pCameraCheckAnalysisy[i]->m_RunConfig.copy(m_RunConfig); + if (camidx == Camera_IDX_0) + { + m_pCameraCheckAnalysisy[i]->m_pConfig = m_pConfig; + } + else + { + m_pCameraCheckAnalysisy[i]->m_pConfig = m_pConfig_Cam2; + } + + int re = m_pCameraCheckAnalysisy[i]->Init(camidx); + if (re != 0) + { + printf("InitCameraCheckAnalysisy Fail ==%d\n", re); + return re; + } + } + + return 0; +} + +int ALLImgCheckAnalysisy::SetCameraImgAndStartDet(std::string strcameraName, std::shared_ptr pCamera) +{ + + if (m_pCameraCheckAnalysisy[0]->m_strCameraName == strcameraName) + { + if (m_pCameraCheckAnalysisy[0]) + { + m_pCameraCheckAnalysisy[0]->StartCheck(pCamera); + } + } + else + { + if (m_pCameraCheckAnalysisy[1]) + { + m_pCameraCheckAnalysisy[1]->StartCheck(pCamera); + } + } + return 0; +} + +int ALLImgCheckAnalysisy::InitData() +{ + + return 0; +} + +int ALLImgCheckAnalysisy::Det_Product() +{ + // 产品是否存在 + { + std::lock_guard lock(mtx_ProductImgDetResultList); + + if (!m_ProductImgDetResult_New) + { + return 1; + } + } + printf(">>>>>>>>>>>>>>>Det_Product****************det start************\n"); + + // 处理每个相机 + while (true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + int cameraNum = 0; + { + std::lock_guard lock(mtx_ProductImgDetResultList); + cameraNum = m_ProductImgDetResult_New->cameraCheckResults.size(); + } + // 暂时没有 相机信息。需要等待。 + if (cameraNum == 0) + { + continue; + } + + // 判断每个相机是否都处理完了。 + bool bdetComplete = false; + { + std::lock_guard lock(mtx_ProductImgDetResultList); + // 送图都已经完成 + if (m_ProductImgDetResult_New->bIsImgComplete) + { + cameraNum = m_ProductImgDetResult_New->cameraCheckResults.size(); + bdetComplete = true; + for (int icam = 0; icam < cameraNum; icam++) + { + { + std::lock_guard lock_cam(m_ProductImgDetResult_New->cameraCheckResults[icam]->mtx_Det); + // 每个相机都已经处理完成了。 + if (m_ProductImgDetResult_New->cameraCheckResults[icam]->checkStep != Check_Step_Complete) + { + bdetComplete = false; + } + } + } + } + } + // 处理完成,退出循环 + if (bdetComplete) + { + break; + } + } + // // 更新参数 + SetNewConfig(); + // 联合分析 + AnalysiyAll(0); + SetProductResult(); + printf(">>>>>>>>>>>>>>>Det_Product****************det End************\n"); + + return 0; +} + +int ALLImgCheckAnalysisy::AnalysiyAll(int productIdx) +{ + std::shared_ptr pProduct; + + // 暗点AD联合分析 + if (true) + { + AD_AllChannelAnalysisy_New(); + } + if (true) + { + POL_AllChannelAnalysisy_New(); + } + + return 0; +} + +int ALLImgCheckAnalysisy::AD_AllChannelAnalysisy(int productIdx, std::shared_ptr &pProduct) +{ + std::vector AD_list; + + std::string strlog = ""; + printf(""); + + int product_AD_num = 0; // 整个产品的 暗点数目。 + + int check_s_Num = 0; + int s_param_value = -1; + int s_param_num = 0; + + // 计算 数量分析 + // 通道 + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + ChannelCheckFunction *pFuntion = GetChannelFuntion(pCheckResult->in_shareImage->strChannel); + if (!pFuntion) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", " %s Channel function Error ", + pCheckResult->in_shareImage->strChannel.c_str()); + AddStrToLog(productIdx, strlog); + continue; + } + if (pFuntion && !pFuntion->function.f_AD_Check.bOpen) + { + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "NUM --> %s Param close", + pCheckResult->in_shareImage->strChannel.c_str()); + AddStrToLog(productIdx, strlog); + } + continue; + } + + bool bana_num = false; + bool bana_dis = false; + bool bana_S = false; + if (pFuntion && pFuntion->function.f_AD_Check.analysis_num.bOpen) + { + bana_num = true; + } + if (pFuntion && pFuntion->function.f_AD_Check.analysis_dis.bOpen) + { + bana_dis = true; + } + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.bOpen) + { + bana_S = true; + } + + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "NUM --> %s Param num check %d dis check %d S check %d", + pCheckResult->in_shareImage->strChannel.c_str(), bana_num, bana_dis, bana_S); + AddStrToLog(productIdx, strlog); + } + if (!bana_num && !bana_dis && !bana_S) + { + continue; + } + + // 缺陷 + for (int j = 0; j < pCheckResult->qxImageResult.size(); j++) + { + if (pCheckResult->qxImageResult.at(j).type != ERROR_TYPE_AD) + { + continue; + } + cv::Rect roi = pCheckResult->qxImageResult.at(j).srcImgroi; + // 暗点 list + int list_idx = -1; + int channel_s = 0; + for (int idx = 0; idx < AD_list.size(); idx++) + { + float fiou = CheckUtil::CalIoU(AD_list.at(idx).roi, roi); + if (fiou > 0.15) + { + list_idx = idx; + } + } + // 在list已存在。 + if (list_idx >= 0) + { + AD_list.at(list_idx).num++; + channel_s = AD_list.at(list_idx).num; + } + else + { // 在list不存在。 + AD_Channel_Info_ tem; + tem.roi = roi; + tem.num = 1; + channel_s = 1; + tem.fdis = 99999999999; + AD_list.push_back(tem); + // 如果要参与数量统计 + if (bana_num) + { + product_AD_num++; + } + } + + int s_det_value = 0; + // 当前通道 要参与s标准分析 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.bOpen) + { + s_param_num = pFuntion->function.f_AD_Check.analysis_s.Check_s_Num; + s_param_value = pFuntion->function.f_AD_Check.analysis_s.Check_s_Value; + + if (pCheckResult->qxImageResult.at(j).area >= pFuntion->function.f_AD_Check.S_standard_3s.area && + pCheckResult->qxImageResult.at(j).len >= pFuntion->function.f_AD_Check.S_standard_3s.len) + { + s_det_value = 3; + } + else if (pCheckResult->qxImageResult.at(j).area >= pFuntion->function.f_AD_Check.S_standard_2s.area && + pCheckResult->qxImageResult.at(j).len >= pFuntion->function.f_AD_Check.S_standard_2s.len) + { + s_det_value = 2; + } + else + { + s_det_value = 1; + } + if (s_det_value >= s_param_value) + { + check_s_Num++; + } + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", " --> %s qx name %s roi %d %d %d %d area %f; AD list size %d; analysis Num %d; channel s num = %d;cur S = %ds param :%ds num %d->S sum = %d", + pCheckResult->in_shareImage->strChannel.c_str(), + pCheckResult->qxImageResult.at(j).strTypeName.c_str(), + roi.x, roi.y, roi.width, roi.height, pCheckResult->qxImageResult.at(j).area, + AD_list.size(), product_AD_num, channel_s, s_det_value, s_param_value, s_param_num, check_s_Num); + AddStrToLog(productIdx, strlog); + } + } + float min_dis = 9999999999; + // 求最小距离 + if (true) + { + for (int ad_i = 0; ad_i < AD_list.size(); ad_i++) + { + for (int ad_j = 0; ad_j < AD_list.size(); ad_j++) + { + if (ad_i == ad_j) + { + continue; + } + double dis = calculateDistanceBetweenRectCenters(AD_list.at(ad_i).roi, AD_list.at(ad_j).roi, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_x, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_y); + if (dis < AD_list.at(ad_i).fdis) + { + AD_list.at(ad_i).fdis = dis; + if (dis < min_dis) + { + min_dis = dis; + } + } + } + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "%d dis = %f ;min dis %f ; scale x y = %f %f", + ad_i, AD_list.at(ad_i).fdis, min_dis, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_x, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_y); + AddStrToLog(productIdx, strlog); + } + } + // 统计 2s 总数 + if (s_param_value > 0) + { + int channels = 0; + int oneimgs = check_s_Num; + for (int ad_i = 0; ad_i < AD_list.size(); ad_i++) + { + if (AD_list.at(ad_i).num >= s_param_value) + { + channels++; + check_s_Num++; + } + } + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "cur %ds Num = %d; %ds oneimg s = %d channel s = %d", + s_param_value, check_s_Num, s_param_value, oneimgs, channels); + AddStrToLog(productIdx, strlog); + } + + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + ChannelCheckFunction *pFuntion = GetChannelFuntion(pCheckResult->in_shareImage->strChannel); + bool bNG = false; + if (pFuntion && pFuntion->function.f_AD_Check.analysis_num.bOpen) + { + // 数量分析 + if (product_AD_num >= pFuntion->function.f_AD_Check.analysis_num.numT) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Num Check result NG ,AD num %d >= parm num %d", + pCheckResult->in_shareImage->strChannel.c_str(), product_AD_num, pFuntion->function.f_AD_Check.analysis_num.numT); + AddStrToLog(productIdx, strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Num Check result OK ,AD num %d < parm num %d", + pCheckResult->in_shareImage->strChannel.c_str(), product_AD_num, pFuntion->function.f_AD_Check.analysis_num.numT); + AddStrToLog(productIdx, strlog); + } + } + + // 不NG + if (!bNG) + { + // 距离判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_dis.bOpen) + { + // 数量分析 + if (min_dis <= pFuntion->function.f_AD_Check.analysis_dis.disT) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Dis Check result NG ,min dis %f <= parm dis %f", + pCheckResult->in_shareImage->strChannel.c_str(), min_dis, pFuntion->function.f_AD_Check.analysis_dis.disT); + AddStrToLog(productIdx, strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Dis Check result OK ,min dis %f > parm dis %f", + pCheckResult->in_shareImage->strChannel.c_str(), min_dis, pFuntion->function.f_AD_Check.analysis_dis.disT); + AddStrToLog(productIdx, strlog); + } + } + } + + // 不NG + if (!bNG) + { + // S标准判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.bOpen) + { + // 数量分析 + if (check_s_Num >= pFuntion->function.f_AD_Check.analysis_s.Check_s_Num) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result NG , Check %ds Num %d >= parm S Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), pFuntion->function.f_AD_Check.analysis_s.Check_s_Value, check_s_Num, pFuntion->function.f_AD_Check.analysis_s.Check_s_Num); + AddStrToLog(productIdx, strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result OK , Check %ds Num %d < parm S Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), pFuntion->function.f_AD_Check.analysis_s.Check_s_Value, check_s_Num, pFuntion->function.f_AD_Check.analysis_s.Check_s_Num); + AddStrToLog(productIdx, strlog); + } + } + } + + // 不NG + if (!bNG) + { + // 3S标准判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.NG_3s) + { + for(int i = 0; i < AD_list.size(); i++) + { + // 数量分析 + if (AD_list.at(i).num >= 3) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result NG , Check 3s Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), AD_list.at(i).num); + AddStrToLog(productIdx, strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result OK , Check 3s Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), AD_list.at(i).num); + AddStrToLog(productIdx, strlog); + } + } + } + + } + + // 已经NG + if (bNG) + { + for (int j = 0; j < pCheckResult->qxImageResult.size(); j++) + { + if (pCheckResult->qxImageResult.at(j).type != ERROR_TYPE_AD) + { + continue; + } + + if (pCheckResult->qxImageResult.at(j).qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + pCheckResult->qxImageResult.at(j).qx_type = QX_ERROR_TYPE_NUM; + pCheckResult->qxImageResult.at(j).qx_num = product_AD_num; + } + } + } + // 循环删除指定的元素 + for (auto it = pCheckResult->qxImageResult.begin(); it != pCheckResult->qxImageResult.end();) + { + if (it->type == ERROR_TYPE_AD && it->qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + it = pCheckResult->qxImageResult.erase(it); // 删除元素,并更新迭代器 + } + else + { + ++it; // 继续检查下一个元素 + } + } + if (pCheckResult->qxImageResult.size() <= 0) + { + pCheckResult->nresult = 0; + } + // 判断暗点是否还是ng的。 + bool bADNG = false; + for (auto it = pCheckResult->qxImageResult.begin(); it != pCheckResult->qxImageResult.end();) + { + if (it->type == ERROR_TYPE_AD) + { + bADNG = true; + break; + } + ++it; // 继续检查下一个元素 + } + if (!bADNG) + { + pCheckResult->defectResultList[ERROR_TYPE_AD].Init(); + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "Result", " %s --> NG :%d qx num %zu ; YS %d ys num %zu", + pCheckResult->in_shareImage->strChannel.c_str(), + pCheckResult->nresult, pCheckResult->qxImageResult.size(), pCheckResult->nYS_result, pCheckResult->YS_ImageResult.size()); + AddStrToLog(productIdx, strlog); + } + + return 0; +} + +int ALLImgCheckAnalysisy::AD_AllChannelAnalysisy_New() +{ + std::vector AD_list; + + std::string strlog = ""; + + int product_AD_num = 0; // 整个产品的 暗点数目。 + + int check_s_Num = 0; + int s_param_value = -1; + int s_param_num = 0; + + // 计算 数量分析 + // 通道 + int nDetCamNum = m_ProductImgDetResult_New->cameraCheckResults.size(); + // 相机2的起始位置 + int Cam2_right_x = 0; + for (int icam = 0; icam < nDetCamNum; icam++) + { + + std::shared_ptr pProduct = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + + if (icam == 0) + { + Cam2_right_x = pProduct->CutRoi.x + pProduct->CutRoi.width; + } + + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + ChannelCheckFunction *pFuntion = GetChannelFuntion(pCheckResult->in_shareImage->strChannel); + if (!pFuntion) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", " %s Channel function Error ", + pCheckResult->in_shareImage->strChannel.c_str()); + AddStrToLog_New(strlog); + continue; + } + if (pFuntion && !pFuntion->function.f_AD_Check.bOpen) + { + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "NUM --> %s Param close", + pCheckResult->in_shareImage->strChannel.c_str()); + AddStrToLog_New(strlog); + } + continue; + } + + bool bana_num = false; + bool bana_dis = false; + bool bana_S = false; + if (pFuntion && pFuntion->function.f_AD_Check.analysis_num.bOpen) + { + bana_num = true; + } + if (pFuntion && pFuntion->function.f_AD_Check.analysis_dis.bOpen) + { + bana_dis = true; + } + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.bOpen) + { + bana_S = true; + } + + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "NUM --> %s Param num check %d dis check %d S check %d", + pCheckResult->in_shareImage->strChannel.c_str(), bana_num, bana_dis, bana_S); + AddStrToLog_New(strlog); + } + if (!bana_num && !bana_dis && !bana_S) + { + continue; + } + + // 缺陷 + for (int j = 0; j < pCheckResult->qxImageResult.size(); j++) + { + if (pCheckResult->qxImageResult.at(j).type != ERROR_TYPE_AD) + { + continue; + } + cv::Rect roi = pCheckResult->qxImageResult.at(j).srcImgroi; + + if (icam == 1) + { + roi.x += Cam2_right_x; + } + // 暗点 list + int list_idx = -1; + int channel_s = 0; + for (int idx = 0; idx < AD_list.size(); idx++) + { + float fiou = CheckUtil::CalIoU(AD_list.at(idx).roi, roi); + if (fiou > 0.15) + { + list_idx = idx; + } + } + // 在list已存在。 + if (list_idx >= 0) + { + AD_list.at(list_idx).num++; + channel_s = AD_list.at(list_idx).num; + } + else + { // 在list不存在。 + AD_Channel_Info_ tem; + tem.roi = roi; + tem.num = 1; + channel_s = 1; + tem.fdis = 99999999999; + AD_list.push_back(tem); + // 如果要参与数量统计 + if (bana_num) + { + product_AD_num++; + } + } + + int s_det_value = 0; + // 当前通道 要参与s标准分析 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.bOpen) + { + s_param_num = pFuntion->function.f_AD_Check.analysis_s.Check_s_Num; + s_param_value = pFuntion->function.f_AD_Check.analysis_s.Check_s_Value; + + if (pCheckResult->qxImageResult.at(j).area >= pFuntion->function.f_AD_Check.S_standard_3s.area && + pCheckResult->qxImageResult.at(j).len >= pFuntion->function.f_AD_Check.S_standard_3s.len) + { + s_det_value = 3; + } + else if (pCheckResult->qxImageResult.at(j).area >= pFuntion->function.f_AD_Check.S_standard_2s.area && + pCheckResult->qxImageResult.at(j).len >= pFuntion->function.f_AD_Check.S_standard_2s.len) + { + s_det_value = 2; + } + else + { + s_det_value = 1; + } + if (s_det_value >= s_param_value) + { + check_s_Num++; + } + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", " --> %s qx name %s roi %d %d %d %d area %f; AD list size %d; analysis Num %d; channel s num = %d;cur S = %ds param :%ds num %d->S sum = %d", + pCheckResult->in_shareImage->strChannel.c_str(), + pCheckResult->qxImageResult.at(j).strTypeName.c_str(), + roi.x, roi.y, roi.width, roi.height, pCheckResult->qxImageResult.at(j).area, + AD_list.size(), product_AD_num, channel_s, s_det_value, s_param_value, s_param_num, check_s_Num); + AddStrToLog_New(strlog); + } + } + } + float min_dis = 9999999999; + // 求最小距离 + if (true) + { + for (int ad_i = 0; ad_i < AD_list.size(); ad_i++) + { + for (int ad_j = 0; ad_j < AD_list.size(); ad_j++) + { + if (ad_i == ad_j) + { + continue; + } + double dis = calculateDistanceBetweenRectCenters(AD_list.at(ad_i).roi, AD_list.at(ad_j).roi, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_x, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_y); + if (dis < AD_list.at(ad_i).fdis) + { + AD_list.at(ad_i).fdis = dis; + if (dis < min_dis) + { + min_dis = dis; + } + } + } + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "%d dis = %f ;min dis %f ; scale x y = %f %f", + ad_i, AD_list.at(ad_i).fdis, min_dis, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_x, + m_AnalysisyConfig.commonCheckConfig.baseConfig.fImage_Scale_y); + AddStrToLog_New(strlog); + } + } + int channels_3 = 0; + // 统计 2s 总数 + if (s_param_value > 0) + { + int channels = 0; + int oneimgs = check_s_Num; + for (int ad_i = 0; ad_i < AD_list.size(); ad_i++) + { + if (AD_list.at(ad_i).num >= s_param_value) + { + channels++; + check_s_Num++; + } + if (AD_list.at(ad_i).num >= 3) + { + channels_3++; + } + } + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "cur %ds Num = %d; %ds oneimg s = %d channel s = %d", + s_param_value, check_s_Num, s_param_value, oneimgs, channels); + AddStrToLog_New(strlog); + } + + for (int icam = 0; icam < nDetCamNum; icam++) + { + std::shared_ptr pProduct = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + ChannelCheckFunction *pFuntion = GetChannelFuntion(pCheckResult->in_shareImage->strChannel); + bool bNG = false; + if (pFuntion && pFuntion->function.f_AD_Check.analysis_num.bOpen) + { + // 数量分析 + if (product_AD_num >= pFuntion->function.f_AD_Check.analysis_num.numT) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Num Check result NG ,AD num %d >= parm num %d", + pCheckResult->in_shareImage->strChannel.c_str(), product_AD_num, pFuntion->function.f_AD_Check.analysis_num.numT); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Num Check result OK ,AD num %d < parm num %d", + pCheckResult->in_shareImage->strChannel.c_str(), product_AD_num, pFuntion->function.f_AD_Check.analysis_num.numT); + AddStrToLog_New(strlog); + } + } + // 不NG + if (!bNG) + { + // 3S直接 NG + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.NG_3s) + { + // 数量分析 + if (channels_3 >= 1) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s 3s NG %d", + pCheckResult->in_shareImage->strChannel.c_str(), channels_3); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s 3s OK %d", + pCheckResult->in_shareImage->strChannel.c_str(), channels_3); + AddStrToLog_New(strlog); + } + } + } + + // 不NG + if (!bNG) + { + // 距离判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_dis.bOpen) + { + // 数量分析 + if (min_dis <= pFuntion->function.f_AD_Check.analysis_dis.disT) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Dis Check result NG ,min dis %f <= parm dis %f", + pCheckResult->in_shareImage->strChannel.c_str(), min_dis, pFuntion->function.f_AD_Check.analysis_dis.disT); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Dis Check result OK ,min dis %f > parm dis %f", + pCheckResult->in_shareImage->strChannel.c_str(), min_dis, pFuntion->function.f_AD_Check.analysis_dis.disT); + AddStrToLog_New(strlog); + } + } + } + + // 不NG + if (!bNG) + { + // S标准判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.bOpen) + { + // 数量分析 + if (check_s_Num >= pFuntion->function.f_AD_Check.analysis_s.Check_s_Num) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result NG , Check %ds Num %d >= parm S Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), pFuntion->function.f_AD_Check.analysis_s.Check_s_Value, check_s_Num, pFuntion->function.f_AD_Check.analysis_s.Check_s_Num); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result OK , Check %ds Num %d < parm S Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), pFuntion->function.f_AD_Check.analysis_s.Check_s_Value, check_s_Num, pFuntion->function.f_AD_Check.analysis_s.Check_s_Num); + AddStrToLog_New(strlog); + } + } + } + + // 不NG + if (!bNG) + { + // 4S标准判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.NG_4s) + { + for(int i = 0; i < AD_list.size(); i++) + { + // 数量分析 + if (AD_list.at(i).num >= 4) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result NG , Check 4s Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), AD_list.at(i).num); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result OK , Check 4s Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), AD_list.at(i).num); + AddStrToLog_New(strlog); + } + } + } + + } + + // 不NG + if (!bNG) + { + // 3S标准判断 + if (pFuntion && pFuntion->function.f_AD_Check.analysis_s.NG_3s) + { + for(int i = 0; i < AD_list.size(); i++) + { + // 数量分析 + if (AD_list.at(i).num >= 3) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result NG , Check 3s Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), AD_list.at(i).num); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "AD RGBL255", "--> %s Check result OK , Check 3s Num %d", + pCheckResult->in_shareImage->strChannel.c_str(), AD_list.at(i).num); + AddStrToLog_New(strlog); + } + } + } + + } + + // 已经NG + if (bNG) + { + for (int j = 0; j < pCheckResult->qxImageResult.size(); j++) + { + if (pCheckResult->qxImageResult.at(j).type != ERROR_TYPE_AD) + { + continue; + } + + if (pCheckResult->qxImageResult.at(j).qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + pCheckResult->qxImageResult.at(j).qx_type = QX_ERROR_TYPE_NUM; + pCheckResult->qxImageResult.at(j).qx_num = product_AD_num; + } + } + } + // 循环删除指定的元素 + for (auto it = pCheckResult->qxImageResult.begin(); it != pCheckResult->qxImageResult.end();) + { + if (it->type == ERROR_TYPE_AD && it->qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + it = pCheckResult->qxImageResult.erase(it); // 删除元素,并更新迭代器 + } + else + { + ++it; // 继续检查下一个元素 + } + } + if (pCheckResult->qxImageResult.size() <= 0) + { + pCheckResult->nresult = 0; + } + // 判断暗点是否还是ng的。 + bool bADNG = false; + for (auto it = pCheckResult->qxImageResult.begin(); it != pCheckResult->qxImageResult.end();) + { + if (it->type == ERROR_TYPE_AD) + { + bADNG = true; + break; + } + ++it; // 继续检查下一个元素 + } + if (!bADNG) + { + pCheckResult->defectResultList[ERROR_TYPE_AD].Init(); + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "Result", " %s --> NG :%d qx num %zu ; YS %d ys num %zu", + pCheckResult->in_shareImage->strChannel.c_str(), + pCheckResult->nresult, pCheckResult->qxImageResult.size(), pCheckResult->nYS_result, pCheckResult->YS_ImageResult.size()); + AddStrToLog_New(strlog); + } + } + + return 0; +} + +int ALLImgCheckAnalysisy::POL_AllChannelAnalysisy_New() +{ + + std::string strlog = ""; + + std::map channle_POL_Num; + + // 计算 数量分析 + // 通道 + int nDetCamNum = m_ProductImgDetResult_New->cameraCheckResults.size(); + // 相机2的起始位置 + int Cam2_right_x = 0; + for (int icam = 0; icam < nDetCamNum; icam++) + { + + std::shared_ptr pProduct = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + + if (icam == 0) + { + Cam2_right_x = pProduct->CutRoi.x + pProduct->CutRoi.width; + } + + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + ChannelCheckFunction *pFuntion = GetChannelFuntion(pCheckResult->in_shareImage->strChannel); + if (!pFuntion) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "POL RGBL255", "icam %d %s Channel function Error ", + icam, pCheckResult->in_shareImage->strChannel.c_str()); + AddStrToLog_New(strlog); + continue; + } + if (pFuntion && !pFuntion->function.f_POL_Check.bOpen) + { + { + strlog = m_PrintLog.printstr(Print_Level_Info, "POL RGBL255", "NUM -->icam %d %s Param close", + icam, pCheckResult->in_shareImage->strChannel.c_str()); + AddStrToLog_New(strlog); + } + continue; + } + + bool bana_num = true; + + // 缺陷 + for (int j = 0; j < pCheckResult->qxImageResult.size(); j++) + { + if (pCheckResult->qxImageResult.at(j).type != ERROR_TYPE_POL_Cell) + { + continue; + } + channle_POL_Num[pCheckResult->in_shareImage->strChannel]++; + + cv::Rect roi = pCheckResult->qxImageResult.at(j).srcImgroi; + + if (icam == 1) + { + roi.x += Cam2_right_x; + } + + int s_det_value = 0; + + strlog = m_PrintLog.printstr(Print_Level_Info, "POL RGBL255", " -->icam %d %s qx name %s roi %d %d %d %d area %f; product_POL_num %d;", + icam, pCheckResult->in_shareImage->strChannel.c_str(), + pCheckResult->qxImageResult.at(j).strTypeName.c_str(), + roi.x, roi.y, roi.width, roi.height, pCheckResult->qxImageResult.at(j).area, + channle_POL_Num[pCheckResult->in_shareImage->strChannel]); + AddStrToLog_New(strlog); + } + } + } + + for (int icam = 0; icam < nDetCamNum; icam++) + { + std::shared_ptr pProduct = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + ChannelCheckFunction *pFuntion = GetChannelFuntion(pCheckResult->in_shareImage->strChannel); + bool bNG = false; + if (pFuntion && pFuntion->function.f_POL_Check.bOpen) + { + // 数量分析 + if (channle_POL_Num[pCheckResult->in_shareImage->strChannel] >= pFuntion->function.f_POL_Check.numT) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "POL RGBL255", "-->icam %d %s Num Check result NG ,POL num %d >= parm num %d", + icam, pCheckResult->in_shareImage->strChannel.c_str(), channle_POL_Num[pCheckResult->in_shareImage->strChannel], pFuntion->function.f_POL_Check.numT); + AddStrToLog_New(strlog); + bNG = true; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "POL RGBL255", "-->icam %d %s Num Check result OK ,POL num %d < parm num %d", + icam, pCheckResult->in_shareImage->strChannel.c_str(), channle_POL_Num[pCheckResult->in_shareImage->strChannel], pFuntion->function.f_POL_Check.numT); + AddStrToLog_New(strlog); + } + } + // 已经NG + if (bNG) + { + for (int j = 0; j < pCheckResult->qxImageResult.size(); j++) + { + if (pCheckResult->qxImageResult.at(j).type != ERROR_TYPE_POL_Cell) + { + continue; + } + + if (pCheckResult->qxImageResult.at(j).qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + pCheckResult->qxImageResult.at(j).qx_type = QX_ERROR_TYPE_NUM; + pCheckResult->qxImageResult.at(j).qx_num = channle_POL_Num[pCheckResult->in_shareImage->strChannel]; + } + } + } + // 循环删除指定的元素 + for (auto it = pCheckResult->qxImageResult.begin(); it != pCheckResult->qxImageResult.end();) + { + if (it->type == ERROR_TYPE_POL_Cell && it->qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + it = pCheckResult->qxImageResult.erase(it); // 删除元素,并更新迭代器 + } + else + { + ++it; // 继续检查下一个元素 + } + } + if (pCheckResult->qxImageResult.size() <= 0) + { + pCheckResult->nresult = 0; + } + // 判断异物是否还是ng的。 + bool bADNG = false; + for (auto it = pCheckResult->qxImageResult.begin(); it != pCheckResult->qxImageResult.end();) + { + if (it->type == ERROR_TYPE_POL_Cell) + { + bADNG = true; + break; + } + ++it; // 继续检查下一个元素 + } + if (!bADNG) + { + pCheckResult->defectResultList[ERROR_TYPE_POL_Cell].Init(); + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "POL RGBL255 Result", "icam %d %s --> NG :%d qx num %zu ; YS %d ys num %zu", + icam, pCheckResult->in_shareImage->strChannel.c_str(), + pCheckResult->nresult, pCheckResult->qxImageResult.size(), pCheckResult->nYS_result, pCheckResult->YS_ImageResult.size()); + AddStrToLog_New(strlog); + } + } + + return 0; +} + +int ALLImgCheckAnalysisy::SetProductResult() +{ + + int nDetCamNum = m_ProductImgDetResult_New->cameraCheckResults.size(); + // 相机2的起始位置 + bool bNG = false; + for (int icam = 0; icam < nDetCamNum; icam++) + { + std::shared_ptr pProduct = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + if (pCheckResult->qxImageResult.size() > 0) + { + bNG = true; + } + if (bNG) + { + break; + } + } + if (bNG) + { + break; + } + } + if (bNG) + { + for (int icam = 0; icam < nDetCamNum; icam++) + { + + std::shared_ptr pProduct = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + + for (int i = 0; i < pProduct->pImageDetResultList.size(); i++) + { + std::shared_ptr pCheckResult = pProduct->pImageDetResultList.at(i)->pBaseImgCheckResult; + pCheckResult->nProductResult = 1; + } + } + } + return 0; +} + +int ALLImgCheckAnalysisy::SetSetComplet(int productIdx, int result, int nerror) +{ + std::shared_ptr tem; + { + // 获取 L255 + std::lock_guard lock(mtx_ProductImgDetResultList); + tem = m_ProductImgDetResultList.at(productIdx); + // 删除指定位置的元素 + m_ProductImgDetResultList.erase(m_ProductImgDetResultList.begin() + productIdx); + printf("SetSetComplet size %ld productIdx %d \n", m_ProductImgDetResultList.size(), productIdx); + for (int i = 0; i < m_ProductImgDetResultList.size(); i++) + { + printf("%d %s \n", i, m_ProductImgDetResultList.at(i)->strSN.c_str()); + } + } + if (tem) + { + std::lock_guard lock(mtx_Last_det_LogList); + Last_det_LogList.erase(Last_det_LogList.begin(), Last_det_LogList.end()); + Last_det_LogList.clear(); + Last_det_LogList.assign(tem->LogList.begin(), tem->LogList.end()); + } + + tem->detImgStatus = 1; + tem->nresult = result; + tem->nError = nerror; + printf("*******************%s********nerror %d****\n", tem->strSN.c_str(), nerror); + if (nerror > 0) + { + for (int i = 0; i < tem->DetImageList.size(); i++) + { + // 检测错误 状态 + tem->DetImageList.at(i)->checkStatus = 1; + tem->DetImageList.at(i)->nresult = -nerror; + } + } + for (int i = 0; i < tem->DetImageList.size(); i++) + { + + std::shared_ptr temresult = tem->DetImageList.at(i); + temresult->det_LogList.insert(temresult->det_LogList.end(), tem->LogList.begin(), tem->LogList.end()); + { + std::lock_guard lock(mtx_CheckResult); + + m_CheckResultList.push(temresult); + } + CheckResult_cond.notify_all(); + } + m_PrintLog.printstr(Print_Level_Info, "SetSetComplet", "Check End "); + return 0; +} + +int ALLImgCheckAnalysisy::SetSetComplet_New(int result, int nerror) +{ + if (m_ProductImgDetResult_New) + { + std::lock_guard lock(mtx_ProductImgDetResultList); + + { + std::lock_guard lock_log(mtx_Last_det_LogList); + Last_det_LogList.erase(Last_det_LogList.begin(), Last_det_LogList.end()); + Last_det_LogList.clear(); + Last_det_LogList.assign(m_ProductImgDetResult_New->LogList.begin(), m_ProductImgDetResult_New->LogList.end()); + } + + int cameraNum = m_ProductImgDetResult_New->cameraCheckResults.size(); + for (int icam = 0; icam < cameraNum; icam++) + { + std::shared_ptr pCamear = m_ProductImgDetResult_New->cameraCheckResults.at(icam); + for (int i = 0; i < pCamear->DetImageList.size(); i++) + { + + std::shared_ptr temresult = pCamear->DetImageList.at(i); + // 如果检测结果为预处理错误 + if (pCamear->checkResultStatus == Check_Result_Status_PreError) + { + // 检测错误 状态 bad roi + temresult->checkStatus = 1; + temresult->nresult = Check_Result_Status_PreError; + } + + temresult->det_LogList.insert(temresult->det_LogList.end(), m_ProductImgDetResult_New->LogList.begin(), m_ProductImgDetResult_New->LogList.end()); + std::string strResult = ">>>>>>>>>>>> checkStatus = " + std::to_string(temresult->checkStatus) + + " nresult = " + std::to_string(temresult->nresult); + temresult->det_LogList.push_back(strResult); + + { + std::lock_guard lock123(mtx_CheckResult); + m_CheckResultList.push(temresult); + } + CheckResult_cond.notify_all(); + } + } + m_ProductImgDetResult_New.reset(); + } + m_PrintLog.printstr(Print_Level_Info, "SetSetComplet", "Check End "); + return 0; +} + +int ALLImgCheckAnalysisy::DetListNum() +{ + // 对数量进行处理 + if (m_ProductImgDetResultList.size() > 5) + { + std::string strlog = ""; + int num = m_ProductImgDetResultList.size(); + printf("******************\n\n m_ProductImgDetResultList %ld \n", m_ProductImgDetResultList.size()); + + { + std::lock_guard lock(mtx_ProductImgDetResultList); + int idx = -1; + for (int i = 0; i < m_ProductImgDetResultList.size(); i++) + { + if (1 == m_ProductImgDetResultList.at(i)->L255ImgStatus) + { + continue; + } + int sub = std::abs(m_CurProductIdx - m_ProductImgDetResultList.at(i)->nNotDetCount); + if (sub > 50) + { + // 删除指定位置的元素 + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "%s Delete size > %d; m_CurProductIdx %d - nNotDetCount %d > 50", + m_ProductImgDetResultList.at(i)->strSN.c_str(), + m_ProductImgDetResultList.size(), m_CurProductIdx, + m_ProductImgDetResultList.at(i)->nNotDetCount); + AddStrToLog(num - 1, strlog); + m_ProductImgDetResultList.erase(m_ProductImgDetResultList.begin() + i); + } + } + } + } + return 0; +} + +int ALLImgCheckAnalysisy::PushInImg_New(std::shared_ptr p) +{ + + // printf("PushInImg======================Status========= %d \n", p->Status); + + std::string strlog = ""; + m_strTest += " PushInImg->SN:"; + m_strTest += p->strImgProductID; + m_strTest += " Channel:"; + m_strTest += p->strChannel; + m_strTest += " CameraID:"; + m_strTest += p->camera_Name; + std::string strBase = ""; + strBase += " PushInImg->SN:"; + strBase += p->strImgProductID; + strBase += " Channel:"; + strBase += p->strChannel; + // printf("strBase %s p->Status %d\n",strBase.c_str(), p->Status); + + { + std::lock_guard lock(mtx_ProductImgDetResultList); + + bool ProductID_Exist = false; // 是否存在当前产品ID + + // 1、通过ID 判断 当前处理产品队列中是否可以继续增加。 + int productIdx = 0; + if (m_ProductImgDetResult_New) + { + ProductID_Exist = true; + } + + // 产品存在 并且 模式 是第一张图, 则,返回异常。 + if (IN_IMG_Status_Start == p->Status && ProductID_Exist) + { + // ErrorReturn(p); + + return CHECK_ERROR_PRODUCT_ID_EXIST; + } + // 产品存在, 但是 产品ID 不等于 已存在的 ID; + if (ProductID_Exist && p->strImgProductID != m_ProductImgDetResult_New->strSN) + { + + ErrorReturn(p); + return CHECK_ERROR_PRODUCT_ID_EXIST; + } + // 产品存在,但是 图片都已经完了的状态 + if (ProductID_Exist && m_ProductImgDetResult_New->bIsImgComplete) + { + + ErrorReturn(p); + return CHECK_ERROR_PRODUCT_ID_EXIST; + } + // 产品的 相机 ID 错误 + if (p->camera_ID < 0 || p->camera_ID >= MAX_Camera_NUM) + { + ErrorReturn(p); + return CHECK_ERROR_Camear_ID_Error; + } + if (p->img.channels() != 1) + { + cv::cvtColor(p->img, p->img, cv::COLOR_BGR2GRAY); + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", " cvtColor %s ", p->strImgProductID.c_str()); + // m_ProductImgDetResult_New->AddLog(strlog); + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "p->img.channels() %s %d %d ", p->strImgProductID.c_str(), p->img.channels(), p->img.cols); + // m_ProductImgDetResult_New->AddLog(strlog); + } + + // 创建产品 + if (!ProductID_Exist) + { + m_ProductImgDetResult_New = std::make_shared(); + m_ProductImgDetResult_New->strSN = p->strImgProductID; + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "add new product %s ", p->strImgProductID.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + } + + if (-1 != p->Status) + { + // 相机id 转换 + std::string strCameraName = p->camera_Name; + + // 对应相机的 检测结果 + std::shared_ptr pCamera = m_ProductImgDetResult_New->GetCameraCheckResult(strCameraName); + + if (pCamera == nullptr) + { + pCamera = m_ProductImgDetResult_New->CreateCameraCheckResult(strCameraName); + pCamera->strSN = p->strImgProductID; + } + if (pCamera == nullptr) + { + ErrorReturn(p); + return CHECK_ERROR_Camear_ID_Error; + } + SetCameraImgAndStartDet(strCameraName, pCamera); + // 添加产品信息 + if (true) + { + std::shared_ptr result = std::make_shared(); + p->time_PushIn = CheckUtil::getcurTime(); + result->in_shareImage = p; + result->checkStatus = 1; + result->nDetStep = 0; + result->nresult = -1; + result->basicResult.img_id = p->img_id; + result->basicResult.imgtype = p->imgtype; + result->basicResult.imgstr = p->imgstr; + result->basicResult.strChannel = p->strChannel; + { + std::lock_guard lock_cam(pCamera->mtx_Det); + pCamera->DetImageList.push_back(result); + pCamera->cameraImage_Status.bHaveImg = true; + } + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", " product %s add new image camid = %s channel = %s", + p->strImgProductID.c_str(), p->camera_Name.c_str(), p->strChannel.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + } + + if (p->strChannel == "L255") + { + { + std::lock_guard lock_cam(pCamera->mtx_Det); + pCamera->cameraImage_Status.bHave_L255 = true; + pCamera->L255ImgStatus = 1; + } + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "%s camid = %s L255 = ok", p->strImgProductID.c_str(), p->camera_Name.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + } + if (p->strChannel == "Down-Particle") + { + { + std::lock_guard lock_cam(pCamera->mtx_Det); + pCamera->cameraImage_Status.bHave_DP = true; + pCamera->bhaveDPImg = true; + } + + pCamera->nDet_DP = 1; + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "%s camid = %s Down-Particle = ok", p->strImgProductID.c_str(), p->camera_Name.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + } + if (p->strChannel == "Up-Particle") + { + { + std::lock_guard lock_cam(pCamera->mtx_Det); + pCamera->cameraImage_Status.bhave_UP = true; + pCamera->bHaveUPImg = true; + } + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "%s camid = %s Up-Particle = ok", p->strImgProductID.c_str(), p->camera_Name.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + } + if (IN_IMG_Status_End == p->Status || + IN_IMG_Status_OneImg == p->Status) + { + m_ProductImgDetResult_New->bIsImgComplete = true; // 所有图都送完了。 + for (int ic = 0; ic < m_ProductImgDetResult_New->cameraCheckResults.size(); ic++) + { + + { + std::lock_guard lock_cam(m_ProductImgDetResult_New->cameraCheckResults.at(ic)->mtx_Det); + m_ProductImgDetResult_New->cameraCheckResults.at(ic)->cameraImage_Status.bImgComplete = true; + } + } + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "%s Add ALL img end", p->strImgProductID.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + } + if (IN_IMG_Status_End == p->Status) + { + m_strTest += "\n"; + m_ProductImgDetResult_New->AddLog(m_strTest); + m_strTest = ""; + } + } + if (-1 == p->Status) + { + m_ProductImgDetResult_New->bIsImgComplete = true; // 所有图都送完了。 + for (int ic = 0; ic < m_ProductImgDetResult_New->cameraCheckResults.size(); ic++) + { + + { + std::lock_guard lock_cam(m_ProductImgDetResult_New->cameraCheckResults.at(ic)->mtx_Det); + m_ProductImgDetResult_New->cameraCheckResults.at(ic)->cameraImage_Status.bImgComplete = true; + } + } + + strlog = m_PrintLog.printstr(Print_Level_Key, "PushInImg", "%s Add ALL img end", p->strImgProductID.c_str()); + m_ProductImgDetResult_New->AddLog(strlog); + m_strTest += "\n"; + m_ProductImgDetResult_New->AddLog(m_strTest); + m_strTest = ""; + } + } + + return 0; +} + +int ALLImgCheckAnalysisy::CurCheckListStatus() +{ + std::lock_guard lock(mtx_ProductImgDetResultList); + if (m_ProductImgDetResultList.size() > 2) + { + return CHECK_ERROR_PushImg_ListSize; + } + return CHECK_OK; +} + +int ALLImgCheckAnalysisy::Run() +{ + + while (!m_bExit) + { + + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + + int re = Det_Product(); + // 检测失败 + if (re != 0) + { + continue; + } + SetSetComplet_New(0, 0); + } + + return 0; +} +int ALLImgCheckAnalysisy::set_cpu_id(const std::vector &cpu_set_vec) +{ + // for cpu affinity + int nRet = 0; +#ifdef __linux + cpu_set_t _cur_cpu_set; + CPU_ZERO(&_cur_cpu_set); + for (auto _id : cpu_set_vec) + { + CPU_SET(_id, &_cur_cpu_set); + } + if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set)) + { + perror("set cpu affinity failed: "); + printf("Warning: set cpu affinity failed ... ...\n"); + nRet = -1; + } +#endif //__linux + return nRet; +} diff --git a/AlgorithmModule/src/Blob.c b/AlgorithmModule/src/Blob.c new file mode 100644 index 0000000..c7b3cfd --- /dev/null +++ b/AlgorithmModule/src/Blob.c @@ -0,0 +1,560 @@ +#include +#include +#include +#include "BlobBase.h" +void pretest(double x) +{ + printf("fff %f \n", x); +} + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +//-------------sxg added + +void AddErrorScan(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int mdx, int *pErrClass) +{ + + if (curRow->scanCount < _MAX_ERROR_SCAN_LINE_PER_ROW) + { + + int lastScanLineIndex = curRow->scanCount++; + ERROR_DOTS_SCAN_DATA *scan = curRow->errorScanLineTab + lastScanLineIndex; + scan->x = x; + scan->count = len; + int ex = x + len - 1; + scan->energy = difSum; + scan->area = scan->count; + scan->xposSum = (x + (len >> 1)) * len; + scan->yposSum = y * len; + scan->minx = x; + scan->miny = y; + scan->maxx = ex; + scan->maxy = y; + scan->macro = mdx; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + scan->ErrClass[ec] = pErrClass[ec]; + } + + curRow->macro[scan->macro] = len; + + int linkIndexTab[_MAX_ERROR_SCAN_LINE_PER_ROW]; + int linkCount = 0; + if (prevRow) + { + for (int t = 0; t < _MAX_MACRO_COUNT; t++) + { + curRow->macro[t] += prevRow->macro[t]; + // prevRow->macro[t]=0; + } + + int prevLastScanLineIndex = prevRow->scanCount - 1; + ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; + for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) + { + int psx = pscan->x - 1; + int pex = psx + pscan->count - 1 + 1; + // sxg modified waitting for valid 9.5 + if (x <= pex && ex >= psx) + { + if (pscan->area > 0) + { + int area = scan->area + (pscan->area); + scan->area = area; + if (scan->macro != pscan->macro) + { + if (scan->macro < pscan->macro) + scan->macro = pscan->macro; + } + scan->energy += pscan->energy; + scan->xposSum += pscan->xposSum; + scan->yposSum += pscan->yposSum; + scan->minx = min(scan->minx, pscan->minx); + scan->miny = min(scan->miny, pscan->miny); + scan->maxx = max(scan->maxx, pscan->maxx); + scan->maxy = max(scan->maxy, pscan->maxy); + pscan->area = 0; + pscan->energy = lastScanLineIndex; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + scan->ErrClass[ec] = pErrClass[ec] + (pscan->ErrClass[ec]); + } + linkIndexTab[/*0xff & */ (linkCount++)] = prevLastScanLineIndex; + } + // else + //{ + // int bindex = 0xff & pscan->energy; + // ERROR_DOTS_SCAN_DATA * hscan = curRow->errorScanLineTab + bindex; + // hscan->count = ex - hscan->x + 1; + // hscan->area += scan->area; + // hscan->energy += scan->energy; + // hscan->xposSum += scan->xposSum; + // hscan->yposSum += scan->yposSum; + // hscan->minx = min(scan->minx , hscan->minx); + // hscan->miny = min(scan->miny , hscan->miny); + // hscan->maxx = max(scan->maxx , hscan->maxx); + // hscan->maxy = max(scan->maxy , hscan->maxy); + // scan->area = 0; + // for(;linkCount > 0 ; --linkCount) + // { + // ERROR_DOTS_SCAN_DATA * p = prevRow->errorScanLineTab + linkIndexTab[0xff & (linkCount - 1)]; + // p->energy = bindex; + // } + // curRow->scanCount--; + // break; + // } + } + } + } + } +} + +void LinkScanLineToBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width) +{ + if (prevRow) + { + int prevLastScanLineIndex = prevRow->scanCount - 1; + ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; + // int minArea = param->minArea; + // int minEnergy = param->minEnergy; + for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) + { + if (pscan->area > 0) + { + int x = pscan->xposSum / pscan->area + sx; + int y = pscan->yposSum / pscan->area + sy; + int minx = pscan->minx + sx; + int miny = pscan->miny + sy; + int maxx = pscan->maxx + sx; + int maxy = pscan->maxy + sy; + if (x < width) + { + int blobIndex = blobs->blobCount; + // int mergeDistance = param->mergeDistance; + ERROR_DOTS_BLOB_DATA *pblob = blobs->blobTab + blobIndex - 1; + int left = minx - mergeDistanceX, right = maxx + mergeDistanceX; + int top = miny - mergeDistanceY, bottom = maxy + mergeDistanceY; + for (int i = blobIndex - 1; i >= 0; --i, --pblob) + { + + if (1) + { + if (pblob->maxy > top && pblob->miny < bottom) + { + if (pblob->maxx > left && pblob->minx < right) + { + int area = pblob->area + pscan->area; + pblob->x = (pblob->x * pblob->area + x * pscan->area) / area; + pblob->y = (pblob->y * pblob->area + y * pscan->area) / area; + pblob->area = area; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + pblob->ErrClass[ec] += pscan->ErrClass[ec]; + } + + pblob->energy += pscan->energy; + pblob->minx = min(pblob->minx, minx); + pblob->miny = min(pblob->miny, miny); + pblob->maxx = max(pblob->maxx, maxx); + pblob->maxy = max(pblob->maxy, maxy); + pblob->macro[pscan->macro] += prevRow->macro[pscan->macro]; + prevRow->macro[pscan->macro] -= pscan->area; + blobIndex = _MAX_ERROR_DOT_BLOB; + break; + } + } + } + } + if (pscan->area > minArea /*|| pscan->energy > minEnergy*/) + { + if (blobIndex < _MAX_ERROR_DOT_BLOB) + { + pblob = blobs->blobTab + blobIndex; + pblob->x = x; + pblob->y = y; + pblob->area = pscan->area; + pblob->energy = pscan->energy; + pblob->minx = minx; + pblob->miny = miny; + pblob->maxx = maxx; + pblob->maxy = maxy; + blobs->blobCount++; + for (int t = 0; t < _MAX_MACRO_COUNT; t++) + { + pblob->macro[t] = 0; + } + pblob->macro[pscan->macro] = pscan->area; + prevRow->macro[pscan->macro] -= pscan->area; + // prevRow->macro[pscan->macro]=0; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + pblob->ErrClass[ec] = pscan->ErrClass[ec]; + } + } + } + } + } + pscan->area = 0; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + pscan->ErrClass[ec] = 0; + } + } + // for (int t=0;tmacro[t]+=prevRow->macro[t]; + // prevRow->macro[t]=0; + // } + } +} + +void MergeBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOB_PARAM *param) +{ + int count = blobs->blobCount; + ERROR_DOTS_BLOB_DATA *blob = blobs->blobTab + count - 1; + int pace = param->mergeDistance; + for (int i = count - 1; i > 0; --i, --blob) + { + int minx = blob->minx; + int miny = blob->miny; + int maxx = blob->maxx; + int maxy = blob->maxy; + int energy = blob->energy; + + int left = minx - pace, right = maxx + pace; + int top = miny - 1, bottom = maxy + 1; + ERROR_DOTS_BLOB_DATA *pblob = blob - 1; + for (int j = i - 1; j >= 0; --j, --pblob) + { + + if (1) + { + if (pblob->maxy > top && pblob->miny < bottom) + { + if (pblob->maxx > left && pblob->minx < right) + { + int areaSum = pblob->area + blob->area; + int x = blob->x, y = blob->y; + pblob->x = (pblob->x * pblob->area + x * blob->area) / areaSum; + pblob->y = (pblob->y * pblob->area + y * blob->area) / areaSum; + pblob->area = areaSum; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + pblob->ErrClass[ec] += blob->ErrClass[ec]; + } + + pblob->energy += energy; + pblob->minx = min(pblob->minx, minx); + pblob->miny = min(pblob->miny, miny); + pblob->maxx = max(pblob->maxx, maxx); + pblob->maxy = max(pblob->maxy, maxy); + for (int t = 0; t < _MAX_MACRO_COUNT; t++) + { + pblob->macro[t] += blob->macro[t]; + blob->macro[t] = 0; + } + count--; + memmove(blob, blob + 1, (count - i) * sizeof(blob[0])); + break; + } + } + } + } + } + blobs->blobCount = count; +} +// static int __cdecl compareBlob(const void * p1, const void * p2) +static int compareBlob(const void *p1, const void *p2) +{ + ERROR_DOTS_BLOB_DATA *b1 = (ERROR_DOTS_BLOB_DATA *)p1; + ERROR_DOTS_BLOB_DATA *b2 = (ERROR_DOTS_BLOB_DATA *)p2; + return (b2->area) - (b1->area); +} + +void SortBlob(ERROR_DOTS_BLOBS *blobs) +{ + int count = blobs->blobCount; + ERROR_DOTS_BLOB_DATA *blob = blobs->blobTab; + qsort(blob, count, sizeof(blob[0]), compareBlob); +} +int GetBlobsFromImg(ERROR_DOTS_BLOBS *blobs_0, ERROR_DOTS_BLOBS *blobs_1, ERROR_DOTS_BLOBS *blobs_2, unsigned char *pB, unsigned char *pr, unsigned char *pc, int width, int height, int obj) +{ + return 0; +} +int GetBlobsFromIm_1(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pGrayErrordata, unsigned char *pRGBErrordata, int width, int height) +{ + + return 0; +} +int GetBlobsFromIm_2(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pGrayErrordata, unsigned char *pRGBErrordata, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT) +{ + + return 0; +} + +int GetBlobsFromIm_All(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pGrayErrordata, unsigned char *pRGBErrordata, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT) +{ + + return 0; +} + +int GetBlobsFromIm_single(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pcropConstructdata, unsigned char *pErrordata, int nstartPos, int nstep, int npitch, int nErrorType, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT) +{ + + return 0; +} + +int GetBlobsFromIm_All_onemask(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pRGBErrordata, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT) +{ + + return 0; +} + +int GetBlobsFromIm_single_onemask(ERROR_DOTS_BLOBS *blobs, unsigned char *pcropdata, unsigned char *pErrordata, int AndValue, int npitch, int nErrorType, unsigned char *pGrayMaskdata, int width, int height, int ndiffValueT) +{ + + return 0; +} +// 当前行和前面行合并 +void AddErrorScan_New(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int errorType) +{ + if (curRow->scanCount < _MAX_ERROR_SCAN_LINE_PER_ROW) + { + + int lastScanLineIndex = curRow->scanCount++; + ERROR_DOTS_SCAN_DATA *scan = curRow->errorScanLineTab + lastScanLineIndex; + scan->x = x; + scan->count = len; + int ex = x + len - 1; + scan->energy = difSum; + scan->area = scan->count; + scan->xposSum = (x + (len >> 1)) * len; + scan->yposSum = y * len; + scan->minx = x; + scan->miny = y; + scan->maxx = ex; + scan->maxy = y; + scan->type = errorType; + + if (prevRow) + { + int prevLastScanLineIndex = prevRow->scanCount - 1; + ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; + for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) + { + int psx = pscan->x - 1; + int pex = psx + pscan->count - 1 + 1; + if (x <= pex && ex >= psx && pscan->type == scan->type) + { + if (pscan->area > 0) + { + int area = scan->area + (pscan->area); + scan->area = area; + scan->energy += pscan->energy; + scan->xposSum += pscan->xposSum; + scan->yposSum += pscan->yposSum; + scan->minx = min(scan->minx, pscan->minx); + scan->miny = min(scan->miny, pscan->miny); + scan->maxx = max(scan->maxx, pscan->maxx); + scan->maxy = max(scan->maxy, pscan->maxy); + pscan->area = 0; + pscan->energy = lastScanLineIndex; + } + } + } + } + } +} + +void LinkScanLineToBlob_New(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width) +{ + if (prevRow) + { + int prevLastScanLineIndex = prevRow->scanCount - 1; + ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; + // int minArea = param->minArea; + // int minEnergy = param->minEnergy; + for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) + { + if (pscan->area > 0) + { + int x = pscan->xposSum / pscan->area + sx; + int y = pscan->yposSum / pscan->area + sy; + int minx = pscan->minx + sx; + int miny = pscan->miny + sy; + int maxx = pscan->maxx + sx; + int maxy = pscan->maxy + sy; + if (x < width) + { + int blobIndex = blobs->blobCount; + // int mergeDistance = param->mergeDistance; + ERROR_DOTS_BLOB_DATA *pblob = blobs->blobTab + blobIndex - 1; + int left = minx - mergeDistanceX, right = maxx + mergeDistanceX; + int top = miny - mergeDistanceY, bottom = maxy + mergeDistanceY; + for (int i = blobIndex - 1; i >= 0; --i, --pblob) + { + if (pblob->ErrType == pscan->type) + { + if (pblob->maxy > top && pblob->miny < bottom) + { + if (pblob->maxx > left && pblob->minx < right) + { + int area = pblob->area + pscan->area; + pblob->x = (pblob->x * pblob->area + x * pscan->area) / area; + pblob->y = (pblob->y * pblob->area + y * pscan->area) / area; + pblob->area = area; + // for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + // { + // pblob->ErrClass[ec] += pscan->ErrClass[ec]; + // } + + pblob->energy += pscan->energy; + pblob->minx = min(pblob->minx, minx); + pblob->miny = min(pblob->miny, miny); + pblob->maxx = max(pblob->maxx, maxx); + pblob->maxy = max(pblob->maxy, maxy); + // pblob->macro[pscan->macro] += prevRow->macro[pscan->macro]; + // prevRow->macro[pscan->macro] -= pscan->area; + blobIndex = _MAX_ERROR_DOT_BLOB; + break; + } + } + } + } + if (pscan->area > minArea /*|| pscan->energy > minEnergy*/) + { + if (blobIndex < _MAX_ERROR_DOT_BLOB) + { + pblob = blobs->blobTab + blobIndex; + pblob->x = x; + pblob->y = y; + pblob->area = pscan->area; + pblob->energy = pscan->energy; + pblob->ErrType = pscan->type; + pblob->minx = minx; + pblob->miny = miny; + pblob->maxx = maxx; + pblob->maxy = maxy; + blobs->blobCount++; + // for (int t = 0; t < _MAX_MACRO_COUNT; t++) + // { + // pblob->macro[t] = 0; + // } + // pblob->macro[pscan->macro] = pscan->area; + // prevRow->macro[pscan->macro] -= pscan->area; + // prevRow->macro[pscan->macro]=0; + // for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + // { + // pblob->ErrClass[ec] = pscan->ErrClass[ec]; + // } + } + } + } + } + pscan->area = 0; + for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) + { + pscan->ErrClass[ec] = 0; + } + } + // for (int t=0;tmacro[t]+=prevRow->macro[t]; + // prevRow->macro[t]=0; + // } + } +} + +int GetBlobs_V2(ERROR_DOTS_BLOBS *blobs, unsigned char *pImgdata, unsigned char *pErrordata, int width, int height, int basev, int minArea) +{ + + if (blobs == NULL || pErrordata == NULL) + { + return 1; + } + int pitch = width; + int offset; + + int point_is_err = 0; + int wLineErrsList = 0; + int errPos_xList = 0; + int difSumList = 0; + int point_is_errList = 0; + + // memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); + + ERROR_DOTS_SCAN_ROW rowDataTab[2]; + ERROR_DOTS_SCAN_ROW *curRow = 0; + ERROR_DOTS_SCAN_ROW *prevRow = 0; + + int MIN_AREA = minArea; + if (minArea <= 0) + { + MIN_AREA = 10; + } + + int minEnergy = 2; + int mergeDistanceX = 1; + int mergeDistanceY = 1; + offset = 0; + int nErrorType = 0; + int lasttype = -1; + + for (int y = 0; y < height; y++) + { + wLineErrsList = 0; + difSumList = 0; + curRow = rowDataTab + (y & 1); + curRow->scanCount = 0; + offset = y * pitch - 1; + nErrorType = -1; + lasttype = -1; + int kh = 0; + for (int x = 0; x < width; x++) + { + offset++; + point_is_err = 0; + if (pErrordata[offset] != 0 && pImgdata[offset] > basev) + { + point_is_err = 1; + difSumList += 1; + wLineErrsList++; + errPos_xList = x; + kh = 1; + } + else // 没有残点 所有缺陷都需要判断是否截止 + { + // 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点 + if (wLineErrsList > 0) + { + AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); + wLineErrsList = 0; + difSumList = 0; + } + kh = 0; + } + + if (x == width - 1) + { + if (wLineErrsList > 0) + { + AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); + } + } + } + + LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); + + prevRow = curRow; + } + + LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); + ERROR_DOTS_BLOB_PARAM blobParam; + memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM)); + blobParam.mergeDistance = 1; + MergeBlob(blobs, &blobParam); + SortBlob(blobs); + + return 0; +} diff --git a/AlgorithmModule/src/CUDA_Det.cu b/AlgorithmModule/src/CUDA_Det.cu new file mode 100644 index 0000000..a959262 --- /dev/null +++ b/AlgorithmModule/src/CUDA_Det.cu @@ -0,0 +1,56 @@ + +#include "CUDA_Det.cuh" + +__global__ void test_print() +{ + + printf("Hello World!\n"); + int index = threadIdx.z * blockDim.x * blockDim.y + + threadIdx.y * blockDim.x + + threadIdx.x; + + int x = blockIdx.x * blockDim.x + threadIdx.x; + int y = blockIdx.y * blockDim.y + threadIdx.y; + printf("blockIdx.x %d blockDim.x %d, threadIdx.x %d\n", blockIdx.x, blockDim.x, threadIdx.x); + printf("block idx: (%3d, %3d, %3d), thread idx: %3d, cord: (%3d, %3d)\n", + blockIdx.z, blockIdx.y, blockIdx.x, + index, x, y); +} +__global__ void ucharToFloat(const unsigned char *input, float *output, int size) +{ + int tid = blockIdx.x * blockDim.x + threadIdx.x; + if (tid < size) + { + output[tid] = static_cast(input[tid]); + } +} +__global__ void floatToUchar(const float *input, unsigned char *output, int size) +{ + int tid = blockIdx.x * blockDim.x + threadIdx.x; + if (tid < size) + { + output[tid] = static_cast(input[tid]); + } +} +void wrap_test_print() +{ + test_print<<<5, 6>>>(); + cudaDeviceSynchronize(); + return; +} + +void Cuda_ucharToFloat(const unsigned char *input, float *output, int size) +{ + cudaDeviceSynchronize(); + int blockSize = 1024; + int numBlocks = (size + blockSize - 1) / blockSize; + ucharToFloat<<>>(input, output, size); +} + +void Cuda_FloatTouchar(const float *input, unsigned char *output, int size) +{ + cudaDeviceSynchronize(); + int blockSize = 1024; + int numBlocks = (size + blockSize - 1) / blockSize; + floatToUchar<<>>(input, output, size); +} diff --git a/AlgorithmModule/src/CameraCheckAnalysisy.cpp b/AlgorithmModule/src/CameraCheckAnalysisy.cpp new file mode 100644 index 0000000..90c042a --- /dev/null +++ b/AlgorithmModule/src/CameraCheckAnalysisy.cpp @@ -0,0 +1,1547 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2025-07-26 12:02:26 + * @LastEditors: xiewenji 527774126@qq.com + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "CameraCheckAnalysisy.hpp" +#include "CheckUtil.hpp" +#include "Define.h" +#include "QX_Analysis.h" + +CameraCheckAnalysisy::CameraCheckAnalysisy() +{ + m_pCamera_Check_Result = nullptr; + m_nErrorCode = 0; // 错误代码 + m_bInitSucc = false; // 初始化状态 + m_bExit = false; // 是否退出检测 + m_bHaveImgeDet = false; + m_ncamera_idx = 0; + m_strCameraName = ""; + nLastCheckAnalysisyThreadIdx = 0; + m_pChannelFuntion = &m_AnalysisyConfig.checkFunction; + m_pbaseCheckFunction = &m_AnalysisyConfig.baseFunction; +} + +CameraCheckAnalysisy::~CameraCheckAnalysisy() +{ +} + +int CameraCheckAnalysisy::set_cpu_id(const std::vector &cpu_set_vec) +{ + // for cpu affinity + int nRet = 0; +#ifdef __linux + cpu_set_t _cur_cpu_set; + CPU_ZERO(&_cur_cpu_set); + for (auto _id : cpu_set_vec) + { + CPU_SET(_id, &_cur_cpu_set); + } + if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set)) + { + perror("set cpu affinity failed: "); + printf("Warning: set cpu affinity failed ... ...\n"); + nRet = -1; + } +#endif //__linux + return nRet; +} +int CameraCheckAnalysisy::WaitDetImg() +{ + std::unique_lock lk(mtx_WaiteImg); + cond_WaiteImg.wait(lk, [this]() + { return m_bHaveImgeDet; }); + + lk.unlock(); + + return 0; +} +int CameraCheckAnalysisy::Detect_Pre() +{ + // L255 通道 + std::shared_ptr L255 = NULL; + + std::string strlog = ""; + std::string strSN; + std::string strBasic; + int channelidx = 0; + + { + // 获取 L255 + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + strSN = m_pCamera_Check_Result->strSN; + strBasic = ">>" + strSN + " cam:" + m_strCameraName.c_str(); + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s CameraCheckAnalysisy Detect_Pre start....", strBasic.c_str()); + AddStrToLog_New(strlog); + for (int i = 0; i < m_pCamera_Check_Result->DetImageList.size(); i++) + { + if (m_pCamera_Check_Result->DetImageList.at(i)->basicResult.strChannel == "L255") + { + L255 = m_pCamera_Check_Result->DetImageList.at(i); + channelidx = i; + } + } + } + + if (L255 == NULL || L255->in_shareImage->img.empty()) + { + if (L255->in_shareImage->img.empty()) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s --L255 is NULL %d ", strBasic.c_str(), channelidx); + AddStrToLog_New(strlog); + } + + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s --L255 is NULL %d ", strBasic.c_str(), channelidx); + AddStrToLog_New(strlog); + return CHECK_ERROR_L255_Empty; + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s --start Edge Run Mode %d", strBasic.c_str(), L255->in_shareImage->Det_Mode); + AddStrToLog_New(strlog); + + // 1、边界搜索 + int re = 0; + // cv::Mat mask; + cv::Rect cutRoi; + + ChannelCheckFunction *pFuntion_L255 = GetChannelFuntion("L255"); + if (!pFuntion_L255) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s --L255 function is error ", strBasic.c_str()); + AddStrToLog_New(strlog); + return CHECK_ERROR_Config_Null; + } + + Function_EdgeROI *pEdgeROI; + pEdgeROI = &pFuntion_L255->function.f_EdgeROI; + pEdgeROI->print("L255"); + // AI 检测的参数模式 + + AI_detConfig.Init(); + AI_detConfig.saveProcessImg = AI_Edge_Algin::Save_Close; + AI_detConfig.nAIErodesize = pEdgeROI->AI_Erode_Size; + AI_detConfig.bUseDrawRoi_Check = pEdgeROI->AI_Fail_UseDraw; + AI_detConfig.ncamId = m_ncamera_idx; + AI_detConfig.strCamName = m_strCameraName; + if (AI_detConfig.bUseDrawRoi_Check) + { + AI_detConfig.drawMask = pEdgeROI->EdgeMask; + } + + if (pEdgeROI->pointArry1.size() <= 0) + { + AI_detConfig.bUseDrawRoi_Check = false; + strlog = m_PrintLog.printstr(Print_Level_Error, "Edge", "Draw roi param error"); + AddStrToLog_New(strlog); + } + AI_detConfig.drawRoi = cv::boundingRect(pEdgeROI->pointArry1); + if (pEdgeROI->EdgeMask.empty()) + { + AI_detConfig.bUseDrawRoi_Check = false; + strlog = m_PrintLog.printstr(Print_Level_Error, "Edge", "Draw roi param error"); + } + + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + m_pCamera_Check_Result->detMode = L255->in_shareImage->Det_Mode; + } + + if (L255->in_shareImage->Det_Mode == DET_MODE_EDGE) + { + AI_detConfig.bUseDrawRoi_Check = false; + AI_detConfig.saveProcessImg = AI_Edge_Algin::Save_Filter; + if (L255->in_shareImage->ninstruct == 999) + { + pEdgeROI->Use_DrawROI = 0; + pEdgeROI->Use_AIEdge = 1; + } + } + + if (L255->in_shareImage->bsaveProcessImg) + { + AI_detConfig.bSaveResultImg = true; + } + // printf("L255->in_shareImage->otherValue %d\n", L255->in_shareImage->otherValue); + + re = ImgEdge(L255->in_shareImage->img, pEdgeROI->Use_DrawROI, + pEdgeROI->EdgeMask, pEdgeROI->threshold_value, + pEdgeROI->AI_Erode_Size, pEdgeROI->Use_AIEdge, + m_pCamera_Check_Result->sheildImg, cutRoi, 0); + // 边界搜索有问题 + if (re != 0) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s --Edge is error", strBasic.c_str()); + AddStrToLog_New(strlog); + return CHECK_ERROR_L255_Edge_Fail; + } + + m_pCamera_Check_Result->CutRoi = cutRoi; + + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s --Edge is Succ", strBasic.c_str()); + AddStrToLog_New(strlog); + if (L255->in_shareImage->Det_Mode == DET_MODE_EDGE) + { + + L255->cutSrcimg = L255->in_shareImage->img; + cv::rectangle(L255->cutSrcimg, cutRoi, cv::Scalar(255, 255, 255)); + L255->resultimg = m_DetEdge.showimg; + L255->resultMaskImg = m_pCamera_Check_Result->sheildImg; + L255->nresult = 0; + return 0; + } + if (!m_DetEdge.detmask.empty()) + { + // m_pCamera_Check_Result->edge_SheildImg = m_DetEdge.detmask.clone(); + + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(40, 40)); + + // 对掩膜图像进行膨胀 + cv::dilate(m_DetEdge.detmask, m_pCamera_Check_Result->edge_SheildImg, kernel); + + /* code */ + } + + // 对齐 + m_align_Result.Init(); + m_align_Result.Crop_Roi_DetImg = cutRoi; + m_align_Result.Crop_Roi_ParmImg = cutRoi; + // 特征定位 :1、启用 AI搜边;2;检测的边缘图像存在 + if (pEdgeROI->Use_AIEdge && + !m_DetEdge.detmask.empty()) + { + + bool bsaveimg = false; + if (L255->in_shareImage->bsaveProcessImg) + { + bsaveimg = true; + } + bool bsaveprocessimg = false; + if (L255->in_shareImage->ninstruct == 898) + { + bsaveprocessimg = true; + } + + re = Feature_Align(L255->in_shareImage->img, 0, cutRoi, pFuntion_L255, m_DetEdge.detmask, bsaveimg, bsaveprocessimg); + } + + if (L255->in_shareImage->ninstruct == 898) + { + return CHECK_OK; + } + bool bmarksave = false; + // MarkLine 线检测 + if (DET_MODE_MarkLine == L255->in_shareImage->Det_Mode) + { + bmarksave = true; + } + if (L255->in_shareImage->bsaveProcessImg) + { + bmarksave = true; + } + Det_MarkLine(L255->in_shareImage->img, cutRoi, &m_pbaseCheckFunction->markLine, + m_pCamera_Check_Result->sheildImg, m_pCamera_Check_Result->markLine_Roi_X, + m_pCamera_Check_Result->markLine_Roi_Y, bmarksave); + + // MarkLine 线检测 + if (DET_MODE_MarkLine == L255->in_shareImage->Det_Mode) + { + return CHECK_OK; + } + + bool bYX_Det = false; + if (L255->in_shareImage->Det_Mode == DET_MODE_YX) + { + bYX_Det = true; + } + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s --start ZF ", strBasic.c_str()); + AddStrToLog_New(strlog); + + L255->in_shareImage->cutRoi = cutRoi; + DetImgInfo_shareP->pBaseImgCheckConfig = L255->in_shareImage; + + std::shared_ptr> pZF_roiList; // 字符的区域 + + // 2、字符检测 + preDet_ZF(DetImgInfo_shareP, m_OneImg_Result_shareP); + + // 字符区域需要屏蔽,把屏蔽maks对应的字符区域设置成255 + pZF_roiList = m_OneImg_Result_shareP->pZF_roiList; + + if (m_OneImg_Result_shareP->bShield_ZF) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "Shield_ZF "); + AddStrToLog_New(strlog); + for (int i = 0; i < pZF_roiList->size(); i++) + { + cv::Rect boundingRect = pZF_roiList->at(i); + m_pCamera_Check_Result->sheildImg(boundingRect).setTo(255); + } + if (L255->in_shareImage->bsaveProcessImg) + { + cv::imwrite("sheildImg.png", m_pCamera_Check_Result->sheildImg); + } + } + if (L255->in_shareImage->bsaveProcessImg) + { + cv::Mat showimg = L255->in_shareImage->img(cutRoi).clone(); + for (int i = 0; i < pZF_roiList->size(); i++) + { + cv::Rect boundingRect = pZF_roiList->at(i); + + cv::rectangle(showimg, boundingRect, cv::Scalar(200), 5); + } + cv::imwrite("zf_result.png", showimg); + } + + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s -- ZF is Succ zf num %zu", strBasic.c_str(), pZF_roiList->size()); + AddStrToLog_New(strlog); + if (DET_MODE_ZF == L255->in_shareImage->Det_Mode) + { + return 0; + } + return 0; +} +int CameraCheckAnalysisy::Detect_Images() +{ + + std::string strlog; + std::string strSN; + std::string strBasic; + + strSN = m_pCamera_Check_Result->strSN; + strBasic = ">>" + strSN + " cam:" + std::to_string(m_ncamera_idx); + printf("Detect_Images==================start \n"); + // 循环处理每个图片 + { + bool bcomplete = false; + long while_t1 = CheckUtil::getcurTime(); + int errorcount1 = 0; + int errorcount2 = 0; + + long time_wait_DetImg = 0; // 等待处理图片的时间 + long time_wait_GetResult = 0; // 等待获取结果的持续时间。 + bool bwait_UPImg = false; + bool bwait_DPImg = false; + while (!bcomplete) + { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); // + ImgCheckBase *pImgCheckAnalysisy = NULL; + + int detidx = -1; + long t1 = CheckUtil::getcurTime(); + // 1、结果处理 + while (true) + { + std::shared_ptr detImg; + + // 有检测完成的。 + if (1 == GetAndAnalysisyCheckResult(detImg)) + { + errorcount2 = 0; + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + + m_pCamera_Check_Result->pImageDetResultList.push_back(detImg); + + int idx = detImg->pBaseImgCheckResult->in_shareImage->img_id; + detImg->pBaseImgCheckResult->nDetStep = 1; + // 如果出现错误,则把结果 初始化 。强制 指定0通道。 + if (idx >= m_pCamera_Check_Result->DetImageList.size()) + { + detImg->pBaseImgCheckResult->Init(); + idx = 0; + } + + m_pCamera_Check_Result->DetImageList.at(idx) = detImg->pBaseImgCheckResult; + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s %s complete ", strBasic.c_str(), detImg->pBaseImgCheckResult->basicResult.strChannel.c_str()); + AddStrToLog_New(strlog); + if (detImg->pBaseImgCheckResult->basicResult.strChannel == "Down-Particle") + { + m_pCamera_Check_Result->DP_MaskImg = detImg->AI_maskImg; + m_pCamera_Check_Result->nDet_DP = 2; + // strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s Down-Particle complete ", strBasic.c_str()); + // AddStrToLog(productIdx, strlog); + } + if (detImg->pBaseImgCheckResult->basicResult.strChannel == "Up-Particle") + { + m_pCamera_Check_Result->Up_MaskImg = detImg->AI_maskImg; + m_pCamera_Check_Result->bDet_Up = true; + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s Up-Particle complete up mask %d ", + strBasic.c_str(), m_pCamera_Check_Result->Up_MaskImg.empty()); + AddStrToLog_New(strlog); + if (m_pCamera_Check_Result->Up_MaskImg.empty()) + { + printf("\n\n\n\n\n\n Up-Particle complete Up_MaskImg.empty() \n"); + } + } + } + + pImgCheckAnalysisy = GetDealResult(detidx); + if (pImgCheckAnalysisy != NULL) + { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); // + long t2 = CheckUtil::getcurTime(); + // 如果 超过秒10都没有 拿到处理资源,则,直接退出 + if (t2 - t1 > 10000) + { + break; + } + } + // 没有分析检测资源,直接退出 + if (pImgCheckAnalysisy == NULL) + { + // strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s pImgCheckAnalysisy IS NULL error", strBasic.c_str()); + // AddStrToLog(productIdx, strlog); + continue; + } + + // 2、送入新的检测图片 + { + bwait_UPImg = false; + bwait_DPImg = false; + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + + for (int i = 0; i < m_pCamera_Check_Result->DetImageList.size(); i++) + { + // 对没有检测过的通道进行 处理 + if (m_pCamera_Check_Result->DetImageList.at(i)->nDetStep == 0) + { + std::shared_ptr tem = m_pCamera_Check_Result->DetImageList.at(i)->in_shareImage; + std::shared_ptr detInConfig = std::make_shared(); + + ChannelCheckFunction *pFuntion = GetChannelFuntion(tem->strChannel); + + bool bUseUpImg = false; + // 没有获得该通道的信息 + if (pFuntion != NULL) + { + bUseUpImg = pFuntion->function.f_UseUpQX.bOpen; + } + // 是否需要DP 画面 + bool bUseDpResult = false; + if (pFuntion != NULL) + { + // 亮点检测 开启 + if (pFuntion->function.f_LDConfig.bOpen) + { + // 需要dp + bUseDpResult = pFuntion->function.f_LDConfig.bUseDP; + } + if (pFuntion->function.f_AIQX.bPOLToWhitePOL&&pFuntion->function.f_AIQX.b127WhitePOl_UseDP) + { + bUseDpResult = true; + } + + } + + // 如果 要使用Up 画 就需要等待 Up检测完成后,才能处理其他画面。 + if (!m_pCamera_Check_Result->bDet_Up && bUseUpImg) + { + if (tem->strChannel != "Up-Particle") + { + bwait_UPImg = true; + // 所有图都送进来完了,但是就是没有 up图片 + // 所有依赖up检测结果的通道都设置成未检。 + if (m_pCamera_Check_Result->cameraImage_Status.bImgComplete && + !m_pCamera_Check_Result->cameraImage_Status.bhave_UP) + { + m_pCamera_Check_Result->DetImageList.at(i)->nDetStep = 1; + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s >>>>>> %s NO UP img ,NO Det", strBasic.c_str(), tem->strChannel.c_str()); + AddStrToLog_New(strlog); + } + + continue; + } + } + tem->ninstruct = CHECK_INSTUCT_NULL; + // 非DP画面 需要判断 亮点检测 时 是否需要DP结果。 + if (tem->strChannel != "Down-Particle") + { + // 如果需要DP 结果,需要等待 dp 检测结束 == 1 表示还没计算完成 + if (bUseDpResult && m_pCamera_Check_Result->nDet_DP != 2) + { + bwait_DPImg = true; + // 所有图都送进来完了,但是就是没有 up图片 + // 所有依赖up检测结果的通道都设置成未检。 + if (m_pCamera_Check_Result->cameraImage_Status.bImgComplete && + !m_pCamera_Check_Result->cameraImage_Status.bHave_DP) + { + m_pCamera_Check_Result->DetImageList.at(i)->nDetStep = 1; + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s >>>>>> %s NO DP img ,NO Det", strBasic.c_str(), tem->strChannel.c_str()); + AddStrToLog_New(strlog); + } + continue; + } + } + // 需要指定 黑白画面 + if (tem->strChannel == "BTW" || + tem->strChannel == "WTB" || + tem->strChannel == "TBW" || + tem->strChannel == "HB3" || + tem->strChannel == "HB4") + { + tem->ninstruct |= CHECK_INSTUCT_WhiteAndBlack; + } + + tem->cutRoi = m_pCamera_Check_Result->CutRoi; + tem->other_channel_Result_mask = m_pCamera_Check_Result->sheildImg.clone(); + + tem->img_id = 0; + if (tem->otherValue_1 != 181) + { + tem->otherValue_1 = 18; + } + + detInConfig->pZF_roiList = m_OneImg_Result_shareP->pZF_roiList; + detInConfig->bUseUpMaskImg = bUseUpImg; + detInConfig->markLine_Roi_X = m_pCamera_Check_Result->markLine_Roi_X; + detInConfig->markLine_Roi_Y = m_pCamera_Check_Result->markLine_Roi_Y; + detInConfig->UpMaskImg = m_pCamera_Check_Result->Up_MaskImg; + detInConfig->DPMaskImg = m_pCamera_Check_Result->DP_MaskImg; + detInConfig->edge_maskImg = m_pCamera_Check_Result->edge_SheildImg; + detInConfig->alignResult.copy(m_align_Result); + printf("---------%s %d\n", tem->strChannel.c_str(), detInConfig->DPMaskImg.empty()); + // printf("other %d %d\n", tem->otherValue, tem->otherValue_1); + + tem->img_id = i; + errorcount1 = 0; + while_t1 = CheckUtil::getcurTime(); + tem->time_sendCheck = CheckUtil::getcurTime(); + detInConfig->pBaseImgCheckConfig = tem; + pImgCheckAnalysisy->SetDataRun_SharePtr(detInConfig); + m_pCamera_Check_Result->DetImageList.at(i)->nDetStep = 1; + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s >>>>>> CheckSO start %s ", strBasic.c_str(), tem->strChannel.c_str()); + AddStrToLog_New(strlog); + if (tem->otherValue == 9) + { + // getchar(); + } + + break; + } + } + } + + bool bImgSendComplete = false; + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + bImgSendComplete = m_pCamera_Check_Result->cameraImage_Status.bImgComplete; + } + + // 3、没有新图送进来,没有需要处理的图片,结果都已经处理。 这时候就可以退出 循环。 + // 3.1最后一张图已经完成 + if (bImgSendComplete) + { + // 3.2最后一张图已经完成 + bool bhavedet = false; + for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++) + { + + if (CHECK_THREAD_STATUS_IDLE != m_pImgCheckAnalysisy[i]->GetStatus()) + { + bhavedet = true; + } + } + bool bdet = false; + // if (!bhavedet) + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + for (int i = 0; i < m_pCamera_Check_Result->DetImageList.size(); i++) + { + // m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s >>>>>> nDetStep t %s %d", strBasic.c_str(), pProduct->DetImageList.at(i)->in_shareImage->strChannel.c_str(), pProduct->DetImageList.at(i)->nDetStep); + if (m_pCamera_Check_Result->DetImageList.at(i)->nDetStep == 0) + { + bdet = true; + break; + } + } + } + // printf("%s bhavedet %d bdet %d\n", strBasic.c_str(), bhavedet, bdet); + // 没有在处理的图片了&& 所有图片都已经处理完成 + // 检测结束 + if (!bhavedet && !bdet) + { + time_wait_DetImg = 0; + time_wait_GetResult = 0; + bcomplete = true; + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s -- Check commplete ", strBasic.c_str()); + AddStrToLog_New(strlog); + } + // 没有在处理的图片了&& 还有没有送入到处理线程处理的图片。同时所有图片已经送完了。 + // 此时需要 评估是否有问题,应当等待一定时间后,强制结束。 + else if (!bhavedet && bdet) + { + time_wait_GetResult = 0; + long t1 = CheckUtil::getcurTime(); + if (time_wait_DetImg == 0) + { + time_wait_DetImg = t1; + } + else + { + long waitTime = t1 - time_wait_DetImg; + // 这种状态持续 超过10秒,则强制退出。 + if (waitTime > 15 * 1000) + { + bcomplete = true; + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s -- exit check: wait Det bwait_UPImg %d bwait_DPImg %d, time > 6 * 1000 ", strBasic.c_str(), bwait_UPImg, bwait_DPImg); + AddStrToLog_New(strlog); + } + } + } + // 处理线程还在处理 && 所有图片都已经 送到处理线程进行处理了 。同时所有图片已经送完了。 + // 此时需要 评估是否有问题,应当等待一定时间后,强制结束。 + else if (bhavedet && !bdet) + { + time_wait_DetImg = 0; + long t1 = CheckUtil::getcurTime(); + if (time_wait_GetResult == 0) + { + time_wait_GetResult = t1; + } + else + { + long waitTime = t1 - time_wait_GetResult; + // printf("%s waitTime %ld \n",strBasic.c_str(),waitTime,waitTime); + // 这种状态持续 超过10秒,则强制退出。 + if (waitTime > 15 * 1000) + { + bcomplete = true; + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s -- exit check: wait Get result time > 10 * 1000 ", strBasic.c_str()); + AddStrToLog_New(strlog); + } + } + // 有在分析的了, 没有检测的图片了。同时所有图片已经送完了。等待所有分析完成。 + // errorcount2++; + // if (errorcount2 > 800) + // { + // bcomplete = true; + // strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s -- exit check: errorcount2 > 800 ", strBasic.c_str()); + // AddStrToLog(productIdx, strlog); + // } + } + } + else + { + long while_t2 = CheckUtil::getcurTime(); + // 20 都还么有送完所有图片,则直接退出。 + if (while_t2 - while_t1 > 20 * 1000) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "DetAllImg", "%s -- exit check: time out ", strBasic.c_str()); + AddStrToLog_New(strlog); + break; + } + } + } + } + strlog = m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "%s -- Check End ", strBasic.c_str()); + AddStrToLog_New(strlog); + return 0; +} +int CameraCheckAnalysisy::Init(Camera_IDX camera_ID) +{ + m_camera_ID = camera_ID; + m_ncamera_idx = static_cast(m_camera_ID); + int re = 0; + re = InitCheckAnalysisy(); + if (CHECK_OK != re) + { + printf("InitCheckAnalysisy error\n"); + return -1; + } + re = m_DetEdge.InitRun(); + if (CHECK_OK != re) + { + printf("m_DetEdge.InitRun error\n"); + return -1; + } + InitMarkLine(); + + re = InitRun(); + if (CHECK_OK != re) + { + printf("InitRun error\n"); + m_nErrorCode = re; + return m_nErrorCode; + } + InitMarkLine(); + m_strCameraName = m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName; + + DetImgInfo_shareP = std::make_shared(); + return 0; +} + +int CameraCheckAnalysisy::StartCheck(std::shared_ptr pCamera_Check_Result) +{ + if (m_bHaveImgeDet) + { + return -1; + } + { + std::lock_guard lock(mtx_WaiteImg); + m_pCamera_Check_Result = pCamera_Check_Result; + m_bHaveImgeDet = true; + } + cond_WaiteImg.notify_all(); + return 0; +} +int CameraCheckAnalysisy::StartThread() +{ + m_bExit = false; + // 开启检测线程 + ptr_thread_Run = std::make_shared(std::bind(&CameraCheckAnalysisy::Run, this)); + return 0; +} +int CameraCheckAnalysisy::StopThread() +{ + m_bExit = true; + if (ptr_thread_Run != nullptr) + { + if (ptr_thread_Run->joinable()) + { + ptr_thread_Run->join(); + } + } + return 0; +} +int CameraCheckAnalysisy::InitRun() +{ + int re; + re = StartThread(); + if (CHECK_OK != re) + { + return re; + } + m_bInitSucc = true; + // 检测前更新参数 + SetNewConfig(); + return 0; +} +int CameraCheckAnalysisy::InitCheckAnalysisy() +{ + + printf("m_ncamera_idx %d ======= \n", m_ncamera_idx); + int re = 0; + int m_nMAX_GPU_NUM = MAX_GPU_NUM; + if (m_nMAX_GPU_NUM <= 0) + { + printf(">>>>error GPU error %d \n", m_nMAX_GPU_NUM); + return 2; + } + + for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++) + { + RunInfoST RunConfig; + if (i % m_nMAX_GPU_NUM == 0) + { + RunConfig.nDeviceId = 0; + } + else + { + RunConfig.nDeviceId = 1; + } + + RunConfig.nThreadIdx = i; + if (m_RunConfig.bRetest) + { + RunConfig.nThreadIdx = IMGCHECKANALYSISY_NUM + i; + RunConfig.bRetest = true; + } + + RunConfig.nCpu_start_Idx = m_RunConfig.nCpu_start_Idx + i * 4; + RunConfig.nCpu_num = 4; + + m_pImgCheckAnalysisy[i] = ImgCheckBase::GetInstance(); + re = m_pImgCheckAnalysisy[i]->UpdateConfig((void *)&RunConfig, CHECK_CONFIG_Run); + if (re != 0) + { + printf("UpdateConfig %d Fail %s\n", CHECK_CONFIG_Run, m_pImgCheckAnalysisy[i]->GetErrorInfo().c_str()); + return re; + } + re = m_pImgCheckAnalysisy[i]->UpdateConfig((void *)m_pConfig, CHECK_CONFIG_Module); + if (re != 0) + { + printf("UpdateConfig %d Fail %s\n", CHECK_CONFIG_Module, m_pImgCheckAnalysisy[i]->GetErrorInfo().c_str()); + return re; + } + + re = m_pImgCheckAnalysisy[i]->RunStart(); + if (re != 0) + { + printf("camidx %d RunStart Fail ==%d\n", m_ncamera_idx, re); + return re; + } + printf(">>>>camidx %d CameraCheckAnalysisy InitCheckAnalysisy: ImgCheckThread %d / %d Start Succ \n", m_ncamera_idx, i, IMGCHECKANALYSISY_NUM); + + if (re != 0) + { + return re; + } + } + + return 0; +} +int CameraCheckAnalysisy::CheckImgRun() +{ + + int re = 0; + Check_Step curcheckStep; + bool bhaveL255; + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + curcheckStep = m_pCamera_Check_Result->checkStep; // 当前检测状态 + bhaveL255 = m_pCamera_Check_Result->cameraImage_Status.bHave_L255; + } + // printf("curcheckStep:%d det model %d\n", curcheckStep,); + // 如果是未检测状态,则开始预处理 + if (curcheckStep == Check_Step_NODet) + { + // 如果还没有 L255 图 则直接返回。 + if (!bhaveL255) + { + // printf("========came %s wait ......................... pre Det \n",m_strCameraName.c_str()); + return 1; + } + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + m_pCamera_Check_Result->checkStep = Check_Step_PreDet; // 进入到预处理阶段 + curcheckStep = m_pCamera_Check_Result->checkStep; // 当前检测状态 + } + } + // 检测前更新参数 + SetNewConfig(); + // 预处理 + if (curcheckStep == Check_Step_PreDet) + { + printf("========came %s start pre Det \n", m_strCameraName.c_str()); + // 预处理 + re = Detect_Pre(); + if (re != 0) + { + printf("========came %s pre Det Fail \n", m_strCameraName.c_str()); + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + // 预处理 错误,则 停止检测 检测完成,状态设置成 error。 + m_pCamera_Check_Result->Set_Det_Step_Result(Check_Step_ImgeDet_End, Check_Result_Status_PreError); + } + return re; + } + { + + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + m_pCamera_Check_Result->checkStep = Check_Step_ImgeDet; // 进入到预图片检测阶段 + curcheckStep = m_pCamera_Check_Result->checkStep; // 当前检测状态 + } + } + bool bDetImage = false; + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + + if (m_pCamera_Check_Result->detMode == DET_MODE_Det) + { + bDetImage = true; + } + } + + // 检测每张图片 + if (curcheckStep == Check_Step_ImgeDet) + { + + if (bDetImage) + { + // 检测每张图片 + Detect_Images(); + } + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + m_pCamera_Check_Result->checkStep = Check_Step_ImgeDet_End; + curcheckStep = m_pCamera_Check_Result->checkStep; // 当前检测状态 + } + } + + if (curcheckStep == Check_Step_ImgeDet_End) + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + // 所有图片都送完了。 + if (m_pCamera_Check_Result->cameraImage_Status.bImgComplete) + { + + m_pCamera_Check_Result->checkStep = Check_Step_Complete; + curcheckStep = m_pCamera_Check_Result->checkStep; // 当前检测状态 + } + else + { + printf("========came %s wait img send end \n", m_strCameraName.c_str()); + } + } + + // 检测完成, + if (curcheckStep == Check_Step_Complete) + { + InsertCameraLog(); + printf("InsertCameraLog:%d \n", curcheckStep); + std::lock_guard lock(mtx_WaiteImg); + m_bHaveImgeDet = false; + m_pCamera_Check_Result.reset(); + printf("========came %s Check ALL end \n", m_strCameraName.c_str()); + } + + return 0; +} +int CameraCheckAnalysisy::AddStrToLog_New(std::string str) +{ + if (m_pCamera_Check_Result) + { + m_pCamera_Check_Result->AddLog(str); + } + + return 0; +} +int CameraCheckAnalysisy::Run() +{ + + while (!m_bExit) + { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + WaitDetImg(); + int re = CheckImgRun(); + // int re = Det_Product(); + // // 检测失败 + // if (re != 0) + // { + // continue; + // } + // SetSetComplet_New(0, 0); + } + + return 0; +} + +int CameraCheckAnalysisy::ImgEdge(cv::Mat img, bool bUseDraw, const cv::Mat ¶MaskImg, int thresholdvalue, int AIErodesize, bool bUseAIDet, cv::Mat &detMaskImg, cv::Rect &roi, int productIdx) +{ + int re = 0; + if (img.empty()) + { + return 1; + } + std::string strlog = ""; + printf("11111111111111111111111ImgEdge111111111111111111111111\n"); + long t1 = CheckUtil::getcurTime(); + bool bsucc = false; + // AI 搜索边界 + if (bUseAIDet) + { // AI 搜索边界 + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "AI Edge start"); + AddStrToLog_New(strlog); + + re = m_DetEdge.AIEdgeDete(img, &AI_detConfig, detMaskImg, roi); + if (re == 0) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "AI Edge Succ"); + AddStrToLog_New(strlog); + return 0; + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "AI Edge Error re = %d", re); + AddStrToLog_New(strlog); + } + if (AI_detConfig.bUseDrawRoi_Check) + { + bUseDraw = true; + } + } + re = 0; + if (bUseDraw) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "UseDraw ROI"); + AddStrToLog_New(strlog); + if (!paraMaskImg.empty()) + { + // cv::imwrite("paraMaskImg.png", paraMaskImg); + if (img.size() == paraMaskImg.size()) + { + m_DetEdge.detmask = paraMaskImg; + // 查找轮廓 + std::vector> contours; + std::vector hierarchy; + cv::findContours(paraMaskImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + // 找到最大轮廓 + int max_contour_index = -1; + double max_area = 0; + + for (size_t i = 0; i < contours.size(); i++) + { + double area = cv::contourArea(contours[i]); + if (area > max_area) + { + max_area = area; + max_contour_index = i; + } + } + if (max_contour_index >= 0) + { + roi = cv::boundingRect(contours[max_contour_index]); + bsucc = true; + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", " roi %d %d %d %d ", roi.x, roi.y, roi.width, roi.height); + AddStrToLog_New(strlog); + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "MaskImg is Error"); + AddStrToLog_New(strlog); + } + + // 计算最大轮廓的外接矩形 + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "MaskImg size != det img size"); + AddStrToLog_New(strlog); + } + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "config MaskImg is empty"); + AddStrToLog_New(strlog); + } + } + + if (!bsucc) + { + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "Detect Edge start"); + AddStrToLog_New(strlog); + re = m_DetEdge.GetImgEdge(img, roi); + } + + long t2 = CheckUtil::getcurTime(); + strlog = m_PrintLog.printstr(Print_Level_Info, "ImgEdge", "use time %ld", t2 - t1); + AddStrToLog_New(strlog); + // printf("cutRoi %d %d %d %d \n", roi.x, roi.y, roi.width, roi.height); + if (roi.x < 0 || roi.y < 0 || roi.width <= 0 || roi.height <= 0) + { + return 1; + } + if (roi.x + roi.width > img.cols) + { + return 1; + } + if (roi.y + roi.height > img.rows) + { + return 1; + } + if (!bsucc) + { + detMaskImg = cv::Mat(roi.height, roi.width, CV_8U, cv::Scalar(0)); + + for (int i = 0; i < 4; i++) + { + int detH = 60; + cv::Rect cutroi; + cv::Rect maskRoi; + + switch (i) + { + case 0: + cutroi.x = roi.x; + cutroi.y = roi.y; + + cutroi.width = roi.width; + cutroi.height = detH; + + maskRoi.x = 0; + maskRoi.y = 0; + maskRoi.width = roi.width; + maskRoi.height = detH; + break; + case 1: + cutroi.x = roi.x; + cutroi.y = roi.y + roi.height - detH; + + cutroi.width = roi.width; + cutroi.height = detH; + + maskRoi.x = 0; + maskRoi.y = roi.height - detH; + maskRoi.width = roi.width; + maskRoi.height = detH; + + break; + case 2: + + cutroi.x = roi.x; + cutroi.y = roi.y; + + cutroi.width = detH; + cutroi.height = roi.height; + + maskRoi.x = 0; + maskRoi.y = 0; + maskRoi.width = detH; + maskRoi.height = roi.height; + + break; + case 3: + cutroi.x = roi.x + roi.width - detH; + cutroi.y = roi.y; + + cutroi.width = detH; + cutroi.height = roi.height; + + maskRoi.x = roi.width - detH; + maskRoi.y = 0; + maskRoi.width = detH; + maskRoi.height = roi.height; + break; + default: + break; + } + + int threshold_value = 11; // 你可以根据需要调整阈值 + + int max_value = 255; // 最大像素值,白色 + int threshold_type = cv::THRESH_BINARY_INV; // 将高于阈值的像素设为白色,低于阈值的像素设为黑色 + cv::Mat temimg; + cv::threshold(img(cutroi), temimg, threshold_value, max_value, threshold_type); + + // 定义膨胀核 + int dilation_size = 13; // 膨胀核的大小 + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(dilation_size, dilation_size + 8)); + + // 进行膨胀操作 + cv::Mat dilated_image; + cv::dilate(temimg, detMaskImg(maskRoi), kernel); + } + } + else + { + detMaskImg = paraMaskImg(roi).clone(); + detMaskImg = ~detMaskImg; + if (thresholdvalue > 0) + { + int threshold_value = 11; // 你可以根据需要调整阈值 + if (thresholdvalue >= 0 && thresholdvalue < 255) + { + threshold_value = thresholdvalue; + } + int max_value = 255; // 最大像素值,白色 + int threshold_type = cv::THRESH_BINARY_INV; // 将高于阈值的像素设为白色,低于阈值的像素设为黑色 + + cv::Mat temimg; + cv::threshold(img(roi), temimg, threshold_value, max_value, threshold_type); + printf("threshold_value %d\n", threshold_value); + // 定义膨胀核 + int dilation_size = 7; // 膨胀核的大小 + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(dilation_size, dilation_size + 8)); + + // 进行膨胀操作 + cv::Mat dilated_image; + cv::dilate(temimg, dilated_image, kernel); + printf("detMaskImg= %d %d %d\n", detMaskImg.cols, detMaskImg.rows, detMaskImg.channels()); + printf("dilated_image= %d %d %d\n", dilated_image.cols, dilated_image.rows, dilated_image.channels()); + detMaskImg += dilated_image; + } + } + return re; +} + +int CameraCheckAnalysisy::InsertCameraLog() +{ + { + std::lock_guard lock(m_pCamera_Check_Result->mtx_Det); + + for (int i = 0; i < m_pCamera_Check_Result->DetImageList.size(); i++) + { + + std::shared_ptr temresult = m_pCamera_Check_Result->DetImageList.at(i); + // 如果检测结果为预处理错误 + if (m_pCamera_Check_Result->checkResultStatus == Check_Result_Status_PreError) + { + // 检测错误 状态 bad roi + temresult->checkStatus = 1; + temresult->nresult = Check_Result_Status_PreError; + } + + temresult->det_LogList.insert(temresult->det_LogList.end(), m_pCamera_Check_Result->LogList.begin(), m_pCamera_Check_Result->LogList.end()); + } + } + return 0; +} +ChannelCheckFunction *CameraCheckAnalysisy::GetChannelFuntion(std::string strChannelName) +{ + ChannelCheckFunction *p = NULL; + // printf("m_pChannelFuntion->channelFunctionArr.size() %zu\n", m_pChannelFuntion->channelFunctionArr.size()); + for (int i = 0; i < m_pChannelFuntion->channelFunctionArr.size(); i++) + { + if (CheckUtil::compareIgnoreCase(m_pChannelFuntion->channelFunctionArr[i].strChannelName, strChannelName)) + { + p = &m_pChannelFuntion->channelFunctionArr[i]; + } + } + + return p; +} +int CameraCheckAnalysisy::SetNewConfig() +{ + if (m_pConfig == NULL) + { + return 1; + } + + if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, MAX_USER_COUNT - 2)) + { + m_pConfig->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig); + printf("***************CameraCheckAnalysisy m_pConfig*************** Update GetConfig \n"); + m_AnalysisyConfig.checkFunction.print("Update GetConfig"); + } + + return 0; +} + +int CameraCheckAnalysisy::InitMarkLine() +{ + // 获取当前gpu号确定的 AI处理线程 + m_AIDeal.Init(0); + m_OtherDet_Config.nDeviceId = 0; + m_OtherDet_Config.pAIDeal = &m_AIDeal; + + m_OtherDet_Config.pTemCheck = &m_TemCheck; + + m_MarkDet.Init(&m_OtherDet_Config); + m_MarkDet.InitModel_ALL(); + + return 0; +} + +int CameraCheckAnalysisy::Feature_Align(const cv::Mat &detSrcImg, int nproductIdx, cv::Rect Det_CropRoi, ChannelCheckFunction *pFuntion_L255, const cv::Mat &detImg_mask, bool bsave, bool bsaveprocessimg) +{ + // 1、要使用 AI 搜边。 + // 2、对齐开关要开启 + // 3、特征maks不为空 + // 4、边缘mask不为空 + + if (!pFuntion_L255) + { + return 1; + } + std::string strlog = ""; + Function_Image_Align *pAlign; + pAlign = &pFuntion_L255->function.f_Image_Align; + + if (pAlign->bOpen && + !pAlign->feature_Mask.empty()) + { + // cv::imwrite("Align_search_img.png", m_DetEdge.detmask(pFuntion_L255->function.f_Image_Align.search_Roi).clone()); + // cv::imwrite("Align_Kernel_img.png", pFuntion_L255->function.f_Image_Align.feature_Mask); + // cv::imwrite("detmaskssss.png", m_DetEdge.detmask); + // cv::imwrite("ssss.png", L255->in_shareImage->img); + CheckUtil::printROI(Det_CropRoi, "Det Img Crop Roi"); + CheckUtil::printROI(pAlign->Crop_Roi, "Param Img Crop Roi"); + Image_Feature_Algin::DetConfig detconfig; + detconfig.DetImg = detImg_mask; + detconfig.TemplateImg = pAlign->feature_Mask; + detconfig.Search_Roi = pAlign->search_Roi; + detconfig.feature_Roi = pAlign->feature_Roi; + detconfig.param_CropRoi = pAlign->Crop_Roi; + detconfig.DetImg_CropROi = Det_CropRoi; + detconfig.bSaveImg = bsave; + detconfig.fscore = pAlign->fscore; + + long t1 = CheckUtil::getcurTime(); + m_Image_Feature_Algin.Detect(&detconfig, &m_align_Result, m_pCamera_Check_Result->LogList); + long t2 = CheckUtil::getcurTime(); + strlog = m_PrintLog.printstr(Print_Level_Info, "Image_Align", "use time %ld ", t2 - t1); + + AddStrToLog_New(strlog); + m_align_Result.bDraw = pAlign->bDraw; + + // 对齐成功 + if (m_align_Result.bDet) + { + if (pAlign->runType == Function_Image_Align::type_Use) + { + m_align_Result.bUse = true; + } + // 更新 特征图像区域在检测图片上的位置。 + for (const auto &point : pFuntion_L255->function.f_Image_Align.pointArry1) + { + cv::Point p = point; + cv::Point ss = m_align_Result.Parm_srcToDet_Crop_Point(p); + m_align_Result.feature_PointList_DetImg.push_back(ss); + } + + if (m_align_Result.Crop_Roi_ParmImg.x < 0) + { + m_align_Result.Crop_Roi_ParmImg.x = 0; + } + if (m_align_Result.Crop_Roi_ParmImg.x + m_align_Result.Crop_Roi_ParmImg.width > detSrcImg.cols) + { + m_align_Result.Crop_Roi_ParmImg.x = detSrcImg.cols - m_align_Result.Crop_Roi_ParmImg.width; + } + if (m_align_Result.Crop_Roi_ParmImg.y < 0) + { + m_align_Result.Crop_Roi_ParmImg.y = 0; + } + if (m_align_Result.Crop_Roi_ParmImg.y + m_align_Result.Crop_Roi_ParmImg.height > detSrcImg.rows) + { + m_align_Result.Crop_Roi_ParmImg.y = detSrcImg.rows - m_align_Result.Crop_Roi_ParmImg.height; + } + + if (bsaveprocessimg) + { + static int erridx = 0; + std::string str_search; + std::string str_Kenerl; + { + + erridx++; + if (erridx > 9999999) + { + erridx = 0; + /* code */ + } + if (!detImg_mask.empty() && !CheckUtil::RoiInImg(pAlign->search_Roi, detImg_mask)) + { + str_search = "/home/aidlux/BOE/Align/" + std::to_string(erridx) + "_search.png"; + cv::imwrite(str_search, detImg_mask(pAlign->search_Roi).clone()); + } + + if (!pAlign->feature_Mask.empty()) + { + str_Kenerl = "/home/aidlux/BOE/Align/" + std::to_string(erridx) + "_Kernel.png"; + cv::imwrite(str_Kenerl, pAlign->feature_Mask); + } + + if (!pAlign->feature_Mask.empty() && !detSrcImg.empty() && !CheckUtil::RoiInImg(pAlign->search_Roi, detSrcImg)) + { + + cv::Mat srcimg = detSrcImg(pAlign->search_Roi).clone(); + + cv::Mat TemplateFeature; + cv::Size sz; + sz.width = int(pAlign->feature_Mask.cols * m_align_Result.fCropROI_Scale_ParmToDet_X); + sz.height = int(pAlign->feature_Mask.rows * m_align_Result.fCropROI_Scale_ParmToDet_Y); + cv::resize(pAlign->feature_Mask, TemplateFeature, sz); + + cv::Rect roi_moban; + cv::Rect det_src_feature_roi = m_align_Result.Parm_srcToDet_src_Rect(pAlign->feature_Roi); + CheckUtil::printROI(det_src_feature_roi, "det_src_feature_roi"); + + roi_moban.x = det_src_feature_roi.x - pAlign->search_Roi.x; + roi_moban.y = det_src_feature_roi.y - pAlign->search_Roi.y; + roi_moban.width = TemplateFeature.cols; + roi_moban.height = TemplateFeature.rows; + + if (!CheckUtil::RoiInImg(roi_moban, srcimg)) + { + cv::Mat temimg = srcimg(roi_moban); + temimg += TemplateFeature * 0.5; + + std::string str_src = "/home/aidlux/BOE/Align/" + std::to_string(erridx) + "_show.png"; + cv::imwrite(str_src, srcimg); + } + } + } + } + } + } + else + { + if (!pAlign->bOpen) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", "-- error :Align Param Close"); + } + else if (pAlign->feature_Mask.empty()) + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", " -- error :AI Edge Det Error"); + } + else + { + strlog = m_PrintLog.printstr(Print_Level_Error, "Image_Align", " -- error :Align Param Error"); + } + + AddStrToLog_New(strlog); + } + return 0; +} + +int CameraCheckAnalysisy::preDet_ZF(std::shared_ptr p, std::shared_ptr &pResult) +{ + ImgCheckBase *pImgCheckAnalysisy = NULL; + long t1 = CheckUtil::getcurTime(); + int outTime = 1000 * 5; + while (true) + { + + pImgCheckAnalysisy = GetDealResult(-1); + if (pImgCheckAnalysisy != NULL) + { + break; + } + long t2 = CheckUtil::getcurTime(); + // 超时 + if (t2 - t1 > outTime) + { + return 1; + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); // 模拟消费过程 + } + p->pBaseImgCheckConfig->imgtype = 1; + pImgCheckAnalysisy->CheckImg(p, pResult); + p->pBaseImgCheckConfig->imgtype = 0; + return 0; +} + +int CameraCheckAnalysisy::Det_MarkLine(const cv::Mat &detSrcImg, cv::Rect Det_CropRoi, Base_Function_MarkLine *pFuntion, cv::Mat &detImg_mask, cv::Rect &markRoi_x, cv::Rect &markRoi_y, bool bsaveprocessimg) +{ + printf("\n\n\nDet_MarkLine -- 1 \n"); + if (pFuntion && !pFuntion->bOpen) + { + return 0; + } + + AI_Mark_Det::DetConfigResult detresult; + detresult.ncamID = m_ncamera_idx; + detresult.searchroi = pFuntion->searchRoi; + detresult.bsaveprocessimg = bsaveprocessimg; + detresult.searchroi.x -= Det_CropRoi.x; + detresult.searchroi.y -= Det_CropRoi.y; + // if (true) + // { + // detresult.bsaveprocessimg = true; + // } + + if (!CheckUtil::RoiInImg(Det_CropRoi, detSrcImg)) + { + + return 0; + } + + cv::Mat detimg = detSrcImg(Det_CropRoi).clone(); + int re = m_MarkDet.Detect(detimg, &detresult); + + if (re != 0) + { + return re; + } + if (detresult.nresult != 0) + { + return -1; + } + // printf("-------------------22222 \n"); + // detresult.markRoi.x -= Det_CropRoi.x; + // detresult.markRoi.y -= Det_CropRoi.y; + + int sheild_h = detresult.markRoi.height; + + if (sheild_h < pFuntion->x_sheild_width) + { + sheild_h = pFuntion->x_sheild_width; + } + + int sheild_w = detresult.markRoi.width; + + if (sheild_w < pFuntion->y_sheild_width) + { + sheild_w = pFuntion->y_sheild_width; + } + + int pc_x = detresult.markRoi.x + detresult.markRoi.width * 0.5; + int pc_y = detresult.markRoi.y + detresult.markRoi.height * 0.5; + + cv::Rect sheildRoi; + sheildRoi.x = pc_x - sheild_w * .5; + sheildRoi.y = pc_y - sheild_h * .5; + sheildRoi.width = sheild_w; + sheildRoi.height = sheild_h; + + if (CheckUtil::RoiInImg(sheildRoi, detImg_mask)) + { + detImg_mask(sheildRoi).setTo(255); + } + + cv::Rect sheild_x_roi; + sheild_x_roi.x = 0; + sheild_x_roi.y = pc_y - sheild_h * .5; + sheild_x_roi.width = detImg_mask.cols; + sheild_x_roi.height = sheild_h; + markRoi_x = sheild_x_roi; + if (CheckUtil::RoiInImg(sheild_x_roi, detImg_mask) && pFuntion->bUse_Roi_Sheild) + { + detImg_mask(sheild_x_roi).setTo(255); + } + + cv::Rect sheild_y_roi; + sheild_y_roi.x = pc_x - sheild_w * 0.5; + sheild_y_roi.y = 0; + sheild_y_roi.width = sheild_w; + sheild_y_roi.height = detImg_mask.rows; + markRoi_y = sheild_y_roi; + if (CheckUtil::RoiInImg(sheild_y_roi, detImg_mask) && pFuntion->bUse_Roi_Sheild) + { + detImg_mask(sheild_y_roi).setTo(255); + } + + return 0; +} + +ImgCheckBase *CameraCheckAnalysisy::GetDealResult(int idx) +{ + + // 特殊情况 + if (idx >= 0 && idx < IMGCHECKANALYSISY_NUM) + { + + if (CHECK_THREAD_STATUS_IDLE == m_pImgCheckAnalysisy[idx]->GetStatus()) + { + // printf("*-*-*-*-*-*-*-*- use m_pImgCheckAnalysisy %d \n", idx); + return m_pImgCheckAnalysisy[idx]; + } + else + { + return NULL; + } + } + + int re = 0; + + int nidx = nLastCheckAnalysisyThreadIdx; + + for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++) + { + if (nidx >= IMGCHECKANALYSISY_NUM) + { + nidx = 0; + } + if (CHECK_THREAD_STATUS_IDLE == m_pImgCheckAnalysisy[nidx]->GetStatus()) + { + nLastCheckAnalysisyThreadIdx = nidx + 1; + // printf("*-*-*-*-*-*-*-*- use m_pImgCheckAnalysisy %d \n", nidx); + return m_pImgCheckAnalysisy[nidx]; + } + nidx++; + } + return NULL; +} + +int CameraCheckAnalysisy::GetAndAnalysisyCheckResult(std::shared_ptr &pResult) +{ + + int re = 0; + for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++) + { + if (CHECK_THREAD_STATUS_COMPLETE == m_pImgCheckAnalysisy[i]->GetStatus()) + { + // 处理结果 + re = m_pImgCheckAnalysisy[i]->GetCheckReuslt(pResult); + m_PrintLog.printstr(Print_Level_Info, "DetAllImg", "reuslt:%d %s -- get reuslt ", pResult->pBaseImgCheckResult->nresult, pResult->pBaseImgCheckResult->in_shareImage->strChannel.c_str()); + return 1; + } + } + return 0; +} diff --git a/AlgorithmModule/src/CheckErrorCodeDefine.cpp b/AlgorithmModule/src/CheckErrorCodeDefine.cpp new file mode 100644 index 0000000..09c87c4 --- /dev/null +++ b/AlgorithmModule/src/CheckErrorCodeDefine.cpp @@ -0,0 +1,35 @@ +#include "CheckErrorCodeDefine.hpp" +std::string GetErrorCodeInfo(int nErrorCode) +{ + std::string str = ""; + switch (nErrorCode) + { + case CHECK_OK: + str = "OK"; + break; + case CHECK_ERROR_VERSION: + str = "interface version or config version error"; + break; + case CHECK_ERROR_Config_Null: + str = "prt* config is null"; + break; + case CHECK_ERROR_Config_Value: + str = "config value error"; + break; + case CHECK_ERROR_Path_NULL: + str = "file Path is Null"; + break; + case CHECK_ERROR_Mask_Empty: + str = "mask Image is empty"; + break; + case CHECK_ERROR_Config_cutRoi: + str = "config Rect Value error"; + break; + case CHECK_ERROR_CheckImg_Empty: + str = "check image is empty"; + break; + default: + break; + } + return str; +} diff --git a/AlgorithmModule/src/CheckUtil.cpp b/AlgorithmModule/src/CheckUtil.cpp new file mode 100644 index 0000000..0ce6222 --- /dev/null +++ b/AlgorithmModule/src/CheckUtil.cpp @@ -0,0 +1,566 @@ +/* + * FileName:CoreLogicFactory.cpp + * Version:V1.0 + * Description: + * Created On:Mon Sep 10 11:13:16 UTC 2018 + * Modified date: + * Author:Sky + */ +#include "CheckUtil.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "snowflake.hpp" + +int _sysmkdir_2(const std::string &dir) +{ + int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (ret && errno == EEXIST) + { + printf("dir[%s] already exist.\n", dir.c_str()); + } + else if (ret) + { + printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno)); + return -1; + } + else + { + printf("create dir[%s] success.\n", dir.c_str()); + } + return 0; +} +std::string __getParentDir_2(const std::string &dir) +{ + std::string pdir = dir; + if (pdir.length() < 1 || (pdir[0] != '/')) + { + return ""; + } + while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/')) + pdir = pdir.substr(0, pdir.length() - 1); + + pdir = pdir.substr(0, pdir.find_last_of('/')); + return pdir; +} + +long CheckUtil::getcurTime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return ((long)tv.tv_sec) * 1000 + ((long)tv.tv_usec) / 1000; +} +std::string CheckUtil::Op_float2String(float nvalue) +{ + char buffer[20]; + sprintf(buffer, "%.1f", nvalue); + std::string st1 = buffer; + return st1; +} + +int64_t CheckUtil::getSnowId() +{ + using snowflake_t = snowflake<1534832906275L, std::mutex>; + static snowflake_t uuid; + static bool bInit = false; + if (!bInit) + { + uuid.init(1, 1); + bInit = true; + } + return uuid.nextid(); + return 0; +} + +bool CheckUtil::JudgRect(cv::Rect roi, int img_w, int img_h) +{ + if (img_w <= 0 || img_h <= 0) + { + return false; + } + if (roi.x < 0 || roi.x >= img_w) + { + return false; + } + if (roi.width <= 0 || roi.width >= img_w) + { + return false; + } + if (roi.y < 0 || roi.y >= img_h) + { + return false; + } + if (roi.height <= 0 || roi.height >= img_h) + { + return false; + } + if (roi.x + roi.width >= img_w) + { + return false; + } + if (roi.y + roi.height >= img_h) + { + return false; + } + return true; +} + +bool CheckUtil::JudgRect_SZ(cv::Rect roi, int w, int h) +{ + if (roi.x < 0 || roi.x >= w) + { + return false; + } + if (roi.width <= 0 || roi.width != w) + { + return false; + } + if (roi.y < 0 || roi.y >= h) + { + return false; + } + if (roi.height <= 0 || roi.height != h) + { + return false; + } + + return true; +} +bool CheckUtil::compareIgnoreCase(const std::string &str1, const std::string &str2) +{ + // 将 str1 和 str2 转换为小写后进行比较 + std::string lower_str1 = str1; + std::string lower_str2 = str2; + + // 使用 std::transform 将字符串转换为小写 + std::transform(lower_str1.begin(), lower_str1.end(), lower_str1.begin(), ::tolower); + std::transform(lower_str2.begin(), lower_str2.end(), lower_str2.begin(), ::tolower); + + // 比较两个转换后的字符串 + return lower_str1 == lower_str2; +} + +bool CheckUtil::RoiInImg(cv::Rect roi, cv::Mat img) +{ + if (roi.width <= 0 || roi.height <= 0) + { + return false; + } + + if ((roi & cv::Rect(0, 0, img.cols, img.rows)) == roi) + { + return true; + } + + return false; +} + +int CheckUtil::printROI(cv::Rect roi, std::string str) +{ + printf("%s x %d y %d w %d h %d\n", str.c_str(), roi.x, roi.y, roi.width, roi.height); + return 0; +} + +float CheckUtil::CalIoU(cv::Rect rect1, cv::Rect rect2) +{ + // 计算交集区域 + cv::Rect intersection = rect1 & rect2; + + // 计算并集区域 + cv::Rect union_rect = rect1 | rect2; + + // 计算交集区域和并集区域的面积 + double intersection_area = intersection.area(); + double union_area = union_rect.area(); + + // 计算IoU值 + double iou = intersection_area / union_area; + + return iou; +} + +float CheckUtil::CalRoi2RoiPre(cv::Rect rect1, cv::Rect rect2) +{ + // 计算交集区域 + cv::Rect intersection = rect1 & rect2; + + // 计算并集区域 + cv::Rect union_rect = rect1; + + // 计算交集区域和并集区域的面积 + double intersection_area = intersection.area(); + double union_area = union_rect.area(); + double iou = 0; + if (union_area != 0) + { + iou = intersection_area / union_area; + } + + // 计算IoU值 + + return iou; +} + +float CheckUtil::CalIoU_t(cv::Rect rect1, cv::Rect rect2) +{ + // 计算交集区域 + cv::Rect intersection = rect1 & rect2; + + // 计算并集区域 + cv::Rect union_rect = rect1; + + // 计算交集区域和并集区域的面积 + double intersection_area = intersection.area(); + double union_area = union_rect.area(); + + // 计算IoU值 + double iou = intersection_area / union_area; + + return iou; +} + +int CheckUtil::CheckRect(cv::Rect &roi, int img_w, int img_h) +{ + if (roi.x < 0 || roi.x >= img_w) + { + roi.x = 0; + } + if (roi.y < 0 || roi.y >= img_h) + { + roi.y = 0; + } + if (roi.width <= 0 || roi.width > img_w) + { + roi.width = 1; + } + if (roi.height <= 0 || roi.height > img_h) + { + roi.height = 1; + } + if (roi.x + roi.width > img_w) + { + roi.x = img_w - roi.width; + if (roi.x < 0) + { + roi.x = 0; + roi.width = img_w; + } + } + if (roi.y + roi.height > img_h) + { + roi.y = img_h - roi.height; + if (roi.y < 0) + { + roi.y = 0; + roi.height = img_h; + } + } + + return 0; +} + +int CheckUtil::SizeRect(cv::Rect &roi, int img_w, int img_h, int addw, int addh) +{ + if (roi.width + 2 * addw > img_w) + { + return 1; + } + if (roi.height + 2 * addh > img_h) + { + return 1; + } + int sx = roi.x - addw; + int ex = roi.x + roi.width + addw; + if (sx < 0) + { + sx = 0; + } + if (ex > img_w) + { + ex = img_w; + } + + int sy = roi.y - addh; + int ey = roi.y + roi.height + addh; + if (sy < 0) + { + sy = 0; + } + if (ey > img_h) + { + ey = img_h; + } + + roi.x = sx; + roi.width = ex - sx; + roi.y = sy; + roi.height = ey - sy; + return 0; +} + +float CheckUtil::CalImgBrightness(cv::Mat imgRoi) +{ + if (imgRoi.empty()) + { + return 0.0f; + } + cv::Mat mat_mean, mat_stddev; + cv::meanStdDev(imgRoi, mat_mean, mat_stddev); // 求灰度图像的均值、均方差 + float m = mat_mean.at(0, 0); + return m; +} + +float CheckUtil::Cal2PointAngle(cv::Point p_left, cv::Point p_right) +{ + double angle = std::atan2(p_left.y - p_right.y, p_right.x - p_left.x); + return angle * 180 / 3.1415926; +} + +cv::Rect CheckUtil::getLargestContourROI(const cv::Mat &binaryImg, bool &found) +{ + std::vector> contours; + std::vector hierarchy; + + // 查找轮廓 + cv::findContours(binaryImg.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + found = false; + if (contours.empty()) + { + return cv::Rect(); // 返回空Rect + } + + // 找到面积最大的轮廓 + double maxArea = 0; + int maxAreaIdx = -1; + for (size_t i = 0; i < contours.size(); i++) + { + double area = cv::contourArea(contours[i]); + if (area > maxArea) + { + maxArea = area; + maxAreaIdx = i; + } + } + + // 如果没有找到有效轮廓(比如所有轮廓面积都为0) + if (maxAreaIdx == -1 || maxArea <= 0) + { + return cv::Rect(); + } + + found = true; + // 返回最大轮廓的边界矩形 + return cv::boundingRect(contours[maxAreaIdx]); +} + +std::string CheckUtil::GetRectString(cv::Rect rect) +{ + std::string str = "[" + std::to_string(rect.x) + "," + std::to_string(rect.y) + "," + std::to_string(rect.width) + "," + std::to_string(rect.height) + "]"; + return str; +} + +int CheckUtil::CreateDir(const std::string &dir) +{ + int ret = 0; + if (dir.empty()) + return -1; + std::string pdir; + if ((ret = _sysmkdir_2(dir)) == -1) + { + pdir = __getParentDir_2(dir); + if ((ret = CreateDir(pdir)) == 0) + { + ret = CreateDir(dir); + } + } + + return ret; +} + +bool CheckUtil::bcalDis(cv::Point p1, cv::Point p2, int disT) +{ + double dis = std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); + if (dis < disT) + return true; + return false; +} + +double CheckUtil::calDis(cv::Point p1, cv::Point p2) +{ + double dis = std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); + return dis; +} + +void CheckUtil::PrintRect(cv::Rect roi, std::string str) +{ + printf("%s x %d y %d w %d h %d \n", str.c_str(), roi.x, roi.y, roi.width, roi.height); +} + +int CheckUtil::cutSmallImg(cv::Mat img, std::vector &samllRoiList, cv::Rect config_roi, int config_SmallImg_Width, int config_SmallImg_Height, int config_MinOverlap_Width, int config_MinOverlap_Height) +{ + if (img.empty()) + { + printf("error >>>> img.empty \n"); + return 1; + /* code */ + } + if (!RoiInImg(config_roi, img)) + { + printf("error >>>> roi != img size \n"); + return 2; + } + if (config_SmallImg_Width <= 0 || + config_SmallImg_Height <= 0 || + config_SmallImg_Width > img.cols || + config_SmallImg_Height > img.rows) + { + printf("error >>>>config_SmallImg_Width %d config_SmallImg_Height %d \n ", config_SmallImg_Width, config_SmallImg_Height); + return 3; + } + if (config_MinOverlap_Width < 0 || + config_MinOverlap_Height < 0 || + config_MinOverlap_Width > img.cols || + config_MinOverlap_Height > img.rows || + config_MinOverlap_Width >= config_SmallImg_Width || + config_MinOverlap_Height >= config_SmallImg_Height) + { + printf("error >>>>config_MinOverlap_Width %d config_MinOverlap_Height %d \n ", config_MinOverlap_Width, config_MinOverlap_Height); + return 4; + } + + int AI_Img_width = config_SmallImg_Width; + int AI_Img_height = config_SmallImg_Height; + + int start_x = config_roi.x; + int start_y = config_roi.y; + + int end_x = config_roi.width + config_roi.x; + int end_y = config_roi.height + config_roi.y; + + // 有效图片 宽 高 + int det_width = config_roi.width; + int det_height = config_roi.height; + + if (AI_Img_width > det_width || AI_Img_height > det_height) + { + printf("error >>>>config_SmallImg_Width %d != roi width %d \n ", config_SmallImg_Width, det_width); + printf("error >>>>config_SmallImg_Height %d != roi height %d \n ", config_SmallImg_Height, det_height); + return 5; + } + + // printf("config_SmallImg_Width %d config_SmallImg_Height %d \n ", config_SmallImg_Width, config_SmallImg_Height); + // printf("config_MinOverlap_Width %d config_MinOverlap_Height %d \n ", config_MinOverlap_Width, config_MinOverlap_Height); + + /////////////////、计算宽度方向 块的个数 和 重叠 /////////////////////// + // 可分为多少块 宽度度方向 + float fBlocknum_x = det_width * 1.0f / AI_Img_width; + // 块的个数 + int nBlocknum_x = std::ceil(fBlocknum_x); + + // 如果 有重叠要求 + if (config_MinOverlap_Width >= 0) + { + float fconfig_BlocknuNum_x = (det_width - AI_Img_width) * 1.0f / (config_SmallImg_Width - config_MinOverlap_Width) + 1; + int nconfig_BlocknuNum_x = std::ceil(fconfig_BlocknuNum_x); + if (nBlocknum_x < nconfig_BlocknuNum_x) + { + nBlocknum_x = nconfig_BlocknuNum_x; + } + } + int use_MinOverlap_Width = 0; + // 计算重叠率 + if (nBlocknum_x > 1) + { + // 有多个块,要判断 块的重叠是否满足要求 + int nSumLen_x = nBlocknum_x * AI_Img_width; // + float fOverlap_x = (nSumLen_x - det_width) * 1.0f / (nBlocknum_x - 1); + use_MinOverlap_Width = int(fOverlap_x); + } + // printf("nBlocknum_x %d use_MinOverlap_Width %d \n", nBlocknum_x, use_MinOverlap_Width); + + /////////////////、计算高度方向 块的个数 和 重叠 /////////////////////// + // 可分为多少块 高度方向 + float fBlocknum_y = det_height * 1.0f / AI_Img_height; + // 块的个数 + int nBlocknum_y = std::ceil(fBlocknum_y); + + // 如果 有重叠要求 + if (config_MinOverlap_Height >= 0) + { + float fconfig_BlocknuNum_y = (det_height - AI_Img_height) * 1.0f / (config_SmallImg_Height - config_MinOverlap_Height) + 1; + int nconfig_BlocknuNum_y = std::ceil(fconfig_BlocknuNum_y); + if (nBlocknum_y < nconfig_BlocknuNum_y) + { + nBlocknum_y = nconfig_BlocknuNum_y; + } + } + int use_MinOverlap_Height = 0; + // 计算重叠率 + if (nBlocknum_y > 1) + { + // 有多个块,要判断 块的重叠是否满足要求 + int nSumLen_y = nBlocknum_y * AI_Img_height; // + float fOverlap_y = (nSumLen_y - det_height) * 1.0f / (nBlocknum_y - 1); + use_MinOverlap_Height = int(fOverlap_y); + } + + // printf("nBlocknum_y %d use_MinOverlap_Height %d \n", nBlocknum_y, use_MinOverlap_Height); + + int cut_sy = start_y; + int cut_ey = start_y + AI_Img_height; + + for (int iy = 0; iy < nBlocknum_y; iy++) + { + int nleny = end_y - cut_ey; + + int cut_sx = start_x; + int cut_ex = start_x + AI_Img_width; + for (int ix = 0; ix < nBlocknum_x; ix++) + { + + cv::Rect roi; + roi.x = cut_sx; + roi.y = cut_sy; + roi.width = AI_Img_width; + roi.height = AI_Img_height; + + samllRoiList.push_back(roi); + + // 剩余长度 + int nlenx = end_x - cut_ex; + if (nlenx > AI_Img_width) + { + cut_sx = cut_sx + AI_Img_width - use_MinOverlap_Width; + cut_ex = cut_sx + AI_Img_width; + } + else + { + cut_sx = end_x - AI_Img_width; + cut_ex = cut_sx + AI_Img_width; + } + } + + if (nleny > AI_Img_height) + { + cut_sy = cut_sy + AI_Img_height - use_MinOverlap_Height; + cut_ey = cut_sy + AI_Img_height; + } + else + { + cut_sy = end_y - AI_Img_height; + cut_ey = cut_sy + AI_Img_height; + } + } + + return 0; +} diff --git a/AlgorithmModule/src/DrawImg.cpp b/AlgorithmModule/src/DrawImg.cpp new file mode 100644 index 0000000..8a7e901 --- /dev/null +++ b/AlgorithmModule/src/DrawImg.cpp @@ -0,0 +1,685 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "DrawImg.h" +#include "QX_Analysis.h" +DrawImg::DrawImg() +{ + m_bstatus_ReJson = false; +} + +DrawImg::~DrawImg() +{ +} + +int DrawImg::DrawResult(std::shared_ptr &result) +{ + + if (result->resultimg.channels() == 1) + { + cv::cvtColor(result->resultimg, result->resultimg, cv::COLOR_GRAY2RGB); // 彩色 可选项 + } + + cv::Mat image_draw = result->resultimg; + m_drawList.erase(m_drawList.begin(), m_drawList.end()); + m_drawList.clear(); + + for (int i = 0; i < result->qxImageResult.size(); i++) + { + + DrawInfoImg_Src(image_draw, result->qxImageResult.at(i).resizeImgroi, + result->qxImageResult.at(i).idx, + result->qxImageResult.at(i).type, + result->qxImageResult.at(i).area, + result->qxImageResult.at(i).energy, + result->qxImageResult.at(i).max_v, + result->qxImageResult.at(i).hj, + result->qxImageResult.at(i).len, + Draw_Type_NG, result->qxImageResult.at(i).strTypeName, result->qxImageResult.at(i).qx_Code, + result->qxImageResult.at(i).qx_type, + result->qxImageResult.at(i).qx_num, + result->qxImageResult.at(i).density, m_bstatus_ReJson); + + // DrawInfoImg(src_draw, result->qxImageResult.at(i).srcImgroi, result->qxImageResult.at(i).type, result->qxImageResult.at(i).area); + if (result->qxImageResult.at(i).srcImg.channels() == 1) + { + cv::cvtColor(result->qxImageResult.at(i).srcImg, result->qxImageResult.at(i).srcImg, cv::COLOR_GRAY2RGB); // 彩色 可选项 + } + + DrawInfoImg(result->qxImageResult.at(i).srcImg, + result->qxImageResult.at(i).CutImgroi, + result->qxImageResult.at(i).idx, + result->qxImageResult.at(i).type, + result->qxImageResult.at(i).area, + result->qxImageResult.at(i).energy, + result->qxImageResult.at(i).max_v, + result->qxImageResult.at(i).hj, + result->qxImageResult.at(i).len, + Draw_Type_NG, result->qxImageResult.at(i).strTypeName, + result->qxImageResult.at(i).qx_Code, + result->qxImageResult.at(i).qx_type, + result->qxImageResult.at(i).qx_num, + result->qxImageResult.at(i).density, m_bstatus_ReJson); + } + + for (int i = 0; i < result->YS_ImageResult.size(); i++) + { + DrawInfoImg_Src(image_draw, result->YS_ImageResult.at(i).resizeImgroi, result->YS_ImageResult.at(i).idx, + result->YS_ImageResult.at(i).type, + result->YS_ImageResult.at(i).area, + result->YS_ImageResult.at(i).energy, + result->YS_ImageResult.at(i).max_v, + result->YS_ImageResult.at(i).hj, + result->YS_ImageResult.at(i).len, + Draw_Type_YS, result->YS_ImageResult.at(i).strTypeName, + result->YS_ImageResult.at(i).qx_Code, + result->YS_ImageResult.at(i).qx_type, + result->YS_ImageResult.at(i).qx_num, + result->YS_ImageResult.at(i).density, m_bstatus_ReJson); + // DrawInfoImg(src_draw, result->qxImageResult.at(i).srcImgroi, result->qxImageResult.at(i).type, result->qxImageResult.at(i).area); + if (result->YS_ImageResult.at(i).srcImg.channels() == 1) + { + cv::cvtColor(result->YS_ImageResult.at(i).srcImg, result->YS_ImageResult.at(i).srcImg, cv::COLOR_GRAY2RGB); // 彩色 可选项 + } + DrawInfoImg(result->YS_ImageResult.at(i).srcImg, + result->YS_ImageResult.at(i).CutImgroi, + result->YS_ImageResult.at(i).idx, + result->YS_ImageResult.at(i).type, + result->YS_ImageResult.at(i).area, + result->YS_ImageResult.at(i).energy, + result->YS_ImageResult.at(i).max_v, + result->YS_ImageResult.at(i).hj, + result->YS_ImageResult.at(i).len, + Draw_Type_YS, result->YS_ImageResult.at(i).strTypeName, + result->YS_ImageResult.at(i).qx_Code, + result->YS_ImageResult.at(i).qx_type, + result->YS_ImageResult.at(i).qx_num, + result->YS_ImageResult.at(i).density, m_bstatus_ReJson); + } + + return 0; +} + +int DrawImg::DrawInfoImg(cv::Mat &img, cv::Rect roi, int blobidx, int type, float fArea, float fenerge, float fmaxv, float fhj, float flen, Draw_Type drayType, std::string strqx_error, std::string strqx_code, int qx_type, int qx_num, float mindis, bool bqxroi) +{ + + cv::Point pc; + pc.x = roi.x; + pc.y = roi.y; + + cv::Rect src_Roi = roi; + + roi.x -= 5; + roi.y -= 5; + + roi.width += 10; + roi.height += 10; + + if (roi.x < 0) + { + roi.x = 0; + } + if (roi.y < 0) + { + roi.y = 0; + } + // printf("roi %s \n", CheckUtil::GetRectString(roi).c_str()); + if (roi.x + roi.width > img.cols) + { + roi.width = img.cols - roi.x; + if (roi.width <= 0) + { + roi.width = 1; + } + } + if (roi.y + roi.height > img.rows) + { + roi.height = img.rows - roi.y; + if (roi.height <= 0) + { + roi.height = 1; + } + } + if (bqxroi) + { + + cv::Scalar roicolor = cv::Scalar(0, 0, 255); + switch (drayType) + { + case Draw_Type_NG: + roicolor = cv::Scalar(0, 0, 255); + break; + case Draw_Type_YS: + roicolor = cv::Scalar(128, 0, 0); + break; + case Draw_Type_Other: + roicolor = cv::Scalar(0, 120, 120); + break; + default: + break; + } + cv::rectangle(img, roi, roicolor); + } + + char buffer[128]; + // sprintf(buffer, " A:%.1f E:%.1f", result->qxiImageResult.at(i).area, result->qxiImageResult.at(i).energy); + // sprintf(buffer, " A:%.1f E:%.1f HJ:%.1f", result->qxiImageResult.at(i).area, result->qxiImageResult.at(i).energy, result->qxiImageResult.at(i).hj); + sprintf(buffer, "%d T:%d %s %s qx %d %d m:%.1f\nA:%.2f E:%.1f Mv:%.1f hj:%.1f len %.1f", blobidx, type, strqx_error.c_str(), strqx_code.c_str(), qx_type, qx_num, mindis, fArea, fenerge, fmaxv, fhj, flen); + std::string st1 = buffer; + + std::string text = st1; + + // 按行分割文本 + std::vector lines; + size_t pos = 0; + while ((pos = text.find("\n")) != std::string::npos) + { + lines.push_back(text.substr(0, pos)); + text.erase(0, pos + 1); + } + lines.push_back(text); + + int baseline; + // 获取文本框的长宽 + cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline); + cv::Rect droi; + droi.width = text_size.width; + droi.height = text_size.height; + // 输出每一行文本 + int lineHeight = text_size.height + baseline; + droi.height = lineHeight; + int line_one_y = 0; + int linenum = lines.size() - 1; + + bool bdrawroi = true; + + if (lines.size() <= 0) + { + return 0; + } + + cv::Rect drawRoi; + drawRoi.x = pc.x; + drawRoi.y = pc.y; + drawRoi.width = text_size.width; + drawRoi.height = text_size.height * lines.size(); + + { + + for (size_t i = 0; i < lines.size(); ++i) + { + // 将文本框居中绘制 + cv::Point origin = cv::Point(drawRoi.x, drawRoi.y + (i + 1) * (text_size.height)); + + double temfont_scale = font_scale * 0.6; + + if (drayType == Draw_Type_NG) + { + if (qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(80, 128, 100), thickness, 1, 0); + } + else + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(0, 255, 0), thickness, 1, 0); + } + } + else + { + + if (drayType == Draw_Type_Other) + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(0, 182, 185), thickness, 1, 0); + } + else + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(128, 125, 0), thickness, 1, 0); + } + } + } + } + + return 0; +} + +int DrawImg::DrawInfoImg_Src(cv::Mat &img, cv::Rect roi, int blobidx, int type, float fArea, float fenerge, float fmaxv, float fhj, float flen, Draw_Type drayType, std::string strqx_error, std::string strqx_code, int qx_type, int qx_num, float mindis, bool bqxroi) +{ + cv::Point pc; + pc.x = roi.x; + pc.y = roi.y; + + cv::Rect src_Roi = roi; + + roi.x -= 5; + roi.y -= 5; + + roi.width += 10; + roi.height += 10; + + if (roi.x < 0) + { + roi.x = 0; + } + if (roi.y < 0) + { + roi.y = 0; + } + // printf("roi %s \n", CheckUtil::GetRectString(roi).c_str()); + if (roi.x + roi.width > img.cols) + { + roi.width = img.cols - roi.x; + if (roi.width <= 0) + { + roi.width = 1; + } + } + if (roi.y + roi.height > img.rows) + { + roi.height = img.rows - roi.y; + if (roi.height <= 0) + { + roi.height = 1; + } + } + if (bqxroi) + { + + cv::Scalar roicolor = cv::Scalar(0, 0, 255); + switch (drayType) + { + case Draw_Type_NG: + roicolor = cv::Scalar(0, 0, 255); + break; + case Draw_Type_YS: + roicolor = cv::Scalar(128, 0, 0); + break; + case Draw_Type_Other: + roicolor = cv::Scalar(0, 120, 120); + break; + default: + break; + } + cv::rectangle(img, roi, roicolor); + } + + char buffer[128]; + if (drayType == Draw_Type_NG) + { + sprintf(buffer, "%d T:%d %s %s qx %d %d m:%.1f\nA:%.2f E:%.1f Mv:%.1f hj:%.1f len %.1f", blobidx, type, strqx_error.c_str(), strqx_code.c_str(), qx_type, qx_num, mindis, fArea, fenerge, fmaxv, fhj, flen); + } + else + { + sprintf(buffer, "%d %s ", blobidx, strqx_error.c_str()); + } + std::string st1 = buffer; + + std::string text = st1; + + // 按行分割文本 + std::vector lines; + size_t pos = 0; + while ((pos = text.find("\n")) != std::string::npos) + { + lines.push_back(text.substr(0, pos)); + text.erase(0, pos + 1); + } + lines.push_back(text); + + int baseline; + // 获取文本框的长宽 + cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline); + cv::Rect droi; + droi.width = text_size.width; + droi.height = text_size.height; + // 输出每一行文本 + int lineHeight = text_size.height + baseline; + droi.height = lineHeight; + int line_one_y = 0; + int linenum = lines.size() - 1; + + bool bdrawroi = true; + + if (lines.size() <= 0) + { + return 0; + } + + cv::Rect drawRoi; + drawRoi.x = pc.x; + drawRoi.y = pc.y; + drawRoi.width = text_size.width; + drawRoi.height = text_size.height * lines.size(); + // //寻找绘制区域 + cv::Point pSearchStart; + pSearchStart.x = pc.x; + pSearchStart.y = pc.y - drawRoi.height; + int search_Y = 300; + int search_X = 500; + int step_x = 30; + int step_y = 20; + if (drayType != Draw_Type_NG) + { + search_Y = 30; + search_X = 30; + step_x = 10; + step_y = 10; + } + bool bSucc = false; + + cv::Rect temRoi; + temRoi.width = drawRoi.width; + temRoi.height = drawRoi.height; + cv::Point line_p_qx = pc; + cv::Point line_p_dr = pc; + + for (int addX = 0; addX < search_X; addX = addX + step_x) + { + int ix = pSearchStart.x + addX; + for (int xcount = 0; xcount < 2; xcount++) + { + if (xcount == 0) + { + ix = pSearchStart.x + addX; + line_p_qx.x = src_Roi.x + src_Roi.width; + line_p_dr.x = ix; + } + else + { + ix = pSearchStart.x - addX; + line_p_qx.x = src_Roi.x; + line_p_dr.x = ix; + } + if (ix < 0) + { + ix = 0; + // continue; + } + if (ix + drawRoi.width > img.cols) + { + ix = img.cols - drawRoi.width; + // continue; + } + temRoi.x = ix; + for (int addY = 0; addY < search_Y; addY = addY + step_y) + { + int iy = addY + pSearchStart.y; + for (int ycount = 0; ycount < 2; ycount++) + { + if (ycount == 0) + { + iy = pSearchStart.y + addY; + line_p_qx.y = src_Roi.y; + line_p_dr.y = iy + temRoi.height; + } + else + { + iy = pSearchStart.y - addY; + line_p_qx.y = src_Roi.y + src_Roi.height; + line_p_dr.y = iy + temRoi.height; + } + + if (iy < 0) + { + iy = 0; + // continue; + } + if (iy + drawRoi.height > img.rows) + { + iy = img.rows - drawRoi.height; + // continue; + } + temRoi.y = iy; + + if (bdraw(temRoi)) + { + bSucc = true; + break; + } + } + if (bSucc) + { + break; + } + } + if (bSucc) + { + break; + } + } + if (bSucc) + { + break; + } + } + + // 如果是NG,则强制绘制 + if (!bSucc && drayType == Draw_Type_NG) + { + temRoi = drawRoi; + bSucc = true; + } + + if (bSucc) + { + drawRoi = temRoi; + // cv::rectangle(img, drawRoi, cv::Scalar(255, 255, 255)); + // cv::Point p1 = cv::Point(drawRoi.x, drawRoi.y); + cv::line(img, line_p_qx, line_p_dr, cv::Scalar(255, 255, 0)); + + m_drawList.push_back(drawRoi); + + for (size_t i = 0; i < lines.size(); ++i) + { + // 将文本框居中绘制 + cv::Point origin = cv::Point(drawRoi.x, drawRoi.y + (i + 1) * (text_size.height)); + + double temfont_scale = font_scale; + + if (drayType == Draw_Type_NG) + { + if (qx_type == QX_ERROR_TYPE_NUM_RGB255) + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(80, 128, 100), thickness, 1, 0); + } + else + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(0, 255, 0), thickness, 1, 0); + } + } + else + { + + if (drayType == Draw_Type_Other) + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(0, 182, 185), thickness, 1, 0); + } + else + { + cv::putText(img, lines[i], origin, font_face, temfont_scale, cv::Scalar(128, 125, 0), thickness, 1, 0); + } + } + } + } + + return 0; +} + +int DrawImg::preDealImg(cv::Mat &srcimg, cv::Mat &image_resize, bool bfilpSrcImg) +{ + return 0; +} + +int DrawImg::DrawPointList(cv::Mat &image_draw, std::vector plist) +{ + return 0; +} + +bool DrawImg::bdraw(cv::Rect roi) +{ + + for (auto &r : m_drawList) + { + if (CheckUtil::CalIoU(r, roi) > 0) + { + return false; + } + } + + return true; +} + +Json::Value CheckResultJson::toJsonValue() +{ + Json::Value root; + + { + + root["cutRoi"]["x"] = m_pOneImgDetResult->CutRoi.x; + root["cutRoi"]["y"] = m_pOneImgDetResult->CutRoi.y; + root["cutRoi"]["width"] = m_pOneImgDetResult->CutRoi.width; + root["cutRoi"]["height"] = m_pOneImgDetResult->CutRoi.height; + } + { + + root["Param_CropRoi"]["x"] = m_pOneImgDetResult->Param_CropRoi.x; + root["Param_CropRoi"]["y"] = m_pOneImgDetResult->Param_CropRoi.y; + root["Param_CropRoi"]["width"] = m_pOneImgDetResult->Param_CropRoi.width; + root["Param_CropRoi"]["height"] = m_pOneImgDetResult->Param_CropRoi.height; + } + for (int i = 0; i < m_pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *p = &m_pOneImgDetResult->pQx_ErrorList->at(i); + Json::Value value; + { + + value["Idx"] = p->Idx; + value["result"] = p->result; + value["result_Name"] = p->result_name; + value["roi"]["x"] = p->roi.x; + value["roi"]["y"] = p->roi.y; + value["roi"]["width"] = p->roi.width; + value["roi"]["height"] = p->roi.height; + value["area"] = p->area; + value["energy"] = p->energy; + value["JudgArea"] = p->JudgArea; + value["JudgArea_second"] = p->JudgArea_second; + value["flen"] = p->flen; + value["nconfig_qx_type"] = p->nconfig_qx_type; + value["qx_name"] = p->qx_name; + value["maxValue"] = p->maxValue; + value["grayDis"] = p->grayDis; + value["fUpIou"] = p->fUpIou; + value["density"] = p->density; + // return root; + } + root["Qx"].append(value); + } + + return root; +} + +void CheckResultJson::toObjectFromValue(Json::Value root) +{ + + m_pOneImgDetResult = std::make_shared(); + m_pOneImgDetResult->pQx_ErrorList = std::make_shared>(); + // std::cout << root << std::endl; + { + auto value = root["cutRoi"]; + if (value.isObject()) + { + + m_pOneImgDetResult->CutRoi.x = root["cutRoi"]["x"].asInt(); + m_pOneImgDetResult->CutRoi.y = root["cutRoi"]["y"].asInt(); + m_pOneImgDetResult->CutRoi.width = root["cutRoi"]["width"].asInt(); + m_pOneImgDetResult->CutRoi.height = root["cutRoi"]["height"].asInt(); + } + } + { + auto value = root["Param_CropRoi"]; + if (value.isObject()) + { + + m_pOneImgDetResult->Param_CropRoi.x = root["Param_CropRoi"]["x"].asInt(); + m_pOneImgDetResult->Param_CropRoi.y = root["Param_CropRoi"]["y"].asInt(); + m_pOneImgDetResult->Param_CropRoi.width = root["Param_CropRoi"]["width"].asInt(); + m_pOneImgDetResult->Param_CropRoi.height = root["Param_CropRoi"]["height"].asInt(); + } + } + { + if (root.isMember("Qx")) + { + + const Json::Value &errorList = root["Qx"]; + for (const auto &errorJson : errorList) + { + + QX_ERROR_INFO_ tem; + tem.Idx = errorJson["Idx"].asInt(); + + // tem.result = errorJson["result"].asInt(); + // tem.result_name = errorJson["result_Name"].asString(); + + tem.roi.x = errorJson["roi"]["x"].asInt(); + tem.roi.y = errorJson["roi"]["y"].asInt(); + tem.roi.width = errorJson["roi"]["width"].asInt(); + tem.roi.height = errorJson["roi"]["height"].asInt(); + tem.area = errorJson["area"].asInt(); + tem.energy = errorJson["energy"].asInt(); + tem.JudgArea = errorJson["JudgArea"].asFloat(); + if (errorJson["JudgArea_second"]) + { + tem.JudgArea_second = errorJson["JudgArea_second"].asFloat(); + } + else + { + tem.JudgArea_second = tem.JudgArea; + } + + tem.flen = errorJson["flen"].asFloat(); + tem.nconfig_qx_type = errorJson["nconfig_qx_type"].asInt(); + tem.qx_name = errorJson["qx_name"].asString(); + tem.maxValue = errorJson["maxValue"].asInt(); + tem.grayDis = errorJson["grayDis"].asFloat(); + tem.fUpIou = errorJson["fUpIou"].asFloat(); + tem.density = errorJson["density"].asFloat(); + + m_pOneImgDetResult->pQx_ErrorList->push_back(tem); + + // tem.print(std::to_string(m_pOneImgDetResult->pQx_ErrorList->size())); + } + } + } +} + +int CheckResultJson::GetConfig(std::string strJson, std::shared_ptr &pOneImgDetResult) +{ + Json::CharReader *reader = readerBuilder.newCharReader(); + string errs; + bool parsingSuccessful = reader->parse(strJson.c_str(), strJson.c_str() + strJson.size(), &root, &errs); + delete reader; + if (!parsingSuccessful) + { + cout << "Failed to parse JSON string: " << errs << endl; + return 1; + } + toObjectFromValue(root); + pOneImgDetResult = m_pOneImgDetResult; + return 0; +} + +std::string CheckResultJson::GetResultString(std::shared_ptr &pOneImgDetResult) +{ + m_pOneImgDetResult = pOneImgDetResult; + + Json::Value root = toJsonValue(); + Json::StreamWriterBuilder writerBuilder; + std::string jsonString = Json::writeString(writerBuilder, root); + + return jsonString; +} diff --git a/AlgorithmModule/src/EdgeDet.cpp b/AlgorithmModule/src/EdgeDet.cpp new file mode 100644 index 0000000..fc4ae70 --- /dev/null +++ b/AlgorithmModule/src/EdgeDet.cpp @@ -0,0 +1,784 @@ + +#include "EdgeDet.h" +#include + +// 计算平均值 +double computeAverage(const std::vector &data) +{ + return std::accumulate(data.begin(), data.end(), 0.0) / data.size(); +} + +// 剔除异常数据,这里以平均值加减两倍标准差为界限 +std::vector removeOutliers(const std::vector &data) +{ + double mean = computeAverage(data); + double sq_sum = std::inner_product(data.begin(), data.end(), data.begin(), 0.0); + double stdev = std::sqrt(sq_sum / data.size() - mean * mean); + std::vector filteredData; + for (double value : data) + { + if (std::abs(value - mean) <= 2 * stdev) + { // 可以根据需要调整异常值判断的标准 + filteredData.push_back(value); + } + } + return filteredData; +} + +EdgeDet_New::EdgeDet_New() +{ + bshowimg = false; + // m_pAI_Edge_Algin = NULL; +} + +EdgeDet_New::~EdgeDet_New() +{ +} + +int EdgeDet_New::InitRun() +{ + m_OtherDet_Config.pAIDeal = &m_AIDeal; + // m_pAI_Edge_Algin = std::make_shared(); + m_pAI_Edge_Algin.Init(&m_OtherDet_Config); + InitModel(); + return 0; +} + +int EdgeDet_New::InitModel() +{ + + printf("EdgeDet_New::InitModel =============\n"); + // 获取当前gpu号确定的 AI处理线程 + m_AIDeal.Init(0); + + // 边缘搜索模型 + //if (m_pAI_Edge_Algin.get() != nullptr) + { + int re = m_pAI_Edge_Algin.InitModel_ALL(); + + if (re != 0) + { + printf("m_pAI_Edge_Algin InitModel_ALL error \n"); + } + } + return 0; +} + +int EdgeDet_New::GetImgEdge(cv::Mat img, cv::Rect &roi) +{ + bool bdetSucc = false; + + if (bshowimg) + { + cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR); + } + int exp = 0; + cv::Rect detroi; + detroi.x = 0; + detroi.y = 0; + detroi.width = img.cols; + detroi.height = img.rows * 0.8; + int re = UDNoiseEdgeDetect(img, 3, 40, 1, detroi, 30, 60); + if (re < 0) + { + printf("edge error 1 %d \n", re); + return re; + } + roi.y = re + exp; + + if (bshowimg && !showimg.empty()) + { + cv::Point p1 = cv::Point(0, re); + cv::Point p2 = cv::Point(img.cols, re); + cv::line(showimg, p1, p2, cv::Scalar(255, 0, 255), 5); + printf(">>>>>1>>000000>\n"); + } + // cv::Point p1 = cv::Point(0, re); + // cv::Point p2 = cv::Point(img.cols, re); + // cv::line(img, p1, p2, cv::Scalar(255)); + + detroi.x = 0; + detroi.y = img.rows * 0.2; + detroi.width = img.cols; + detroi.height = img.rows * 0.8 - 1; + re = UDNoiseEdgeDetect(img, -3, 40, 10, detroi, 30, 60); + if (re < 0) + { + printf("edge error 2 %d \n", re); + return re; + } + roi.height = re - exp - roi.y; + if (bshowimg && !showimg.empty()) + { + cv::Point p1 = cv::Point(0, re); + cv::Point p2 = cv::Point(img.cols, re); + cv::line(showimg, p1, p2, cv::Scalar(255, 0, 255), 5); + } + + // p1 = cv::Point(0, re); + // p2 = cv::Point(img.cols, re); + // cv::line(img, p1, p2, cv::Scalar(255)); + // cv::imwrite("showimg.png", img); + // printf(">>>>>>>>\n"); + // getchar(); + + detroi.x = 0; + detroi.y = 0; + detroi.width = img.cols / 2; + detroi.height = img.rows; + re = LRNoiseEdgeDetect(img, 3, 40, 1, detroi, 30, 60); + if (re < 0) + { + printf("edge error 333 v %d \n", re); + return re; + } + roi.x = re + exp; + + if (bshowimg && !showimg.empty()) + { + cv::Point p1 = cv::Point(re, 0); + cv::Point p2 = cv::Point(re, img.rows); + cv::line(showimg, p1, p2, cv::Scalar(255, 0, 255), 5); + } + // p1 = cv::Point(re, 0); + // p2 = cv::Point(re, img.rows); + // cv::line(img, p1, p2, cv::Scalar(255)); + // cv::imwrite("showimg.png", img); + // printf(">>>>>>>>\n"); + // getchar(); + // cv::imwrite("showimg.png", showimg); + // printf(">>>>>1>>>re %d\n", re); + // getchar(); + detroi.x = img.cols / 2; + detroi.y = 0; + detroi.width = img.cols / 2 - 1; + detroi.height = img.rows; + re = LRNoiseEdgeDetect(img, -3, 40, 1, detroi, 30, 60); + if (re < 0) + { + printf(">>>>>>>>\n"); + printf("edge error 4 %d \n", re); + return re; + } + roi.width = re - exp - roi.x; + // int len = roi.width / 4 * 4; + // roi.width = len; + + if (bshowimg && !showimg.empty()) + { + + cv::Point p1 = cv::Point(re, 0); + cv::Point p2 = cv::Point(re, img.rows); + cv::line(showimg, p1, p2, cv::Scalar(255, 0, 255), 5); + cv::rectangle(showimg, roi, cv::Scalar(0, 255, 0)); + } + + // cv::Mat temimg = showimg(real_roi).clone(); + + // if (real_roi.width > real_roi.height) + // { + // sz.width = 2048; + // fx = sz.width * 1.0f / real_roi.width; + // sz.height = real_roi.height * fx; + // } + // else + // { + // sz.height = 2048; + // fx = sz.height * 1.0f / real_roi.height; + // sz.width = real_roi.width * fx; + // } + + // cv::resize(temimg, showimg, sz); + + if (bshowimg && !showimg.empty() && true) + { + + printf(">>>>>>>>\n"); + static int ssss = 0; + + cv::Size sz; + + if (img.cols > img.rows) + { + sz.width = 2732; + sz.height = 2048; + } + else + { + sz.width = 2048; + sz.height = 2732; + } + + // cv::Mat detsizeimg; + cv::resize(showimg, showimg, sz); + // std::string strpath22 = "./img/edge/" + std::to_string(ssss++) + "_det.png"; + // printf(">>>>>>>>strpath22 %s\n", strpath22.c_str()); + // cv::imwrite(strpath22, detsizeimg); + + // std::string strpath22222 = "./img/edge/" + std::to_string(ssss++) + "_src.png"; + // printf(">>>>>>>>strpath22 %s\n", strpath22.c_str()); + // cv::imwrite(strpath22222, img); + + // cv::imwrite("showimg.png", showimg); + // printf(">>>>>>>>\n"); + } + + // p1 = cv::Point(re, 0); + // p2 = cv::Point(re, img.rows); + // cv::line(img, p1, p2, cv::Scalar(255)); + // cv::imwrite("showimg.png", img); + // printf(">>>>>>>>\n"); + // getchar(); + // cv::rectangle(img, roi, cv::Scalar(255)); + // cv::imwrite("showimg.png", img); + // printf(">>>>>>>>\n"); + // getchar(); + + return 0; +} + +int EdgeDet_New::AIEdgeDete(const cv::Mat &img, AI_Edge_Algin::DetConfig *pdetConfig, cv::Mat &detMaskImg, cv::Rect &roi) +{ + std::shared_ptr CheckResult_Aling; + //if (m_pAI_Edge_Algin.get() != nullptr) + { + if (!detmask.empty()) + { + detmask.release(); + } + + int re = m_pAI_Edge_Algin.Detect(img, pdetConfig, CheckResult_Aling); + + if (re != 0) + { + printf("AIEdgeDete error \n"); + return re; + } + detMaskImg = CheckResult_Aling->mask.clone(); + roi = CheckResult_Aling->roi; + detmask = CheckResult_Aling->DetMask_src.clone(); + } + // else + // { + // return 1; + // } + return 0; +} + +int EdgeDet_New::UDNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit) +{ + if (img.empty()) + { + return -11; + } + if (img.channels() != 1) + { + printf("*****************************channels\n"); + + return -12; + } + if (StepCount < 0 || StepCount >= roi.width) + { + printf("*****************************StepCount\n"); + + return -22; + } + std::vector data; + // cv::Mat showimg; + // cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR); + uchar *pdata = (uchar *)img.data; + + int sx = roi.x; + int ex = roi.x + roi.width; + int sy = roi.y; + int ey = roi.y + roi.height; + // 表示 反向搜索 + if (DirectSign < 0) + { + sy = roi.y + roi.height; + ey = roi.y; + } + int step = roi.width / StepCount; + int offt = 0; + int sumsite = 0; + int sumcount = 0; + // 表示搜索黑点 + if (BorW == 0) + { + } + else // 表示搜索白点 + { + for (int x = roi.x; x < ex; x = x + step) + { + + int ncount = 0; + int start = 0; + + for (int y = sy;; y = y + DirectSign) + { + if (DirectSign > 0 && y > ey) + { + break; + } + if (DirectSign < 0 && y < ey) + { + break; + } + int maxv = 0; + // 1、计算当前值是否 满足基本要求 + offt = y * img.cols + x; + maxv = pdata[offt]; + + if (maxv < 40) + { + for (int ix = -4; ix < 5; ix++) + { + int newx = x + ix; + if (newx < 0) + { + newx = 0; + } + if (newx > img.cols) + { + newx = img.cols; + } + + offt = y * img.cols + newx; + + if (pdata[offt] > maxv) + { + maxv = pdata[offt]; + } + } + } + + if (maxv > 40) + { + // 2、计算区域最大值 + for (int k = -4; k < 5; k++) + { + int newy = y + k; + if (newy < 0) + { + newy = 0; + } + if (newy >= img.rows) + { + newy = img.rows - 1; + } + + for (int ix = -4; ix < 5; ix++) + { + int newx = x + ix; + if (newx < 0) + { + newx = 0; + } + if (newx > img.cols) + { + newx = img.cols; + } + + offt = newy * img.cols + newx; + + if (pdata[offt] > maxv) + { + maxv = pdata[offt]; + } + } + + /* code */ + } + if (bshowimg) + { + cv::Rect roi; + roi.x = x - 2; + roi.width = 5; + if (roi.x < 0) + { + roi.x = 0; + } + int rdp = roi.x + roi.width; + if (rdp > showimg.cols) + { + rdp = showimg.cols; + } + roi.width = rdp - roi.x; + + roi.y = y - 2; + roi.height = 5; + if (roi.y < 0) + { + roi.y = 0; + } + rdp = roi.y + roi.height; + if (rdp > showimg.rows) + { + rdp = showimg.rows; + } + roi.height = rdp - roi.y; + cv::rectangle(showimg, roi, cv::Scalar(0, 0, 255)); + /* code */ + } + } + else + { + // if (start > 0) + // { + // printf("error p %d %d %d \n", x, y, maxv); + // /* code */ + // } + } + // 3、满足要求 记录 + if (maxv >= Gate) + { + ncount += 2; + if (start == 0) + { + start = y; + } + if (ncount > Limit) + { + break; + } + } + else + { + // if (maxv < 15) + // { + // ncount = 0; + // } + ncount--; + if (ncount < 0) + { + ncount = 0; + start = 0; + } + } + } + // 4、满足退出要求,就退出 + if (ncount > Limit) + { + sumcount++; + sumsite += start; + data.push_back(start); + + if (bshowimg && !showimg.empty()) + { + cv::Point p(x, start); + cv::circle(showimg, p, 13, cv::Scalar(0, 255, 0), 5); + // cv::imwrite("showimg.png", showimg); + // printf(">>>>>>>> %d %d \n",x,start); + // getchar(); + } + } + } + } + + if (sumcount <= 0) + { + return -3; + } + else + { + // 先剔除异常数据 + std::vector filteredData = removeOutliers(data); + + if (bshowimg && !showimg.empty()) + { + + // for (int i = 0; i < data.size(); i++) + // { + // printf("%d %f \n ", i, data.at(i)); + // } + + // for (int i = 0; i < filteredData.size(); i++) + // { + // printf("%d %f \n ", i, filteredData.at(i)); + // } + } + sumsite = 0; + sumcount = 0; + int mean = 0; + for (int i = 0; i < filteredData.size(); i++) + { + sumsite += filteredData.at(i); + sumcount++; + } + if (sumcount > 0) + { + mean = sumsite / sumcount; + } + + mean = sumsite / sumcount; + return mean; + } + + return -5; +} + +int EdgeDet_New::LRNoiseEdgeDetect(cv::Mat img, int DirectSign, int Gate, int BorW, cv::Rect roi, int StepCount, int Limit) +{ + + if (img.empty()) + { + return -1; + } + if (img.channels() != 1) + { + printf("*****************************channels\n"); + + return -1; + } + if (StepCount < 0 || StepCount >= roi.width) + { + printf("*****************************StepCount\n"); + + return -2; + } + + std::vector data; + // cv::Mat showimg; + // cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR); + uchar *pdata = (uchar *)img.data; + + int sx = roi.x; + int ex = roi.x + roi.width; + int sy = roi.y; + int ey = roi.y + roi.height; + // 表示 反向搜索 + if (DirectSign < 0) + { + sx = roi.x + roi.width; + ex = roi.x; + } + int step = roi.height / StepCount; + int offt = 0; + int sumsite = 0; + int sumcount = 0; + // 表示搜索黑点 + if (BorW == 0) + { + } + else // 表示搜索白点 + { + // printf("---- y sy %d ey %d sx %d ex %d\n", sy, ey, sx, ex); + for (int y = sy; y < ey; y = y + step) + { + int ncount = 0; + int start = 0; + + for (int x = sx;; x = x + DirectSign) + { + if (DirectSign > 0 && x > ex) + { + break; + } + if (DirectSign < 0 && x < ex) + { + break; + } + int maxv = 0; + // 1、计算当前值是否 满足基本要求 + offt = y * img.cols + x; + maxv = pdata[offt]; + if (maxv < 40) + { + for (int k = -4; k < 5; k++) + { + int newy = y + k; + if (newy < 0) + { + newy = 0; + } + if (newy >= img.rows) + { + newy = img.rows - 1; + } + offt = newy * img.cols + x; + maxv = pdata[offt]; + if (pdata[offt] > maxv) + { + maxv = pdata[offt]; + } + } + } + + if (maxv > 40) + { + // 2、计算区域最大值 + for (int k = -4; k < 5; k++) + { + int newy = y + k; + if (newy < 0) + { + newy = 0; + } + if (newy >= img.rows) + { + newy = img.rows - 1; + } + + for (int ix = -4; ix < 5; ix++) + { + int newx = x + ix; + if (newx < 0) + { + newx = 0; + } + if (newx > img.cols) + { + newx = img.cols; + } + + offt = newy * img.cols + newx; + + if (pdata[offt] > maxv) + { + maxv = pdata[offt]; + } + } + + /* code */ + } + if (bshowimg) + { + cv::Rect roi; + roi.x = x - 2; + roi.width = 5; + if (roi.x < 0) + { + roi.x = 0; + } + int rdp = roi.x + roi.width; + if (rdp > showimg.cols) + { + rdp = showimg.cols; + } + roi.width = rdp - roi.x; + + roi.y = y - 2; + roi.height = 5; + if (roi.y < 0) + { + roi.y = 0; + } + rdp = roi.y + roi.height; + if (rdp > showimg.rows) + { + rdp = showimg.rows; + } + roi.height = rdp - roi.y; + cv::rectangle(showimg, roi, cv::Scalar(0, 0, 255)); + /* code */ + } + } + else + { + // if (start > 0) + // { + // //printf("error p %d %d %d \n", x, y, maxv); + // /* code */ + // } + } + // 3、满足要求 记录 + + if (maxv >= Gate) + { + ncount += 2; + if (start == 0) + { + start = x; + // printf("---- %d %d y %d\n", pdata[offt], start, y); + } + if (ncount > Limit) + { + break; + } + } + else + { + // if (maxv < 15) + // { + // ncount = 0; + // } + ncount--; + if (ncount < 0) + { + start = 0; + ncount = 0; + } + } + } + if (ncount > Limit) + { + sumcount++; + sumsite += start; + data.push_back(start); + if (bshowimg && !showimg.empty()) + { + cv::Point p(start, y); + cv::circle(showimg, p, 13, cv::Scalar(255, 255, 125), 5); + // cv::imwrite("showimg.png", showimg); + // printf(">>>>>>>>\n"); + // getchar(); + } + } + } + } + + // if (bshowimg && !showimg.empty()) + // { + // cv::imwrite("showimg.png", showimg); + // printf(">>>>>>123>> DirectSign %d \n",DirectSign); + // getchar(); + // } + // if (DirectSign < 0) + // { + + // cv::imwrite("showimg.png", img); + // printf(">>>>>>>>\n"); + // getchar(); + // } + if (sumcount <= 0) + { + return -3; + } + else + { + + // 先剔除异常数据 + std::vector filteredData = removeOutliers(data); + + if (bshowimg && !showimg.empty()) + { + + // for (int i = 0; i < data.size(); i++) + // { + // printf("%d %f \n ", i, data.at(i)); + // } + + // for (int i = 0; i < filteredData.size(); i++) + // { + // printf("%d %f \n ", i, filteredData.at(i)); + // } + } + sumsite = 0; + sumcount = 0; + int mean = 0; + for (int i = 0; i < filteredData.size(); i++) + { + sumsite += filteredData.at(i); + sumcount++; + } + if (sumcount > 0) + { + mean = sumsite / sumcount; + } + + mean = sumsite / sumcount; + return mean; + } + + return -5; +} diff --git a/AlgorithmModule/src/ImageDetBase.cpp b/AlgorithmModule/src/ImageDetBase.cpp new file mode 100644 index 0000000..f1d624a --- /dev/null +++ b/AlgorithmModule/src/ImageDetBase.cpp @@ -0,0 +1,14 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ImageDetBase.h" +#include "ImgCheckAnalysisy.hpp" +ImgCheckBase *ImgCheckBase::GetInstance() +{ + return (ImgCheckBase *)new ImgCheckAnalysisy(); +} diff --git a/AlgorithmModule/src/ImageStorage.cpp b/AlgorithmModule/src/ImageStorage.cpp new file mode 100644 index 0000000..36ca486 --- /dev/null +++ b/AlgorithmModule/src/ImageStorage.cpp @@ -0,0 +1,77 @@ +#include "ImageStorage.h" +#include +#include + +ImageStorage *ImageStorage::instance = nullptr; + +ImageStorage::ImageStorage() : stopFlag(false) +{ + // 启动存储线程 + storageThread = std::thread(&ImageStorage::storeImages, this); +} + +ImageStorage::~ImageStorage() +{ + stop(); // 在销毁时确保线程被正确停止 +} + +// 获取单例实例的静态方法 +ImageStorage *ImageStorage::getInstance() +{ + if (instance == nullptr) + { + instance = new ImageStorage(); // 如果实例为空,则创建新实例 + } + return instance; +} + +void ImageStorage::storeImages() +{ + while (!stopFlag) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep for 100 milliseconds + std::unique_lock lock(queueMutex); + cv.wait(lock, [this]() + { return !imageQueue.empty() || stopFlag; }); + + if (stopFlag && imageQueue.empty()) + break; + + auto item = imageQueue.front(); + imageQueue.pop(); + lock.unlock(); + cv::Mat temimg = item.first; + if (!temimg.empty()) + { + cv::imwrite(item.second, item.first); // 保存图片到文件 + std::cout << "Image saved to: " << item.second << std::endl; + } + } +} + +int ImageStorage::addImage(const std::string &path, const cv::Mat &image,bool badd) +{ + std::lock_guard lock(queueMutex); + + if (imageQueue.size() > 20 && !badd) + { + std::cout << "Queue has more than 10 items, not adding new images." << std::endl; + return 1; + } + else + { + imageQueue.push({image, path}); + cv.notify_one(); // 通知存储线程处理新任务 + } + return 0; +} + +void ImageStorage::stop() +{ + stopFlag = true; + cv.notify_one(); // 通知存储线程停止 + if (storageThread.joinable()) + { + storageThread.join(); // 等待线程退出 + } +} diff --git a/AlgorithmModule/src/ImgCheckAnalysisy.cpp b/AlgorithmModule/src/ImgCheckAnalysisy.cpp new file mode 100644 index 0000000..3ff4787 --- /dev/null +++ b/AlgorithmModule/src/ImgCheckAnalysisy.cpp @@ -0,0 +1,6915 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ImgCheckAnalysisy.hpp" +#include "CheckUtil.hpp" +#include "Define.h" +// 用于排序轮廓的比较函数 +static bool compareContourAreas(const vector &contour1, const vector &contour2) +{ + double i = contourArea(contour1); + double j = contourArea(contour2); + return (i > j); +} +ImgCheckAnalysisy::ImgCheckAnalysisy() +{ + m_nErrorCode = CHECK_OK; + m_nThreadIdx = -1; + m_bInitSucc = false; + m_bExit = false; + m_nRun_Status = CHECK_THREAD_STATUS_IDLE; + m_nWaite_AIDeal_SmallImg_Num = 0; + m_nWaite_AIComplete_SmallImg_Num = 0; + m_Cut_roi = cv::Rect(0, 0, 0, 0); + m_curLogLevel = 0; + m_bShield_ZF = false; + m_fImgage_Scale_X = 0.03f; + m_fImgage_Scale_Y = 0.03f; + m_pBasicConfig = NULL; + m_bstatus_ReJson = false; + m_pbaseCheckFunction = &m_AnalysisyConfig.baseFunction; +} + +ImgCheckAnalysisy::~ImgCheckAnalysisy() +{ + ExitSystem(); +} +int ImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType) +{ + int re = 0; + switch (nConfigType) + { + case CHECK_CONFIG_Run: + re = LoadRunConfig(pconfig); + if (re == 0) + { + printf("---> LoadRunConfig Succ\n"); + } + else + { + printf("---> LoadRunConfig Fail\n"); + } + break; + case CHECK_CONFIG_Module: + re = LoadCheckConfig(pconfig); + if (re == 0) + { + printf("---> LoadAnalysisConfig Succ\n"); + } + else + { + printf("---> LoadAnalysisConfig Fail\n"); + } + break; + default: + break; + } + return re; +} +int ImgCheckAnalysisy::RunStart(void *pconfig1) +{ + + // 1 、更新参数 并判断参数是否合法 + int re = CHECK_OK; + re = SetNewConfig(); + if (CHECK_OK != re) + { + m_nErrorCode = re; + return m_nErrorCode; + } + printf("---> RunStart Start m_RunConfig.nThreadIdx %d %s\n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.defect_model_path.c_str()); + if (!m_CheckConfig.modelConfig.valid()) + { + m_nErrorCode = CHECK_ERROR_Path_NULL; + return m_nErrorCode; + } + m_nThreadIdx = m_RunConfig.nThreadIdx; + + re = InitRun(m_RunConfig.nCpu_start_Idx); + if (CHECK_OK != re) + { + m_nErrorCode = re; + return m_nErrorCode; + } + + m_nErrorCode = CHECK_OK; + printf("ImgCheckAnalysisy >>>> ImgCheckThread %d Start Succ \n", m_nThreadIdx); + return m_nErrorCode; +} + +int ImgCheckAnalysisy::SetDataRun_SharePtr(std::shared_ptr p) +{ + ImageDet_shareP = p; + DetImgInfo_shareP = p->pBaseImgCheckConfig; + // printf("%d DetImgInfo_shareP count %ld \n", m_RunConfig.nThreadIdx, DetImgInfo_shareP.use_count()); + StartCheck(); + m_nErrorCode = CHECK_OK; + // printf(">>>>>>>>>1>>>>>>>>>\n"); + return m_nErrorCode; +} + +int ImgCheckAnalysisy::GetCheckReuslt(std::shared_ptr &pResult) +{ + m_ImageDetResult_shareP->pBaseImgCheckResult = m_CheckResult_shareP; + pResult = m_ImageDetResult_shareP; + m_ImageDetResult_shareP.reset(); + m_CheckResult_shareP.reset(); + DetImgInfo_shareP.reset(); + SetIDLE(); + // m_nErrorCode = CHECK_OK; + // printf("4 DetImgInfo_shareP count %ld m_nCheckResultErrorCode %d \n", DetImgInfo_shareP.use_count(), m_nCheckResultErrorCode); + return m_nCheckResultErrorCode; +} + +int ImgCheckAnalysisy::CheckImg(std::shared_ptr p, std::shared_ptr &pResult) +{ + m_nRun_Status = CHECK_THREAD_STATUS_BUSY; + CheckImgInit(); + DetImgInfo_shareP = p->pBaseImgCheckConfig; + cv::Rect cutroi = DetImgInfo_shareP->cutRoi; + cv::Mat image; + image = DetImgInfo_shareP->img(cutroi); + + // printf("-------s1 %d %d %d %d\n", cutroi.x, cutroi.y, cutroi.width, cutroi.height); + if (DetImgInfo_shareP->imgtype == 1) + { + cv::Mat outMask; + cv::Mat InImg; + ZF_Check(image, InImg, outMask); + m_CheckResult_shareP->cutSrcimg = InImg; + m_CheckResult_shareP->resultimg = outMask; + } + if (DetImgInfo_shareP->imgtype == 2 || + DetImgInfo_shareP->imgtype == 3) + { + cv::Mat yx_reuslt; + int yxres = YX_Check_L255(image, m_CheckResult_shareP->SrcResultImg, m_CheckResult_shareP->resultMaskImg); + m_CheckResult_shareP->nresult = yxres; + } + m_ImageDetResult_shareP->pBaseImgCheckResult = m_CheckResult_shareP; + m_ImageDetResult_shareP->bShield_ZF = m_bShield_ZF; + if (m_pBasicConfig->fUP_IOU <= 0) + { + + m_ImageDetResult_shareP->bUseUpImg = false; + } + else + { + m_ImageDetResult_shareP->bUseUpImg = true; + } + + pResult = m_ImageDetResult_shareP; + + m_nRun_Status = CHECK_THREAD_STATUS_IDLE; + return 0; +} + +int ImgCheckAnalysisy::ReJsonResul(std::shared_ptr p, std::shared_ptr &pResult) +{ + CheckImgInit(); + SetNewConfig(); + m_TemCheck.bPrintStr = true; + m_TemCheck.addLogLevel = DET_LOG_LEVEL_3; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "ReJsonResul", " Start"); + ImageDet_shareP = p; + DetImgInfo_shareP = p->pBaseImgCheckConfig; + pResult = m_ImageDetResult_shareP; + // std::cout << DetImgInfo_shareP->resultJson << std::endl; + if (DetImgInfo_shareP->resultJson == "") + { + return 1; + } + if (m_pBasicConfig == NULL) + { + printf("m_pBasicConfig == NULL \n"); + return 2; + } + + m_CheckResult_shareP->in_shareImage = DetImgInfo_shareP; + m_qx_Analysis.m_pTemCheck = &m_TemCheck; + m_pFuntion = GetChannelFuntion(m_CheckResult_shareP->in_shareImage->strChannel); + m_CheckResultJson.GetConfig(DetImgInfo_shareP->resultJson, m_ImageDetResult_shareP->pOneImgDetResult); + m_ImageDetResult_shareP->pOneImgDetResult->print("result"); + m_AnalysisyConfig.commonCheckConfig.baseConfig.print(); + // m_AnalysisyConfig.checkFunction.print("ReJsonResul"); + + if (m_pFuntion == NULL) + { + printf("********m_pFuntion ==NULL \n"); + } + + if (DetImgInfo_shareP->img.empty()) + { + m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop] = cv::Mat( + m_ImageDetResult_shareP->pOneImgDetResult->CutRoi.height, + m_ImageDetResult_shareP->pOneImgDetResult->CutRoi.width, CV_8U, cv::Scalar(0)); + + printf("DetImgInfo_shareP->img.empty() \n"); + } + else + { + m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop] = DetImgInfo_shareP->img; + } + m_CutRoi = m_ImageDetResult_shareP->pOneImgDetResult->CutRoi; + m_Crop_Roi_paramImg = m_ImageDetResult_shareP->pOneImgDetResult->Param_CropRoi; + + ImageDet_shareP->alignResult.Init(); + ImageDet_shareP->alignResult.Crop_Roi_DetImg = m_CutRoi; + ImageDet_shareP->alignResult.Crop_Roi_ParmImg = m_Crop_Roi_paramImg; + ImageDet_shareP->alignResult.CalOfftScal(); + // getchar(); + + // cv::Point dst_p; + // dst_p.x = (p.x - offt_x) / fCropROI_Scale_ParmToDet_X; + // dst_p.y = (p.y - offt_y) / fCropROI_Scale_ParmToDet_Y; + + ResizeImg(); + Update_DetRoiList(); + m_bstatus_ReJson = true; + + AnalysisResult_Param_Judge(); + + // 整理 log日志 + m_TemCheck.bInTemList = false; + + int ok_num = 0; + int ng_num = 0; + int ys_num = 0; + int sum = 0; + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result == QX_RESULT_TYPE_NG) + { + ng_num++; + } + else if (QX_info->result == QX_RESULT_TYPE_YS) + { + ys_num++; + } + else + { + ok_num++; + } + sum++; + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================sum = %d; NG %d;YS %d;OK %d====================================", sum, ng_num, ys_num, ok_num); + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================1、NG qx Num = %d=====================\n", ng_num); + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result == QX_RESULT_TYPE_NG) + { + m_TemCheck.analysisInfoList.insert(m_TemCheck.analysisInfoList.end(), QX_info->detLogList.begin(), QX_info->detLogList.end()); + } + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================YS qx Num = %d=====================\n", ys_num); + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result == QX_RESULT_TYPE_YS) + { + m_TemCheck.analysisInfoList.insert(m_TemCheck.analysisInfoList.end(), QX_info->detLogList.begin(), QX_info->detLogList.end()); + } + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================OK qx Num = %d=====================\n", ok_num); + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result != QX_RESULT_TYPE_YS && QX_info->result != QX_RESULT_TYPE_NG) + { + m_TemCheck.analysisInfoList.insert(m_TemCheck.analysisInfoList.end(), QX_info->detLogList.begin(), QX_info->detLogList.end()); + } + } + + m_DrawImg.m_bstatus_ReJson = m_bstatus_ReJson; + DrawResult(); + + // printf("-------m_CheckResult.basicResult.checkUseTimeMs %ld t7 - t1 %ld \n", m_CheckResult_shareP->basicResult.checkUseTimeMs, t7 - t1); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "ReJsonResul", " End result %d", m_CheckResult_shareP->nresult); + + m_CheckResult_shareP->det_LogList.assign(m_TemCheck.analysisInfoList.begin(), m_TemCheck.analysisInfoList.end()); // 使用assign函数进行拷贝 + + m_ImageDetResult_shareP->pBaseImgCheckResult = m_CheckResult_shareP; + printf("m_CheckResult_shareP->det_LogList %ld %ld\n", m_CheckResult_shareP->det_LogList.size(), m_TemCheck.analysisInfoList.size()); + pResult = m_ImageDetResult_shareP; + return 0; +} + +int ImgCheckAnalysisy::InitRun(int nId) +{ + if (m_RunConfig.flag2 == 1) + { + m_bInitSucc = true; + return CHECK_OK; + /* code */ + } + // return 0; + int re = CHECK_OK; + if (m_bInitSucc) + { + return CHECK_OK; + } + + re = InitOtherDet(); + if (CHECK_OK != re) + { + return re; + } + re = InitModel(); + if (CHECK_OK != re) + { + return re; + } + m_nRun_Status = CHECK_THREAD_STATUS_IDLE; + re = StartThread(nId); + if (CHECK_OK != re) + { + return re; + } + m_bInitSucc = true; + return re; +} + +int ImgCheckAnalysisy::GetStatus() +{ + return m_nRun_Status; +} + +std::string ImgCheckAnalysisy::GetVersion() +{ + return std::string("BOE_1.7.5"); +} + +std::string ImgCheckAnalysisy::GetErrorInfo() +{ + std::string str = GetErrorCodeInfo(m_nErrorCode); + printf("%s\n", str.c_str()); + return str; +} + +int ImgCheckAnalysisy::LoadRunConfig(void *p) +{ + if (p == NULL) + { + m_nErrorCode = CHECK_ERROR_Config_Null; + return m_nErrorCode; + } + RunInfoST *pconfig = (RunInfoST *)p; + if (pconfig->nDeviceId < 0 || + pconfig->nDeviceId > 1 || + pconfig->nCpu_start_Idx < 0 || + pconfig->nCpu_start_Idx > 128 || + pconfig->nThreadIdx < 0 || + pconfig->nThreadIdx > 100) + { + m_nErrorCode = CHECK_ERROR_Config_Value; + return m_nErrorCode; + } + + m_RunConfig.copy(*pconfig); + + return CHECK_OK; +} + +int ImgCheckAnalysisy::LoadCheckConfig(void *p) +{ + if (p == NULL) + { + m_nErrorCode = CHECK_ERROR_Config_Null; + return m_nErrorCode; + } + m_pConfig = (ConfigBase *)p; + m_nErrorCode = CHECK_OK; + return m_nErrorCode; +} + +// 开启检测 +int ImgCheckAnalysisy::StartCheck() +{ + m_nRun_Status = CHECK_THREAD_STATUS_READY; + return 0; +} + +int ImgCheckAnalysisy::SetIDLE() +{ + // 更新参数 + SetNewConfig(); + m_nRun_Status = CHECK_THREAD_STATUS_IDLE; + return 0; +} + +int ImgCheckAnalysisy::StartThread(int nId) +{ + // 开启检测线程 + ptr_thread_Run = std::make_shared(std::bind(&ImgCheckAnalysisy::Run, this, nId)); + if (!m_RunConfig.bRetest) + { + ptr_thread_AI = std::make_shared(std::bind(&ImgCheckAnalysisy::ThreadAI, this, nId + 2)); + } + + return 0; +} + +int ImgCheckAnalysisy::StopThread() +{ + m_bExit = true; + if (ptr_thread_Run != nullptr) + { + if (ptr_thread_Run->joinable()) + { + ptr_thread_Run->join(); + } + } + if (ptr_thread_AI != nullptr) + { + if (ptr_thread_AI->joinable()) + { + ptr_thread_AI->join(); + } + } + return 0; +} + +int ImgCheckAnalysisy::ExitSystem() +{ + StopThread(); + return 0; +} + +int ImgCheckAnalysisy::InitModel() +{ + + // 获取当前gpu号确定的 AI处理线程 + m_AIDeal.Init(m_RunConfig.nDeviceId); + m_OtherDet_Config.nDeviceId = m_RunConfig.nDeviceId; + m_OtherDet_Config.pAIDeal = &m_AIDeal; + m_OtherDet_Config.pTemCheck = &m_TemCheck; + if (m_RunConfig.bRetest) + { + int re = InitModel_Clas(); + if (re != 0) + { + printf("InitModel_Clas error \n"); + return 1; + } + + printf("bRetest = true status \n"); + return 0; + } + + int re = InitModel_NF(); + if (re != 0) + { + printf("InitModel_NF error \n"); + return 1; + } + // 异显检测 + re = InitModel_YX(); + if (re != 0) + { + printf("InitModel_NF error \n"); + return 1; + } + re = InitModel_Clas(); + if (re != 0) + { + printf("InitModel_Clas error \n"); + return 1; + } + re = InitModel_ZF(); + if (re != 0) + { + printf("InitModel_ZF error \n"); + return 1; + } + re = InitModel_127Cell(); + if (re != 0) + { + printf("InitModel_127Cell error \n"); + } + + // 缺失Pol检测初始化 + m_LackPolDet.Init(&m_OtherDet_Config); + m_LackPolDet.InitModel_ALL(); + + m_SecondDet.Init(&m_OtherDet_Config); + m_SecondDet.InitModel_ALL(); + + return 0; +} + +int ImgCheckAnalysisy::InitModel_NF() +{ + + AIInitConfig config_nf; + config_nf.nGpuIdx = m_RunConfig.nDeviceId; + config_nf.engine_file_path = m_CheckConfig.modelConfig.defect_model_path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = AI_NF_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = AI_NF_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = AI_NF_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = AI_NF_out_0_IMAGE_Name; + m_AIDeal.Init_BOE(config_nf); + + { + AIInitConfig config_nf; + config_nf.nGpuIdx = m_RunConfig.nDeviceId; + config_nf.engine_file_path = m_CheckConfig.modelConfig.defect_wtb_model_path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = AI_NF_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = AI_NF_IN_0_IMAGE_Name; + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = AI_NF_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = AI_NF_out_0_IMAGE_Name; + m_AIDeal.Init_BOE_Type2(config_nf); + } + + { + AIInitConfig config_up; + config_up.nGpuIdx = m_RunConfig.nDeviceId; + config_up.engine_file_path = m_CheckConfig.modelConfig.UP_model_path; + config_up.bufferList[0].ntype = AIBufferType_IN; + config_up.bufferList[0].ndatalength = AI_NF_IN_0_DATA_LENGTH; + config_up.bufferList[0].strName = AI_NF_IN_0_IMAGE_Name; + config_up.bufferList[1].ntype = AIBufferType_OUT; + config_up.bufferList[1].ndatalength = AI_NF_out_0_DATA_LENGTH; + config_up.bufferList[1].strName = AI_NF_out_0_IMAGE_Name; + m_AIDeal.Init_BOE_UP(config_up); + } + + { + AIInitConfig config_up; + config_up.nGpuIdx = m_RunConfig.nDeviceId; + config_up.engine_file_path = m_CheckConfig.modelConfig.defect_chess_model_path; + config_up.bufferList[0].ntype = AIBufferType_IN; + config_up.bufferList[0].ndatalength = AI_NF_IN_0_DATA_LENGTH; + config_up.bufferList[0].strName = AI_NF_IN_0_IMAGE_Name; + config_up.bufferList[1].ntype = AIBufferType_OUT; + config_up.bufferList[1].ndatalength = AI_NF_out_0_DATA_LENGTH; + config_up.bufferList[1].strName = AI_NF_out_0_IMAGE_Name; + m_AIDeal.Init_BOE_Chess(config_up); + } + return 0; +} + +int ImgCheckAnalysisy::InitModel_YX() +{ + AIInitConfig config_nf; + config_nf.nGpuIdx = m_RunConfig.nDeviceId; + config_nf.engine_file_path = m_CheckConfig.modelConfig.YX_1_model_path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = AI_YX_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = AI_YX_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = AI_YX_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = AI_YX_out_0_IMAGE_Name; + m_AIDeal.Init_YX_1(config_nf); + { + AIInitConfig config_nf; + config_nf.nGpuIdx = m_RunConfig.nDeviceId; + config_nf.engine_file_path = m_CheckConfig.modelConfig.YX_2_model_path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = AI_YX_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = AI_YX_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = AI_YX_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = AI_YX_out_0_IMAGE_Name; + m_AIDeal.Init_YX_2(config_nf); + } + return 0; +} + +int ImgCheckAnalysisy::InitModel_Clas() +{ + if (USE_WHITEBACK_CLASS) + { + { + // L0 + AIInitConfig config_cls; + config_cls.nGpuIdx = m_RunConfig.nDeviceId; + // config_cls.engine_file_path = "/home/aidlux/xianlan/deliverModel/HTDL_MC_MultiClass_20231020_new_MobilenetV2_160_160_fp16.engine"; + config_cls.engine_file_path = m_CheckConfig.modelConfig.class_L0_model_path; // 1024dyy + std::cout << "InitModel_XL()-config_cls.engine_file_path=" << config_cls.engine_file_path << std::endl; // 1125dyy + config_cls.bufferList[0].ntype = AIBufferType_IN; + config_cls.bufferList[0].ndatalength = AI_Cls_IN_0_IMAGE_DATA_LENGTH; + config_cls.bufferList[0].strName = AI_Cls_IN_0_IMAGE_Name; + + config_cls.bufferList[1].ntype = AIBufferType_OUT; + config_cls.bufferList[1].ndatalength = AI_Cls_14_out_0_IMAGE_DATA_LENGTH; + config_cls.bufferList[1].strName = AI_Cls_14_out_0_IMAGE_Name; + return m_AIDeal.Init_Cls(config_cls, 1); + } + } + else + { + AIInitConfig config_cls; + config_cls.nGpuIdx = m_RunConfig.nDeviceId; + // config_cls.engine_file_path = "/home/aidlux/xianlan/deliverModel/HTDL_MC_MultiClass_20231020_new_MobilenetV2_160_160_fp16.engine"; + config_cls.engine_file_path = m_CheckConfig.modelConfig.class_model_path; // 1024dyy + std::cout << "InitModel_XL()-config_cls.engine_file_path=" << config_cls.engine_file_path << std::endl; // 1125dyy + config_cls.bufferList[0].ntype = AIBufferType_IN; + config_cls.bufferList[0].ndatalength = AI_Cls_IN_0_IMAGE_DATA_LENGTH; + config_cls.bufferList[0].strName = AI_Cls_IN_0_IMAGE_Name; + + config_cls.bufferList[1].ntype = AIBufferType_OUT; + config_cls.bufferList[1].ndatalength = AI_Cls_out_0_IMAGE_DATA_LENGTH; + config_cls.bufferList[1].strName = AI_Cls_out_0_IMAGE_Name; + return m_AIDeal.Init_Cls(config_cls, 0); + } + + return 0; +} + +int ImgCheckAnalysisy::InitModel_ZF() +{ + AIInitConfig config_zf; + config_zf.nGpuIdx = m_RunConfig.nDeviceId; + // config_cls.engine_file_path = "/home/aidlux/xianlan/deliverModel/HTDL_MC_MultiClass_20231020_new_MobilenetV2_160_160_fp16.engine"; + config_zf.engine_file_path = m_CheckConfig.modelConfig.zf_model_path; // 1024dyy + std::cout << "InitModel_ZF.engine_file_path=" << config_zf.engine_file_path << std::endl; // 1125dyy + config_zf.bufferList[0].ntype = AIBufferType_IN; + config_zf.bufferList[0].ndatalength = AI_ZF_IN_0_DATA_LENGTH; + config_zf.bufferList[0].strName = AI_ZF_IN_0_IMAGE_Name; + config_zf.bufferList[1].ntype = AIBufferType_OUT; + config_zf.bufferList[1].ndatalength = AI_ZF_out_0_DATA_LENGTH; + config_zf.bufferList[1].strName = AI_ZF_out_0_IMAGE_Name; + return m_AIDeal.Init_zf(config_zf); +} + +int ImgCheckAnalysisy::InitModel_Up() +{ + return 0; +} + +int ImgCheckAnalysisy::InitModel_127Cell() +{ + AIInitConfig config_nf; + config_nf.nGpuIdx = m_RunConfig.nDeviceId; + config_nf.engine_file_path = str_AI_127Cell_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = AI_127Cell_IN_0_DATA_LENGTH; + config_nf.bufferList[0].strName = AI_127Cell_IN_0_IMAGE_Name; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = AI_127Cell_out_0_DATA_LENGTH; + config_nf.bufferList[1].strName = AI_127Cell_out_0_IMAGE_Name; + m_AIDeal.Init_127Cell(config_nf); + return 0; +} + +int ImgCheckAnalysisy::CheckRun() +{ + + long t1, t2, t3, t4, t5, t6, t7; + SetNewConfig(); + t1 = CheckUtil::getcurTime(); + DetImgInfo_shareP->time_startCheck = t1; + CheckImgInit(); + if (DetImgInfo_shareP->otherValue == 9) + { + m_TemCheck.bPrintStr = true; + } + + // m_TemCheck.bPrintStr = true; + m_TemCheck.addLogLevel = DET_LOG_LEVEL_3; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "1、basic Info", "---------------------------1、basic Info---------------------------------"); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Version", "%s", GetVersion().c_str()); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Start", " Check Run %s - %s", DetImgInfo_shareP->strImgProductID.c_str(), DetImgInfo_shareP->strChannel.c_str()); + // printf("threadid %d Check Run %s %s\n", m_nThreadIdx, DetImgInfo_shareP->strImgProductID.c_str(), DetImgInfo_shareP->strChannel.c_str()); + + m_qx_Analysis.m_pTemCheck = &m_TemCheck; + m_CheckResult_shareP->in_shareImage = DetImgInfo_shareP; + m_CheckResult_shareP->checkStatus = 1; + m_CheckResult_shareP->nresult = -1; + + UpdateImgageScale(DetImgInfo_shareP->img); + + // 2、参数检查 + int rec = ConfigCheck(DetImgInfo_shareP->img); + if (rec != CHECK_OK) + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Error", "ConfigCheck is error type = %d", rec); + m_nErrorCode = rec; + m_nCheckResultErrorCode = m_nErrorCode; + return m_nErrorCode; + } + // 3、基本信息 + + m_CheckResult_shareP->checkStatus = 1; + m_curLogLevel = DetImgInfo_shareP->nlogLevel; + + m_CheckResult_shareP->basicResult.img_id = m_CheckResult_shareP->in_shareImage->img_id; + m_CheckResult_shareP->basicResult.imgtype = m_CheckResult_shareP->in_shareImage->imgtype; + m_CheckResult_shareP->basicResult.imgstr = m_CheckResult_shareP->in_shareImage->imgstr; + m_CheckResult_shareP->basicResult.strChannel = m_CheckResult_shareP->in_shareImage->strChannel; + m_ImageDetResult_shareP->fUP_IOU = m_pBasicConfig->fUP_IOU; + + cv::Rect cutroi = DetImgInfo_shareP->cutRoi; + m_CutRoi = cutroi; + m_Crop_Roi_paramImg = cutroi; + + float fw = m_CutRoi.width * m_fImgage_Scale_X; + float fh = m_CutRoi.height * m_fImgage_Scale_Y; + fw = std::ceil(fw * 10) / 10; + fh = std::ceil(fh * 10) / 10; + m_CheckResult_shareP->productWidht_mm = fw; + m_CheckResult_shareP->productHeight_mm = fh; + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Det ROI", " [w %d,h %d] (piexl) -> [w %f h %f](mm),scale %f %f", + m_CutRoi.width, m_CutRoi.height, fw, fh, m_fImgage_Scale_X, m_fImgage_Scale_Y); + + cv::Mat image; + image = m_CheckResult_shareP->in_shareImage->img; + m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop] = image(cutroi).clone(); + + { + if (!ImageDet_shareP->edge_maskImg.empty() && !m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].empty()) + { + cv::Mat shieldmask = ~ImageDet_shareP->edge_maskImg(cutroi).clone(); + if (shieldmask.size() == m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].size()) + { + m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].setTo(180, shieldmask); // 在 mask 区域设置值为 180 + // cv::imwrite(m_CheckResult_shareP->in_shareImage->strChannel + "sss.png", m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + // getchar(); + } + else + { + // printf("eeeeee22222eeeeeeeeeeee\n"); + // getchar(); + } + } + else + { + // printf("eeeeeeeeeeeeeeeeee\n"); + // getchar(); + } + } + + m_ImageDetResult_shareP->pOneImgDetResult->CutRoi = cutroi; + m_ImageDetResult_shareP->pOneImgDetResult->Param_CropRoi = m_Crop_Roi_paramImg; + cv::Rect cutShield_roi = cutroi; + + UpdateImgageScale(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + GetInstruct(DetImgInfo_shareP->ninstruct); + + m_pFuntion = GetChannelFuntion(m_CheckResult_shareP->in_shareImage->strChannel); + int nfunction = 0; + if (m_pFuntion != NULL) + { + // 检测分析 1、先进行异显检测如果,结果是异显,则不进行后续检测判断 + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Detect function", "%s", + m_pFuntion->GetInfo("").c_str()); + } + else + { + nfunction = 1; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Error", "m_pFuntion is NULL"); + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "1、basic Info", "-------------------------2、Detect function %s---------------\n", Re_TO_STR_Error(nfunction)); + + // 更新 参数图片的crop。 + if (ImageDet_shareP && ImageDet_shareP->alignResult.bDet && ImageDet_shareP->alignResult.bUse) + { + m_Crop_Roi_paramImg = ImageDet_shareP->alignResult.Crop_Roi_ParmImg; + if (m_Crop_Roi_paramImg.x < 0) + { + m_Crop_Roi_paramImg.x = 0; + } + if (m_Crop_Roi_paramImg.x + m_Crop_Roi_paramImg.width > image.cols) + { + m_Crop_Roi_paramImg.x = image.cols - m_Crop_Roi_paramImg.width; + } + if (m_Crop_Roi_paramImg.y < 0) + { + m_Crop_Roi_paramImg.y = 0; + } + if (m_Crop_Roi_paramImg.y + m_Crop_Roi_paramImg.height > image.rows) + { + m_Crop_Roi_paramImg.y = image.rows - m_Crop_Roi_paramImg.height; + } + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "1、basic Info", "-------------------------3、Align : Crop ROI cur Img [%d %d %d %d] -> config Img ROI [%d %d %d %d] judge [x y] = [%d %d]---Scale = [%f %f]------------\n", + cutroi.x, cutroi.y, cutroi.width, cutroi.height, + m_Crop_Roi_paramImg.x, m_Crop_Roi_paramImg.y, m_Crop_Roi_paramImg.width, m_Crop_Roi_paramImg.height, + ImageDet_shareP->alignResult.offt_x, ImageDet_shareP->alignResult.offt_y, + ImageDet_shareP->alignResult.fCropROI_Scale_ParmToDet_X, ImageDet_shareP->alignResult.fCropROI_Scale_ParmToDet_Y); + } + else + { + if (ImageDet_shareP) + { + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "1、basic Info", "-------------------------3、Align : det :%d != 1 or use :%d != 1---------------\n", + ImageDet_shareP->alignResult.bDet, + ImageDet_shareP->alignResult.bUse); + } + } + m_ImageDetResult_shareP->pOneImgDetResult->Param_CropRoi = m_Crop_Roi_paramImg; + + if (DetImgInfo_shareP->Det_Mode == DET_MODE_YX) + { + // printf("\n %s det yx >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n",DetImgInfo_shareP->strChannel.c_str()); + cv::Mat yx_reuslt; + int yxres = YX_Check_L255(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], m_CheckResult_shareP->SrcResultImg, m_CheckResult_shareP->resultMaskImg); + m_CheckResult_shareP->nresult = yxres; + return 0; + } + + rec = UpdateSheildMask(m_CheckResult_shareP->in_shareImage->strChannel, m_Crop_Roi_paramImg); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "2、pre detect", "-------------------------1、add Web config : sheild mask %s---------------\n", Re_TO_STR_Error(rec)); + // 字符区域 用以屏蔽 + GetZfCropMask(cutroi); + + m_CheckResult_shareP->cutSrcimg = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]; + + rec = GetDetMaskImg(DetImgInfo_shareP->other_channel_Result_mask, cutroi); + if (rec != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "GetDetMaskImg is error type = %d", rec); + m_nErrorCode = rec; + m_nCheckResultErrorCode = m_nErrorCode; + return m_nErrorCode; + } + + ResizeImg(); + // 更新检测区域 + Update_DetRoiList(); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "2、pre detect", "-------------------------2、DrawShieldR---------------\n"); + m_CheckResult_shareP->nresult = 0; + + if (m_pFuntion != NULL) + { + // 检测分析 1、先进行异显检测如果,结果是异显,则不进行后续检测判断 + rec = AI_Det_YX(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "2、pre detect", "-------------------------3、YX Detect --result %s-------------\n", Re_TO_STR_NG(m_OtherResult.result_YX.nresult)); + + if (m_OtherResult.result_YX.nresult != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", " result YX"); + + m_ImageDetResult_shareP->Yx_result = 1; + + printf("m_CheckResult_shareP->nresult %d %zu\n", m_CheckResult_shareP->nresult, m_CheckResult_shareP->qxImageResult.size()); + } + else + { + // 缺失 POL检测 + rec = Detect_LackPol(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "2、pre detect", "-------------------------4、Detect_LackPol --result %s-------------\n", Re_TO_STR_NG(m_OtherResult.result_LackPol.nresult)); + + if (m_OtherResult.result_LackPol.nresult != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Detect_LackPol", " result Lack POL"); + printf("m_CheckResult_shareP->nresult %d %zu\n", m_CheckResult_shareP->nresult, m_CheckResult_shareP->qxImageResult.size()); + } + else + { + // 检测分析 2、结果不是异显,则进行后续检测判断 + // 只有 开启基础检测的或者 只有Up画面分析的 才进行AI 推 + if (m_pFuntion && + (m_pFuntion->function.f_BaseDet.bOpen || + m_pFuntion->function.f_OnlyBLob.bOpen)) + { + + t2 = CheckUtil::getcurTime(); + + AI_Detect_Thread(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], m_TemCheck.temImgList[TEM_IMG_IDX_AImask]); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "3、detect", "-------------------------1、AI Detect---------------\n"); + + t3 = CheckUtil::getcurTime(); + m_CheckResult_shareP->resultMaskImg = m_TemCheck.temImgList[TEM_IMG_IDX_AImask]; + + t4 = CheckUtil::getcurTime(); + CheckAnalysisResult(); + t5 = CheckUtil::getcurTime(); + + if (m_pFuntion->function.f_OnlyBLob.bOpen) + { + m_CheckResult_shareP->SrcResultImg = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]; + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Base Det", "function close"); + } + } + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Error", "m_pFuntion is NULL"); + } + + m_ImageDetResult_shareP->AI_maskImg = m_CheckResult_shareP->resultMaskImg.clone(); + + DrawResult(); + t6 = CheckUtil::getcurTime(); + + m_CheckResult_shareP->strResultJson = m_CheckResultJson.GetResultString(m_ImageDetResult_shareP->pOneImgDetResult); + + t7 = CheckUtil::getcurTime(); + DetImgInfo_shareP->time_EndCheck = t7; + m_CheckResult_shareP->basicResult.checkUseTimeMs = t7 - DetImgInfo_shareP->getImgTimeMs; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "result", " %d ALL use Time %ld det time sum %ld init %ld AI %ld ResizeImg %ld analysis %ld draw %ld ", + m_CheckResult_shareP->nresult, m_CheckResult_shareP->basicResult.checkUseTimeMs, t7 - t1, t2 - t1, t3 - t2, t4 - t3, t5 - t4, t6 - t5); + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "time", "ALL use Time %ld readImg %ld send list %ld PushIn %ld sendCheck %ld startCheck %ld EndCheck %ld ", + DetImgInfo_shareP->time_EndCheck - DetImgInfo_shareP->readImg_start, + DetImgInfo_shareP->readImg_end - DetImgInfo_shareP->readImg_start, + DetImgInfo_shareP->getImgTimeMs - DetImgInfo_shareP->readImg_end, + DetImgInfo_shareP->time_PushIn - DetImgInfo_shareP->getImgTimeMs, + DetImgInfo_shareP->time_sendCheck - DetImgInfo_shareP->time_PushIn, + DetImgInfo_shareP->time_startCheck - DetImgInfo_shareP->time_sendCheck, + DetImgInfo_shareP->time_EndCheck - DetImgInfo_shareP->time_startCheck); + + // printf("-------m_CheckResult.basicResult.checkUseTimeMs %ld t7 - t1 %ld \n", m_CheckResult_shareP->basicResult.checkUseTimeMs, t7 - t1); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "End", " Check Run"); + + m_CheckResult_shareP->det_LogList.assign(m_TemCheck.analysisInfoList.begin(), m_TemCheck.analysisInfoList.end()); // 使用assign函数进行拷贝 + if (DetImgInfo_shareP->otherValue == 9) + { + m_TemCheck.saveImg(); + /* code */ + } + + return 0; +} + +int ImgCheckAnalysisy::SetNewConfig() +{ + printf("************** ImgCheckAnalysisy::SetNewConfig m_RunConfig.nThreadIdx %d\n", m_RunConfig.nThreadIdx); + // 是否有参数更新 + if (m_pConfig->GetConfigUpdataStatus(ConfigType_Check_XL, m_RunConfig.nThreadIdx)) + { + m_pConfig->GetConfig(ConfigType_Check_XL, &m_CheckConfig); + if (true) + { + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.defect_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.defect_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.class_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.class_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.YX_1_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.YX_1_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.YX_2_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.YX_2_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.defect_wtb_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.defect_wtb_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.defect_chess_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.defect_chess_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.zf_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.zf_model_path.c_str()); + printf("SetNewConfig nThreadIdx %d m_CheckConfig.modelConfig.UP_model_path %s \n", m_RunConfig.nThreadIdx, m_CheckConfig.modelConfig.UP_model_path.c_str()); + } + } + if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, m_RunConfig.nThreadIdx)) + { + m_pConfig->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig); + if (m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size() > 0) + { + m_pCommonAnalysisyConfig = &m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(0); + m_pBasicConfig = &m_AnalysisyConfig.commonCheckConfig.baseConfig; + m_pRegionAnalysisyParam = &m_pCommonAnalysisyConfig->regionConfigArr.at(0); + GetParamidx(); + CreateMaskImg(); + SetInDetConfig(); + UPdateLDConfig(); + if (true) + { + printf("SetNewConfig nThreadIdx %d m_CheckConfig.strSkuName %s \n", m_RunConfig.nThreadIdx, m_AnalysisyConfig.strSkuName.c_str()); + } + m_bShield_ZF = m_pBasicConfig->bShield_ZF; + if (m_bShield_ZF) + { + printf("m_bShield_ZF is open \n"); + } + else + { + printf("m_bShield_ZF is close \n"); + } + } + else + { + printf("m_AnalysisyConfig.commonCheckConfig.nodeConfigArr == 0 \n"); + } + } + else + { + printf("ConfigType_Analysisy_Common_XL no Update \n"); + } + m_nErrorCode = CHECK_OK; + return CHECK_OK; +} + +int ImgCheckAnalysisy::GetParamidx() +{ + int region = 0; + if (m_pCommonAnalysisyConfig->regionConfigArr.size() <= 0) + { + return 1; + } + + CheckConfig_Regions_type *p = &m_pCommonAnalysisyConfig->regionConfigArr.at(region).checkConfig_Regions_type[0]; + for (int iqx = 0; iqx < CONFIG_QX_NAME_count; iqx++) + { + m_QxInParamListIdx[iqx] = -1; + std::string strqx_name = CONFIG_QX_NAME_Names[iqx]; + for (int i = 0; i < p->checkConfig_Regions_Param.size(); i++) + { + std::string strconfig_name = p->checkConfig_Regions_Param[i].param_name; + + // getchar(); + if (strqx_name == strconfig_name) + { + printf("strqx_name %s strconfig_name %s \n", strqx_name.c_str(), strconfig_name.c_str()); + m_QxInParamListIdx[iqx] = i; + break; + } + } + } + // getchar(); + return 0; +} +int ImgCheckAnalysisy::AddCheckLog(int nlevel, std::string str) +{ + if (nlevel <= m_curLogLevel && str != "") + { + m_CheckResult_shareP->det_LogList.push_back(str); + } + + return 0; +} +int ImgCheckAnalysisy::GetRegionIdx(int x, int y) +{ + int regionidx = -1; + if (m_AnalysisyMaskImg.empty()) + { + printf("--m_AnalysisyMaskImg.empty()-\n"); + return regionidx; + } + int pnx = x + m_CutRoi.x; + int pny = y + m_CutRoi.y; + + if (pnx > 0 && pnx <= m_AnalysisyMaskImg.cols && + pny > 0 && pny <= m_AnalysisyMaskImg.rows) + { + /* code */ + } + else + { + printf("region x, y %d %d error -\n", pnx, pny); + return regionidx; + } + // for (int i = 0; i < m_pCommonAnalysisyConfig->regionConfigArr.size(); i++) + // { + // printf("%d region lay %d %s \n", i, m_pCommonAnalysisyConfig->regionConfigArr.at(i).basicInfo.lay, m_pCommonAnalysisyConfig->regionConfigArr.at(i).basicInfo.name.c_str()); + // } + + int vcommonvalue = m_AnalysisyMaskImg.at(pny, pnx); + + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "GetRegionIdx", " crop x y = %d %d, src img x y = %d %d,mask value vcommonvalue %d", x, y, pnx, pny, vcommonvalue); + + int kregion = (vcommonvalue - MASK_IMG_STARTVALUE) / MASK_IMG_STEP; + // int nv = MASK_IMG_STEP*i+MASK_IMG_STARTVALUE; + // printf("size %d id %d x y %d %d \n", m_pCommonAnalysisyConfig->regionConfigArr.size(), kregion, x, y); + if (kregion >= 0 && kregion < m_pCommonAnalysisyConfig->regionConfigArr.size()) + { + regionidx = kregion; + } + return regionidx; +} +ChannelCheckFunction *ImgCheckAnalysisy::GetChannelFuntion(std::string strChannelName) +{ + ChannelCheckFunction *p = NULL; + for (int i = 0; i < m_AnalysisyConfig.checkFunction.channelFunctionArr.size(); i++) + { + if (CheckUtil::compareIgnoreCase(m_AnalysisyConfig.checkFunction.channelFunctionArr[i].strChannelName, strChannelName)) + { + p = &m_AnalysisyConfig.checkFunction.channelFunctionArr[i]; + } + } + + return p; +} +int ImgCheckAnalysisy::Run(int nId) +{ + std::vector vi; + vi.push_back(nId); + vi.push_back(nId + 1); + auto nRet = set_cpu_id(vi); + printf("Check So %d bind cpu ret %d, %d\n", m_nThreadIdx, nRet, nId); + while (!m_bExit) + { + // 数据准备完成,开启检测 + if (m_nRun_Status == CHECK_THREAD_STATUS_READY) + { + m_nRun_Status = CHECK_THREAD_STATUS_BUSY; + /* 检测 */ + CheckRun(); + m_nRun_Status = CHECK_THREAD_STATUS_COMPLETE; + // printf("*--------%d\n", m_nRun_Status); + } + else + { + + usleep(1000); + } + // printf("*-"); + usleep(1000); + } + return 0; +} +int ImgCheckAnalysisy::set_cpu_id(const std::vector &cpu_set_vec) +{ + // for cpu affinity + int nRet = 0; +#ifdef __linux + cpu_set_t _cur_cpu_set; + CPU_ZERO(&_cur_cpu_set); + for (auto _id : cpu_set_vec) + { + CPU_SET(_id, &_cur_cpu_set); + } + if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set)) + { + perror("set cpu affinity failed: "); + printf("Warning: set cpu affinity failed ... ...\n"); + nRet = -1; + } +#endif //__linux + return nRet; +} + +int ImgCheckAnalysisy::saveAIImg() +{ + if (DetImgInfo_shareP->otherValue_1 == 181) + { + for (int i = 0; i < AI_DetImgList.size(); i++) + { + cv::Mat temimg = AI_DetImgList.at(i).outimg; + int non_zero_count = cv::countNonZero(temimg); + + if (non_zero_count > 3) + { + static int saveIdx = 0; + + std::string str_in = "/home/aidlux/BOE/AI/" + DetImgInfo_shareP->strChannel + "_" + std::to_string(saveIdx) + ".png"; + std::string str_out = "/home/aidlux/BOE/AI/" + DetImgInfo_shareP->strChannel + "_" + std::to_string(saveIdx) + "_mask.png"; + if (!AI_DetImgList.at(i).img.empty()) + { + cv::imwrite(str_in, AI_DetImgList.at(i).img); + /* code */ + } + if (!AI_DetImgList.at(i).outimg.empty()) + { + cv::imwrite(str_out, AI_DetImgList.at(i).outimg); + /* code */ + } + saveIdx++; + if (saveIdx > 99990) + { + saveIdx = 0; + } + } + } + } + return 0; +} + +int ImgCheckAnalysisy::AnalysisResult_New() +{ + std::string strBaseLog = "AnalysisResult"; + // 不进行缺陷分析 + if (m_pFuntion->function.f_OnlyBLob.bOpen) + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Analysis Close Only Det"); + return 0; + } + // m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AnalysisResult Start"); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "4、qx AnalysisResult", "-------------------------1、qx judge---------------\n"); + + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + + float fs_resize_x = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fs_resize_y = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, "fscale_x %f fscale_y %f", fs_x, fs_y); + // 整理缺陷信息 + saveAIImg(); + AnalysisResult_Qx(); + CalBlobDensity_QX(); + m_bstatus_ReJson = false; + // 参数判断 + AnalysisResult_Param_Judge(); + + // 整理 log日志 + m_TemCheck.bInTemList = false; + + int ok_num = 0; + int ng_num = 0; + int ys_num = 0; + int sum = 0; + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result == QX_RESULT_TYPE_NG) + { + ng_num++; + } + else if (QX_info->result == QX_RESULT_TYPE_YS) + { + ys_num++; + } + else + { + ok_num++; + } + sum++; + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================sum = %d; NG %d;YS %d;OK %d====================================", sum, ng_num, ys_num, ok_num); + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================1、NG qx Num = %d=====================\n", ng_num); + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result == QX_RESULT_TYPE_NG) + { + m_TemCheck.analysisInfoList.insert(m_TemCheck.analysisInfoList.end(), QX_info->detLogList.begin(), QX_info->detLogList.end()); + } + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================YS qx Num = %d=====================\n", ys_num); + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result == QX_RESULT_TYPE_YS) + { + m_TemCheck.analysisInfoList.insert(m_TemCheck.analysisInfoList.end(), QX_info->detLogList.begin(), QX_info->detLogList.end()); + } + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "result", "=====================OK qx Num = %d=====================\n", ok_num); + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + if (QX_info->result != QX_RESULT_TYPE_YS && QX_info->result != QX_RESULT_TYPE_NG) + { + m_TemCheck.analysisInfoList.insert(m_TemCheck.analysisInfoList.end(), QX_info->detLogList.begin(), QX_info->detLogList.end()); + } + } + return 0; +} + +int ImgCheckAnalysisy::AnalysisResult_Qx() +{ + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "QX", " Start"); + + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + + float fs_resize_x = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fs_resize_y = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + m_TemCheck.bInTemList = true; + m_TemCheck.temLogListInit(); + + // 遍历每个检测blob + for (int i = 0; i < blobs.blobCount; i++) + { + m_TemCheck.temLogListInit(); + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Blob", "%d/%d start", i, blobs.blobCount); + + cv::Rect roi; + roi.x = blobs.blobTab[i].minx; + roi.y = blobs.blobTab[i].miny; + roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1; + roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1; + float JudgArea = blobs.blobTab[i].area * fs_x * fs_y; + blobs.blobTab[i].JudgArea = JudgArea; + float flen = roi.width * fs_x; + if (roi.height * fs_y > flen) + { + flen = roi.height * fs_y; + } + blobs.blobTab[i].len = flen; + + int nerrortype = 0; + int checkFlage = 0; + + float fmaxScore = 0; + int config_qx_type = 0; + // printf("blobs.blobTab[i].ErrDesc %d \n",blobs.blobTab[i].ErrDesc); + if (blobs.blobTab[i].ErrDesc == CONFIG_QX_NAME_white_Cell || blobs.blobTab[i].ErrDesc == CONFIG_QX_NAME_black_Cell) + { + config_qx_type = blobs.blobTab[i].ErrDesc; + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "127Cell Det Blob", "error type %d", config_qx_type); + } + else + { + config_qx_type = AI_Classify_New(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], roi, JudgArea, &fmaxScore); + // config_qx_type = AI_Classify(sizeimg, roi, JudgArea, &fmaxScore); + // 方格线判断 + if (config_qx_type == CONFIG_QX_NAME_Y_line || config_qx_type == CONFIG_QX_NAME_X_line) + { + bool bchange = false; + float fwh = roi.width * 1.0f / roi.height; + if (roi.height > roi.width) + { + fwh = roi.height * 1.0f / roi.width; + } + else + { + fwh = roi.width * 1.0f / roi.height; + } + if (fwh < 7) + { + bchange = true; + } + if (bchange) + { + config_qx_type = CONFIG_QX_NAME_Fangge; + } + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, " Y line to fangge line ", "change = %d width %f < 7", bchange, fwh); + } + } + + std::string qx_name123 = CONFIG_QX_NAME_Names[config_qx_type]; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "1、AI_Classify", "qx %d = %s %f", config_qx_type, qx_name123.c_str(), fmaxScore); + + // 精确计算长度 + float re_len = Cal_QXLen(m_TemCheck.temImgList[TEM_IMG_IDX_AImask](roi), config_qx_type, fs_x, fs_y); + + if (re_len >= 0) + { + flen = re_len; + blobs.blobTab[i].len = flen; + } + + // 精确计算能量(基于像素灰度差) + { + cv::Scalar result = calc_blob_info_withstats( + m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], + m_TemCheck.temImgList[TEM_IMG_IDX_AImask], + roi); + blobs.blobTab[i].energy = static_cast(result[1]); + } + + float fsecondArea = JudgArea; + // 异物和暗点进行二次分割 精确计算面积和长度的精确计算 + if (config_qx_type == CONFIG_QX_NAME_AD || + config_qx_type == CONFIG_QX_NAME_POL_Cell) + { + AI_SecondDet::DetConfigResult detconfigresult; + detconfigresult.pfunction_secondDet = &m_pFuntion->function.f_SecondDetect; + detconfigresult.SetAreaAndLen(blobs.blobTab[i].area, flen); + detconfigresult.qx_roi = roi; + detconfigresult.qx_name = qx_name123; + detconfigresult.qx_type = config_qx_type; + detconfigresult.strChannel = m_CheckResult_shareP->in_shareImage->strChannel; + detconfigresult.fImgage_Scale_X = m_fImgage_Scale_X; + detconfigresult.fImgage_Scale_Y = m_fImgage_Scale_Y; + + int detre = ReCalQX_AreaAndLen(&detconfigresult); + + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "2、AICheck_RE Area Len", "Old area %f (mm2) New Area %f; old len %0.2f new %0.2f", + JudgArea, detconfigresult.new_Area * fs_x * fs_y, detconfigresult.old_len, detconfigresult.new_len); + if (detre == 0) + { + if (config_qx_type == CONFIG_QX_NAME_POL_Cell) + { + if (detconfigresult.pfunction_secondDet->pol_open_SingleCheck) + { + fsecondArea = detconfigresult.new_Area * fs_x * fs_y; + } + else + { + blobs.blobTab[i].area = detconfigresult.new_Area; + JudgArea = blobs.blobTab[i].area * fs_x * fs_y; + blobs.blobTab[i].JudgArea = JudgArea; + fsecondArea = JudgArea; + } + } + else + { + blobs.blobTab[i].area = detconfigresult.new_Area; + JudgArea = blobs.blobTab[i].area * fs_x * fs_y; + blobs.blobTab[i].JudgArea = JudgArea; + fsecondArea = JudgArea; + } + flen = detconfigresult.new_len; + blobs.blobTab[i].len = flen; + } + } + + bool bLD_Standard = false; // 是否通过LD标准判定(跳过UP/DP的IOU检查) + if (config_qx_type == CONFIG_QX_NAME_MTX || + config_qx_type == CONFIG_QX_NAME_POL_Cell || + config_qx_type == CONFIG_QX_NAME_LD) + { + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + // m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD", "stsrt config_qx_type %s ", qx_name.c_str()); + int dbresult = -1; + if(m_pFuntion->function.f_LDConfig.bOpen && m_pFuntion->function.f_LDConfig.bUseLD_Standard) + { + if(blobs.blobTab[i].JudgArea >= m_pFuntion->function.f_LDConfig.fLD_Area && + blobs.blobTab[i].grayDis >= m_pFuntion->function.f_LDConfig.fLD_HJ && + blobs.blobTab[i].energy >= m_pFuntion->function.f_LDConfig.fLD_En && + blobs.blobTab[i].len >= m_pFuntion->function.f_LDConfig.fLD_Len) + { + dbresult = 1; + bLD_Standard = true; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", "Area %0.2f > %0.2f , hj %0.2f > %0.2f , Energy %0.2f > %0.2f , len %0.2f > %0.2f", + blobs.blobTab[i].JudgArea, m_pFuntion->function.f_LDConfig.fLD_Area, blobs.blobTab[i].grayDis, m_pFuntion->function.f_LDConfig.fLD_HJ, blobs.blobTab[i].energy, m_pFuntion->function.f_LDConfig.fLD_En, blobs.blobTab[i].len, m_pFuntion->function.f_LDConfig.fLD_Len); + } + if(dbresult != 1) + { + dbresult = LDJudge(config_qx_type, roi, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis); + } + // int detre = 1; + // 表示L0 和 DP 都有的 亮的 + if (dbresult == 1) + { + config_qx_type = CONFIG_QX_NAME_LD; + nerrortype = 1; + } + qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "3、LD", "%s qx %s ", Re_TO_STR_False(dbresult), qx_name.c_str()); + } + + // 如果是chess 画面,缺陷类型直接是chess异常。 + if (m_pFuntion->function.f_AIQX.bAllToChess) + { + config_qx_type = CONFIG_QX_NAME_Chess; + qx_name123 = CONFIG_QX_NAME_Names[config_qx_type]; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "4、AI_Classify", "change Chess, qx %d = %s ", config_qx_type, qx_name123.c_str()); + } + + if (m_pFuntion->function.f_AIQX.bPOLToWhitePOL && config_qx_type == CONFIG_QX_NAME_POL_Cell) + { + bool bchange = true; + if (m_pFuntion->function.f_AIQX.b127WhitePOl_UseDP) + { + cv::Mat DPMaskImg = ImageDet_shareP->DPMaskImg; + if (!DPMaskImg.empty()) + { + float fiou = CalImgScorl_t(m_TemCheck.temImgList[TEM_IMG_IDX_AImask](roi).clone(), DPMaskImg(roi).clone()); + // IOU + if (fiou > m_pFuntion->function.f_AIQX.f127WhitePOl_DP_IOU) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "pol change 127Cell", " fiou %f > %f ", fiou, m_pFuntion->function.f_AIQX.f127WhitePOl_DP_IOU); + bchange = false; + // break; + } + else + { + bchange = true; + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "pol change 127Cell", " fiou %f <= %f ", fiou, m_pFuntion->function.f_AIQX.f127WhitePOl_DP_IOU); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "pol change 127Cell", " DPMaskImg is empty() "); + } + + // m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "UseDPMask", " fiou %f < 0.1 ", fiou); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "pol change 127Cell", " NO Use DP "); + } + + if (bchange) + { + config_qx_type = CONFIG_QX_NAME_127Cell; + qx_name123 = CONFIG_QX_NAME_Names[config_qx_type]; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "4、AI_Classify", "pol change 127Cell Suc, qx %d = %s ", config_qx_type, qx_name123.c_str()); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "4、AI_Classify", "pol change 127Cell Fail"); + } + + + // m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "DET", " 127 CONFIG_QX_NAME_POL_Cell change CONFIG_QX_NAME_127Cell "); + + + } + + blobs.blobTab[i].AIclasstype = config_qx_type; + + blobs.blobTab[i].UserErrorType = config_qx_type; + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + + float fupS = UseUpMaskAnalysis(roi, m_TemCheck.temImgList[TEM_IMG_IDX_AImask]); + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "5、Up Mask judge", " IOU = %f ", fupS); + // m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, + // "6、QX info", "roi[%d %d %d %d] qx %d %s area %d JudgArea %f hj %f len %f energy %d density %f,", + // roi.x, roi.y, roi.width, roi.height, config_qx_type, qx_name.c_str(), blobs.blobTab[i].area, + // JudgArea, blobs.blobTab[i].grayDis, flen, blobs.blobTab[i].energy, blobs.blobTab[i].density); + + if (true) + { + QX_ERROR_INFO_ temerror; + temerror.roi = roi; + temerror.Idx = i; + temerror.area = blobs.blobTab[i].area; + temerror.JudgArea = JudgArea; + temerror.JudgArea_second = fsecondArea; + temerror.energy = blobs.blobTab[i].energy; + temerror.flen = flen; + temerror.nconfig_qx_type = config_qx_type; + temerror.qx_name = qx_name; + temerror.maxValue = blobs.blobTab[i].maxValue; + temerror.grayDis = blobs.blobTab[i].grayDis; + temerror.density = blobs.blobTab[i].density; + temerror.fUpIou = fupS; + temerror.bIsStandardLD = bLD_Standard; + temerror.detLogList.insert(temerror.detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->push_back(temerror); + + // printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen); + } + } + m_TemCheck.bInTemList = false; + return 0; +} + +int ImgCheckAnalysisy::AnalysisResult_Param_Judge() +{ + std::string strBaseLog = "Param_Judge"; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Param_Judge", " Start"); + + m_TemCheck.bInTemList = true; + m_TemCheck.temLogListInit(); + + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + + float fs_resize_x = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fs_resize_y = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "info", "fscale_x %f fscale_y %f", fs_x, fs_y); + int nSumBLobNUm = 0; + float fSunBLobArea = 0; + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + m_TemCheck.temLogListInit(); + if (m_bstatus_ReJson) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Blob", "%d/%d start", i, m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size()); + } + // m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "qx", "%d/%d start", i, m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size()); + + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + cv::Rect roi = QX_info->roi; + float JudgArea = QX_info->JudgArea; + float JudgArea_second = QX_info->JudgArea_second; + float flen = QX_info->flen; + float grayDis = QX_info->grayDis; + int energy = QX_info->energy; + float fupS = QX_info->fUpIou; + int maxValue = QX_info->maxValue; + float density = QX_info->density; + + int config_qx_type = QX_info->nconfig_qx_type; + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, + "6、QX info", "roi[%d %d %d %d] qx %d %s JudgArea %f second %f hj %f len %f energy %d density %f,", + roi.x, roi.y, roi.width, roi.height, config_qx_type, qx_name.c_str(), + JudgArea, JudgArea_second, grayDis, flen, energy, density); + + bool ban = JudgeQXAnalysis(config_qx_type); + if (!ban) + { + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "7、QX function", "qx close, config_qx_type %s Not Det", + qx_name.c_str()); + + addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + continue; + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, + "7、QX function", "qx %s Open", qx_name.c_str()); + bool isMarksheildQX = false; + isMarksheildQX = Judge_MarkLine_QX(config_qx_type, roi); + if (isMarksheildQX) + { + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "7、QX function", "MarkLine_QX close, config_qx_type %s Not Det", + qx_name.c_str()); + + addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + continue; + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, + "7、QX function", "MarkLine_QX qx %s Open", qx_name.c_str()); + + int center_x = roi.x + roi.width * 0.5; + int center_y = roi.y + roi.height * 0.5; + + int regionidx = GetRegionIdx(center_x, center_y); + // 已经有blob 的缺陷,但是regionidx < 0 是有可能的。需要避免这样的情况出现。 + if (regionidx < 0) + { + regionidx = 0; + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, + "8、QX region ", "qx regionidx = %d ", regionidx); + + QXImageResult tem; + tem.idx = i; + cv::Rect CutRoi = GetCutRoi(roi, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + // CheckUtil::printROI(CutRoi, "CutRoi"); + tem.srcImg = m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc](CutRoi).clone(); + cv::Size sz = cv::Size(QX_SAMLLIMG_WIDTH, QX_SAMLLIMG_HEIGHT); + cv::resize(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](CutRoi).clone(), tem.resizeImg, sz); + // printf("strChannel %s \n", m_CheckResult_shareP->in_shareImage->strChannel.c_str()); + // m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "info ", "regionidx %d", regionidx); + bool bpreSucc = true; + // 弱化框处理 + int pre_re = AnalysisResult_Pre(QX_info, m_CheckResult_shareP->in_shareImage->strChannel); + // 没有通过弱化区验证 + if (pre_re != 0) + { + bpreSucc = false; + + // addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + // QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + // continue; + } + else + { + nSumBLobNUm++; + fSunBLobArea += JudgArea; + } + + int nerrortype = 0; + int checkFlage = 0; + // 基础分析 + if (config_qx_type >= 0 && config_qx_type != CONFIG_QX_NAME_LD) + { + int regionIdx = 0; + int def_type = config_qx_type; + if (regionIdx >= m_pCommonAnalysisyConfig->regionConfigArr.size()) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Blob", "Error regionIdx %d param size %d ", + regionIdx, m_pCommonAnalysisyConfig->regionConfigArr.size()); + addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + continue; + } + if (def_type >= CONFIG_QX_NAME_count) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Blob", "Error def_type %d size %d ", + def_type, CONFIG_QX_NAME_count); + addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + continue; + } + int paramIdx = m_QxInParamListIdx[config_qx_type]; + if (paramIdx < 0) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "qx error", " paramIdx < 0 "); + addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + continue; + } + + for (int ict = 0; ict < ANALYSIS_TYPE_COUNT; ict++) + { + // 没有通过弱化区验证 + if (!bpreSucc) + { + // 只对疑是检测 + if (ict == ANALYSIS_TYPE_TF) + { + continue; + } + } + + std::string str_checkflag = "QX-check"; + checkFlage = ict; + if (ict == ANALYSIS_TYPE_YS) + { + str_checkflag = "YS-check"; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "info", " %s start", str_checkflag.c_str()); + + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ict].checkConfig_Regions_Param.at(paramIdx); + + bool bUse = false; + + for (int j = 0; j < pParam->useNum; j++) + { + if (config_qx_type == CONFIG_QX_NAME_Scratch_L1 || + config_qx_type == CONFIG_QX_NAME_Scratch_L2 || + config_qx_type == CONFIG_QX_NAME_X_line || + config_qx_type == CONFIG_QX_NAME_Y_line) + { + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "error ", "IS Scratch and Line"); + continue; + } + + bool result = true; + if (!pParam->paramArr[j].bEnable) + { + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "error ", "param is CLosed"); + continue; + } + if (pParam->paramArr[j].num > 0 || pParam->paramArr[j].dis > 0) + { + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "param---", "num %d >0 or dis %f > 0 QX_ALL Analysisy", pParam->paramArr[j].num, pParam->paramArr[j].dis); + continue; + } + + bUse = true; + float At = pParam->paramArr[j].area; + float Et = pParam->paramArr[j].energy; + float hj = pParam->paramArr[j].hj; + float Len = pParam->paramArr[j].length; + float md = pParam->paramArr[j].density; + + float detArea = JudgArea; + if (config_qx_type == CONFIG_QX_NAME_POL_Cell && JudgArea_second > 0) + { + detArea = JudgArea_second; + } + + if (energy >= Et && + detArea >= At && + grayDis >= hj && + flen >= Len && + density >= md) + { + nerrortype = 1; + result = false; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "result", "%s param idx %d / %d", BOOL_TO_STROK(result), j + 1, pParam->useNum); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(detArea >= At), detArea, BOOL_TO_ThanLess(detArea >= At), At); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Energy", "%s -> %d %s %f ", + BOOL_TO_STR(energy >= Et), energy, BOOL_TO_ThanLess(energy >= Et), Et); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "HJ", "%s -> %f %s %f ", + BOOL_TO_STR(grayDis > hj), grayDis, BOOL_TO_ThanLess(grayDis > hj), hj); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(flen > Len), flen, BOOL_TO_ThanLess(flen > Len), Len); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "md", "%s -> %f %s %f ", + BOOL_TO_STR(density >= md), density, BOOL_TO_ThanLess(density >= md), md); + + if (!result) + { + break; + } + } + if (!bUse) + { + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "info", "Not Use Param Judge"); + } + + if (nerrortype != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "info", " %s end result: erorr type %s", str_checkflag.c_str(), qx_name.c_str()); + break; + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "info", " %s end result: OK ", str_checkflag.c_str()); + } + } + } + else + { + // 亮点 + if (config_qx_type == CONFIG_QX_NAME_LD) + { + checkFlage = ANALYSIS_TYPE_TF; + nerrortype = 1; + } + } + // 暗点 3S 分析 + if ((nerrortype == 0 || checkFlage != ANALYSIS_TYPE_TF) && + config_qx_type == CONFIG_QX_NAME_AD && + m_pFuntion->function.f_AD_Check.bOpen && + m_pFuntion->function.f_AD_Check.analysis_s.bOpen && + m_pFuntion->function.f_AD_Check.analysis_s.NG_3s) + { + int det_s_Vale = 0; + if (JudgArea >= m_pFuntion->function.f_AD_Check.S_standard_3s.area && + flen >= m_pFuntion->function.f_AD_Check.S_standard_3s.len) + { + nerrortype = 1; + checkFlage = ANALYSIS_TYPE_TF; + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "info", " AD 3S result NG, det area %f len %f >=3s param area %f len %f ", + JudgArea, flen, m_pFuntion->function.f_AD_Check.S_standard_3s.area, m_pFuntion->function.f_AD_Check.S_standard_3s.len); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "info", " AD 3S result OK, det area %f len %f < 3s param area %f len %f ", + JudgArea, flen, m_pFuntion->function.f_AD_Check.S_standard_3s.area, m_pFuntion->function.f_AD_Check.S_standard_3s.len); + } + } + + std::string resultType = "OK"; + if (nerrortype == 1) + { + if (checkFlage == ANALYSIS_TYPE_TF) + { + resultType = "NG"; + QX_info->result = QX_RESULT_TYPE_NG; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG]; + } + else + { + resultType = "YS"; + QX_info->result = QX_RESULT_TYPE_YS; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_YS]; + } + } + qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "10、Param Judge", "qx %s ,result = %s", qx_name.c_str(), resultType.c_str()); + + // //预处理没有过。 + // if (!bpreSucc) + // { + + // addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + // QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + // continue; + // } + + bool bUP = false; + if (fupS > m_pFuntion->function.f_UseUpQX.fIOU && m_pFuntion->function.f_UseUpQX.bOpen && !QX_info->bIsStandardLD) + { + checkFlage = ANALYSIS_TYPE_YS; + bUP = true; + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "delete blob IOU %f > param %f ", fupS, m_pBasicConfig->fUP_IOU); + } + else + { + if (m_pFuntion->function.f_UseUpQX.bOpen) + { + if (QX_info->bIsStandardLD) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "skip, LD from standard check "); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "IOU %f < param %f ", fupS, m_pFuntion->function.f_UseUpQX.fIOU); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "function close "); + } + } + if (bUP) + { + resultType = "OK"; + if (nerrortype == 1) + { + if (checkFlage == ANALYSIS_TYPE_TF) + { + resultType = "NG"; + QX_info->result = QX_RESULT_TYPE_NG; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG]; + } + else + { + resultType = "YS"; + QX_info->result = QX_RESULT_TYPE_YS; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_YS]; + } + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "11、Up Mask Judge", "qx %s ,result = %s", qx_name.c_str(), resultType.c_str()); + } + + // 大缺陷判断---如果和UP没关系 + if (!bUP && bpreSucc) + { + // 目前为止判断是好品 + if ((nerrortype == 0 || checkFlage != ANALYSIS_TYPE_TF) && m_pFuntion->function.f_Big_QX.bOpen) + { + bool berror = false; + // 满足大缺陷的判断要求,则 NG + if (JudgArea >= m_pFuntion->function.f_Big_QX.Single_Area && + grayDis >= m_pFuntion->function.f_Big_QX.Single_HJ && + flen >= m_pFuntion->function.f_Big_QX.Single_Len) + { + berror = true; + nerrortype = 1; + checkFlage = ANALYSIS_TYPE_TF; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Big QX single result ", "%s ", BOOL_TO_STROK(!berror)); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(JudgArea >= m_pFuntion->function.f_Big_QX.Single_Area), JudgArea, BOOL_TO_ThanLess(JudgArea >= m_pFuntion->function.f_Big_QX.Single_Area), m_pFuntion->function.f_Big_QX.Single_Area); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "HJ", "%s -> %f %s %d", + BOOL_TO_STR(grayDis >= m_pFuntion->function.f_Big_QX.Single_HJ), grayDis, BOOL_TO_ThanLess(grayDis >= m_pFuntion->function.f_Big_QX.Single_HJ), m_pFuntion->function.f_Big_QX.Single_HJ); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(flen >= m_pFuntion->function.f_Big_QX.Single_Len), flen, BOOL_TO_ThanLess(flen >= m_pFuntion->function.f_Big_QX.Single_Len), m_pFuntion->function.f_Big_QX.Single_Len); + } + + // 总面积判断 + if ((nerrortype == 0 || checkFlage != ANALYSIS_TYPE_TF) && m_pFuntion->function.f_Big_QX.bOpen) + { + if (nSumBLobNUm <= m_pFuntion->function.f_Big_QX.Sum_blob_Num) + { + bool berror = false; + if (nSumBLobNUm <= m_pFuntion->function.f_Big_QX.Sum_blob_Num && + fSunBLobArea >= m_pFuntion->function.f_Big_QX.Sum_Area) + { + berror = true; + nerrortype = 1; + checkFlage = ANALYSIS_TYPE_TF; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Big QX sum result", "%s ", BOOL_TO_STROK(!berror)); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(fSunBLobArea >= m_pFuntion->function.f_Big_QX.Sum_Area), fSunBLobArea, BOOL_TO_ThanLess(fSunBLobArea >= m_pFuntion->function.f_Big_QX.Sum_Area), m_pFuntion->function.f_Big_QX.Sum_Area); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "nSumBLobNUm", "cur Num %d <= %d ", + nSumBLobNUm, m_pFuntion->function.f_Big_QX.Sum_blob_Num); + } + } + resultType = "OK"; + if (nerrortype == 1) + { + if (checkFlage == ANALYSIS_TYPE_TF) + { + resultType = "NG"; + QX_info->result = QX_RESULT_TYPE_NG; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG]; + } + else + { + resultType = "YS"; + QX_info->result = QX_RESULT_TYPE_YS; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_YS]; + } + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "12、big qx or Sum qx", "qx %s ,result = %s", qx_name.c_str(), resultType.c_str()); + } + + // 生成缺陷小图 + if (nerrortype != 0) + { + + int nqx_type = ConfigTypeToResultType(config_qx_type); + tem.type = nqx_type; + tem.area = JudgArea; + tem.energy = energy; + tem.hj = grayDis; + tem.max_v = maxValue; + tem.strTypeName = QX_Result_Names[nqx_type]; + tem.qx_Code = QX_Result_Code[nqx_type]; + tem.srcImgroi = roi; + tem.len = flen; + tem.qx_type = QX_ERROR_TYPE_AREA; + tem.fScore = fupS; + tem.density = density; + + tem.resizeImgroi.x = roi.x * fs_resize_x; + tem.resizeImgroi.width = roi.width * fs_resize_x; + tem.resizeImgroi.y = roi.y * fs_resize_y; + tem.resizeImgroi.height = roi.height * fs_resize_y; + + tem.x_pixel = roi.x + roi.width * 0.5; + tem.y_pixel = roi.y + roi.height * 0.5; + + tem.x_mm = tem.x_pixel * fs_x; + tem.y_mm = tem.y_pixel * fs_y; + + tem.CutImgroi = roi; + tem.CutImgroi.x -= CutRoi.x; + tem.CutImgroi.y -= CutRoi.y; + + if (checkFlage == ANALYSIS_TYPE_TF) + { + + m_CheckResult_shareP->defectResultList[nqx_type].nresult = 1; + m_CheckResult_shareP->defectResultList[nqx_type].keyName = QX_Result_Names[nqx_type]; + m_CheckResult_shareP->defectResultList[nqx_type].keyCode = QX_Result_Code[nqx_type]; + m_CheckResult_shareP->defectResultList[nqx_type].num++; + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).result = 1; + if (m_CheckResult_shareP->nresult <= ERROR_TYPE_OK) + { + m_CheckResult_shareP->nresult = nqx_type; + } + GetAIDetImg(tem.srcImgroi, tem.AI_in_Img, tem.AI_out_img); + m_CheckResult_shareP->qxImageResult.push_back(tem); + } + else + { + + if (m_CheckResult_shareP->nYS_result <= ERROR_TYPE_OK) + { + m_CheckResult_shareP->nYS_result = nqx_type; + } + + GetAIDetImg(tem.srcImgroi, tem.AI_in_Img, tem.AI_out_img); + m_CheckResult_shareP->YS_ImageResult.push_back(tem); + } + } + else + { + addInDrawBlob_New(config_qx_type, i, QX_info, fs_resize_x, fs_resize_y); + } + + // 对于大面积 的zara和 异显NG ,可以不接着分析后续的数据了。应为后续估计有很多错误类别。 + if (nerrortype != 0 && checkFlage == ANALYSIS_TYPE_TF && JudgArea > 500) + { + + if (config_qx_type == CONFIG_QX_NAME_AD_YX || config_qx_type == CONFIG_QX_NAME_zara) + { + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "13、stop Judge ", "stop : JudgArea > 500 onfig_qx_type == CONFIG_QX_NAME_AD_YX || config_qx_type == CONFIG_QX_NAME_zara"); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + break; + } + } + + // 加入到 缺陷 分析类中 + if (!bUP && bpreSucc) + { + { + + int qxidx = ConfigTypeToQXAnalysis(config_qx_type); + if (qxidx >= 0) + { + + QX_Info temqx; + temqx.result = 0; + if (checkFlage == ANALYSIS_TYPE_TF && nerrortype != 0) + { + temqx.result = 1; + } + + temqx.area = JudgArea; + temqx.blobIdx = i; + temqx.energy = energy; + temqx.hj = grayDis; + temqx.length = flen; + temqx.density = density; + + temqx.plocatin_pixel.x = roi.x + roi.width * 0.5; + temqx.plocatin_pixel.y = roi.y + roi.height * 0.5; + + temqx.plocatin_mm.x = temqx.plocatin_pixel.x * fs_x; + temqx.plocatin_mm.y = temqx.plocatin_pixel.y * fs_y; + bool bad = m_qx_Analysis.AddQxInfo(qxidx, temqx); + + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "14、Use Num And Dis Judge ", "qx %s ,Add %s ", qx_name.c_str(), BOOL_TO_STR_Error(bad)); + } + } + } + + std::string strresult = "OK"; + if (nerrortype != 0) + { + if (checkFlage == ANALYSIS_TYPE_TF) + { + strresult = "NG"; + QX_info->result = QX_RESULT_TYPE_NG; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG]; + } + else + { + strresult = "YS"; + QX_info->result = QX_RESULT_TYPE_YS; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_YS]; + } + } + + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "15、 Cur Result ", "qx %s ,result = %s", qx_name.c_str(), strresult.c_str()); + // temerror.detLogList.assign(m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + } + + { + m_TemCheck.bInTemList = false; + m_TemCheck.temLogListInit(); + QX_Analysis_Result_List *ptemre; + m_qx_Analysis.GetReusult(ptemre); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "4、qx AnalysisResult", "-------------------------2、Num And Dis Judge---------------\n"); + m_TemCheck.bInTemList = true; + for (int iqx = 0; iqx < (int)ptemre->resultList.size(); iqx++) + { + // 遍历每个检测blob + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + m_TemCheck.temLogListInit(); + + if (i != ptemre->resultList.at(iqx).blobIdx) + { + continue; + } + + // m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "qx", " Add QX %d / %d", iqx, (int)ptemre->resultList.size()); + + QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + cv::Rect roi = QX_info->roi; + float JudgArea = QX_info->JudgArea; + float flen = QX_info->flen; + float grayDis = QX_info->grayDis; + int energy = QX_info->energy; + float fupS = QX_info->fUpIou; + int maxValue = QX_info->maxValue; + float density = QX_info->density; + + int config_qx_type = QX_info->nconfig_qx_type; + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + + // 确认错误类别 + QXImageResult tem; + tem.idx = i; + cv::Rect CutRoi = GetCutRoi(roi, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + + tem.srcImg = m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc](CutRoi).clone(); + cv::Size sz = cv::Size(QX_SAMLLIMG_WIDTH, QX_SAMLLIMG_HEIGHT); + cv::resize(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](CutRoi).clone(), tem.resizeImg, sz); + + int nerrortype = 1; + int checkFlage = ANALYSIS_TYPE_TF; + + float fmaxScore = 0; + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, + "qx", "roi[%d %d %d %d] qx %d %s JudgArea %f hj %f len %f energy %d,", + roi.x, roi.y, roi.width, roi.height, config_qx_type, qx_name.c_str(), + JudgArea, grayDis, flen, energy); + // 生成缺陷小图 + if (nerrortype != 0) + { + + int nqx_type = ConfigTypeToResultType(config_qx_type); + tem.type = nqx_type; + tem.area = JudgArea; + tem.energy = energy; + tem.hj = grayDis; + tem.max_v = maxValue; + tem.density = density; + tem.strTypeName = QX_Result_Names[nqx_type]; + tem.qx_Code = QX_Result_Code[nqx_type]; + tem.srcImgroi = roi; + tem.len = flen; + tem.qx_type = ptemre->resultList.at(iqx).error_Type; + tem.minDis_mm = ptemre->resultList.at(iqx).mindis; + tem.qx_num = ptemre->resultList.at(iqx).qx_Num; + + tem.resizeImgroi.x = roi.x * fs_resize_x; + tem.resizeImgroi.width = roi.width * fs_resize_x; + tem.resizeImgroi.y = roi.y * fs_resize_y; + tem.resizeImgroi.height = roi.height * fs_resize_y; + + tem.x_pixel = roi.x + roi.width * 0.5; + tem.y_pixel = roi.y + roi.height * 0.5; + + tem.x_mm = tem.x_pixel * fs_x; + tem.y_mm = tem.y_pixel * fs_y; + + tem.CutImgroi = roi; + tem.CutImgroi.x -= CutRoi.x; + tem.CutImgroi.y -= CutRoi.y; + + if (checkFlage == ANALYSIS_TYPE_TF) + { + + m_CheckResult_shareP->defectResultList[nqx_type].nresult = 1; + m_CheckResult_shareP->defectResultList[nqx_type].keyName = QX_Result_Names[nqx_type]; + m_CheckResult_shareP->defectResultList[nqx_type].keyCode = QX_Result_Code[nqx_type]; + m_CheckResult_shareP->defectResultList[nqx_type].num++; + + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).result = 1; + + if (m_CheckResult_shareP->nresult <= ERROR_TYPE_OK) + { + m_CheckResult_shareP->nresult = nqx_type; + } + GetAIDetImg(tem.srcImgroi, tem.AI_in_Img, tem.AI_out_img); + m_CheckResult_shareP->qxImageResult.push_back(tem); + } + } + addInDrawBlob_New(-9, i, QX_info, fs_resize_x, fs_resize_y); + if (config_qx_type != CONFIG_QX_NAME_AD && config_qx_type != CONFIG_QX_NAME_POL_Cell) + { + for (auto it_ys = m_CheckResult_shareP->YS_ImageResult.begin(); it_ys != m_CheckResult_shareP->YS_ImageResult.end();) + { + if (it_ys->idx == i) + { + it_ys = m_CheckResult_shareP->YS_ImageResult.erase(it_ys); // 删除元素,并更新迭代器 + } + else + { + ++it_ys; // 继续检查下一个元素 + } + } + } + + std::string strresult = "OK"; + if (nerrortype != 0) + { + if (checkFlage == ANALYSIS_TYPE_TF) + { + strresult = "NG"; + QX_info->result = QX_RESULT_TYPE_NG; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG]; + } + else + { + strresult = "YS"; + QX_info->result = QX_RESULT_TYPE_YS; + QX_info->result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_YS]; + } + } + + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "16、 Add num or Dis reuslt ", "qx %s ,result = %s", qx_name.c_str(), strresult.c_str()); + + QX_info->detLogList.insert(QX_info->detLogList.end(), m_TemCheck.temlogList.begin(), m_TemCheck.temlogList.end()); + } + } + } + + m_TemCheck.bInTemList = false; + + bool error = true; + if (m_CheckResult_shareP->nresult > ERROR_TYPE_OK) + { + error = false; + } + bool YS_error = true; + if (m_CheckResult_shareP->nYS_result > ERROR_TYPE_OK) + { + YS_error = false; + } + std::string qx_name11 = QX_Result_Names[m_CheckResult_shareP->nresult]; + std::string qx_YS_name11 = QX_Result_Names[m_CheckResult_shareP->nYS_result]; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "result", " TF %s type %d %s ", BOOL_TO_STROK(error), m_CheckResult_shareP->nresult, qx_name11.c_str()); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "result", " YS %s type %d %s ", BOOL_TO_STROK(YS_error), m_CheckResult_shareP->nYS_result, qx_YS_name11.c_str()); + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Param_Judge", " End"); + return 0; +} + +int ImgCheckAnalysisy::AnalysisResult_Pre(QX_ERROR_INFO_ *pQX_info, std::string strChannel) +{ + cv::Rect roi = pQX_info->roi; + float JudgArea = pQX_info->JudgArea; + float flen = pQX_info->flen; + float grayDis = pQX_info->grayDis; + int energy = pQX_info->energy; + float fupS = pQX_info->fUpIou; + int maxValue = pQX_info->maxValue; + float density = pQX_info->density; + + cv::Point pCenter; + pCenter.x = roi.x + roi.width * 0.5; + pCenter.y = roi.y + roi.height * 0.5; + + int config_qx_type = pQX_info->nconfig_qx_type; + std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type]; + + int pre_re = 0; + // 参数的 索引 + int paramIdx_1 = m_QxInParamListIdx[config_qx_type]; + if (paramIdx_1 < 0) + { + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "9、pre Judge", " Not done, paramIdx %d < 0 ", paramIdx_1); + return pre_re; + } + // 如果 检测区域 只有1个,就是没有弱化区 + if (m_pCommonAnalysisyConfig->regionConfigArr.size() < 2) + { + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "9、pre Judge", " Not done, region num %d < 2 ", m_pCommonAnalysisyConfig->regionConfigArr.size()); + return pre_re; + } + + bool bpre_succ = true; // 预处理是否成功 + // 遍历所有的区域 + for (int iregion = 1; iregion < m_DetRoiList.roiList_Src.size(); iregion++) + { + const std::vector &polygon = m_DetRoiList.roiList_Src[iregion]; + double result = cv::pointPolygonTest(polygon, pCenter, false); + if (result < 0) + { + continue; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "pre Judge", "regionidx %d / %d start", iregion, m_DetRoiList.roiList_Src.size()); + bool bInChannel = false; + // 当前区域是否有包含的通道。 + if (m_pCommonAnalysisyConfig->regionConfigArr.at(iregion).basicInfo.ChannelArry.size() > 0) + { + std::string strchannelshow = ""; + for (const auto &chanel : m_pCommonAnalysisyConfig->regionConfigArr.at(iregion).basicInfo.ChannelArry) + { + strchannelshow += chanel; + strchannelshow += ";"; + if (CheckUtil::compareIgnoreCase(strChannel, chanel)) + { + bInChannel = true; + } + } + + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "pre Judge", "channel %s ,channellist %s", + BOOL_TO_STR(bInChannel), strchannelshow.c_str()); + } + // 通道要被处理 + if (bInChannel) + { + bool buse_region = false; + CheckConfig_Regions_Param *pParam = &m_pCommonAnalysisyConfig->regionConfigArr.at(iregion).checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx_1); + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + buse_region = true; + break; + } + } + if (!buse_region) + { + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "pre Judge", "error %s param is CLosed", qx_name.c_str()); + continue; // 下一个区域判断。 + } + // 参数判断 + for (int j = 0; j < pParam->useNum; j++) + { + if (!pParam->paramArr[j].bEnable) + { + continue; + } + + float At = pParam->paramArr[j].area; + float Et = pParam->paramArr[j].energy; + float hj = pParam->paramArr[j].hj; + float Len = pParam->paramArr[j].length; + float md = pParam->paramArr[j].density; + bool bjudge = false; + if (energy >= Et && + JudgArea >= At && + grayDis >= hj && + flen >= Len && + density >= md) + { + bjudge = true; + } + else + { + bpre_succ = false; // 没有通过预处理。 + } + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "result", "%s param idx %d / %d", BOOL_TO_STR(bjudge), j + 1, pParam->useNum); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(JudgArea >= At), JudgArea, BOOL_TO_ThanLess(JudgArea >= At), At); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Energy", "%s -> %d %s %f ", + BOOL_TO_STR(energy >= Et), energy, BOOL_TO_ThanLess(energy >= Et), Et); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "HJ", "%s -> %f %s %f ", + BOOL_TO_STR(grayDis > hj), grayDis, BOOL_TO_ThanLess(grayDis > hj), hj); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(flen > Len), flen, BOOL_TO_ThanLess(flen > Len), Len); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "md", "%s -> %f %s %f ", + BOOL_TO_STR(density >= md), density, BOOL_TO_ThanLess(density >= md), md); + // 没有通过预处理。退出下次参数判断 + if (!bpre_succ) + { + break; + } + } + // 没有通过弱化区验证 + if (!bpre_succ) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "pre Judge", "check fail ,break "); + break; // 没有通过预处理。退出下个 区域判断 + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "pre Judge", "channel list is Error or NULL"); + } + } + if (!bpre_succ) + { + // 没有通过预处理。 + pre_re = 1; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "9、pre Judge", "check fail ,Stop Judge"); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "9、pre Judge", "check Succ ,Continue Judge"); + } + return pre_re; +} + +int ImgCheckAnalysisy::AI_Det(cv::Mat inImg, cv::Mat &outimg) +{ + // 检测未开启 + if (!m_pFuntion->function.f_BaseDet.bOpen) + { + outimg = cv::Mat(inImg.rows, inImg.cols, CV_8UC1, cv::Scalar(0)); + return 0; + } + + if (m_pFuntion && m_pFuntion->function.f_BaseDet.strAIMode == "UP") + { + m_AIDeal.AICheck_BOE_UP(inImg, outimg); + } + else + { + if (m_pFuntion && m_pFuntion->function.f_BaseDet.strAIMode == "WandB") + { + m_AIDeal.AICheck_BOE_Type2(inImg, outimg); + // printf("------------------------------------\n"); + } + else if (m_pFuntion && m_pFuntion->function.f_BaseDet.strAIMode == "Chess") + { + m_AIDeal.AICheck_BOE_Chess(inImg, outimg); + } + else + { + m_AIDeal.AICheck_BOE(inImg, outimg); + } + } + + return 0; +} + +float ImgCheckAnalysisy::UseUpMaskAnalysis(cv::Rect teroi, cv::Mat AIMaskImg) +{ + float fs = 0; + if (!m_pFuntion->function.f_UseUpQX.bOpen) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "bUseUpImg close "); + // printf(">>>>>>>>>>>>>bUseUpImg close \n"); + return fs; + } + if (AIMaskImg.empty()) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "AIMaskImg.empty() "); + return fs; + } + cv::Mat upMaskImg = ImageDet_shareP->UpMaskImg; + if (upMaskImg.empty()) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "upMaskImg.empty() "); + return fs; + } + if (teroi.width > 500 || teroi.height > 500) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "teroi.width > 500 || teroi.height > 500"); + return fs; + } + CheckUtil::SizeRect(teroi, AIMaskImg.cols, AIMaskImg.rows, 20, 20); + + fs = CalImgScorl(AIMaskImg(teroi).clone(), upMaskImg(teroi).clone()); + // m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "x w h d %d %d %d %d fs = %f", teroi.x, teroi.y, teroi.width, teroi.height, fs); + // getchar(); + + return fs; +} + +float ImgCheckAnalysisy::CalImgScorl(cv::Mat det_img, cv::Mat up_img) +{ + + float fs = 0; + + unsigned char *det_img_data = (unsigned char *)det_img.data; + unsigned char *up_img_data = (unsigned char *)up_img.data; + int w = det_img.cols; + int h = det_img.rows; + int pitch = w; + int offset = 0; + int sum_jc = 0; // 交集 都有的 + int sum_bj = 0; // 并集 有一个有的 + int sum_up = 0; + int sum_det = 0; + for (int y = 0; y < h; y++) + { + offset = y * pitch; + int kh = 0; + for (int x = 0; x < w; x++) + { + + if (det_img_data[offset] != 0 && up_img_data[offset] != 0) + { + sum_jc++; + sum_bj++; + sum_up++; + sum_det++; + } + else if (det_img_data[offset] != 0 || up_img_data[offset] != 0) + { + sum_bj++; + if (det_img_data[offset] != 0) + { + sum_det++; + } + if (up_img_data[offset] != 0) + { + sum_up++; + } + } + offset++; + } + } + if (sum_bj != 0) + { + fs = sum_jc * 1.0f / sum_bj; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Up Mask ", "sum_bj %d sum_jc %d sum_up %d sum_det %d", sum_bj, sum_jc, sum_up, sum_det); + if (sum_up > sum_det * 2) + { + // fs = 0; + } + + return fs; +} + +float ImgCheckAnalysisy::CalImgScorl_t(cv::Mat det_img, cv::Mat up_img) +{ + + float fs = 0; + + unsigned char *det_img_data = (unsigned char *)det_img.data; + unsigned char *up_img_data = (unsigned char *)up_img.data; + int w = det_img.cols; + int h = det_img.rows; + int pitch = w; + int offset = 0; + int sum_jc = 0; // 交集 都有的 + int sum_bj = 0; // 并集 有一个有的 + int sum_up = 0; + int sum_det = 0; + for (int y = 0; y < h; y++) + { + offset = y * pitch; + int kh = 0; + for (int x = 0; x < w; x++) + { + + if (det_img_data[offset] != 0 && up_img_data[offset] != 0) + { + sum_jc++; + sum_bj++; + sum_up++; + sum_det++; + } + else if (det_img_data[offset] != 0 || up_img_data[offset] != 0) + { + sum_bj++; + if (det_img_data[offset] != 0) + { + sum_det++; + } + if (up_img_data[offset] != 0) + { + sum_up++; + } + } + offset++; + } + } + if (sum_bj != 0) + { + fs = sum_jc * 1.0f / sum_bj; + } + + return fs; +} + +int ImgCheckAnalysisy::AI_Classify(cv::Mat img, cv::Rect qx_roi, float fjustarea, float *fmaxScore) +{ + // + + // 太小的 直接认定成 CONFIG_QX_NAME_POL_Cell; + // if (fjustarea < 0.09) + // { + // int max = qx_roi.width; + // int min = qx_roi.height; + // if (qx_roi.height > qx_roi.width) + // { + // max = qx_roi.height; + // min = qx_roi.width; + // } + // float f = max * 1.0 / min; + // if (f < 2) + // { + // return CONFIG_QX_NAME_POL_Cell; + // } + // } + // printf("AI classify %f %d %d \n", fjustarea, qx_roi.width, qx_roi.height); + // img = cv::imread("c.png", 0); + + cv::Mat detimg; + if (1 == img.channels()) + { + cv::cvtColor(img, detimg, cv::COLOR_GRAY2BGR); + } + else + { + detimg = img; + } + int type = 0; + // 启用黑白分类 + if (USE_WHITEBACK_CLASS) + { + type = 1; + } + // cv::imwrite("test_class222.png",detimg); + int cls_num = m_AIDeal.AICheck_Cls(detimg, type, fmaxScore); + + std::string strclassName = ""; + // 启用黑白分类 + if (USE_WHITEBACK_CLASS) + { + // AI_CLass_QX_NAME_ok_yisi, // 疑似 + // AI_CLass_QX_NAME_yixian, // 异显 + // AI_CLass_QX_NAME_POL_CEL, // 亮点 异物 + // AI_CLass_QX_NAME_zara, // ZARA + // AI_CLass_QX_NAME_ps, // PS + // AI_CLass_QX_NAME_line, // 线 + // AI_CLass_QX_NAME_fangge_line, // 方格线 + // AI_CLass_QX_NAME_qipao, // 气泡 + // AI_CLass_QX_NAME_qing_huashang, // 轻划伤 + // AI_CLass_QX_NAME_mtx, // MTX + // AI_CLass_QX_NAME_yisi_qianzangwu, // 疑似浅层脏污 + // AI_CLass_QX_NAME_qing_zangwu, // 轻脏污 + // AI_CLass_QX_NAME_zhong_zangwu, // 严重脏污 + // AI_CLass_QX_NAME_andian, // 暗点 + // AI_CLass_QX_NAME_huashang, // 划伤 + // AI_CLass_QX_NAME_zf, // zf + + int temClass = cls_num; + + { + switch (temClass) + { + case 0: + cls_num = AI_CLass_QX_NAME_ok_yisi; + strclassName = "ok_ys"; + break; + case 1: + cls_num = AI_CLass_QX_NAME_POL_CEL; + strclassName = "POL_CEL"; + break; + case 2: + cls_num = AI_CLass_QX_NAME_zara; + strclassName = "zara"; + break; + case 3: + cls_num = AI_CLass_QX_NAME_andian; + strclassName = "andian"; + break; + case 4: + cls_num = AI_CLass_QX_NAME_yisi_qianzangwu; + strclassName = "yisi_qianzangwu"; + break; + case 5: + cls_num = AI_CLass_QX_NAME_huashang; + strclassName = "huashang"; + break; + case 6: + cls_num = AI_CLass_QX_NAME_line; + strclassName = "line"; + break; + case 7: + cls_num = AI_CLass_QX_NAME_ps; + strclassName = "ps"; + break; + case 8: + cls_num = AI_CLass_QX_NAME_mtx; + strclassName = "mtx"; + break; + case 9: + cls_num = AI_CLass_QX_NAME_yixian; + strclassName = "yixian"; + break; + case 10: + cls_num = AI_CLass_QX_NAME_zhong_zangwu; + strclassName = "zhong_zangwu"; + break; + case 11: + cls_num = AI_CLass_QX_NAME_qipao; + strclassName = "qipao"; + break; + case 12: + cls_num = AI_CLass_QX_NAME_qing_zangwu; + strclassName = "qing_zangwu"; + break; + case 13: + cls_num = AI_CLass_QX_NAME_other; + strclassName = "other"; + break; + default: + break; + } + } + } + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Classify", "AI Class num %d = %s %f", cls_num, strclassName.c_str(), *fmaxScore); + // 已经分成 线的 进行二次判断 + if (AI_CLass_QX_NAME_line == cls_num) + { + /* + // 长宽比 + float flenr = 1; + int len = 0; + int widt = 0; + if (qx_roi.width > qx_roi.height) + { + flenr = qx_roi.width * 1.0 / qx_roi.height; + len = qx_roi.width; + widt = qx_roi.height; + } + else + { + flenr = qx_roi.height * 1.0 / qx_roi.width; + widt = qx_roi.width; + len = qx_roi.height; + } + if (flenr > 18 && + len > 500 && + widt < 220 && + fjustarea < 850) + { + } + else + { + cls_num = AI_CLass_QX_NAME_yisi_qianzangwu; + } + */ + cls_num = AI_CLass_QX_NAME_line; + // printf("\n\n\n\n\n\n\n\n\n--------- flenr %f len %d,widt %d,fjustarea %f\n", flenr, len, widt, fjustarea); + } + else + { + // 对不是线的 进行也进行二次判断 + // 线的补充分类 + if (true) + { + // 长宽比 + float flenr = 1; + int len = 0; + int widt = 0; + if (qx_roi.width > qx_roi.height) + { + flenr = qx_roi.width * 1.0 / qx_roi.height; + len = qx_roi.width; + widt = qx_roi.height; + } + else + { + flenr = qx_roi.height * 1.0 / qx_roi.width; + widt = qx_roi.width; + len = qx_roi.height; + } + + // 长宽比过大,判断成 + if (flenr > 18 && + len > 500 && + widt < 220 && + fjustarea < 850) + { + // printf("\n\n\n\n\n\n\n\n\n--------- flenr %f len %d,widt %d,fjustarea %f\n", flenr,len,widt,fjustarea); + // getchar(); + cls_num = AI_CLass_QX_NAME_line; + strclassName = "line"; + } + } + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Classify", "Det Class num %d = %s %f", cls_num, strclassName.c_str(), *fmaxScore); + // printf("--------- 0 cls_num %d \n", cls_num); + return AIClassTypeToConfigType(cls_num, qx_roi); +} + +int ImgCheckAnalysisy::AI_Classify_New(const cv::Mat &src_Img, cv::Rect qx_roi, float fjustarea, float *fmaxScore) +{ + int re_ConfigType = CONFIG_QX_NAME_ok_yisi; + std::vector SmallRoiList; + int re = m_AIClassify.GetDetRoiList(src_Img, qx_roi, SmallRoiList); + int blobNum = SmallRoiList.size(); + if (re != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Classify", "SmallRoiList Error"); + return re_ConfigType; + } + if (blobNum <= 0) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Classify", "SmallRoiList is empyt"); + return re_ConfigType; + } + + cv::Size sz = cv::Size(QX_SAMLLIMG_WIDTH, QX_SAMLLIMG_HEIGHT); + + int maxcls = 20; + int ClsList[20] = {0}; + int AI_result = -1; + + int halfnum = std::ceil(blobNum * 1.0f / 2); + + AI_Classify_Info ClassifyList[20]; + for (int i = 0; i < maxcls; i++) + { + ClassifyList[i].Init(); + } + + // 开始 对每个区域进行分类推理 + for (int i = 0; i < blobNum; i++) + { + cv::Rect roi = SmallRoiList.at(i); + if (!CheckUtil::RoiInImg(roi, src_Img)) + { + continue; + } + cv::Mat AIDetImg; + if (roi.width == QX_SAMLLIMG_WIDTH && + roi.height == QX_SAMLLIMG_HEIGHT) + { + AIDetImg = src_Img(roi).clone(); + } + else + { + cv::resize(src_Img(roi), AIDetImg, sz); + } + + if (1 == AIDetImg.channels()) + { + cv::cvtColor(AIDetImg, AIDetImg, cv::COLOR_GRAY2BGR); + } + int type = 0; + // 启用黑白分类 + if (USE_WHITEBACK_CLASS) + { + type = 1; + } + int cls_num = m_AIDeal.AICheck_Cls(AIDetImg, type, fmaxScore); + if (cls_num >= 0 && cls_num < maxcls) + { + ClassifyList[cls_num].num++; + ClassifyList[cls_num].score += *fmaxScore; + ClassifyList[cls_num].avgScore = ClassifyList[cls_num].score / ClassifyList[cls_num].num; + } + int max_num = 0; + float max_avgScore = 0; + int tem_result = 0; + for (int idx = 0; idx < maxcls; idx++) + { + // 数量优先 + if (ClassifyList[idx].num > max_num) + { + max_num = ClassifyList[idx].num; + max_avgScore = ClassifyList[idx].avgScore; + tem_result = idx; + } + else if (ClassifyList[idx].num == max_num) + { + // 得分优先 + if (ClassifyList[idx].avgScore > max_avgScore) + { + max_num = ClassifyList[idx].num; + max_avgScore = ClassifyList[idx].avgScore; + tem_result = idx; + } + } + } + // printf("%d -> AI_result %d cls %d fmaxScore %f max_num %d halfnum %d\n", i, AI_result, cls_num, *fmaxScore, max_num, halfnum); + m_TemCheck.AddCheckstr(PrintLevel_4, DET_LOG_LEVEL_3, "AI_Classify", "%d -> Model Out %d cls %d fmaxScore %f max_num %d halfnum %d", i, tem_result, cls_num, *fmaxScore, max_num, halfnum); + if (max_num >= halfnum) + { + AI_result = tem_result; + break; + } + } + + int max_num = 0; + float max_avgScore = 0; + for (int idx = 0; idx < maxcls; idx++) + { + // ClassifyList[idx].print(std::to_string(idx)); + // 数量优先 + if (ClassifyList[idx].num > max_num) + { + max_num = ClassifyList[idx].num; + max_avgScore = ClassifyList[idx].avgScore; + AI_result = idx; + } + else if (ClassifyList[idx].num == max_num) + { + // 得分优先 + if (ClassifyList[idx].avgScore > max_avgScore) + { + max_num = ClassifyList[idx].num; + max_avgScore = ClassifyList[idx].avgScore; + AI_result = idx; + } + } + } + + // printf("*********** Model Out %d max_num %d halfnum %d\n", AI_result, max_num, halfnum); + int cls_num = AI_result; + *fmaxScore = max_avgScore; + std::string strclassName = ""; + // 启用黑白分类 + if (USE_WHITEBACK_CLASS) + { + // AI_CLass_QX_NAME_ok_yisi, // 疑似 + // AI_CLass_QX_NAME_yixian, // 异显 + // AI_CLass_QX_NAME_POL_CEL, // 亮点 异物 + // AI_CLass_QX_NAME_zara, // ZARA + // AI_CLass_QX_NAME_ps, // PS + // AI_CLass_QX_NAME_line, // 线 + // AI_CLass_QX_NAME_fangge_line, // 方格线 + // AI_CLass_QX_NAME_qipao, // 气泡 + // AI_CLass_QX_NAME_qing_huashang, // 轻划伤 + // AI_CLass_QX_NAME_mtx, // MTX + // AI_CLass_QX_NAME_yisi_qianzangwu, // 疑似浅层脏污 + // AI_CLass_QX_NAME_qing_zangwu, // 轻脏污 + // AI_CLass_QX_NAME_zhong_zangwu, // 严重脏污 + // AI_CLass_QX_NAME_andian, // 暗点 + // AI_CLass_QX_NAME_huashang, // 划伤 + // AI_CLass_QX_NAME_zf, // zf + + int temClass = cls_num; + + { + switch (temClass) + { + case 0: + cls_num = AI_CLass_QX_NAME_ok_yisi; + strclassName = "ok_ys"; + break; + case 1: + cls_num = AI_CLass_QX_NAME_POL_CEL; + strclassName = "POL_CEL"; + break; + case 2: + cls_num = AI_CLass_QX_NAME_zara; + strclassName = "zara"; + break; + case 3: + cls_num = AI_CLass_QX_NAME_andian; + strclassName = "andian"; + break; + case 4: + cls_num = AI_CLass_QX_NAME_yisi_qianzangwu; + strclassName = "yisi_qianzangwu"; + break; + case 5: + cls_num = AI_CLass_QX_NAME_huashang; + strclassName = "huashang"; + break; + case 6: + cls_num = AI_CLass_QX_NAME_line; + strclassName = "line"; + break; + case 7: + cls_num = AI_CLass_QX_NAME_ps; + strclassName = "ps"; + break; + case 8: + cls_num = AI_CLass_QX_NAME_mtx; + strclassName = "mtx"; + break; + case 9: + cls_num = AI_CLass_QX_NAME_yixian; + strclassName = "yixian"; + break; + case 10: + cls_num = AI_CLass_QX_NAME_zhong_zangwu; + strclassName = "zhong_zangwu"; + break; + case 11: + cls_num = AI_CLass_QX_NAME_qipao; + strclassName = "qipao"; + break; + case 12: + cls_num = AI_CLass_QX_NAME_qing_zangwu; + strclassName = "qing_zangwu"; + break; + case 13: + cls_num = AI_CLass_QX_NAME_other; + strclassName = "other"; + break; + default: + break; + } + } + } + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Classify", "AI Model Out %d = AI Class num %d = %s %f", AI_result, cls_num, strclassName.c_str(), *fmaxScore); + // 已经分成 线的 进行二次判断 + if (AI_CLass_QX_NAME_line == cls_num) + { + + cls_num = AI_CLass_QX_NAME_line; + // printf("\n\n\n\n\n\n\n\n\n--------- flenr %f len %d,widt %d,fjustarea %f\n", flenr, len, widt, fjustarea); + } + else + { + // 对不是线的 进行也进行二次判断 + // 线的补充分类 + if (true) + { + // 长宽比 + float flenr = 1; + int len = 0; + int widt = 0; + if (qx_roi.width > qx_roi.height) + { + flenr = qx_roi.width * 1.0 / qx_roi.height; + len = qx_roi.width; + widt = qx_roi.height; + } + else + { + flenr = qx_roi.height * 1.0 / qx_roi.width; + widt = qx_roi.width; + len = qx_roi.height; + } + + // 长宽比过大,判断成 + if (flenr > 18 && + len > 500 && + widt < 220 && + fjustarea < 850) + { + // printf("\n\n\n\n\n\n\n\n\n--------- flenr %f len %d,widt %d,fjustarea %f\n", flenr,len,widt,fjustarea); + // getchar(); + cls_num = AI_CLass_QX_NAME_line; + strclassName = "line"; + } + } + } + + // printf("--------- 0 cls_num %d \n", cls_num); + re_ConfigType = AIClassTypeToConfigType(cls_num, qx_roi); + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Classify", "AI Class %d = %s --> Config Class %d , score %f ", cls_num, strclassName.c_str(), re_ConfigType, *fmaxScore); + // getchar(); + + return re_ConfigType; +} + +float ImgCheckAnalysisy::Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y) +{ + if (qx_type == CONFIG_QX_NAME_Scratch_L1 || + qx_type == CONFIG_QX_NAME_Scratch_L2 || + qx_type == CONFIG_QX_NAME_X_line || + qx_type == CONFIG_QX_NAME_Fangge || + qx_type == CONFIG_QX_NAME_Y_line) + { + } + else + { + // return -1; + } + + float nlen = -1; + cv::Mat detimg = qx_maskImg; + + // 寻找轮廓 + vector> contours; + cv::findContours(detimg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + + // 找到最大面积的轮廓 + double maxArea = -1; + int maxAreaIdx = -1; + for (size_t i = 0; i < contours.size(); ++i) + { + double area = contourArea(contours[i]); + if (area > maxArea) + { + maxArea = area; + maxAreaIdx = i; + } + } + + // 如果找到了最大面积的轮廓 + if (maxAreaIdx >= 0) + { + + // 使用minAreaRect找到最小外接矩形 + cv::RotatedRect rect = cv::minAreaRect(contours[maxAreaIdx]); + + // // 绘制最小外接矩形 + // Point2f vertices[4]; + // rect.points(vertices); + // for (int i = 0; i < 4; ++i) + // { + // line(detimg, vertices[i], vertices[(i + 1) % 4], Scalar(128, 255, 0), 2); // 绿色线 + // } + // 输出结果 + + // 获取最小外接矩形的尺寸 + float width = rect.size.width; + float height = rect.size.height; + + // std::cout << "1 Width: " << width << ", Height: " << height << std::endl; + Point2f vertices[4]; + rect.points(vertices); + + vector newcont; + for (int i = 0; i < 4; ++i) + { + Point2f p; + p.x = vertices[i].x * fsc_x; + p.y = vertices[i].y * fsc_y; + newcont.push_back(p); + } + vector> contours_New; + contours_New.push_back(newcont); + // Recreate the rotated rectangle with scaled vertices + RotatedRect scaledRect = minAreaRect(contours_New[0]); + + // Calculate scaled width and height + width = scaledRect.size.width; + height = scaledRect.size.height; + // std::cout << "2 width: " << width << ", height: " << height << std::endl; + // float scale = 0.5; // 缩放比例 + // rect.size.width *= fsc_x; + // rect.size.height *= fsc_y; + // std::cout << "fsc_x: " << fsc_x << ", fsc_y: " << fsc_y << std::endl; + // std::cout << "Width: " << width << ", Height: " << height << std::endl; + // 获取最小外接矩形的尺寸 + // width = rect.size.width; + // height = rect.size.height; + if (width > height) + { + nlen = width; + /* code */ + } + else + { + nlen = height; + } + + // std::cout << "nlen: " << nlen << ", nlen: " << nlen << std::endl; + // printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + // cv::imwrite("Cal_detimg.png", detimg); + // getchar(); + + // // 对最大面积轮廓进行多边形逼近 + // vector approxCurve; + // double epsilon = 0.01 * arcLength(contours[maxAreaIdx], true); // 逼近精度设定为曲线周长的1% + // approxPolyDP(contours[maxAreaIdx], approxCurve, epsilon, true); + + // // 计算逼近后的曲线长度 + // double curveLength = arcLength(approxCurve, true); + // cout << "Approximated length of contour with max area: " << curveLength << endl; + } + + // getchar(); + return nlen; +} + +cv::Scalar ImgCheckAnalysisy::calc_blob_info_withstats(cv::Mat &img, const cv::Mat &mask, cv::Rect &stats, cv::Size k_size, int expand, double threshold) +{ + + // 解包 stats(x, y, w, h, area) + int x = stats.x, y = stats.y, w = stats.width, h = stats.height; + + // 将图像转换为灰度图像 + + // 计算感兴趣区域 (ROI) + cv::Rect roi(x - expand, y - expand, w + 2 * expand, h + 2 * expand); + roi &= cv::Rect(0, 0, img.cols, img.rows); // 确保ROI在图像内 + + cv::Mat cimg = img(roi); + + // cv::cvtColor(cimg, cimg, cv::COLOR_BGR2GRAY); + // return cv::Scalar(0, 0, 0); + // CheckUtil::printROI(roi, "roi-----------"); + // printf("img --%d %d \n", img.cols, img.rows); + // printf("mask --%d %d \n", mask.cols, mask.rows); + cv::Mat cmask = mask(roi); + // getchar(); + // 扩张掩膜 + + cv::Scalar mean_bk = cv::mean(cimg, ~cmask); + double fbk = mean_bk[0]; + + cv::Scalar mean_det = cv::mean(cimg, cmask); + double fdet = mean_det[0]; + + // 计算差异图像 + cv::Mat diff = cv::abs(cimg - fbk); + + // cv::imwrite("cimg.png",cimg); + // cv::imwrite("cmask.png",cmask); + // printf("%f %f - %f \n",fbk,fdet,fbk-fdet); + // getchar(); + + // diff = diff.mul(cmask > 0); + cv::Mat masked_image; + diff.copyTo(masked_image, cmask); + // 计算能量 + double energy = cv::sum(masked_image)[0]; + + // 计算 hj(差异图像大于0的像素均值) + // double hj = std::abs(fbk - fdet); + // double hj = CheckUtil::CalHj(cimg, cmask, mean_bk.val[0]); + // double hj = CheckUtil::CalHjWeighted(cimg, cmask, fbk, 2.0f); + + int worb = 0; + if (fdet >= fbk) + { + worb = 1; + } + // cv::imwrite("cimg.png", cimg); + // cv::imwrite("cmask.png", cmask); + // cv::imwrite("diff.png", diff); + // cv::imwrite("masked_image.png", masked_image); + // printf("fbk %f fdet %f energy %f\n", fbk, fdet, energy); + // getchar(); + + return cv::Scalar(worb, energy, 0); +} + +int ImgCheckAnalysisy::StartAIDeal() +{ + + std::unique_lock lk(mutex_AIDeal); + m_nWaite_AIDeal_SmallImg_Num++; + lk.unlock(); + condVar_AI.notify_all(); + return 0; + return 0; +} + +int ImgCheckAnalysisy::waitImgAIDealEnd() +{ + + std::unique_lock lk(mutex_AIDeal); + condVar_AI.wait(lk, [this]() + { return m_nWaite_AIComplete_SmallImg_Num > 0; }); + + lk.unlock(); + + return 0; +} + +void ImgCheckAnalysisy::waitAIData() +{ + std::unique_lock lk(mutex_AIDeal); + // printf("======= AI Thread : wait SamllImg Data \n"); + condVar_AI.wait(lk, [this]() + { return m_nWaite_AIDeal_SmallImg_Num > 0; }); + // printf("======= AI Thread : m_nWaite_AIDeal_SmallImg_Num %d \n", m_nWaite_AIDeal_SmallImg_Num); +} + +int ImgCheckAnalysisy::CheckAnalysisResult() +{ + long t1, t2, t3, t4, t5, t6, t7; + t1 = CheckUtil::getcurTime(); + BlobAnalysis_new(); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "3、detect", "-------------------------2、Cal qx BLob---------------\n"); + ReCheck127Cell(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "3、detect", "-------------------------3、Detect 127 Cell ---------------\n"); + + Contours(); + + // m_TemCheck.saveImg(); + // 结果判断 + t2 = CheckUtil::getcurTime(); + + AnalysisResult_New(); + + t3 = CheckUtil::getcurTime(); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "3、detect", "-------------------------4、QX Analysis ---- 2-4 use time %ld-----------\n", t3 - t1); + + return 0; +} + +int ImgCheckAnalysisy::BlobAnalysis_new() +{ + std::string strBaseLog = "Blob"; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "image Blob Analysis Start"); + if (m_TemCheck.temImgList[TEM_IMG_IDX_AImask].empty()) + { + return 1; + } + + long t1 = CheckUtil::getcurTime(); + + unsigned char *pGrayErrordata = (unsigned char *)m_TemCheck.temImgList[TEM_IMG_IDX_AImask].data; + unsigned char *pImgdata = (unsigned char *)m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].data; + + int width = m_TemCheck.temImgList[TEM_IMG_IDX_AImask].cols; + int height = m_TemCheck.temImgList[TEM_IMG_IDX_AImask].rows; + memset(&blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); + + GetBlobs_V2(&blobs, pImgdata, pGrayErrordata, width, height, 0, 200); + // printf("%s blobs.blobCount-----1: %d \n", m_CheckResult_shareP->in_shareImage->strChannel.c_str(), blobs.blobCount); + if (blobs.blobCount < _MAX_ERROR_DOT_BLOB) + { + + ERROR_DOTS_BLOBS blobs_tem; + memset(&blobs_tem, 0x00, sizeof(ERROR_DOTS_BLOBS)); + + GetBlobs_V2(&blobs_tem, pImgdata, pGrayErrordata, width, height, 0, 100); + // printf("%s blobs.blobCount-----2: %d \n", m_CheckResult_shareP->in_shareImage->strChannel.c_str(), blobs_tem.blobCount); + for (int i = 0; i < blobs_tem.blobCount; i++) + { + bool bhave = false; + for (int j = 0; j < blobs.blobCount; j++) + { + if (blobs_tem.blobTab[i].minx == blobs.blobTab[j].minx && + blobs_tem.blobTab[i].miny == blobs.blobTab[j].miny && + blobs_tem.blobTab[i].maxx == blobs.blobTab[j].maxx && + blobs_tem.blobTab[i].maxy == blobs.blobTab[j].maxy) + { + bhave = true; + break; + } + } + if (bhave) + { + continue; + } + blobs_tem.blobTab[i].badd = 1; + } + for (int i = 0; i < blobs_tem.blobCount; i++) + { + if (blobs_tem.blobTab[i].badd == 1) + { + int ncount = blobs.blobCount; + if (ncount < _MAX_ERROR_DOT_BLOB) + { + memcpy(&blobs.blobTab[ncount], &blobs_tem.blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA)); + blobs.blobCount++; + } + } + } + } + if (blobs.blobCount < _MAX_ERROR_DOT_BLOB) + { + ERROR_DOTS_BLOBS blobs_tem; + memset(&blobs_tem, 0x00, sizeof(ERROR_DOTS_BLOBS)); + GetBlobs_V2(&blobs_tem, pImgdata, pGrayErrordata, width, height, 0, 50); + // printf("%s blobs.blobCount-----3: %d \n", m_CheckResult_shareP->in_shareImage->strChannel.c_str(), blobs.blobCount); + for (int i = 0; i < blobs_tem.blobCount; i++) + { + bool bhave = false; + for (int j = 0; j < blobs.blobCount; j++) + { + if (blobs_tem.blobTab[i].minx == blobs.blobTab[j].minx && + blobs_tem.blobTab[i].miny == blobs.blobTab[j].miny && + blobs_tem.blobTab[i].maxx == blobs.blobTab[j].maxx && + blobs_tem.blobTab[i].maxy == blobs.blobTab[j].maxy) + { + bhave = true; + break; + } + } + if (bhave) + { + continue; + } + blobs_tem.blobTab[i].badd = 1; + } + for (int i = 0; i < blobs_tem.blobCount; i++) + { + if (blobs_tem.blobTab[i].badd == 1) + { + int ncount = blobs.blobCount; + if (ncount < _MAX_ERROR_DOT_BLOB) + { + memcpy(&blobs.blobTab[ncount], &blobs_tem.blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA)); + blobs.blobCount++; + } + } + } + } + if (blobs.blobCount < _MAX_ERROR_DOT_BLOB) + { + ERROR_DOTS_BLOBS blobs_tem; + memset(&blobs_tem, 0x00, sizeof(ERROR_DOTS_BLOBS)); + GetBlobs_V2(&blobs_tem, pImgdata, pGrayErrordata, width, height, 0, 30); + // printf("%s blobs.blobCount-----4: %d \n", m_CheckResult_shareP->in_shareImage->strChannel.c_str(), blobs.blobCount); + for (int i = 0; i < blobs_tem.blobCount; i++) + { + bool bhave = false; + for (int j = 0; j < blobs.blobCount; j++) + { + if (blobs_tem.blobTab[i].minx == blobs.blobTab[j].minx && + blobs_tem.blobTab[i].miny == blobs.blobTab[j].miny && + blobs_tem.blobTab[i].maxx == blobs.blobTab[j].maxx && + blobs_tem.blobTab[i].maxy == blobs.blobTab[j].maxy) + { + bhave = true; + break; + } + } + if (bhave) + { + continue; + } + blobs_tem.blobTab[i].badd = 1; + } + for (int i = 0; i < blobs_tem.blobCount; i++) + { + if (blobs_tem.blobTab[i].badd == 1) + { + int ncount = blobs.blobCount; + if (ncount < _MAX_ERROR_DOT_BLOB) + { + memcpy(&blobs.blobTab[ncount], &blobs_tem.blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA)); + blobs.blobCount++; + } + } + } + } + if (blobs.blobCount < _MAX_ERROR_DOT_BLOB) + { + ERROR_DOTS_BLOBS blobs_tem; + memset(&blobs_tem, 0x00, sizeof(ERROR_DOTS_BLOBS)); + GetBlobs_V2(&blobs_tem, pImgdata, pGrayErrordata, width, height, 0, 12); + // printf("%s blobs.blobCount-----5: %d \n", m_CheckResult_shareP->in_shareImage->strChannel.c_str(), blobs.blobCount); + for (int i = 0; i < blobs_tem.blobCount; i++) + { + bool bhave = false; + for (int j = 0; j < blobs.blobCount; j++) + { + if (blobs_tem.blobTab[i].minx == blobs.blobTab[j].minx && + blobs_tem.blobTab[i].miny == blobs.blobTab[j].miny && + blobs_tem.blobTab[i].maxx == blobs.blobTab[j].maxx && + blobs_tem.blobTab[i].maxy == blobs.blobTab[j].maxy) + { + bhave = true; + break; + } + } + if (bhave) + { + continue; + } + blobs_tem.blobTab[i].badd = 1; + } + for (int i = 0; i < blobs_tem.blobCount; i++) + { + if (blobs_tem.blobTab[i].badd == 1) + { + int ncount = blobs.blobCount; + if (ncount < _MAX_ERROR_DOT_BLOB) + { + memcpy(&blobs.blobTab[ncount], &blobs_tem.blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA)); + blobs.blobCount++; + } + } + } + } + if (blobs.blobCount > 100) + { + blobs.blobCount = 100; + } + CalBLobMean_GrayDis(); + long t2 = CheckUtil::getcurTime(); + // CalBlobDensity(); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, "blob Num %d time %ld mm ", blobs.blobCount, t2 - t1); + + if (true && DetImgInfo_shareP->otherValue == 9) + { + int font_face = cv::FONT_HERSHEY_SIMPLEX; + double font_scale = 0.5; + int thickness = 1; + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, "Save Tem Img"); + cv::Mat tm; + cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], tm, cv::COLOR_GRAY2RGB); // 彩色 可选项 + for (int i = 0; i < blobs.blobCount; i++) + { + cv::Rect roi; + roi.x = blobs.blobTab[i].minx; + roi.y = blobs.blobTab[i].miny; + roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1; + roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1; + + cv::rectangle(tm, roi, cv::Scalar(0, 0, 255)); + + char buffer[128]; + sprintf(buffer, " E:%d m %0.1f", blobs.blobTab[i].energy, blobs.blobTab[i].density); + std::string text = buffer; + cv::Point origin = cv::Point(roi.x, roi.y); + cv::putText(tm, text, origin, font_face, font_scale, cv::Scalar(0, 255, 0), thickness, 1, 0); + + printf("type: %d %d %d %d %d %d %d\n", blobs.blobTab[i].ErrType, blobs.blobTab[i].area, blobs.blobTab[i].energy, roi.x, roi.y, roi.width, roi.height); + } + cv::imwrite(m_CheckResult_shareP->in_shareImage->strChannel + "_image_resize_blob.png", tm); + if (!m_DetImgMask.empty()) + { + // cv::imwrite("DetImgMask.png", m_DetImgMask); + + cv::imwrite(m_CheckResult_shareP->in_shareImage->strChannel + "_DetImgMask.png", m_DetImgMask); + } + } + + // if (!m_DetImgMask.empty()) + // { + // // cv::imwrite("DetImgMask.png", m_DetImgMask); + + // cv::imwrite(m_CheckResult_shareP->in_shareImage->strChannel + "_DetImgMask.png", m_DetImgMask); + // } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "image Blob Analysis End"); + return 0; +} + +int ImgCheckAnalysisy::CalBLobMean_GrayDis() +{ + if (blobs.blobCount <= 0) + { + return 0; + } + + cv::Size sz; + sz.width = 640; + sz.height = 480; + cv::Mat temimg; + cv::resize(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], temimg, sz, 0, 0, 1); + cv::Rect roi1; + roi1.x = 0; + roi1.y = 0; + roi1.width = temimg.cols; + roi1.height = temimg.rows; + + cv::Rect roi2; + roi2.x = 0; + roi2.y = 0; + roi2.width = temimg.cols; + roi2.height = temimg.rows; + + int mean1 = 0; + int mean2 = 0; + + // 上黑下白 。。。。 + if (m_CheckInstruct.bWhiteAndBlack) + { + + cv::Mat binary_image; + // 应用模糊 + + cv::blur(temimg, temimg, cv::Size(3, 3)); // 15x15 的模糊核 + cv::threshold(temimg, binary_image, 100, 255, cv::THRESH_BINARY); + // 寻找轮廓 + std::vector> contours; + cv::findContours(binary_image, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + // 找到最大轮廓 + double max_area = 0; + int max_area_contour_index = -1; + for (size_t i = 0; i < contours.size(); ++i) + { + double area = cv::contourArea(contours[i]); + if (area > max_area) + { + max_area = area; + max_area_contour_index = i; + } + } + // cv::imwrite("temimg123.png", temimg); + // cv::imwrite("binary_image.png", binary_image); + // printf("max_area_contour_index %d \n", max_area_contour_index); + // getchar(); + if (max_area_contour_index >= 0) + { + + float fx = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols * 1.0f / temimg.cols; + float fy = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows * 1.0f / temimg.rows; + + float fs_resize_x = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fs_resize_y = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + + // 计算最大轮廓的外接矩形 + cv::Rect bounding_rect = cv::boundingRect(contours[max_area_contour_index]); + + cv::Rect roi_wtb = bounding_rect; + if (roi_wtb.x < 5) + { + roi_wtb.x = 0; + } + // printf(" \n\n\n\n\n%d %d %d %d %d %d \n\n",roi_wtb.x ,roi_wtb.y ,roi_wtb.width ,roi_wtb.height,temimg.cols,temimg.rows); + if (temimg.cols - (roi_wtb.x + roi_wtb.width) < 5) + { + roi_wtb.width = temimg.cols - roi_wtb.x; + } + // printf(" \n\n\n\n\n%d %d %d %d %d %d \n\n",roi_wtb.x ,roi_wtb.y ,roi_wtb.width ,roi_wtb.height,temimg.cols,temimg.rows); + if (roi_wtb.y < 5) + { + roi_wtb.y = 0; + } + if (temimg.rows - (roi_wtb.y + roi_wtb.height) < 5) + { + roi_wtb.height = temimg.rows - roi_wtb.y; + } + + m_OtherResult.WTB_Check_Result.roi_src.x = roi_wtb.x * fx; + m_OtherResult.WTB_Check_Result.roi_src.y = roi_wtb.y * fy; + m_OtherResult.WTB_Check_Result.roi_src.width = roi_wtb.width * fx; + m_OtherResult.WTB_Check_Result.roi_src.height = roi_wtb.height * fy; + + // printf(" \n\n\n\n\n%d %d %d %d %d %d \n\n",m_OtherResult.WTB_Check_Result.roi_src.x ,m_OtherResult.WTB_Check_Result.roi_src.y ,m_OtherResult.WTB_Check_Result.roi_src.width ,m_OtherResult.WTB_Check_Result.roi_src.height, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows); + + m_OtherResult.WTB_Check_Result.roi_show.x = m_OtherResult.WTB_Check_Result.roi_src.x * fs_resize_x; + m_OtherResult.WTB_Check_Result.roi_show.y = m_OtherResult.WTB_Check_Result.roi_src.y * fs_resize_y; + m_OtherResult.WTB_Check_Result.roi_show.width = m_OtherResult.WTB_Check_Result.roi_src.width * fs_resize_x; + m_OtherResult.WTB_Check_Result.roi_show.height = m_OtherResult.WTB_Check_Result.roi_src.height * fs_resize_y; + + // printf(" \n\n\n\n\n%d %d %d %d %d %d \n\n",m_OtherResult.WTB_Check_Result.roi_show.x ,m_OtherResult.WTB_Check_Result.roi_show.y ,m_OtherResult.WTB_Check_Result.roi_show.width ,m_OtherResult.WTB_Check_Result.roi_show.height,m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols,m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows); + + int dis_w = std::abs(bounding_rect.width - temimg.cols); + int dis_h = std::abs(bounding_rect.height - temimg.rows); + + if (dis_w < dis_h) + { + int line_h_up = std::abs(bounding_rect.y - 0); + int line_h_dpwn = std::abs(bounding_rect.y + bounding_rect.height - temimg.rows); + if (line_h_up > line_h_dpwn) + { + roi1.x = 0; + roi1.y = 0; + roi1.width = temimg.cols; + roi1.height = bounding_rect.y; + + roi2.x = 0; + roi2.y = bounding_rect.y; + roi2.width = temimg.cols; + roi2.height = temimg.rows - bounding_rect.y; + } + else + { + roi1.x = 0; + roi1.y = 0; + roi1.width = temimg.cols; + roi1.height = bounding_rect.y + bounding_rect.height; + + roi2.x = 0; + roi2.y = bounding_rect.y + bounding_rect.height; + roi2.width = temimg.cols; + roi2.height = temimg.rows - (bounding_rect.y + bounding_rect.height); + } + } + else + { + int line_w_l = std::abs(bounding_rect.x - 0); + int line_w_r = std::abs(bounding_rect.x + bounding_rect.width - temimg.cols); + if (line_w_l > line_w_r) + { + roi1.x = 0; + roi1.y = 0; + roi1.width = bounding_rect.x; + roi1.height = temimg.rows; + + roi2.x = bounding_rect.x; + roi2.y = 0; + roi2.width = temimg.cols - bounding_rect.x; + roi2.height = temimg.rows; + } + else + { + roi1.x = 0; + roi1.y = 0; + roi1.width = bounding_rect.x + bounding_rect.width; + roi1.height = temimg.rows; + + roi2.x = bounding_rect.x + bounding_rect.width; + roi2.y = 0; + roi2.width = temimg.cols - (bounding_rect.x + bounding_rect.width); + roi2.height = temimg.rows; + } + } + + // cv::Mat showimg; + // cv::cvtColor(temimg, showimg, cv::COLOR_GRAY2BGR); + // cv::rectangle(showimg, bounding_rect, cv::Scalar(0, 255, 0), 2); + // cv::rectangle(showimg, roi1, cv::Scalar(255, 0, 0), 2); + // cv::rectangle(showimg, roi2, cv::Scalar(0, 0, 255), 2); + // cv::imwrite("ddddd.png", showimg); + // getchar(); + + cv::Rect mean_roi1; + int dw1 = roi1.width * 0.1; + if (dw1 < 10) + { + dw1 = 10; + } + int dh1 = roi1.height * 0.1; + if (dh1 < 10) + { + dh1 = 10; + } + mean_roi1.x = roi1.x + dw1; + mean_roi1.y = roi1.y + dh1; + mean_roi1.width = roi1.width - 2 * dw1; + mean_roi1.height = roi1.height - 2 * dh1; + + CheckUtil::CheckRect(mean_roi1, temimg.cols, temimg.rows); + + cv::Scalar mean_v1 = cv::mean(temimg(mean_roi1)); + mean1 = mean_v1[0]; + + cv::Rect mean_roi2; + int dw2 = roi2.width * 0.1; + if (dw2 < 10) + { + dw2 = 10; + } + int dh2 = roi2.height * 0.1; + if (dh2 < 10) + { + dh2 = 10; + } + mean_roi2.x = roi2.x + dw2; + mean_roi2.y = roi2.y + dh2; + mean_roi2.width = roi2.width - 2 * dw2; + mean_roi2.height = roi2.height - 2 * dh2; + CheckUtil::CheckRect(mean_roi2, temimg.cols, temimg.rows); + + cv::Scalar mean_v2 = cv::mean(temimg(mean_roi2)); + mean2 = mean_v2[0]; + + // cv::Mat showimg; + // cv::cvtColor(temimg, showimg, cv::COLOR_GRAY2BGR); + // cv::rectangle(showimg, bounding_rect, cv::Scalar(0, 255, 0), 2); + // cv::rectangle(showimg, roi1, cv::Scalar(255, 0, 0), 2); + // cv::rectangle(showimg, roi2, cv::Scalar(0, 0, 255), 2); + + // cv::rectangle(showimg, mean_roi1, cv::Scalar(255, 255, 0), 2); + + // cv::rectangle(showimg, mean_roi2, cv::Scalar(255, 255, 0), 2); + // cv::imwrite("ddddd.png", showimg); + // getchar(); + } + else + { + cv::Scalar mean_v1 = cv::mean(temimg(roi1)); + mean1 = mean_v1[0]; + mean2 = mean1; + } + } + else + { + cv::Scalar mean_v1 = cv::mean(temimg(roi1)); + mean1 = mean_v1[0]; + mean2 = mean1; + } + + // printf("mean1 %d mean2 %d\n", mean1, mean2); + + float fsx = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols * 1.0f / temimg.cols; + float fsy = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows * 1.0f / temimg.rows; + + roi1.x *= fsx; + roi1.y *= fsy; + roi1.width *= fsx; + roi1.height *= fsy; + + roi2.x *= fsx; + roi2.y *= fsy; + roi2.width *= fsx; + roi2.height *= fsy; + + for (int i = 0; i < blobs.blobCount; i++) + { + cv::Rect roi; + roi.x = blobs.blobTab[i].minx; + roi.y = blobs.blobTab[i].miny; + roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1; + roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1; + + cv::Point p; + p.x = roi.x + roi.width * 0.5; + p.y = roi.y + roi.height * 0.5; + + int mean_v = mean1; + if (p.x >= roi1.x && p.x <= (roi1.x + roi1.width) && + p.y >= roi1.y && p.y <= (roi1.y + roi1.height)) + { + mean_v = mean1; + // printf("p %d %d in %d %d %d %d \n", p.x, p.y, roi1.x, roi1.y, roi1.width, roi1.height); + } + else + { + mean_v = mean2; + // printf("p %d %d in %d %d %d %d \n", p.x, p.y, roi2.x, roi2.y, roi2.width, roi2.height); + } + + // 寻找图像的最大灰度值和其位置 + double min_val, max_val; + cv::Point min_loc, max_loc; + cv::minMaxLoc(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](roi), &min_val, &max_val, &min_loc, &max_loc); + // printf("mean %d max %f \n", mean_v, max_val); + cv::Scalar mean123 = cv::mean(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](roi)); + int mean_roi = mean123[0]; + blobs.blobTab[i].maxValue = max_val; + blobs.blobTab[i].grayDis = std::abs(mean_v - max_val); + // 黑色 + if (mean_roi < (mean_v - blobs.blobTab[i].grayDis)) + { + blobs.blobTab[i].grayDis = std::abs(mean_v - mean_roi); + } + + /* code */ + } + return 0; +} + +int ImgCheckAnalysisy::CalBLobMean_GrayDis_127Cell() +{ + + if (blobs_127.blobCount <= 0) + { + return 0; + } + + cv::Size sz; + sz.width = 640; + sz.height = 480; + cv::Mat temimg; + cv::resize(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], temimg, sz, 0, 0, 1); + cv::Rect roi1; + roi1.x = 0; + roi1.y = 0; + roi1.width = temimg.cols; + roi1.height = temimg.rows; + + cv::Rect roi2; + roi2.x = 0; + roi2.y = 0; + roi2.width = temimg.cols; + roi2.height = temimg.rows; + + int mean1 = 0; + int mean2 = 0; + + // 上黑下白 。。。。 + + { + cv::Scalar mean_v1 = cv::mean(temimg(roi1)); + mean1 = mean_v1[0]; + mean2 = mean1; + } + + float fsx = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols * 1.0f / temimg.cols; + float fsy = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows * 1.0f / temimg.rows; + + roi1.x *= fsx; + roi1.y *= fsy; + roi1.width *= fsx; + roi1.height *= fsy; + + roi2.x *= fsx; + roi2.y *= fsy; + roi2.width *= fsx; + roi2.height *= fsy; + + for (int i = 0; i < blobs_127.blobCount; i++) + { + cv::Rect roi; + roi.x = blobs_127.blobTab[i].minx; + roi.y = blobs_127.blobTab[i].miny; + roi.width = blobs_127.blobTab[i].maxx - blobs_127.blobTab[i].minx + 1; + roi.height = blobs_127.blobTab[i].maxy - blobs_127.blobTab[i].miny + 1; + + cv::Point p; + p.x = roi.x + roi.width * 0.5; + p.y = roi.y + roi.height * 0.5; + + int mean_v = mean1; + + double min_val, max_val; + cv::Point min_loc, max_loc; + cv::minMaxLoc(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](roi), &min_val, &max_val, &min_loc, &max_loc); + // printf("mean %d max %f \n", mean_v, max_val); + + cv::Scalar mean123 = cv::mean(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](roi)); + int mean_roi = mean123[0]; + cv::Rect big_roi; + big_roi.x = p.x - 100; + if (big_roi.x < 0) + { + big_roi.x = 0; + } + big_roi.y = p.y - 100; + if (big_roi.y < 0) + { + big_roi.y = 0; + } + big_roi.width = 200; + big_roi.height = 200; + if (big_roi.x + big_roi.width > m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols) + { + big_roi.x = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols - big_roi.width; + } + if (big_roi.y + big_roi.height > m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows) + { + big_roi.y = m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows - big_roi.height; + } + int mean_big = mean_v; + if (CheckUtil::RoiInImg(big_roi, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop])) + { + cv::Scalar meanbig = cv::mean(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](big_roi)); + mean_big = meanbig[0]; + } + + // printf("======mean %d max %f %d\n", mean_v, max_val, mean_roi); + blobs_127.blobTab[i].maxValue = max_val; + blobs_127.blobTab[i].grayDis = std::abs(mean_v - max_val); + + if (mean_roi >= mean_big) + { + blobs_127.blobTab[i].ErrDesc = CONFIG_QX_NAME_white_Cell; + } + else + { + blobs_127.blobTab[i].grayDis = std::abs(mean_v - mean_roi); + blobs_127.blobTab[i].ErrDesc = CONFIG_QX_NAME_black_Cell; + } + // printf("====127cell==mean_big %d mean_cur %d result %d\n", mean_big, mean_roi, blobs_127.blobTab[i].ErrDesc); + /* code */ + } + return 0; +} + +int ImgCheckAnalysisy::CalBlobDensity() +{ + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + double dis_T = m_pBasicConfig->density_R_mm; + if (dis_T <= 0 || dis_T > 99999) + { + dis_T = 5; + } + + if (blobs.blobCount <= 0) + { + return 0; + } + for (int i = 0; i < blobs.blobCount; i++) + { + cv::Rect roi; + roi.x = blobs.blobTab[i].minx; + roi.y = blobs.blobTab[i].miny; + roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1; + roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1; + + cv::Point p; + p.x = roi.x + roi.width * 0.5; + p.y = roi.y + roi.height * 0.5; + + int num = 1; + double sum_dis = 0; + + for (int j = 0; j < blobs.blobCount; j++) + { + if (i == j) + { + continue; + } + cv::Rect roi123; + roi123.x = blobs.blobTab[j].minx; + roi123.y = blobs.blobTab[j].miny; + roi123.width = blobs.blobTab[j].maxx - blobs.blobTab[j].minx + 1; + roi123.height = blobs.blobTab[j].maxy - blobs.blobTab[j].miny + 1; + cv::Point p123; + p123.x = roi123.x + roi123.width * 0.5; + p123.y = roi123.y + roi123.height * 0.5; + + double dis_x = std::abs(p123.x - p.x) * fs_x; + double dis_y = std::abs(p123.y - p.y) * fs_y; + double dis = std::sqrt(dis_x * dis_x + dis_y * dis_y); + if (dis > dis_T) + { + continue; + } + num++; + sum_dis += dis; + } + float avdis = dis_T; + if (num > 1) + { + avdis = sum_dis / (num - 1); + } + float fScore = (dis_T - avdis) / dis_T; + + double fD = num + fScore; + blobs.blobTab[i].density = fD; + } + + return 0; +} + +int ImgCheckAnalysisy::Contours() +{ + std::string strBaseLog = "Contours"; + // m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Contours Start"); + cv::Mat detimg; + { + // 膨胀 + cv::Mat se = getStructuringElement(0, Size(5, 5)); // 构造矩形结构元素 + cv::dilate(m_TemCheck.temImgList[TEM_IMG_IDX_AImask], detimg, se); + } + + std::vector> contours; + std::vector hierarchy; + cv::findContours(detimg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); // 只找最外层轮廓 + + // cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc], cv::COLOR_GRAY2BGR); + + for (int i = 0; i < contours.size(); ++i) + { // 绘制所有轮廓 + cv::drawContours(m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc], contours, i, cv::Scalar(255, 0, 255)); // thickness为-1时为填充整个轮廓 + } + + float fx = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fy = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + for (int i = 0; i < contours.size(); ++i) + { + for (int j = 0; j < contours.at(i).size(); ++j) + { + contours.at(i).at(j).x *= fx; + contours.at(i).at(j).y *= fy; + } + } + // cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_Result], m_TemCheck.temImgList[TEM_IMG_IDX_Result], cv::COLOR_GRAY2BGR); + + for (int i = 0; i < contours.size(); ++i) + { // 绘制所有轮廓 + cv::drawContours(m_TemCheck.temImgList[TEM_IMG_IDX_Result], contours, i, cv::Scalar(255, 0, 255)); // thickness为-1时为填充整个轮廓 + } + // cv::imwrite("TEM_IMG_IDX_Result.png", m_TemCheck.temImgList[TEM_IMG_IDX_Result]); + // cv::imwrite("deeeee.png", m_TemCheck.temImgList[TEM_IMG_IDX_Drawmask]); + // getchar(); + // m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Contours End"); + return 0; +} + +int ImgCheckAnalysisy::Contours_New(cv::Mat mask) +{ + return 0; +} + +cv::Rect ImgCheckAnalysisy::GetCutRoi(cv::Rect roi, cv::Mat img) +{ + + cv::Rect cutroi; + int pc_x = roi.x + roi.width * 0.5; + int pc_y = roi.y + roi.height * 0.5; + bool bresize = false; + if (roi.width < QX_SAMLLIMG_WIDTH && roi.height < QX_SAMLLIMG_HEIGHT) + { + cutroi.width = QX_SAMLLIMG_WIDTH; + cutroi.x = pc_x - QX_SAMLLIMG_WIDTH * 0.5; + cutroi.height = QX_SAMLLIMG_HEIGHT; + cutroi.y = pc_y - QX_SAMLLIMG_HEIGHT * 0.5; + } + else + { + // 宽 高 + if (roi.width > roi.height) + { + cutroi.width = roi.width + 20; + cutroi.x = roi.x - 10; + + float fsx = QX_SAMLLIMG_HEIGHT * 1.0f / QX_SAMLLIMG_WIDTH; + cutroi.height = cutroi.width * fsx; + cutroi.y = pc_y - cutroi.height * 0.5; + } + else + { + cutroi.height = roi.height + 20; + cutroi.y = roi.y - 10; + + float fsy = QX_SAMLLIMG_WIDTH * 1.0f / QX_SAMLLIMG_HEIGHT; + cutroi.width = cutroi.height * fsy; + cutroi.x = pc_x - cutroi.width * 0.5; + } + + bresize = true; + } + + if (cutroi.x < 0) + { + cutroi.x = 0; + } + if (cutroi.y < 0) + { + cutroi.y = 0; + } + if (cutroi.x + cutroi.width >= img.cols) + { + cutroi.x = img.cols - cutroi.width; + if (cutroi.x < 0) + { + cutroi.x = 0; + if (cutroi.x + cutroi.width >= img.cols) + { + cutroi.width = img.cols; + } + } + } + if (cutroi.y + cutroi.height >= img.rows) + { + cutroi.y = img.rows - cutroi.height; + if (cutroi.y < 0) + { + cutroi.y = 0; + if (cutroi.y + cutroi.height >= img.rows) + { + cutroi.height = img.rows; + } + } + } + + return cutroi; +} + +int ImgCheckAnalysisy::AI_Det_YX(cv::Mat cropImg) +{ + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "Start"); + if (m_pFuntion && m_pFuntion->function.f_YXDet.bOpen) + { + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "function close"); + return 1; + } + + int paramIdx = m_QxInParamListIdx[CONFIG_QX_NAME_AD_YX]; + if (paramIdx < 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", " paramIdx < 0 "); + return 1; + } + bool bopenYX = false; + + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "param name %s parmm Num %d ", pParam->param_name.c_str(), pParam->useNum); + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + bopenYX = true; + break; + } + } + if (bopenYX) + { + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "Start"); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "YX Param close , Stop Detect"); + return 1; + } + cv::Mat maskimg; + cv::Mat inImg; + cv::Size sz; + cv::Mat detmask_size; + + sz.width = AI_YX_IN_0_IMAGE_WIDTH; + sz.height = AI_YX_IN_0_IMAGE_HEIGHT; + cv::resize(cropImg, inImg, sz, 0, 0, cv::INTER_AREA); + cv::resize(m_DetImgMask, detmask_size, sz, 0, 0, cv::INTER_AREA); + if (m_pFuntion && m_pFuntion->function.f_YXDet.strModle == "YX_1") + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "Use YX_1 Model"); + m_AIDeal.AICheck_YX_1(inImg, maskimg); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "Use YX_2 Model"); + m_AIDeal.AICheck_YX_2(inImg, maskimg); + } + + // 定义腐蚀操作的内核 + int kernelSize = 11; // 内核大小 + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(kernelSize, kernelSize)); + + // 执行腐蚀操作 + cv::Mat erodedImage; + cv::erode(maskimg, erodedImage, kernel); + + erodedImage.setTo(0, detmask_size); + + if (DetImgInfo_shareP->otherValue == 9) + { + if (!inImg.empty()) + { + cv::imwrite("Yx_img_In.png", inImg); + } + if (!erodedImage.empty()) + { + cv::imwrite("Yx_img_out.png", erodedImage); + } + } + + float fx_src = cropImg.cols * 1.0f / inImg.cols; + float fy_src = cropImg.rows * 1.0f / inImg.rows; + + float fx_Result = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fy_Result = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + + // 轮廓检测 + std::vector> contours; + cv::findContours(erodedImage, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + int nresult = 0; + bool bUse = false; + for (size_t i = 0; i < contours.size(); ++i) + { + + double area = cv::contourArea(contours.at(i)); + double judgeArea = area * m_fImgage_Scale_X * m_fImgage_Scale_Y; + + int curresult = 0; + cv::Rect roi = cv::boundingRect(contours[i]); + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + if (judgeArea > pParam->paramArr[j].area) + { + nresult = 1; + curresult = 1; + } + else + { + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Det_YX", "Area== %s -> %f %s %f ", + BOOL_TO_STR(judgeArea > pParam->paramArr[j].area), judgeArea, + BOOL_TO_ThanLess(judgeArea > pParam->paramArr[j].area), pParam->paramArr[j].area); + bUse = true; + if (curresult != 0) + { + break; + } + } + } + + if (curresult != 0) + { + if (true) + { + QX_ERROR_INFO_ temerror; + temerror.roi = roi; + temerror.Idx = i; + temerror.area = area; + temerror.JudgArea = judgeArea; + temerror.energy = 999999999; + temerror.flen = 9999999999; + temerror.nconfig_qx_type = CONFIG_QX_NAME_AD_YX; + temerror.qx_name = "AD_YX"; + temerror.maxValue = 99999999; + temerror.grayDis = 999999999; + temerror.fUpIou = 0; + temerror.density = 0; + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->push_back(temerror); + // printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen); + } + + int nqx_type = ConfigTypeToResultType(CONFIG_QX_NAME_AD_YX); + cv::Rect roi_src = roi; + roi_src.x *= fx_src; + roi_src.y *= fy_src; + roi_src.width *= fx_src; + roi_src.height *= fy_src; + cv::Rect roi_resize; + roi_resize.x = roi_src.x * fx_Result; + roi_resize.y = roi_src.y * fy_Result; + roi_resize.width = roi_src.width * fx_Result; + roi_resize.height = roi_src.height * fy_Result; + + for (int j = 0; j < contours.at(i).size(); ++j) + { + contours.at(i).at(j).x *= fx_src; + contours.at(i).at(j).y *= fy_src; + } + cv::drawContours(m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc], contours, i, cv::Scalar(0, 255, 255), 2); // thickness为-1时为填充整个轮 + + for (int j = 0; j < contours.at(i).size(); ++j) + { + contours.at(i).at(j).x *= fx_Result; + contours.at(i).at(j).y *= fy_Result; + } + cv::drawContours(m_TemCheck.temImgList[TEM_IMG_IDX_Result], contours, i, cv::Scalar(0, 255, 255)); // thickness为-1时为填充整个轮 + AddQXResult(roi_src, roi_resize, nqx_type, judgeArea, 0, 0, inImg, erodedImage); + // printf("1111\n"); + // cv::imwrite("Yx_img_result123.png", m_TemCheck.temImgList[TEM_IMG_IDX_Result]); + // getchar(); + } + } + if (contours.size() <= 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "blob is empty"); + } + else + { + if (!bUse) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "Error param Is NULL"); + } + } + + m_OtherResult.result_YX.nresult = nresult; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "End result = %d", nresult); + + return 0; +} + +cv::Rect ImgCheckAnalysisy::GetREAIRoi(cv::Rect roi, cv::Mat img) +{ + + int Dst_Width = str_AI_RE_AD_IN_0_IMAGE_WIDTH; + int Dst_Height = str_AI_RE_AD_IN_0_IMAGE_HEIGHT; + cv::Rect cutroi; + int pc_x = roi.x + roi.width * 0.5; + int pc_y = roi.y + roi.height * 0.5; + bool bresize = false; + if (roi.width <= Dst_Width && roi.height <= Dst_Height) + { + cutroi.width = Dst_Width; + cutroi.x = pc_x - Dst_Width * 0.5; + cutroi.height = Dst_Height; + cutroi.y = pc_y - Dst_Height * 0.5; + } + else + { + cutroi = cv::Rect(0, 0, 0, 0); + } + + if (cutroi.x < 0) + { + cutroi.x = 0; + } + if (cutroi.y < 0) + { + cutroi.y = 0; + } + if (cutroi.x + cutroi.width >= img.cols) + { + cutroi.x = img.cols - cutroi.width; + if (cutroi.x < 0) + { + cutroi.x = 0; + if (cutroi.x + cutroi.width >= img.cols) + { + cutroi.width = img.cols; + } + } + } + if (cutroi.y + cutroi.height >= img.rows) + { + cutroi.y = img.rows - cutroi.height; + if (cutroi.y < 0) + { + cutroi.y = 0; + if (cutroi.y + cutroi.height >= img.rows) + { + cutroi.height = img.rows; + } + } + } + + return cutroi; +} + +int ImgCheckAnalysisy::CheckImgInit() +{ + // 1、初始化 + m_CheckResult_shareP = std::make_shared(); + m_ImageDetResult_shareP = std::make_shared(); + m_ImageDetResult_shareP->pOneImgDetResult = std::make_shared(); + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList = std::make_shared>(); + m_TemCheck.Init(); + memset(&blobs, 0, sizeof(ERROR_DOTS_BLOBS)); + m_nCheckResultErrorCode = 0; + m_OtherResult.Init(); + m_CheckInstruct.Init(); + AI_DetImgList.erase(AI_DetImgList.begin(), AI_DetImgList.end()); + m_qx_Analysis.Init(); + m_DetResult.Init(); + m_Draw_qxImageResult.erase(m_Draw_qxImageResult.begin(), m_Draw_qxImageResult.end()); + + m_DetRoiList.Init(); + + return 0; +} + +int ImgCheckAnalysisy::ConfigCheck(cv::Mat img) +{ + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "start", "Config Check"); + int re = CHECK_OK; + if (img.empty()) + { + m_nErrorCode = CHECK_ERROR_CheckImg_Empty; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "check Img empty"); + return m_nErrorCode; + } + + if (m_pCommonAnalysisyConfig->regionConfigArr.size() <= 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "regionConfig Num = 0"); + m_nErrorCode = CHECK_ERROR_Config_Value; + return m_nErrorCode; + } + + if (!CheckUtil::RoiInImg(DetImgInfo_shareP->cutRoi, img)) + { + printf("img %d %d \n", img.cols, img.rows); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "cutRoi Is Error"); + CheckUtil::printROI(DetImgInfo_shareP->cutRoi, "cutRoi"); + m_nErrorCode = CHECK_ERROR_Config_cutRoi; + return m_nErrorCode; + }; + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "Succ", "Config Check Succ"); + return re; +} + +int ImgCheckAnalysisy::AI_Detect_Thread(cv::Mat img, cv::Mat &ResultImg) +{ + std::string strBaseLog = "AI_Detect"; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect Start"); + long t1, t2, t3; + t1 = CheckUtil::getcurTime(); + bool badd = false; + cv::Rect tem_ROI = cv::Rect(0, 0, img.cols, img.rows); + + if (img.rows < SRC_AI_In_IMAGE_HEIGHT) + { + cv::Mat temImg = cv::Mat(SRC_AI_In_IMAGE_HEIGHT, img.cols, CV_8U, cv::Scalar(180)); + img.copyTo(temImg(tem_ROI)); + img = temImg.clone(); + badd = true; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect add img w : img.cols %d img.rows %d != 1024", img.cols, img.rows); + } + if (img.cols < SRC_AI_In_IMAGE_WIDTH) + { + cv::Mat temImg = cv::Mat(img.rows, SRC_AI_In_IMAGE_WIDTH, CV_8U, cv::Scalar(180)); + img.copyTo(temImg(tem_ROI)); + img = temImg.clone(); + badd = true; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect add img H: img.cols %d img.rows %d != 1024", img.cols, img.rows); + } + ResultImg = cv::Mat(img.rows, img.cols, CV_8U, cv::Scalar(0)); + + SmallRoiList.clear(); + SmallRoiList.erase(SmallRoiList.begin(), SmallRoiList.end()); + cv::Rect cutRoi; + cutRoi.x = 0; + cutRoi.y = 0; + cutRoi.width = img.cols - 0; + cutRoi.height = img.rows - 0; + + int re = CheckUtil::cutSmallImg(img, SmallRoiList, cutRoi, SRC_AI_In_IMAGE_WIDTH, SRC_AI_In_IMAGE_HEIGHT, 0, 0); + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg re %d Num %d", re, SmallRoiList.size()); + if (re != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg error %d", re); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End"); + return re; + /* code */ + } + if (SmallRoiList.size() <= 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " SmallList Num Is Null"); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End"); + return 1; + } + + // cv::Mat imshow; + // if (true) + // { + // if (img.channels() == 1) + // { + // cv::cvtColor(img, imshow, cv::COLOR_GRAY2RGB); // 彩色 可选项 + // } + // else + // { + // imshow = img.clone(); + // } + + // /* code */ + // } + std::vector addroi; + // 字符 居中 处理 + for (int izf = 0; izf < m_ZF_centerPoint.size(); izf++) + { + bool bedg = false; + cv::Point p = m_ZF_centerPoint.at(izf); + // cv::circle(imshow, p, 5, cv::Scalar(0, 255, 255)); + for (int i = 0; i < SmallRoiList.size(); i++) + { + cv::Rect roi = SmallRoiList.at(i); + if (std::abs(p.x - roi.x) < 150 || + std::abs(p.x - (roi.x + roi.width)) < 150 || + std::abs(p.y - roi.y) < 150 || + std::abs(p.y - (roi.y + roi.height)) < 150) + { + bedg = true; + } + // cv::rectangle(imshow, roi, cv::Scalar(0, 0, 255)); + } + if (bedg) + { + cv::Rect newroi; + newroi.x = p.x - SRC_AI_In_IMAGE_WIDTH / 2; + newroi.width = SRC_AI_In_IMAGE_WIDTH; + if (newroi.x < 0) + { + newroi.x = 0; + /* code */ + } + if ((newroi.x + SRC_AI_In_IMAGE_WIDTH) > img.cols) + { + newroi.x = img.cols - SRC_AI_In_IMAGE_WIDTH; + } + newroi.y = p.y - SRC_AI_In_IMAGE_HEIGHT / 2; + newroi.height = SRC_AI_In_IMAGE_HEIGHT; + if (newroi.y < 0) + { + newroi.y = 0; + /* code */ + } + if ((newroi.y + SRC_AI_In_IMAGE_HEIGHT) > img.rows) + { + newroi.y = img.rows - SRC_AI_In_IMAGE_HEIGHT; + } + + addroi.push_back(newroi); + + // printf("---------- at edg \n"); + // cv::imwrite("edg.png", imshow); + // /* code */ + // getchar(); + } + } + // printf("***zf num size=%zu, add New AI roi %zu\n", m_ZF_centerPoint.size(), addroi.size()); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, "zf num size=%zu, add New AI roi %zu", m_ZF_centerPoint.size(), addroi.size()); + det_SmallImgNum = SmallRoiList.size(); + + for (int izf = 0; izf < addroi.size(); izf++) + { + SmallRoiList.push_back(addroi.at(izf)); + // cv::rectangle(imshow, addroi.at(izf), cv::Scalar(0, 255, 255)); + } + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " Add New zf AI roi %d", m_ZF_centerPoint.size()); + // cv::imwrite("edg.png", imshow); + // printf("---------- at edg 1111111\n"); + // getchar(); + // 判断 字符 是否在切图的中心 + + m_nWaite_AIDeal_SmallImg_Num = 0; + m_nWaite_AIComplete_SmallImg_Num = 0; + int nDetSmallListIdx = -1; + + t2 = CheckUtil::getcurTime(); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Start"); + for (int i = 0; i < SmallRoiList.size();) + { + + // 1、如果 ai完成,则开始 AI后处理 + nDetSmallListIdx = Multi_Thread_GetSmallImgIdx(AT_THRESHOLD_TYPE_COMPLETE); + if (nDetSmallListIdx >= 0) + { + + // printf(">>>>>>> main Thread : m_nWaite_AIComplete_SmallImg_Num %d \n", m_nWaite_AIComplete_SmallImg_Num); + + // printf(">>>>>>> main Thread :-- AI result det idx %d \n", nDetSmallListIdx); + // AI 后处理; + Multi_Thread_AIResultDet(ResultImg, nDetSmallListIdx); + + // 更新同步数据 + { + std::lock_guard lock(mutex_AIDeal); + m_nWaite_AIComplete_SmallImg_Num--; + } + Multi_Thread_SetSmallType(nDetSmallListIdx, AT_THRESHOLD_TYPE_NULL); + } + // 2、如果有可以预处理的 则预处理一个 + nDetSmallListIdx = Multi_Thread_GetSmallImgIdx(AT_THRESHOLD_TYPE_NULL); + if (nDetSmallListIdx < 0) + { + // printf(">>>>>>> main Thread :-- waitImgAIDealEnd **************** \n"); + waitImgAIDealEnd(); + // printf(">>>>>>> main Thread :-- waitImgAIDealEnd *******start********* \n"); + + continue; + } + // printf(">>>>>>> main Thread : small idx %d start pre det idx %d \n", i, nDetSmallListIdx); + + cv::Rect roi = SmallRoiList.at(i); + Multi_Thread_DetSmallImgList[nDetSmallListIdx].Roi = roi; + Multi_Thread_DetSmallImgList[nDetSmallListIdx].nidx = i; + Multi_Thread_DetSmallImgList[nDetSmallListIdx].flag = 0; + if (i >= det_SmallImgNum) + { + // cv::rectangle(imshow, roi, cv::Scalar(255, 255, 0)); + // printf("zf---idx %d\n",i); + Multi_Thread_DetSmallImgList[nDetSmallListIdx].flag = 9; + } + + AI_PreImg(img(roi), Multi_Thread_DetSmallImgList[nDetSmallListIdx].img); + Multi_Thread_SetSmallType(nDetSmallListIdx, AT_THRESHOLD_TYPE_READY); + + // CheckUtil::printROI(roi); + // printf("-----------roi %d ---\n", i); + + if (true) + { + // cv::rectangle(imshow, roi, cv::Scalar(255, 0, 0)); + // cv::imwrite("imshow.png", imshow); + // getchar(); + } + + // 2、通知ai开始 处理 + StartAIDeal(); + // printf(">>>>>>> main Thread : m_nWaite_AIDeal_SmallImg_Num %d \n", m_nWaite_AIDeal_SmallImg_Num); + + i++; + } + + // printf("\n\n\n=========== m_nWaite_AIComplete_SmallImg_Num %d \n", m_nWaite_AIComplete_SmallImg_Num); + // printf("\n\n\n=========== m_nWaite_AIDeal_SmallImg_Num %d \n", m_nWaite_AIDeal_SmallImg_Num); + while (m_nWaite_AIComplete_SmallImg_Num > 0 || m_nWaite_AIDeal_SmallImg_Num > 0) + { + waitImgAIDealEnd(); + // 1、如果 ai完成,则开始 AI后处理 + nDetSmallListIdx = Multi_Thread_GetSmallImgIdx(AT_THRESHOLD_TYPE_COMPLETE); + if (nDetSmallListIdx >= 0) + { + + // printf(">>>>>>> main Thread : m_nWaite_AIComplete_SmallImg_Num %d \n", m_nWaite_AIComplete_SmallImg_Num); + + // printf(">>>>>>> main Thread :-- AI result det idx %d \n", nDetSmallListIdx); + // AI 后处理; + Multi_Thread_AIResultDet(ResultImg, nDetSmallListIdx); + + // 更新同步数据 + { + std::lock_guard lock(mutex_AIDeal); + m_nWaite_AIComplete_SmallImg_Num--; + } + Multi_Thread_SetSmallType(nDetSmallListIdx, AT_THRESHOLD_TYPE_NULL); + } + } + if (badd) + { + cv::Mat temresult; + ResultImg(tem_ROI).copyTo(temresult); + ResultImg = temresult.clone(); + } + t3 = CheckUtil::getcurTime(); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run complete"); + float mean_AI = (t3 - t2) / SmallRoiList.size(); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI); + // printf("-----------complete ---time sum %ld step 1 %ld step 2 %ld \n", t3 - t1, t2 - t1, t3 - t2); + // cv::imwrite("imshow.png", imshow); + // cv::imwrite("ResultImg.png", ResultImg); + // getchar(); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End"); + return 0; +} + +int ImgCheckAnalysisy::Multi_Thread_GetSmallImgIdx(int ntype) +{ + std::lock_guard lock(mutex_SmallImgList); // 在函数内部创建互斥量的锁定对象 + + for (int i = 0; i < MAX_THREAD_AIDET_NUM; i++) + { + if (Multi_Thread_DetSmallImgList[i].nDetType == ntype) + { + return i; + } + } + return -1; +} + +int ImgCheckAnalysisy::Multi_Thread_SetSmallType(int idx, int ntype) +{ + std::lock_guard lock(mutex_SmallImgList); // 在函数内部创建互斥量的锁定对象 + if (idx >= 0 && idx < MAX_THREAD_AIDET_NUM) + { + Multi_Thread_DetSmallImgList[idx].nDetType = ntype; + } + + return 0; +} + +int ImgCheckAnalysisy::Multi_Thread_AIResultDet(cv::Mat &resultImg, int idx) +{ + + // 存储 AI识别结果 + if (DetImgInfo_shareP->otherValue_1 == 18 || DetImgInfo_shareP->otherValue_1 == 181) + { + // printf("++++++++++++++++++++++++++++++++ \n"); + AI_DetImgList.push_back(Multi_Thread_DetSmallImgList[idx]); + } + + cv::Rect Roi = Multi_Thread_DetSmallImgList[idx].Roi; + + cv::Size sz; + sz.width = SRC_AI_In_IMAGE_WIDTH; + sz.height = SRC_AI_In_IMAGE_HEIGHT; + cv::Mat AIresult; + cv::resize(Multi_Thread_DetSmallImgList[idx].outimg, AIresult, sz, 0, 0, 0); + + { + + bool bchangeroi = false; + cv::Rect remROI = Roi; + if (remROI.width > m_DetImgMask.cols) + { + remROI.width = m_DetImgMask.cols; + bchangeroi = true; + } + if (remROI.height > m_DetImgMask.rows) + { + remROI.height = m_DetImgMask.rows; + bchangeroi = true; + } + if (bchangeroi) + { + cv::Rect AIMaskROI = remROI; + AIMaskROI.x = 0; + AIMaskROI.y = 0; + + AIresult(AIMaskROI).setTo(0, m_DetImgMask(remROI)); + } + else + { + AIresult.setTo(0, m_DetImgMask(Roi)); + } + + // printf(" m_DetImgMask %d %d %d %d %d %d\n", m_DetImgMask.cols, m_DetImgMask.rows, Roi.x, Roi.y, Roi.width, Roi.height); + // AIresult.setTo(0, m_DetImgMask(Roi)); + + // cv::imwrite("r1.png", temimg(roi)); + if (Multi_Thread_DetSmallImgList[idx].flag == 9) + { + // cv::imwrite("resultImg11.png", resultImg); + AIresult.copyTo(resultImg(Roi)); + // printf("123123\n"); + // cv::imwrite("AIresult.png", AIresult); + // cv::imwrite("resultImg222.png", resultImg); + // getchar(); + } + else + { + + AIresult.copyTo(resultImg(Roi), AIresult); + + // static int ddd = 0; + // std::string str = "AIresult_" + std::to_string(ddd) + "_.png"; + // cv::imwrite(str, AIresult); + // std::string str123 = "resultImg" + std::to_string(ddd) + "_.png"; + // cv::imwrite(str123, resultImg); + // ddd++; + // getchar(); + } + + // printf("--m_nWaite_AIComplete_SmallImg_Num %d \n", m_nWaite_AIComplete_SmallImg_Num); + // cv::imwrite("AIresult.png", AIresult); + // cv::imwrite("resultImg.png", resultImg); + // getchar(); + } + // m_nRoiImgIdx++; + return 0; +} + +int ImgCheckAnalysisy::AI_PreImg(cv::Mat img, cv::Mat &AI_DealImg) +{ + long t1, t2, t3, t4; + t1 = CheckUtil::getcurTime(); + + AI_DealImg = img.clone(); + + t2 = CheckUtil::getcurTime(); + + // printf("AI_PreImg time %ld \n", t2 - t1); + return 0; +} + +int ImgCheckAnalysisy::ThreadAI(int nId) +{ + std::vector vi; + vi.push_back(nId); + vi.push_back(nId + 1); + auto nRet = set_cpu_id(vi); + printf("Check SO %d ThreadAI bind cpu ret %d, %d\n", m_nThreadIdx, nRet, nId); + + // printf("ImgCheckAnalysisy ThreadAI\n"); + + while (!m_bExit) + { + // 等待有处理数据 + waitAIData(); + // printf("======= AI Thread : AI in m_nWaite_AIDeal_SmallImg_Num %d \n", m_nWaite_AIDeal_SmallImg_Num); + // printf("======= AI Thread : AI in m_nWaite_AIComplete_SmallImg_Num %d \n", m_nWaite_AIComplete_SmallImg_Num); + int nDetSmallListIdx = Multi_Thread_GetSmallImgIdx(AT_THRESHOLD_TYPE_READY); + // printf("======= AI Thread : AI start >>>>>> det ---> SmallListIdx %d \n", nDetSmallListIdx); + if (nDetSmallListIdx >= 0) + { + // printf("======= AI Thread : AI start small idx %d \n", Multi_Thread_DetSmallImgList[nDetSmallListIdx].nidx); + Multi_Thread_SetSmallType(nDetSmallListIdx, AT_THRESHOLD_TYPE_BUSY); + cv::Mat AIresult; + int re = AI_Det(Multi_Thread_DetSmallImgList[nDetSmallListIdx].img, Multi_Thread_DetSmallImgList[nDetSmallListIdx].outimg); + // int re = AI_DetModel.run_data(&Multi_Thread_DetSmallImgList[nDetSmallListIdx].img_32F, Multi_Thread_DetSmallImgList[nDetSmallListIdx].foutput, Multi_Thread_DetSmallImgList[nDetSmallListIdx].foutput); + // printf("---re %d \n", re); + { + + // imwrite("inimg.png", Multi_Thread_DetSmallImgList[nDetSmallListIdx].img); + // imwrite("outimg.png", Multi_Thread_DetSmallImgList[nDetSmallListIdx].outimg); + // getchar(); + } + Multi_Thread_SetSmallType(nDetSmallListIdx, AT_THRESHOLD_TYPE_COMPLETE); + // printf("======= AI Thread : AI End small idx %d \n", Multi_Thread_DetSmallImgList[nDetSmallListIdx].nidx); + } + // 更新同步数据 + { + std::lock_guard lock(mutex_AIDeal); + m_nWaite_AIDeal_SmallImg_Num--; + m_nWaite_AIComplete_SmallImg_Num++; + } + + // printf("======= AI Thread :AI out m_nWaite_AIDeal_SmallImg_Num %d \n", m_nWaite_AIDeal_SmallImg_Num); + // printf("======= AI Thread :AI out m_nWaite_AIComplete_SmallImg_Num %d \n", m_nWaite_AIComplete_SmallImg_Num); + // printf("======= AI Thread :AI End ------- det ---> SmallListIdx %d \n", nDetSmallListIdx); + condVar_AI.notify_all(); + usleep(1000); + } + return 0; +} + +int ImgCheckAnalysisy::ResizeImg() +{ + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Info", "ResizeImg Start"); + + cv::Size sz; + sz.width = RESIZE_IMAGE_WIDTH; + + float fw = RESIZE_IMAGE_WIDTH * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + sz.height = int(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows * fw); + + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Info", "Src [%d %d] --> det[%d %d]", + // m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows, + // sz.width, sz.height); + cv::resize(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], m_TemCheck.temImgList[TEM_IMG_IDX_Result], sz); + cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_Result], m_TemCheck.temImgList[TEM_IMG_IDX_Result], cv::COLOR_GRAY2BGR); + cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc], cv::COLOR_GRAY2BGR); + if ((m_pBasicConfig && m_pBasicConfig->bDrawShieldRoi) || (m_pFuntion && m_pFuntion->function.f_ShieldRegion.bDraw)) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "DrawShieldR", " param is open"); + + if (!m_DetImgMask.empty()) + { + cv::resize(m_DetImgMask, m_ShieldImg_resize, sz); + m_ShieldImg_resize *= 0.2; + cv::cvtColor(m_ShieldImg_resize, m_ShieldImg_resize, cv::COLOR_GRAY2BGR); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "DrawShieldR", "param is close"); + } + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Info", "ResizeImg End"); + return 0; +} + +int ImgCheckAnalysisy::Update_DetRoiList() +{ + float fx = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fy = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + + for (const auto ®ion : m_pCommonAnalysisyConfig->regionConfigArr) + { + // 启用定位,则用 定位的参数进行弱化区域的转换。如果没有启用就用原来的参数。 + if (ImageDet_shareP->alignResult.bDet && ImageDet_shareP->alignResult.bUse) + { + std::vector adjustedPolygon; + std::vector adjustedPolygon_size; + for (auto &p : region.basicInfo.pointArry) + { + cv::Point p_param = p; + cv::Point p_detImg = ImageDet_shareP->alignResult.Parm_srcToDet_Crop_Point(p_param); + adjustedPolygon.push_back(p_detImg); + cv::Point p_detimg_size; + p_detimg_size.x = p_detImg.x * fx; + p_detimg_size.y = p_detImg.y * fy; + adjustedPolygon_size.push_back(p_detimg_size); + } + m_DetRoiList.roiList_Src.push_back(adjustedPolygon); + m_DetRoiList.roiList_Show.push_back(adjustedPolygon_size); + } + else + { + m_DetRoiList.Update(region.basicInfo.pointArry, m_Crop_Roi_paramImg, fx, fy); + } + + // + } + + // if (true) + // { + // for (const auto &polygon : m_DetRoiList.roiList_Src) + // { + // // 绘制多边形的边界(不填充),使用绿色线条,线宽为2 + // cv::polylines(m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc], polygon, true, cv::Scalar(0, 255, 0), 2); // true表示闭合多边形 + // } + // for (const auto &polygon : m_DetRoiList.roiList_Show) + // { + // // 绘制多边形的边界(不填充),使用绿色线条,线宽为2 + // cv::polylines(m_TemCheck.temImgList[TEM_IMG_IDX_Result], polygon, true, cv::Scalar(128, 255, 0), 2); // true表示闭合多边形 + // } + // cv::imwrite(DetImgInfo_shareP->strChannel + "roi_src.png", m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc]); + // cv::imwrite(DetImgInfo_shareP->strChannel + "roi_ss.png", m_TemCheck.temImgList[TEM_IMG_IDX_Result]); + + // getchar(); + // } + + m_DetRoiList.print("m_DetRoiList"); + return 0; +} + +int ImgCheckAnalysisy::DrawResult() +{ + + // if (m_TemCheck.temImgList[TEM_IMG_IDX_Result].channels() == 1) + // { + // cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_Result], m_TemCheck.temImgList[TEM_IMG_IDX_Result], cv::COLOR_GRAY2RGB); // 彩色 可选项 + // } + m_CheckResult_shareP->resultimg = m_TemCheck.temImgList[TEM_IMG_IDX_Result]; + // cv::imwrite("rrrr.png", m_CheckResult_shareP->resultimg); + + m_DrawImg.DrawResult(m_CheckResult_shareP); + + DrawOther(); + + return 0; +} + +int ImgCheckAnalysisy::ReCalQX_AreaAndLen(AI_SecondDet::DetConfigResult *pdetConfig) +{ + + int paramIdx = m_QxInParamListIdx[pdetConfig->qx_type]; + if (paramIdx < 0) + { + return 0; + /* code */ + } + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + + float min_detArea = 99999; + bool bhave = false; + + for (int j = 0; j < pParam->useNum; j++) + { + if (!pParam->paramArr[j].bEnable) + { + + continue; + } + bhave = true; + float At = pParam->paramArr[j].area; + if (At < min_detArea) + { + min_detArea = At; + } + } + if (!bhave) + { + min_detArea = 0; + } + pdetConfig->min_DetArea = min_detArea; + + int re = m_SecondDet.Detect(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], m_TemCheck.temImgList[TEM_IMG_IDX_AImask], pdetConfig); + + return re; +} + +int ImgCheckAnalysisy::ReCheck127Cell(const cv::Mat &DetImage) +{ + if (m_pFuntion && m_pFuntion->function.f_Det127Cell.bOpen) + { + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "ReCheck127Cell", "Close"); + return 0; + } + cv::Mat img = DetImage; + bool badd = false; + cv::Rect tem_ROI = cv::Rect(0, 0, img.cols, img.rows); + // printf("11=========img.cols %d img.rows %d\n", img.cols, img.rows); + if (img.rows < SRC_AI_In_IMAGE_WIDTH) + { + cv::Mat temImg = cv::Mat(SRC_AI_In_IMAGE_HEIGHT, img.cols, CV_8U, cv::Scalar(0)); + + img.copyTo(temImg(tem_ROI)); + + img = temImg.clone(); + badd = true; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "ReCheck127Cell", "AI_Detect add img w"); + } + if (img.cols < SRC_AI_In_IMAGE_WIDTH) + { + cv::Mat temImg = cv::Mat(img.rows, SRC_AI_In_IMAGE_WIDTH, CV_8U, cv::Scalar(0)); + img.copyTo(temImg(tem_ROI)); + img = temImg.clone(); + badd = true; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "ReCheck127Cell", "AI_Detect add img H"); + } + m_127CellAIMask = cv::Mat(img.rows, img.cols, CV_8U, cv::Scalar(0)); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "ReCheck127Cell", "Start Det"); + + for (int i = 0; i < SmallRoiList.size(); i++) + { + cv::Rect Roi = SmallRoiList.at(i); + // CheckUtil::printROI(Roi, "ROI"); + cv::Mat detimg = img(Roi).clone(); + cv::Mat outimg; + int re12 = m_AIDeal.AICheck_127Cell(detimg, outimg); + if (re12 != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "ReCheck127Cell", "Error AI Model Error"); + /* code */ + } + + cv::Size sz; + sz.width = SRC_AI_In_IMAGE_WIDTH; + sz.height = SRC_AI_In_IMAGE_HEIGHT; + cv::Mat AIresult; + cv::resize(outimg, AIresult, sz, 0, 0, 0); + + { + + bool bchangeroi = false; + cv::Rect remROI = Roi; + if (remROI.width > m_DetImgMask.cols) + { + remROI.width = m_DetImgMask.cols; + bchangeroi = true; + } + if (remROI.height > m_DetImgMask.rows) + { + remROI.height = m_DetImgMask.rows; + bchangeroi = true; + } + if (bchangeroi) + { + cv::Rect AIMaskROI = remROI; + AIMaskROI.x = 0; + AIMaskROI.y = 0; + AIresult(AIMaskROI).setTo(0, m_DetImgMask(remROI)); + } + else + { + AIresult.setTo(0, m_DetImgMask(Roi)); + } + + if (i >= det_SmallImgNum) + { + + AIresult.copyTo(m_127CellAIMask(Roi)); + } + else + { + + AIresult.copyTo(m_127CellAIMask(Roi), AIresult); + } + } + } + + if (badd) + { + cv::Mat temresult; + m_127CellAIMask(tem_ROI).copyTo(temresult); + m_127CellAIMask = temresult.clone(); + } + if (DetImgInfo_shareP->otherValue == 9) + { + if (!m_127CellAIMask.empty()) + { + cv::imwrite("ReCheck127CellMask.png", m_127CellAIMask); + } + } + // + memset(&blobs_127, 0x00, sizeof(ERROR_DOTS_BLOBS)); + + unsigned char *pGrayErrordata = (unsigned char *)m_127CellAIMask.data; + unsigned char *pImgdata = (unsigned char *)DetImage.data; + + int width = DetImage.cols; + int height = DetImage.rows; + GetBlobs_V2(&blobs_127, pImgdata, pGrayErrordata, width, height, 0, 1); + printf("blobs_127-----: %d \n", blobs.blobCount); + CalBLobMean_GrayDis_127Cell(); + + if (blobs.blobCount < _MAX_ERROR_DOT_BLOB) + { + for (int i = 0; i < blobs_127.blobCount; i++) + { + + int ncount = blobs.blobCount; + if (ncount < _MAX_ERROR_DOT_BLOB) + { + memcpy(&blobs.blobTab[ncount], &blobs_127.blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA)); + blobs.blobCount++; + } + } + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "ReCheck127Cell", "Blob Num %d", blobs_127.blobCount); + m_TemCheck.temImgList[TEM_IMG_IDX_AImask].setTo(180, m_127CellAIMask); + + if (true && DetImgInfo_shareP->otherValue == 9) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "info", "Save 127cell Tem Img"); + cv::Mat tm; + cv::cvtColor(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop], tm, cv::COLOR_GRAY2RGB); // 彩色 可选项 + for (int i = 0; i < blobs_127.blobCount; i++) + { + cv::Rect roi; + roi.x = blobs_127.blobTab[i].minx; + roi.y = blobs_127.blobTab[i].miny; + roi.width = blobs_127.blobTab[i].maxx - blobs_127.blobTab[i].minx + 1; + roi.height = blobs_127.blobTab[i].maxy - blobs_127.blobTab[i].miny + 1; + + cv::rectangle(tm, roi, cv::Scalar(0, 0, 255)); + + printf("type: %d %d %d %d %d %d %d\n", blobs_127.blobTab[i].ErrType, blobs_127.blobTab[i].area, blobs_127.blobTab[i].energy, roi.x, roi.y, roi.width, roi.height); + } + cv::imwrite("ReCheck127Cell.png", tm); + } + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "ReCheck127Cell", "Det End"); + return 0; +} + +int ImgCheckAnalysisy::DetResultToJson() +{ + + return 0; +} + +int ImgCheckAnalysisy::DrawOther() +{ + + if (m_OtherResult.WTB_Check_Result.roi_show.width > 0 || m_OtherResult.WTB_Check_Result.roi_show.height > 0) + { + cv::rectangle(m_CheckResult_shareP->resultimg, m_OtherResult.WTB_Check_Result.roi_show, cv::Scalar(255, 0, 0)); + } + if ((m_pBasicConfig->bDrawShieldRoi || (m_pFuntion && m_pFuntion->function.f_ShieldRegion.bDraw)) && !m_ShieldImg_resize.empty()) + { + m_CheckResult_shareP->resultimg += m_ShieldImg_resize; + } + + cv::Mat image_draw = m_CheckResult_shareP->resultimg; + + for (int i = 0; i < m_Draw_qxImageResult.size(); i++) + { + if (m_Draw_qxImageResult.at(i).idx < 0) + { + continue; + } + + m_DrawImg.DrawInfoImg_Src(image_draw, m_Draw_qxImageResult.at(i).resizeImgroi, + m_Draw_qxImageResult.at(i).idx, + m_Draw_qxImageResult.at(i).type, + m_Draw_qxImageResult.at(i).area, + m_Draw_qxImageResult.at(i).energy, + m_Draw_qxImageResult.at(i).max_v, + m_Draw_qxImageResult.at(i).hj, + m_Draw_qxImageResult.at(i).len, + DrawImg::Draw_Type_Other, m_Draw_qxImageResult.at(i).strTypeName, m_Draw_qxImageResult.at(i).qx_Code, + m_Draw_qxImageResult.at(i).qx_type, + m_Draw_qxImageResult.at(i).qx_num, + m_Draw_qxImageResult.at(i).density, m_bstatus_ReJson); + } + // printf("--------------m_pBasicConfig->bDrawPreRoi %d roi size %ld \n", m_pBasicConfig->bDrawPreRoi, m_DetRoiList.roiList_Show.size()); + // 绘制弱化框 + if (m_pBasicConfig->bDrawPreRoi) + { + int k = 0; + for (const auto &polygon : m_DetRoiList.roiList_Show) + { + k++; + if (k == 1) + { + continue; + /* code */ + } + // std::cout << polygon << std::endl; + + // 绘制多边形的边界(不填充),使用绿色线条,线宽为2 + cv::polylines(m_CheckResult_shareP->resultimg, polygon, true, cv::Scalar(128, 255, 0), 1); // true表示闭合多边形 + } + // cv::imwrite(DetImgInfo_shareP->strChannel + "roi_src.png", m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc]); + // cv::imwrite(DetImgInfo_shareP->strChannel + "roi_ss.png", m_TemCheck.temImgList[TEM_IMG_IDX_Result]); + + // getchar(); + } + + // 绘制对齐 + if (ImageDet_shareP && ImageDet_shareP->alignResult.bDet && ImageDet_shareP->alignResult.bDraw) + { + float fs_resize_x = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fs_resize_y = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + + std::vector points; + for (auto point : ImageDet_shareP->alignResult.feature_PointList_DetImg) + { + cv::Point p; + p.x = point.x * fs_resize_x; + p.y = point.y * fs_resize_y; + points.push_back(p); + } + cv::polylines(m_CheckResult_shareP->resultimg, points, true, cv::Scalar(255, 255, 0), 2); + + // cv::Rect droi = ImageDet_shareP->alignResult.Crop_Roi_DetImg; + // droi.x = 0; + // droi.y = 0; + // droi.x *= fs_resize_x; + // droi.width *= fs_resize_x; + + // droi.y *= fs_resize_y; + // droi.height *= fs_resize_y; + + // cv::rectangle(m_CheckResult_shareP->resultimg, droi, cv::Scalar(255, 255, 0)); + } + + return 0; +} + +int ImgCheckAnalysisy::CreateMaskImg() +{ + // 如果mask存在 就不在更新,不然生成mask + if (!m_AnalysisyMaskImg.empty()) + { + // return 1; + } + if (!m_pCommonAnalysisyConfig->mask.empty()) + { + m_AnalysisyMaskImg = m_pCommonAnalysisyConfig->mask; + return 1; + } + + return 0; +} + +int ImgCheckAnalysisy::SetInDetConfig() +{ + m_qx_Analysis.InitConfig(); + for (int i = 0; i < CONFIG_QX_NAME_count; i++) + { + int paramIdx = m_QxInParamListIdx[i]; + if (paramIdx < 0) + { + continue; + } + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + int qxidx = ConfigTypeToQXAnalysis(i); + if (qxidx < 0) + { + continue; + } + if (i == CONFIG_QX_NAME_X_line || i == CONFIG_QX_NAME_Y_line || i == CONFIG_QX_NAME_Fangge) + { + continue; + } + + for (int j = 0; j < pParam->useNum; j++) + { + bool result = true; + if (!pParam->paramArr[j].bEnable) + { + continue; + } + QXAnalysis_Config temconfig; + temconfig.area = pParam->paramArr[j].area; + temconfig.dis = pParam->paramArr[j].dis; + temconfig.num = pParam->paramArr[j].num; + temconfig.len = pParam->paramArr[j].length; + temconfig.hj = pParam->paramArr[j].hj; + temconfig.density = pParam->paramArr[j].density; + temconfig.bok = pParam->paramArr[j].bOk; + temconfig.sum_area = pParam->paramArr[j].area_max; + m_qx_Analysis.SetConfig(qxidx, temconfig); + } + } + + // int paramIdx = m_QxInParamListIdx[config_qx_type]; + // if (paramIdx < 0) + // { + // m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "qx error", " paramIdx < 0 "); + // continue; + // } + + // for (int ict = 0; ict < ANALYSIS_TYPE_COUNT; ict++) + // { + // std::string str_checkflag = "QX-check"; + // checkFlage = ict; + // if (ict == ANALYSIS_TYPE_YS) + // { + // str_checkflag = "YS-check"; + // } + // m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "info", " %s start", str_checkflag.c_str()); + + // CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ict].checkConfig_Regions_Param.at(paramIdx); + + return 0; +} + +int ImgCheckAnalysisy::UPdateLDConfig() +{ + + for (int i = 0; i < CONFIG_QX_NAME_count; i++) + { + if (i != CONFIG_QX_NAME_LD) + { + continue; + } + int paramIdx = m_QxInParamListIdx[i]; + if (paramIdx < 0) + { + continue; + } + + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + for (int j = 0; j < pParam->useNum; j++) + { + if (!pParam->paramArr[j].bEnable) + { + continue; + } + m_LDConfig.minArea = pParam->paramArr[j].area; + m_LDConfig.maxArea = pParam->paramArr[j].area_max; + m_LDConfig.hj = pParam->paramArr[j].hj; + m_LDConfig.buse = true; + } + } + for (int i = 0; i < CONFIG_QX_NAME_count; i++) + { + if (i != CONFIG_QX_NAME_LD_WTB) + { + continue; + } + int paramIdx = m_QxInParamListIdx[i]; + if (paramIdx < 0) + { + continue; + } + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + for (int j = 0; j < pParam->useNum; j++) + { + if (!pParam->paramArr[j].bEnable) + { + continue; + } + m_LD_WTBConfig.minArea = pParam->paramArr[j].area; + m_LD_WTBConfig.maxArea = pParam->paramArr[j].area_max; + m_LD_WTBConfig.hj = pParam->paramArr[j].hj; + m_LD_WTBConfig.buse = true; + } + } + for (int i = 0; i < CONFIG_QX_NAME_count; i++) + { + if (i != CONFIG_QX_NAME_LD_HS) + { + continue; + } + int paramIdx = m_QxInParamListIdx[i]; + if (paramIdx < 0) + { + continue; + } + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + for (int j = 0; j < pParam->useNum; j++) + { + if (!pParam->paramArr[j].bEnable) + { + continue; + } + m_LD_HSConfig.minArea = pParam->paramArr[j].area; + m_LD_HSConfig.maxArea = pParam->paramArr[j].area_max; + m_LD_HSConfig.hj = pParam->paramArr[j].hj; + m_LD_HSConfig.buse = true; + } + } + + return 0; +} + +int ImgCheckAnalysisy::AddQXResult(cv::Rect qx_roi_src, cv::Rect qx_roi_resize, int qx_type, float fJudgArea, float fenergy, float fgrayDis, cv::Mat YX_AI_InImg, cv::Mat YX_AI_OUTImg) +{ + // 确认错误类别 + QXImageResult tem; + cv::Rect CutRoi = GetCutRoi(qx_roi_src, m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop]); + tem.srcImg = m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc](CutRoi).clone(); + + cv::Size sz = cv::Size(QX_SAMLLIMG_WIDTH, QX_SAMLLIMG_HEIGHT); + cv::resize(m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop](CutRoi), tem.resizeImg, sz); + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + + float flen = qx_roi_src.width * fs_x; + if (qx_roi_src.height * fs_y > flen) + { + flen = qx_roi_src.height * fs_y; + } + + tem.type = qx_type; + int nerrortype = 1; + // 生成缺陷小图 + if (nerrortype != 0) + { + tem.area = fJudgArea; + tem.energy = fenergy; + tem.hj = fgrayDis; + tem.strTypeName = QX_Result_Names[tem.type]; + tem.qx_Code = QX_Result_Code[tem.type]; + tem.srcImgroi = qx_roi_src; + tem.len = flen; + + tem.resizeImgroi = qx_roi_resize; + + tem.x_pixel = qx_roi_src.x + qx_roi_src.width * 0.5; + tem.y_pixel = qx_roi_src.y + qx_roi_src.height * 0.5; + + tem.x_mm = tem.x_pixel * fs_x; + tem.y_mm = tem.y_pixel * fs_y; + + tem.CutImgroi = qx_roi_src; + tem.CutImgroi.x -= CutRoi.x; + tem.CutImgroi.y -= CutRoi.y; + + m_CheckResult_shareP->defectResultList[tem.type].nresult = 1; + m_CheckResult_shareP->defectResultList[tem.type].keyName = QX_Result_Names[tem.type]; + m_CheckResult_shareP->defectResultList[tem.type].keyCode = QX_Result_Code[tem.type]; + m_CheckResult_shareP->defectResultList[tem.type].num++; + + if (m_CheckResult_shareP->nresult <= ERROR_TYPE_OK) + { + m_CheckResult_shareP->nresult = tem.type; + } + tem.AI_in_Img = YX_AI_InImg; + tem.AI_out_img = YX_AI_OUTImg; + m_CheckResult_shareP->qxImageResult.push_back(tem); + } + return 0; +} + +int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType, cv::Rect qx_roi) +{ + // CONFIG_QX_NAME_ok_yisi, // 疑似 + // CONFIG_QX_NAME_AD_YX, // AD异显(P6873) + // CONFIG_QX_NAME_X_line, // X_line(P3351) + // CONFIG_QX_NAME_Y_line, // Y_line(P3452) + // CONFIG_QX_NAME_Broken_line, // 断线(P3379) + // CONFIG_QX_NAME_zara, // ZARA(P1153) + // CONFIG_QX_NAME_MTX, // MTX(P1164) + // CONFIG_QX_NAME_POL_Cell, // 异物(P1101) + // CONFIG_QX_NAME_LD, // 亮点(P1112) + // CONFIG_QX_NAME_AD, // 暗点(P1111) + // CONFIG_QX_NAME_Scratch_L1, // 一级 轻 划伤(P1557) + // CONFIG_QX_NAME_Scratch_L2, // 二级 严重 划伤(P1557) + // CONFIG_QX_NAME_Dirty_L0, // 疑似浅层脏污(P0000) + // CONFIG_QX_NAME_Dirty_L1, // 轻脏污(P0000) + // CONFIG_QX_NAME_Dirty_L2, // 严重脏污(P0000) + // CONFIG_QX_NAME_qipao, // 气泡(P0001) + // CONFIG_QX_NAME_PS, // ps(P0002) + // CONFIG_QX_NAME_Weak_Bright_Mura, // 白GAP(P1654) + // CONFIG_QX_NAME_No_Label, // 缺POL(P2833) + + int resultError_type = CONFIG_QX_NAME_ok_yisi; + switch (nAIQXType) + { + case AI_CLass_QX_NAME_ok_yisi: + resultError_type = CONFIG_QX_NAME_ok_yisi; + break; + case AI_CLass_QX_NAME_yixian: + resultError_type = CONFIG_QX_NAME_Class_AD_YX; + break; + case AI_CLass_QX_NAME_POL_CEL: + resultError_type = CONFIG_QX_NAME_POL_Cell; + break; + case AI_CLass_QX_NAME_zara: + resultError_type = CONFIG_QX_NAME_zara; + break; + case AI_CLass_QX_NAME_ps: + resultError_type = CONFIG_QX_NAME_PS; + break; + case AI_CLass_QX_NAME_line: + if (qx_roi.width > qx_roi.height) + { + resultError_type = CONFIG_QX_NAME_X_line; + } + else + { + resultError_type = CONFIG_QX_NAME_Y_line; + } + + break; + case AI_CLass_QX_NAME_fangge_line: + resultError_type = CONFIG_QX_NAME_Y_line; + break; + case AI_CLass_QX_NAME_qipao: + resultError_type = CONFIG_QX_NAME_qipao; + break; + case AI_CLass_QX_NAME_qing_huashang: + resultError_type = CONFIG_QX_NAME_Scratch_L1; + break; + case AI_CLass_QX_NAME_mtx: + resultError_type = CONFIG_QX_NAME_MTX; + break; + case AI_CLass_QX_NAME_yisi_qianzangwu: + resultError_type = CONFIG_QX_NAME_Dirty_L0; + break; + case AI_CLass_QX_NAME_qing_zangwu: + resultError_type = CONFIG_QX_NAME_Dirty_L1; + break; + case AI_CLass_QX_NAME_zhong_zangwu: + resultError_type = CONFIG_QX_NAME_Dirty_L2; + break; + case AI_CLass_QX_NAME_andian: + resultError_type = CONFIG_QX_NAME_AD; + break; + case AI_CLass_QX_NAME_huashang: + resultError_type = CONFIG_QX_NAME_Scratch_L1; + break; + case AI_CLass_QX_NAME_zf: + resultError_type = CONFIG_QX_NAME_ok_yisi; + break; + case AI_CLass_QX_NAME_other: + resultError_type = CONFIG_QX_NAME_Other; + break; + default: + break; + } + return resultError_type; +} + +int ImgCheckAnalysisy::ConfigTypeToResultType(int nconfigType) +{ + + // CONFIG_QX_NAME_ok_yisi, // 疑似 + // CONFIG_QX_NAME_AD_YX, // AD异显(P6873) + // CONFIG_QX_NAME_X_line, // X_line(P3351) + // CONFIG_QX_NAME_Y_line, // Y_line(P3452) + // CONFIG_QX_NAME_Broken_line, // 断线(P3379) + // CONFIG_QX_NAME_zara, // ZARA(P1153) + // CONFIG_QX_NAME_MTX, // MTX(P1164) + // CONFIG_QX_NAME_POL_Cell, // 异物(P1101) + // CONFIG_QX_NAME_LD, // 亮点(P1112) + // CONFIG_QX_NAME_AD, // 暗点(P1111) + // CONFIG_QX_NAME_Scratch_L1, // 一级 轻 划伤(P1557) + // CONFIG_QX_NAME_Scratch_L2, // 二级 严重 划伤(P1557) + // CONFIG_QX_NAME_Dirty_L0, // 疑似浅层脏污(P0000) + // CONFIG_QX_NAME_Dirty_L1, // 轻脏污(P0000) + // CONFIG_QX_NAME_Dirty_L2, // 严重脏污(P0000) + // CONFIG_QX_NAME_qipao, // 气泡(P0001) + // CONFIG_QX_NAME_PS, // ps(P0002) + // CONFIG_QX_NAME_Weak_Bright_Mura, // 白GAP(P1654) + // CONFIG_QX_NAME_No_Label, // 缺POL(P2833) + + // ERROR_TYPE_OK, // 0 疑是 + // ERROR_TYPE_AD_YX, // 1 AD-异常显示 + // ERROR_TYPE_Line_X, // 2 x line + // ERROR_TYPE_Line_Y, // 3 y line + // ERROR_TYPE_Rubbing_Mura, // 4 + // ERROR_TYPE_line_Broken, // 5 断线 + // ERROR_TYPE_ZARA, // 6 ZARA + // ERROR_TYPE_MTX, // 7 MTX + // ERROR_TYPE_POL_Cell, // 8 异物 + // ERROR_TYPE_LD, // 9 亮点 + // ERROR_TYPE_AD, // 10 暗点 + // ERROR_TYPE_BD, // 11 黑点 + // ERROR_TYPE_WD, // 12 白点 + // ERROR_TYPE_Scratch, // 13 划伤 + // ERROR_TYPE_Weak_Bright_Mura, // 14 白GAP + // ERROR_TYPE_No_Label, // 15 缺POL + // ERROR_TYPE_PS, // 16 PS + // ERROR_TYPE_GRID_LINE, // 17 方格线 + // ERROR_TYPE_STEAM_POCKET, // 19 气泡 + // ERROR_TYPE_Dirty, // 19 脏污 + + int resultError_type = ERROR_TYPE_OK; + switch (nconfigType) + { + case CONFIG_QX_NAME_ok_yisi: + resultError_type = ERROR_TYPE_OK; + break; + case CONFIG_QX_NAME_AD_YX: + resultError_type = ERROR_TYPE_AD_YX; + break; + case CONFIG_QX_NAME_Class_AD_YX: + resultError_type = ERROR_TYPE_AD_YX; + break; + case CONFIG_QX_NAME_X_line: + resultError_type = ERROR_TYPE_Line_X; + break; + case CONFIG_QX_NAME_Y_line: + resultError_type = ERROR_TYPE_Line_Y; + break; + case CONFIG_QX_NAME_Fangge: + resultError_type = ERROR_TYPE_Line_fangge; + break; + case CONFIG_QX_NAME_Broken_line: + resultError_type = ERROR_TYPE_line_Broken; + break; + case CONFIG_QX_NAME_zara: + resultError_type = ERROR_TYPE_ZARA; + break; + case CONFIG_QX_NAME_MTX: + resultError_type = ERROR_TYPE_MTX; + break; + case CONFIG_QX_NAME_POL_Cell: + resultError_type = ERROR_TYPE_POL_Cell; + break; + case CONFIG_QX_NAME_LD: + resultError_type = ERROR_TYPE_LD; + break; + case CONFIG_QX_NAME_AD: + resultError_type = ERROR_TYPE_AD; + break; + case CONFIG_QX_NAME_Scratch_L1: + resultError_type = ERROR_TYPE_Scratch; + break; + case CONFIG_QX_NAME_Scratch_L2: + resultError_type = ERROR_TYPE_Scratch; + break; + case CONFIG_QX_NAME_Dirty_L0: + resultError_type = ERROR_TYPE_Dirty; + break; + case CONFIG_QX_NAME_Dirty_L1: + resultError_type = ERROR_TYPE_Dirty; + break; + case CONFIG_QX_NAME_Dirty_L2: + resultError_type = ERROR_TYPE_Dirty; + break; + case CONFIG_QX_NAME_qipao: + resultError_type = ERROR_TYPE_STEAM_POCKET; + break; + case CONFIG_QX_NAME_PS: + resultError_type = ERROR_TYPE_PS; + break; + case CONFIG_QX_NAME_Weak_Bright_Mura: + resultError_type = ERROR_TYPE_Weak_Bright_Mura; + break; + case CONFIG_QX_NAME_No_Label: + resultError_type = ERROR_TYPE_No_Label; + break; + case CONFIG_QX_NAME_Other: + resultError_type = ERROR_TYPE_Other; + break; + case CONFIG_QX_NAME_Chess: + resultError_type = ERROR_TYPE_CHESS; + break; + case CONFIG_QX_NAME_127Cell: + resultError_type = ERROR_TYPE_POL_Cell; + break; + case CONFIG_QX_NAME_white_Cell: + resultError_type = ERROR_TYPE_Cell_W; + break; + case CONFIG_QX_NAME_black_Cell: + resultError_type = ERROR_TYPE_Cell_B; + break; + case CONFIG_QX_NAME_LackPOL: + resultError_type = ERROR_TYPE_LackPol; + break; + default: + break; + } + return resultError_type; + return 0; +} + +int ImgCheckAnalysisy::ConfigTypeToQXAnalysis(int nconfigType) +{ + + int QXAnalysis_type = -1; + switch (nconfigType) + { + case CONFIG_QX_NAME_POL_Cell: + QXAnalysis_type = QX_ANALYSIS_POL_CELL; // 异物 + break; + case CONFIG_QX_NAME_AD: + QXAnalysis_type = QX_ANALYSIS_AD; // 暗点 + break; + case CONFIG_QX_NAME_Scratch_L1: + case CONFIG_QX_NAME_Scratch_L2: + QXAnalysis_type = QX_ANALYSIS_Scratch; // 划伤 + break; + case CONFIG_QX_NAME_X_line: + case CONFIG_QX_NAME_Y_line: + case CONFIG_QX_NAME_line: + case CONFIG_QX_NAME_Fangge: + QXAnalysis_type = QX_ANALYSIS_LINE; // 线类 + break; + case CONFIG_QX_NAME_MTX: + QXAnalysis_type = QX_ANALYSIS_MTX; // MTX + break; + // case CONFIG_QX_NAME_Broken_line: + // QXAnalysis_type = QX_ANALYSIS_ALL, // MTX&异物 + // break; + + default: + QXAnalysis_type = -1; + break; + } + return QXAnalysis_type; +} + +bool ImgCheckAnalysisy::IsPointQX(int config_qx_tpe) +{ + if (config_qx_tpe == CONFIG_QX_NAME_LD || + config_qx_tpe == CONFIG_QX_NAME_AD || + config_qx_tpe == CONFIG_QX_NAME_MTX) + { + return true; + } + + return false; +} + +int ImgCheckAnalysisy::GetInstruct(int nInstruct) +{ + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "GetInstruct", "start %d", nInstruct); + + if (int(nInstruct & CHECK_INSTUCT_WhiteAndBlack) == (int)CHECK_INSTUCT_WhiteAndBlack) + { + m_CheckInstruct.bWhiteAndBlack = true; + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "GetInstruct", "CHECK_INSTUCT_WhiteAndBlack open"); + } + + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "GetInstruct", "end"); + + // getchar(); + return 0; +} + +int ImgCheckAnalysisy::GetZfCropMask(cv::Rect roi) +{ + + m_ZF_centerPoint.erase(m_ZF_centerPoint.begin(), m_ZF_centerPoint.end()); + for (size_t i = 0; i < ImageDet_shareP->pZF_roiList->size(); ++i) + { + // 获取当前轮廓的边界矩形 + cv::Rect boundingRect = ImageDet_shareP->pZF_roiList->at(i); + cv::Point p; + p.x = boundingRect.x + boundingRect.width * 0.5f; + p.y = boundingRect.y + boundingRect.height * 0.5f; + // printf("--- zf %d %d %d %d \n", boundingRect.x, boundingRect.y, boundingRect.width, boundingRect.height); + m_ZF_centerPoint.push_back(p); + } + + return 0; +} + +int ImgCheckAnalysisy::ZF_Check(cv::Mat img, cv::Mat &inImg, cv::Mat &maskimg) +{ + + cv::Size sz; + sz.width = AI_ZF_IN_0_IMAGE_WIDTH; + sz.height = AI_ZF_IN_0_IMAGE_HEIGHT; + cv::Mat AIoutimg; + cv::resize(img, inImg, sz, 0, 0, cv::INTER_AREA); + m_AIDeal.AICheck_zf(inImg, AIoutimg); + if (DetImgInfo_shareP->otherValue == 9) + { + if (!inImg.empty()) + { + cv::imwrite("ZF_img_In.png", inImg); + } + if (!AIoutimg.empty()) + { + cv::imwrite("ZF_img_out.png", AIoutimg); + } + } + + { + + float fx = img.cols * 1.0f / AIoutimg.cols; + float fy = img.rows * 1.0f / AIoutimg.rows; + + // 轮廓检测 + std::vector> contours; + findContours(AIoutimg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + m_ImageDetResult_shareP->pZF_roiList = std::make_shared>(); + // 根据面积大小对轮廓进行排序 + sort(contours.begin(), contours.end(), compareContourAreas); + + int kd = 0; + for (size_t i = 0; i < contours.size(); ++i) + { + + // 获取当前轮廓的边界矩形 + cv::Rect boundingRect = cv::boundingRect(contours[i]); + + cv::Rect roi; + roi.x = boundingRect.x * fx; + roi.y = boundingRect.y * fy; + roi.width = boundingRect.width * fx; + roi.height = boundingRect.height * fy; + m_ImageDetResult_shareP->pZF_roiList->push_back(roi); + + if (DetImgInfo_shareP->otherValue == 9) + { + // cv::rectangle(img, roi, cv::Scalar(255, 0, 0)); + } + + kd++; + if (kd >= 2) + { + break; + } + } + if (DetImgInfo_shareP->otherValue == 9) + { + cv::imwrite("ZF_img_result.png", img); + } + } + + // cv::Scalar mean_v1 = cv::mean(inImg); + // int mean1 = mean_v1[0]; + // mean1 += 20; + // if (mean1 < 100) + // { + // mean1 = 100; + // /* code */ + // } + + // cv::Mat temimg; + // cv::threshold(inImg, temimg, mean1, 255, cv::THRESH_BINARY); + + // cv::Mat newmask; + // AIoutimg.copyTo(newmask, temimg); + + // sz.width = img.cols; + // sz.height = img.rows; + + maskimg = AIoutimg; + + // cv::resize(newmask, maskimg, sz, 0, 0, 0); + + // cv::imwrite("ZF_Thresholdimg_out.png", temimg); + // cv::imwrite("ZF_newmask_out.png", newmask); + + // printf("------------zf ------mean1 %dend \n", mean1); + // getchar(); + return 0; +} + +int ImgCheckAnalysisy::YX_Check_L255(cv::Mat cropImg, cv::Mat &inImg, cv::Mat &outmaskimg) +{ + + if (m_pFuntion && m_pFuntion->function.f_YXDet.bOpen) + { + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "function close"); + return 0; + } + int paramIdx = m_QxInParamListIdx[CONFIG_QX_NAME_AD_YX]; + if (paramIdx < 0) + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", " paramIdx < 0 "); + return 0; + } + bool bopenYX = false; + + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "param name %s usenum %d ", pParam->param_name.c_str(), pParam->useNum); + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + bopenYX = true; + break; + } + } + if (bopenYX) + { + + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX ", "Start channel "); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "close Not Check"); + return 1; + } + cv::Mat maskimg; + // cv::Mat inImg; + cv::Size sz; + + sz.width = AI_YX_IN_0_IMAGE_WIDTH; + sz.height = AI_YX_IN_0_IMAGE_HEIGHT; + cv::resize(cropImg, inImg, sz, 0, 0, cv::INTER_AREA); + + if (m_pFuntion && m_pFuntion->function.f_YXDet.strModle == "YX_1") + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "Use YX_1 Model"); + m_AIDeal.AICheck_YX_1(inImg, maskimg); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "Use YX_2 Model"); + m_AIDeal.AICheck_YX_2(inImg, maskimg); + } + + // 定义腐蚀操作的内核 + int kernelSize = 11; // 内核大小 + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(kernelSize, kernelSize)); + + // 执行腐蚀操作 + cv::Mat erodedImage; + cv::erode(maskimg, erodedImage, kernel); + + float fx_src = cropImg.cols * 1.0f / inImg.cols; + float fy_src = cropImg.rows * 1.0f / inImg.rows; + + float fx_Result = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fy_Result = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + + // 轮廓检测 + std::vector> contours; + cv::findContours(erodedImage, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + int nresult = 0; + bool bUse = false; + for (size_t i = 0; i < contours.size(); ++i) + { + + double area = cv::contourArea(contours.at(i)); + double judgeArea = area * m_fImgage_Scale_X * m_fImgage_Scale_Y; + + int curresult = 0; + cv::Rect roi = cv::boundingRect(contours[i]); + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + if (judgeArea > pParam->paramArr[j].area) + { + nresult = 1; + curresult = 1; + } + else + { + } + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "Area== %s -> %f %s %f ", + BOOL_TO_STR(judgeArea > pParam->paramArr[j].area), judgeArea, + BOOL_TO_ThanLess(judgeArea > pParam->paramArr[j].area), pParam->paramArr[j].area); + bUse = true; + if (curresult != 0) + { + break; + } + } + } + } + outmaskimg = erodedImage; + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "AI_Det_YX", "End result = %d", nresult); + + return nresult; +} + +int ImgCheckAnalysisy::UseDPMask(int L0, int nconfigtype, cv::Rect roi, float JudgeArea, int maxV, int hj) +{ + if (!m_pFuntion->function.f_LDConfig.bOpen) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", "function close"); + return 0; + } + // 要使用 DP 的结果 + if (m_pFuntion->function.f_LDConfig.bUseDP) + { + cv::Mat DPMaskImg = ImageDet_shareP->DPMaskImg; + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", "Use Dp Mask"); + if (DPMaskImg.empty()) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", "Error Dp Mask is empty"); + return 0; + } + if (true && DetImgInfo_shareP->otherValue == 9) + { + cv::imwrite("DPMaskImgj.png", DPMaskImg); + // getchar(); + } + + bool bhave = false; + { + + float fiou = CalImgScorl_t(m_TemCheck.temImgList[TEM_IMG_IDX_AImask](roi).clone(), DPMaskImg(roi).clone()); + + // IOU + if (fiou > m_pFuntion->function.f_LDConfig.fDP_IOU) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", " fiou %f > %f ", fiou, m_pFuntion->function.f_LDConfig.fDP_IOU); + bhave = true; + // break; + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", " fiou %f <= %f ", fiou, m_pFuntion->function.f_LDConfig.fDP_IOU); + } + + // m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "UseDPMask", " fiou %f < 0.1 ", fiou); + } + // 上电(L0)有 下电(DP)没有 + if (bhave) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", " L0 = DP "); + return 0; + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", " L0 != DP "); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "LD Analysis", "No Use Dp Mask"); + } + + bool bhave = false; + if (m_pFuntion->function.f_LDConfig.bHSLD) + { + float aT1 = m_LD_HSConfig.minArea; + float aT2 = m_LD_HSConfig.maxArea; + int vT = m_LD_HSConfig.hj; + if (JudgeArea >= aT1 && + JudgeArea <= aT2 && + hj >= vT) + { + bhave = true; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "HS LD check ", "result %s -> JudgeArea %f [%f %f] hj %d %s %d ", + BOOL_TO_STR(bhave), + JudgeArea, aT1, aT2, + hj, BOOL_TO_ThanLess(hj > vT), vT); + } + else if (m_pFuntion->function.f_LDConfig.bWTBLD) + { + float aT1 = m_LD_WTBConfig.minArea; + float aT2 = m_LD_WTBConfig.maxArea; + int vT = m_LD_WTBConfig.hj; + if (JudgeArea >= aT1 && + JudgeArea <= aT2 && + hj >= vT) + { + bhave = true; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "WTB LD check ", "result %s -> JudgeArea %f [%f %f] hj %d %s %d ", + BOOL_TO_STR(bhave), + JudgeArea, aT1, aT2, + hj, BOOL_TO_ThanLess(hj > vT), vT); + } + else + { + float aT1 = m_LDConfig.minArea; + float aT2 = m_LDConfig.maxArea; + int vT = m_LDConfig.hj; + if (JudgeArea >= aT1 && + JudgeArea <= aT2 && + hj >= vT) + { + bhave = true; + } + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "L0 LD check ", "result %s -> JudgeArea %f [%f %f] hj %d %s %d ", + BOOL_TO_STR(bhave), + JudgeArea, aT1, aT2, + hj, BOOL_TO_ThanLess(hj > vT), vT); + } + + if (bhave) + { + return 1; + } + + return 0; +} + +int ImgCheckAnalysisy::GetDetMaskImg(cv::Mat img, cv::Rect cutroi) +{ + if (img.empty()) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "DetMask image is null"); + if (cutroi.width > 0 && cutroi.height > 0) + { + + m_DetImgMask = cv::Mat(cutroi.height, cutroi.width, CV_8UC1, cv::Scalar(0)); + + // printf("11111 %d %d \n",m_DetImgMask.cols,m_DetImgMask.rows); + } + else + { + return 1; + } + } + else + { + m_DetImgMask = img; + } + + return 0; +} + +int ImgCheckAnalysisy::LDJudge(int nconfigtype, cv::Rect roi, float JudgeArea, int maxV, int hj) +{ + + int dbresult = UseDPMask(0, nconfigtype, roi, JudgeArea, maxV, hj); + if (dbresult > 0) + { + return 1; + } + + return 0; +} + +int ImgCheckAnalysisy::GetAIDetImg(cv::Rect Qx_roi, cv::Mat &AI_InImg, cv::Mat &AI_OutImg) +{ + + cv::Point pcenter; + pcenter.x = Qx_roi.x + Qx_roi.width * 0.5; + pcenter.y = Qx_roi.y + Qx_roi.height * 0.5; + + // printf("%d %d \n", pcenter.x, pcenter.y); + + for (int i = 0; i < AI_DetImgList.size(); i++) + { + cv::Rect roi = AI_DetImgList.at(i).Roi; + + if (pcenter.x >= roi.x && pcenter.x <= (roi.x + roi.width) && + pcenter.y >= roi.y && pcenter.y <= (roi.y + roi.height)) + { + // printf("%d %d %d %d \n", roi.x, roi.y, roi.width, roi.height); + // 点 (x, y) 在矩形区域内 + // printf("--------------------------\n"); + AI_InImg = AI_DetImgList.at(i).img.clone(); + AI_OutImg = AI_DetImgList.at(i).outimg.clone(); + } + } + + return 0; +} + +int ImgCheckAnalysisy::GetUpMaskImg(cv::Mat inImg, cv::Mat &maskimg) +{ + + // 定义滑动窗口的大小和步长 + int windowWidth = 128; + int windowHeight = 128; + int stepX = 110; // 横向步长 + int stepY = 110; // 纵向步长 + + maskimg = cv::Mat(inImg.rows, inImg.cols, CV_8U, cv::Scalar(0)); + int sx = 0; + int ex = inImg.cols; + int sy = 0; + int ey = inImg.rows; + + cv::Rect detroi; + detroi.width = windowWidth; + detroi.height = windowHeight; + cv::Rect maskroi; + maskroi.width = windowWidth; + maskroi.height = windowHeight; + cv::Mat temmask; + // 遍历图像,使用滑动窗口 + for (int y = sy; y <= ey; y += stepY) + { + detroi.y = y; + if (detroi.y + windowHeight > ey) + { + detroi.y = ey - windowHeight; + } + maskroi.y = detroi.y - sy; + + for (int x = sx; x <= ex; x += stepX) + { + detroi.x = x; + if (detroi.x + windowWidth > ex) + { + detroi.x = ex - windowWidth; + } + maskroi.x = detroi.x - sx; + int thresholdValue = 30; // 初始阈值,OTSU将自动计算 + int maxVal = 255; // 最大值 + double otsuThreshold; + + cv::Scalar mean, stddev; + cv::meanStdDev(inImg(detroi), mean, stddev); + + int varianceImg; + varianceImg = mean[0] + 1 * mean[0]; + if (mean[0] > 100) + { + continue; + } + + // 使用 OTSU 阈值处理 + otsuThreshold = cv::threshold(inImg(detroi), temmask, thresholdValue, maxVal, cv::THRESH_BINARY | cv::THRESH_OTSU); + thresholdValue = otsuThreshold; + + if (thresholdValue < 30) + { + thresholdValue = 30; + } + if (thresholdValue < varianceImg) + { + thresholdValue = varianceImg; + } + + if (thresholdValue > 100) + { + continue; + } + // std::cout << "varianceImg value is: " << varianceImg << std::endl; + // std::cout << "OTSU threshold value is: " << otsuThreshold << std::endl; + // std::cout << "stddev[0] value is: " << stddev[0] << std::endl; + otsuThreshold = cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY); + // cv::threshold(inImg(detroi), maskimg(maskroi), thresholdValue, maxVal, cv::THRESH_BINARY + cv::THRESH_OTSU); + // 提取当前窗口 + + // cv::rectangle(inImg, detroi, cv::Scalar(255, 0, 0)); + } + } + // cv::imwrite("inImg1123.png", inImg); + // cv::imwrite("maskimg.png", maskimg); + // getchar(); + return 0; +} + +int ImgCheckAnalysisy::UpdateImgageScale(const cv::Mat &srcimg) +{ + if (srcimg.empty()) + { + return 0; + } + + if (m_pBasicConfig->bCal_ImageScale) + { + if (m_pBasicConfig->Product_Size_Width_mm > 0 && + m_pBasicConfig->Product_Size_Height_mm > 0) + { + m_fImgage_Scale_X = m_pBasicConfig->Product_Size_Width_mm * 1.0f / srcimg.cols; + m_fImgage_Scale_Y = m_pBasicConfig->Product_Size_Height_mm * 1.0f / srcimg.rows; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "ImgageScale", "Scale_X %f = Product_Size_Width %f / img cols %d", + m_fImgage_Scale_X, m_pBasicConfig->Product_Size_Width_mm, srcimg.cols); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "ImgageScale", "Scale_Y %f = Product_Size_Height %f / img rows %d", + m_fImgage_Scale_Y, m_pBasicConfig->Product_Size_Height_mm, srcimg.rows); + } + } + else + { + if (m_pBasicConfig->fImage_Scale_x > 0 && m_pBasicConfig->fImage_Scale_x < 1 && + m_pBasicConfig->fImage_Scale_y > 0 && m_pBasicConfig->fImage_Scale_y < 1) + { + + m_fImgage_Scale_X = m_pBasicConfig->fImage_Scale_x; + m_fImgage_Scale_Y = m_pBasicConfig->fImage_Scale_y; + } + } + m_TemCheck.AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "ImgageScale", "Scale_X = %f Scale_Y = %f", m_fImgage_Scale_X, m_fImgage_Scale_Y); + return 0; +} + +int ImgCheckAnalysisy::UpdateSheildMask(std::string strChannel, cv::Rect roi) +{ + int re = 1; + if (m_pFuntion != NULL && m_pFuntion->function.f_ShieldRegion.bOpen) + { + cv::Mat temmask = m_pFuntion->function.f_ShieldRegion.shieldMask; + if (!temmask.empty()) + { + if (CheckUtil::RoiInImg(roi, temmask)) + { + if (DetImgInfo_shareP->other_channel_Result_mask.cols == roi.width && + DetImgInfo_shareP->other_channel_Result_mask.rows == roi.height) + { + DetImgInfo_shareP->other_channel_Result_mask.setTo(255, temmask(roi)); + // cv::imwrite(strChannel+"1.png",DetImgInfo_shareP->other_channel_Result_mask); + // cv::imwrite(strChannel+"2.png",temmask(roi)); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "UpdateSheildMask", "strChannel %s Succ", strChannel.c_str()); + re = 0; + } + else + { + cv::Size sz; + cv::Mat shieldmask; + sz.width = DetImgInfo_shareP->other_channel_Result_mask.cols; + sz.height = DetImgInfo_shareP->other_channel_Result_mask.rows; + cv::resize(temmask(roi), shieldmask, sz, 0, 0, cv::INTER_AREA); + + DetImgInfo_shareP->other_channel_Result_mask.setTo(255, shieldmask); + + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "UpdateSheildMask", "DetImgInfo_shareP shieldmask resize------", strChannel.c_str()); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "UpdateSheildMask", " strChannel %s roi %d %d %d %d != img %d %d error", strChannel.c_str(), + roi.x, roi.y, roi.width, roi.height, temmask.cols, temmask.rows); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "UpdateSheildMask", "strChannel %s m_SheildMask empty error ", strChannel.c_str()); + } + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "UpdateSheildMask", "strChannel %s m_pFuntion is NULL error ", strChannel.c_str()); + } + + return re; +} + +bool ImgCheckAnalysisy::JudgeQXAnalysis(int nqx_configType) +{ + bool re = false; + std::string qx_name = CONFIG_QX_NAME_Names[nqx_configType]; + std::string det_qx = ConfigTypeToWebDetType(nqx_configType); + for (int i = 0; i < m_pFuntion->function.f_BaseDet.DetQXList.size(); i++) + { + std::string strqx = m_pFuntion->function.f_BaseDet.DetQXList.at(i); + if (det_qx == strqx) + { + re = true; + break; + } + } + + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Judge QX ", "det qx %s -> Funtion qx %s open = %s ", qx_name.c_str(), det_qx.c_str(), BOOL_TO_STR(re)); + + return re; +} + +bool ImgCheckAnalysisy::Judge_MarkLine_QX(int nqx_configType, cv::Rect detqx_Roi) +{ + + if (!m_pbaseCheckFunction->markLine.bOpen || !m_pbaseCheckFunction->markLine.bUse_qx_Sheild) + { + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "MarkLine_QX ", "markline qx sheild is close "); + return false; + } + + bool re = false; + std::string qx_name = CONFIG_QX_NAME_Names[nqx_configType]; + std::string det_qx = ConfigTypeToWebDetType(nqx_configType); + for (int i = 0; i < m_pbaseCheckFunction->markLine.sheil_qx_List.size(); i++) + { + std::string strqx = m_pbaseCheckFunction->markLine.sheil_qx_List.at(i); + if (det_qx == strqx) + { + re = true; + break; + } + } + if (!re) + { + return re; + } + if (ImageDet_shareP->markLine_Roi_X.width > 0 && ImageDet_shareP->markLine_Roi_X.height > 0) + { + float ioux = CheckUtil::CalRoi2RoiPre(detqx_Roi, ImageDet_shareP->markLine_Roi_X); + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Judge_MarkLine_QX ", "det qx %s -> markline qx %s x iou %f : %f ", + qx_name.c_str(), det_qx.c_str(), ioux, m_pbaseCheckFunction->markLine.qx_sheild_iou); + + if (ioux > m_pbaseCheckFunction->markLine.qx_sheild_iou) + { + return true; + } + } + if (ImageDet_shareP->markLine_Roi_Y.width > 0 && ImageDet_shareP->markLine_Roi_Y.height > 0) + { + float iouy = CheckUtil::CalRoi2RoiPre(detqx_Roi, ImageDet_shareP->markLine_Roi_Y); + m_TemCheck.AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "Judge_MarkLine_QX ", "det qx %s -> markline qx %s y iou %f : %f ", + qx_name.c_str(), det_qx.c_str(), iouy, m_pbaseCheckFunction->markLine.qx_sheild_iou); + + if (iouy > m_pbaseCheckFunction->markLine.qx_sheild_iou) + { + return true; + } + } + + return false; +} + +std::string ImgCheckAnalysisy::ConfigTypeToWebDetType(int nconfigType) +{ + + // Function_CONFIG_QX_NAME_ok_yisi, // 疑似 + // Function_CONFIG_QX_NAME_YX, // AD异显(P6873) + // Function_CONFIG_QX_NAME_line, // X_line(P3351) + // Function_CONFIG_QX_NAME_zara, // ZARA(P1153) + // Function_CONFIG_QX_NAME_MTX, // MTX(P1164) + // Function_CONFIG_QX_NAME_POL_Cell, // 异物(P1101) + // Function_CONFIG_QX_NAME_LD, // 亮点(P1112) + // Function_CONFIG_QX_NAME_AD, // 暗点(P1111) + // Function_CONFIG_QX_NAME_Scratch, // 划伤(P1557) + // Function_CONFIG_QX_NAME_Dirty, // 脏污(P0000) + // Function_CONFIG_QX_NAME_qipao, // 气泡(P0001) + // Function_CONFIG_QX_NAME_PS, // ps(P0002) + // Function_CONFIG_QX_NAME_Weak_Bright_Mura, // 白GAP(P1654) + // Function_CONFIG_QX_NAME_No_Label, // 缺POL(P2833) + // Function_CONFIG_QX_NAME_Other, // 缺POL(P2833) + // Function_CONFIG_QX_NAME_Chess, // Chess 异常 + // Function_CONFIG_QX_NAME_127Cell, // 白cell + std::string strqx = ""; + switch (nconfigType) + { + case CONFIG_QX_NAME_ok_yisi: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_ok_yisi]; + break; + case CONFIG_QX_NAME_AD_YX: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_YX]; + break; + case CONFIG_QX_NAME_LackPOL: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_YX]; + break; + case CONFIG_QX_NAME_Class_AD_YX: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_YX]; + break; + case CONFIG_QX_NAME_X_line: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_line]; + break; + case CONFIG_QX_NAME_Y_line: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_line]; + break; + case CONFIG_QX_NAME_Fangge: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_line]; + break; + case CONFIG_QX_NAME_Broken_line: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_line]; + break; + case CONFIG_QX_NAME_zara: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_zara]; + break; + case CONFIG_QX_NAME_MTX: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_MTX]; + break; + case CONFIG_QX_NAME_POL_Cell: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_POL_Cell]; + break; + case CONFIG_QX_NAME_LD: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_LD]; + break; + case CONFIG_QX_NAME_AD: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_AD]; + break; + case CONFIG_QX_NAME_Scratch_L1: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Scratch]; + break; + case CONFIG_QX_NAME_Scratch_L2: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Scratch]; + break; + case CONFIG_QX_NAME_Dirty_L0: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Dirty]; + break; + case CONFIG_QX_NAME_Dirty_L1: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Dirty]; + break; + case CONFIG_QX_NAME_Dirty_L2: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Dirty]; + break; + case CONFIG_QX_NAME_qipao: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_qipao]; + break; + case CONFIG_QX_NAME_PS: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_PS]; + break; + case CONFIG_QX_NAME_Weak_Bright_Mura: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Weak_Bright_Mura]; + break; + case CONFIG_QX_NAME_No_Label: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_No_Label]; + break; + case CONFIG_QX_NAME_Other: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Other]; + break; + case CONFIG_QX_NAME_Chess: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Chess]; + break; + case CONFIG_QX_NAME_127Cell: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_127Cell]; + break; + case CONFIG_QX_NAME_white_Cell: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Cell]; + break; + case CONFIG_QX_NAME_black_Cell: + strqx = Function_CONFIG_QX_NAME_Names[Function_CONFIG_QX_NAME_Cell]; + break; + break; + default: + break; + } + return strqx; +} + +int ImgCheckAnalysisy::addInDrawBlob_New(int errortype, int blobidx, QX_ERROR_INFO_ *QX_info, float fs_resize_x, float fs_resize_y) +{ + + if (errortype < 0) + { + for (int i = 0; i < m_Draw_qxImageResult.size(); i++) + { + if (m_Draw_qxImageResult.at(i).idx == blobidx) + { + m_Draw_qxImageResult.at(i).idx = -1; + } + } + } + else + { + if (QX_info->JudgArea < 0.01) + { + return 0; + } + + QXImageResult tem; + cv::Rect roi = QX_info->roi; + + int nqx_type = ConfigTypeToResultType(errortype); + tem.type = nqx_type; + tem.area = QX_info->JudgArea; + tem.energy = QX_info->energy; + tem.hj = QX_info->grayDis; + tem.max_v = QX_info->maxValue; + tem.density = QX_info->density; + tem.strTypeName = QX_Result_Names[nqx_type]; + tem.qx_Code = QX_Result_Code[nqx_type]; + + tem.srcImgroi = roi; + tem.len = QX_info->flen; + + tem.qx_type = QX_ERROR_TYPE_AREA; + + tem.resizeImgroi.x = roi.x * fs_resize_x; + tem.resizeImgroi.width = roi.width * fs_resize_x; + tem.resizeImgroi.y = roi.y * fs_resize_y; + tem.resizeImgroi.height = roi.height * fs_resize_y; + + tem.x_pixel = roi.x + roi.width * 0.5; + tem.y_pixel = roi.y + roi.height * 0.5; + tem.idx = blobidx; + + m_Draw_qxImageResult.push_back(tem); + } + + return 0; +} + +int ImgCheckAnalysisy::InitOtherDet() +{ + return 0; +} + +int ImgCheckAnalysisy::OtherDetect() +{ + + return 0; +} + +int ImgCheckAnalysisy::Detect_LackPol(const cv::Mat &DetImage) +{ + if (m_pFuntion && m_pFuntion->function.f_Dectect_LackPol.bOpen) + { + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "Close"); + return 0; + } + int paramIdx = m_QxInParamListIdx[CONFIG_QX_NAME_LackPOL]; + if (paramIdx < 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", " paramIdx < 0 "); + return 1; + } + bool bopenYX = false; + + CheckConfig_Regions_Param *pParam = &m_pRegionAnalysisyParam->checkConfig_Regions_type[ANALYSIS_TYPE_TF].checkConfig_Regions_Param.at(paramIdx); + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "param name %s parmm Num %d ", pParam->param_name.c_str(), pParam->useNum); + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + bopenYX = true; + break; + } + } + if (bopenYX) + { + // m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "AI_Det_YX", "Start"); + } + else + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "YX Param close , Stop Detect"); + return 1; + } + LackPolDet::DetConfig detcofig; + detcofig.detMaskImg = m_DetImgMask; + detcofig.strChannel = DetImgInfo_shareP->strChannel; + detcofig.fImgage_Scale_X = m_fImgage_Scale_X; + detcofig.fImgage_Scale_Y = m_fImgage_Scale_Y; + if (DetImgInfo_shareP->otherValue == 9) + { + detcofig.bSaveResultImg = true; + } + cv::Mat detMask; + int re = m_LackPolDet.Detect(DetImage, &detcofig, detMask); + if (re != 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "Detect Error %d , Stop Detect", re); + return re; + } + + // det To src + float fx_src = DetImage.cols * 1.0f / str_AI_LOSSPOL_IN_0_IMAGE_WIDTH; + float fy_src = DetImage.rows * 1.0f / str_AI_LOSSPOL_IN_0_IMAGE_HEIGHT; + + // src To show + float fx_Result = m_TemCheck.temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].cols; + float fy_Result = m_TemCheck.temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_TemCheck.temImgList[TEM_IMG_IDX_SrcCrop].rows; + + // 轮廓检测 + std::vector> contours; + cv::findContours(detMask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); + int nresult = 0; + bool bUse = false; + for (size_t i = 0; i < contours.size(); ++i) + { + + double area = cv::contourArea(contours.at(i)); + double judgeArea = area * fx_src * fy_src * m_fImgage_Scale_X * m_fImgage_Scale_Y; + + int curresult = 0; + cv::Rect roi = cv::boundingRect(contours[i]); + cv::Mat temMask = detMask(roi); + roi.x *= fx_src; + roi.width *= fx_src; + + roi.y *= fy_src; + roi.height *= fy_src; + + for (int j = 0; j < pParam->useNum; j++) + { + if (pParam->paramArr[j].bEnable) + { + if (judgeArea > pParam->paramArr[j].area) + { + nresult = 1; + curresult = 1; + } + else + { + } + m_TemCheck.AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "Detect_LackPol", "Area== %s -> %f %s %f ", + BOOL_TO_STR(judgeArea > pParam->paramArr[j].area), judgeArea, + BOOL_TO_ThanLess(judgeArea > pParam->paramArr[j].area), pParam->paramArr[j].area); + bUse = true; + if (curresult != 0) + { + break; + } + } + } + + if (curresult != 0) + { + float flen = 0; + { + + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + + flen = roi.width * fs_x; + if (roi.height * fs_y > flen) + { + flen = roi.height * fs_y; + } + } + float energy = area * fx_src * fy_src; + + if (true) + { + QX_ERROR_INFO_ temerror; + temerror.roi = roi; + temerror.Idx = i; + temerror.area = area; + temerror.JudgArea = judgeArea; + temerror.energy = energy; + temerror.flen = flen; + temerror.nconfig_qx_type = CONFIG_QX_NAME_LackPOL; + temerror.qx_name = CONFIG_QX_NAME_Names[CONFIG_QX_NAME_LackPOL]; + temerror.maxValue = 0; + temerror.grayDis = 255; + temerror.fUpIou = 0; + temerror.density = 0; + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->push_back(temerror); + // printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen); + } + + int nqx_type = ConfigTypeToResultType(CONFIG_QX_NAME_LackPOL); + cv::Rect roi_src = roi; + cv::Rect roi_resize; + roi_resize.x = roi_src.x * fx_Result; + roi_resize.y = roi_src.y * fy_Result; + roi_resize.width = roi_src.width * fx_Result; + roi_resize.height = roi_src.height * fy_Result; + + for (int j = 0; j < contours.at(i).size(); ++j) + { + contours.at(i).at(j).x *= fx_src; + contours.at(i).at(j).y *= fy_src; + } + cv::drawContours(m_TemCheck.temImgList[TEM_IMG_IDX_DrawSrc], contours, i, cv::Scalar(0, 255, 255), 2); // thickness为-1时为填充整个轮 + + for (int j = 0; j < contours.at(i).size(); ++j) + { + contours.at(i).at(j).x *= fx_Result; + contours.at(i).at(j).y *= fy_Result; + } + cv::drawContours(m_TemCheck.temImgList[TEM_IMG_IDX_Result], contours, i, cv::Scalar(0, 255, 255)); // thickness为-1时为填充整个轮 + AddQXResult(roi_src, roi_resize, nqx_type, judgeArea, energy, 255, DetImage(roi), temMask); + // printf("1111\n"); + // cv::imwrite("Yx_img_result123.png", m_TemCheck.temImgList[TEM_IMG_IDX_Result]); + // getchar(); + } + } + if (contours.size() <= 0) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "blob is empty"); + } + else + { + if (!bUse) + { + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "Error param Is NULL"); + } + } + + m_OtherResult.result_LackPol.nresult = nresult; + m_TemCheck.AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Detect_LackPol", "End result = %d", nresult); + + return 0; +} + +int ImgCheckAnalysisy::addInDrawBlob(int errortype, int blobidx, ERROR_DOTS_BLOB_DATA *blob, float fs_resize_x, float fs_resize_y) +{ + if (errortype < 0) + { + for (int i = 0; i < m_Draw_qxImageResult.size(); i++) + { + if (m_Draw_qxImageResult.at(i).idx == blobidx) + { + m_Draw_qxImageResult.at(i).idx = -1; + } + } + } + else + { + if (blob->JudgArea < 0.05) + { + return 0; + } + + QXImageResult tem; + + cv::Rect roi; + roi.x = blob->minx; + roi.y = blob->miny; + roi.width = blob->maxx - blob->minx + 1; + roi.height = blob->maxy - blob->miny + 1; + + int nqx_type = ConfigTypeToResultType(errortype); + tem.type = nqx_type; + tem.area = blob->JudgArea; + tem.energy = blob->energy; + tem.hj = blob->grayDis; + tem.max_v = blob->maxValue; + tem.density = blob->density; + tem.strTypeName = QX_Result_Names[nqx_type]; + tem.qx_Code = QX_Result_Code[nqx_type]; + + tem.srcImgroi = roi; + tem.len = blob->len; + + tem.qx_type = QX_ERROR_TYPE_AREA; + + tem.resizeImgroi.x = roi.x * fs_resize_x; + tem.resizeImgroi.width = roi.width * fs_resize_x; + tem.resizeImgroi.y = roi.y * fs_resize_y; + tem.resizeImgroi.height = roi.height * fs_resize_y; + + tem.x_pixel = roi.x + roi.width * 0.5; + tem.y_pixel = roi.y + roi.height * 0.5; + tem.idx = blobidx; + + m_Draw_qxImageResult.push_back(tem); + } + + return 0; +} + +int ImgCheckAnalysisy::CalBlobDensity_QX() +{ + float fs_x = m_fImgage_Scale_X; + float fs_y = m_fImgage_Scale_Y; + double dis_T = m_pBasicConfig->density_R_mm; + if (dis_T <= 0 || dis_T > 99999) + { + dis_T = 5; + } + + if (blobs.blobCount <= 0) + { + return 0; + } + for (int i = 0; i < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); i++) + { + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).density = 1; + + if (m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_MTX || + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_POL_Cell || + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_LD || + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_AD) + { + /* code */ + } + else + { + continue; + } + + // QX_ERROR_INFO_ *QX_info = &m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i); + cv::Rect roi = m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).roi; + + cv::Point p; + p.x = roi.x + roi.width * 0.5; + p.y = roi.y + roi.height * 0.5; + + int num = 1; + double sum_dis = 0; + + for (int j = 0; j < m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->size(); j++) + { + if (i == j) + { + continue; + } + if (m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_MTX || + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_POL_Cell || + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_LD || + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_AD) + { + /* code */ + } + else + { + continue; + } + cv::Rect roi123 = m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(j).roi; + ; + + cv::Point p123; + p123.x = roi123.x + roi123.width * 0.5; + p123.y = roi123.y + roi123.height * 0.5; + + double dis_x = std::abs(p123.x - p.x) * fs_x; + double dis_y = std::abs(p123.y - p.y) * fs_y; + double dis = std::sqrt(dis_x * dis_x + dis_y * dis_y); + if (dis > dis_T) + { + continue; + } + num++; + sum_dis += dis; + // printf("111111111111111111111111111111 %d %f %f\n",num,sum_dis,dis_T); + } + + float avdis = dis_T; + if (num > 1) + { + avdis = sum_dis / (num - 1); + } + float fScore = (dis_T - avdis) / dis_T; + + double fD = num + fScore; + // printf("11111111111111112222222222222211111111111111 %d %f \n",num,fD); + m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).density = fD; + // printf("11111111111111112222222222222211111111111111 %f \n", m_ImageDetResult_shareP->pOneImgDetResult->pQx_ErrorList->at(i).density); + } + + return 0; +} diff --git a/AlgorithmModule/src/ImgCheckBase.cpp b/AlgorithmModule/src/ImgCheckBase.cpp new file mode 100644 index 0000000..2def4df --- /dev/null +++ b/AlgorithmModule/src/ImgCheckBase.cpp @@ -0,0 +1,21 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ImgCheckBase.h" +#include "ImgCheckAnalysisy.hpp" +#include "ImgCheckConfig.h" +#include "ALLImgCheckAnalysisy.hpp" +ALLImgCheckBase *ALLImgCheckBase::instance = nullptr; +ALLImgCheckBase *ALLImgCheckBase::GetInstance() +{ + // if (instance == nullptr) + // { + // instance = (ALLImgCheckBase *)new ALLImgCheckAnalysisy(); + // } + return (ALLImgCheckBase *)new ALLImgCheckAnalysisy();; +} diff --git a/AlgorithmModule/src/OtherDetect.cpp b/AlgorithmModule/src/OtherDetect.cpp new file mode 100644 index 0000000..bc5e852 --- /dev/null +++ b/AlgorithmModule/src/OtherDetect.cpp @@ -0,0 +1,103 @@ + +#include "OtherDetect.h" +#include "CheckErrorCodeDefine.hpp" + +AIDetectBase ::AIDetectBase(/* args */) +{ + m_pOtherDet_Config = NULL; + m_pAIDeal = NULL; + m_bInitialized = false; + m_bModelSucc = false; +} + +AIDetectBase ::~AIDetectBase() +{ +} +int AIDetectBase ::Init(OtherDet_Config *pOtherDet_Config) +{ + m_pOtherDet_Config = pOtherDet_Config; + m_pAIDeal = pOtherDet_Config->pAIDeal; + m_pTemCheck = pOtherDet_Config->pTemCheck; + m_bInitialized = true; + return 0; +} + +LackPolDet::LackPolDet(/* args */) +{ +} + +LackPolDet::~LackPolDet() +{ +} +int LackPolDet::Init_LackPol() +{ + + AIInitConfig config_nf; + config_nf.nGpuIdx = m_pOtherDet_Config->nDeviceId; + config_nf.engine_file_path = str_AI_LOSSPOL_Model_Path; + config_nf.bufferList[0].ntype = AIBufferType_IN; + config_nf.bufferList[0].ndatalength = str_AI_LOSSPOL_IN_0_DATA_LENGTH; + + config_nf.bufferList[1].ntype = AIBufferType_OUT; + config_nf.bufferList[1].ndatalength = str_AI_LOSSPOL_out_0_DATA_LENGTH; + + int re = m_pAIDeal->Init_LackPol(config_nf); + + return re; +} +int LackPolDet::InitModel_ALL() +{ + m_bModelSucc = false; + int re = Init_LackPol(); + if (re != 0) + { + printf("AI_Edge_Algin Init_LackPol Error \n"); + return re; + } + m_bModelSucc = true; + return 0; +} +int LackPolDet::Detect(const cv::Mat &img, DetConfig *pDetConfig, cv::Mat &outMask) +{ + cv::Mat inImg; + cv::Size sz; + cv::Mat detmask_size; + if (pDetConfig == NULL) + { + return 1; + } + if (img.empty()) + { + return 2; + } + if (pDetConfig->detMaskImg.empty()) + { + return 3; + } + if (!m_bModelSucc) + { + return 4; + } + + sz.width = str_AI_LOSSPOL_IN_0_IMAGE_WIDTH; + sz.height = str_AI_LOSSPOL_IN_0_IMAGE_HEIGHT; + + cv::resize(img, inImg, sz, 0, 0, cv::INTER_AREA); + cv::resize(pDetConfig->detMaskImg, detmask_size, sz, 0, 0, cv::INTER_AREA); + m_pAIDeal->AICheck_LackPol(inImg, outMask); + + if (pDetConfig->bSaveResultImg) + { + if (!inImg.empty()) + { + cv::imwrite(pDetConfig->strChannel + "_LackPol_In.png", inImg); + } + if (!outMask.empty()) + { + cv::imwrite(pDetConfig->strChannel + "_LackPol_out.png", outMask); + } + } + + outMask.setTo(0, detmask_size); + return 0; +} \ No newline at end of file diff --git a/AlgorithmModule/src/QX_Analysis.cpp b/AlgorithmModule/src/QX_Analysis.cpp new file mode 100644 index 0000000..0081d3c --- /dev/null +++ b/AlgorithmModule/src/QX_Analysis.cpp @@ -0,0 +1,534 @@ + +#include "QX_Analysis.h" +#include "CheckErrorCodeDefine.hpp" +QX_Analysis::QX_Analysis(/* args */) +{ +} + +QX_Analysis::~QX_Analysis() +{ +} + +void QX_Analysis::SetConfig(int qxidx, QXAnalysis_Config config) +{ + if (!Idx(qxidx)) + { + return; + } + // printf("SetConfig type %d %s add \n", qxidx, QX_ANALYSIS_NAME_Names[qxidx].c_str()); + config.print(QX_ANALYSIS_NAME_Names[qxidx]); + m_ConfigList[qxidx].configlsit.push_back(config); +} + +void QX_Analysis::InitConfig() +{ + for (int i = 0; i < QX_ANALYSIS_COUNT; i++) + { + m_ConfigList[i].Init(); + } +} + +bool QX_Analysis::AddQxInfo(int qxidx, QX_Info qxinfo) +{ + if (!Idx(qxidx)) + { + return false; + } + // printf("AddQxInfo type %d %s add \n", qxidx, QX_ANALYSIS_NAME_Names[qxidx].c_str()); + // qxinfo.print(QX_ANALYSIS_NAME_Names[qxidx]); + + // 初步筛选一次 + bool badd = false; + for (int i = 0; i < (int)m_ConfigList[qxidx].configlsit.size(); i++) + { + QXAnalysis_Config *pconfig = &m_ConfigList[qxidx].configlsit.at(i); + // 面积 灰阶满足要求 + if (qxinfo.area >= pconfig->area && + qxinfo.hj >= pconfig->hj && + qxinfo.length >= pconfig->len && + qxinfo.density >= pconfig->density) + { + + badd = true; + } + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "preA", "add = %s congfig idx %d / %d ", BOOL_TO_STR(badd), i, (int)m_ConfigList[qxidx].configlsit.size()); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(qxinfo.area >= pconfig->area), qxinfo.area, BOOL_TO_ThanLess(qxinfo.area >= pconfig->area), pconfig->area); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "HJ", "%s -> %f %s %d ", + BOOL_TO_STR(qxinfo.hj >= pconfig->hj), qxinfo.hj, BOOL_TO_ThanLess(qxinfo.hj >= pconfig->hj), pconfig->hj); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(qxinfo.length >= pconfig->len), qxinfo.length, BOOL_TO_ThanLess(qxinfo.length >= pconfig->len), pconfig->len); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "md", "%s -> %f %s %f ", + BOOL_TO_STR(qxinfo.density >= pconfig->density), qxinfo.density, BOOL_TO_ThanLess(qxinfo.density >= pconfig->density), pconfig->density); + + if (badd) + { + break; + /* code */ + } + } + if (badd) + { + m_QXList[qxidx].qxList.push_back(qxinfo); + } + return badd; +} + +int QX_Analysis::Init() +{ + for (int i = 0; i < QX_ANALYSIS_COUNT; i++) + { + m_QXList[i].Init(); + } + m_reultList.Init(); + return 0; +} + +int QX_Analysis::GetReusult(QX_Analysis_Result_List *&presult) +{ + m_pTemCheck->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "==========Start========"); + // 分析每一个缺陷类型 + for (int i = 0; i < QX_ANALYSIS_COUNT; i++) + { + if (QX_ANALYSIS_POL_CELL != i && QX_ANALYSIS_AD != i && QX_ANALYSIS_MTX != i && QX_ANALYSIS_Scratch != i && QX_ANALYSIS_LINE != i) + { + continue; + } + if (m_QXList[i].qxList.size() <= 0 || m_ConfigList[i].configlsit.size() <= 0) + { + continue; + } + + m_pTemCheck->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "%s start", QX_ANALYSIS_NAME_Names[i].c_str()); + Analysis(&m_ConfigList[i], &m_QXList[i], i); + m_pTemCheck->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "%s end", QX_ANALYSIS_NAME_Names[i].c_str()); + } + + presult = &m_reultList; + + m_pTemCheck->AddCheckstr(PrintLevel_0, 3, "Num And Dis Judge", "==========End ======== Add New QX Num = %d", m_reultList.resultList.size()); + return 0; +} + +bool QX_Analysis::Idx(int qxidx) +{ + if (qxidx < 0 || qxidx >= QX_ANALYSIS_COUNT) + { + return false; + } + return true; +} + +int QX_Analysis::Analysis(QX_Config_List *pconfigList, QX_ALL_List *pqxList, int qx_type) +{ + for (int i = 0; i < (int)pconfigList->configlsit.size(); i++) + { + m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "param %d / %d Analysis start ", i, (int)pconfigList->configlsit.size()); + Analysis_s(&pconfigList->configlsit.at(i), pqxList, qx_type); + // m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "param %d / %d Analysis end ", i, (int)pconfigList->configlsit.size()); + } + if (qx_type == QX_ANALYSIS_AD) + { + m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", " AD Num Deal"); + for (int i = 0; i < (int)pconfigList->configlsit.size(); i++) + { + m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "param %d / %d AD Num start ", i, (int)pconfigList->configlsit.size()); + Analysis_AD_Num(&pconfigList->configlsit.at(i), pqxList, qx_type); + // m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "param %d / %d AD Num end ", i, (int)pconfigList->configlsit.size()); + } + } + if (qx_type == QX_ANALYSIS_POL_CELL) + { + m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", " POL_CELL Num Deal"); + for (int i = 0; i < (int)pconfigList->configlsit.size(); i++) + { + m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "param %d / %d POL_CELL Num %d start ", i, (int)pconfigList->configlsit.size(),(int)pqxList->qxList.size()); + Analysis_POL_Num(&pconfigList->configlsit.at(i), pqxList, qx_type); + // m_pTemCheck->AddCheckstr(PrintLevel_1, 3, "Num And Dis Judge", "param %d / %d AD Num end ", i, (int)pconfigList->configlsit.size()); + } + } + + return 0; +} + +int QX_Analysis::Analysis_s(QXAnalysis_Config *pconfig, QX_ALL_List *pqxList, int qx_type) +{ + int num = 0; + m_pTemCheck->AddCheckstr(PrintLevel_2, 3, "param", " okparam = %d area %f max_area %f hj %d num %d dis %f len %f md %f", pconfig->bok, pconfig->area, pconfig->sum_area, pconfig->hj, pconfig->num, pconfig->dis, pconfig->len, pconfig->density); + float sumarea = 0; + float fmaxarea = 0; + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + // 面积 灰阶满足要求 + if (pqxList->qxList.at(i).area >= pconfig->area && + pqxList->qxList.at(i).hj >= pconfig->hj && + pqxList->qxList.at(i).density >= pconfig->density && + pqxList->qxList.at(i).length >= pconfig->len) + { + num++; + pqxList->qxList.at(i).nstatus = 1; + sumarea += pqxList->qxList.at(i).area; + if (pqxList->qxList.at(i).area > fmaxarea) + { + fmaxarea = pqxList->qxList.at(i).area; + } + } + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "preA", "qx_idx %d : %s num = %d ", i, Re_TO_STR_Pass_1(pqxList->qxList.at(i).nstatus), num); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).area >= pconfig->area), pqxList->qxList.at(i).area, BOOL_TO_ThanLess(pqxList->qxList.at(i).area >= pconfig->area), pconfig->area); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "HJ", "%s -> %f %s %d ", + BOOL_TO_STR(pqxList->qxList.at(i).hj >= pconfig->hj), pqxList->qxList.at(i).hj, BOOL_TO_ThanLess(pqxList->qxList.at(i).hj >= pconfig->hj), pconfig->hj); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).length >= pconfig->len), pqxList->qxList.at(i).length, BOOL_TO_ThanLess(pqxList->qxList.at(i).length >= pconfig->len), pconfig->len); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "md", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).density >= pconfig->density), pqxList->qxList.at(i).density, BOOL_TO_ThanLess(pqxList->qxList.at(i).density >= pconfig->density), pconfig->density); + } + if (pconfig->bok == 1) + { + m_pTemCheck->AddCheckstr(PrintLevel_2, 3, "OK Param Judge", "Num %d ", num); + // 只要有一个条件大于阈值参数,就NG; + if (num > 0) + { + int are = QX_ERROR_TYPE_OK; + // 数量超过阈值 + if (num > pconfig->num) + { + are = QX_ERROR_TYPE_NUM; + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + // 面积 灰阶满足要求 + if (pqxList->qxList.at(i).nstatus == 1) + { + pqxList->qxList.at(i).nqx_type = QX_ERROR_TYPE_NUM; + } + } + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "result NG", "num %d > config num %d nqx_type %d ", num, pconfig->num, are); + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "Num", " %s -> num %d %s %d ", BOOL_TO_STR(num < pconfig->num), num, BOOL_TO_LessThan(num < pconfig->num), pconfig->num); + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "Num And Dis Judge", "Blob info %d / %d idx %d: area %f e %f len %f hj %f", i, (int)pqxList->qxList.size(), + pqxList->qxList.at(i).blobIdx, pqxList->qxList.at(i).area, pqxList->qxList.at(i).energy, pqxList->qxList.at(i).length, pqxList->qxList.at(i).hj); + if (pqxList->qxList.at(i).nstatus == 1) + { + // 长度超过阈值 + if (pqxList->qxList.at(i).length > pconfig->len) + { + pqxList->qxList.at(i).nqx_type = QX_ERROR_TYPE_Len; + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "result NG", "length %f > config len %f nqx_type %d ", pqxList->qxList.at(i).length, pconfig->len, pconfig->dis, pqxList->qxList.at(i).nqx_type); + } + + int minidx = -1; + // 对距离有要求 + if (pconfig->dis > 0) + { + double mindis = 99999999999; + + for (int j = 0; j < (int)pqxList->qxList.size(); j++) + { + if (i == j) + { + continue; + } + // 面积 灰阶满足要求 + if (pqxList->qxList.at(j).nstatus == 1) + { + double dis = CheckUtil::calDis(pqxList->qxList.at(i).plocatin_mm, pqxList->qxList.at(j).plocatin_mm); + if (dis < mindis) + { + mindis = dis; + minidx = j; + } + } + } + // 最小距离 大于 阈值 + if (mindis <= pconfig->dis) + { + pqxList->qxList.at(i).nqx_type = QX_ERROR_TYPE_DIS; + pqxList->qxList.at(i).fmindis = mindis; + pqxList->qxList.at(i).nmindis_BlobIdx = minidx; + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "result NG", "mindis %f < config dis %f nqx_type %d ", mindis, pconfig->dis, pqxList->qxList.at(i).nqx_type); + } + // m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "QX_Analysis", "mindis %f minidx %d config dis %f nqx_type %d ", mindis, minidx, pconfig->dis,pqxList->qxList.at(i).nqx_type); + } + } + } + } + + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + + if (pqxList->qxList.at(i).nqx_type > QX_ERROR_TYPE_OK) + { + if (pqxList->qxList.at(i).result == 0) + { + pqxList->qxList.at(i).result = 1; + + QX_RESULT tem; + tem.blobIdx = pqxList->qxList.at(i).blobIdx; + tem.qx_Num = num; + tem.mindis = pqxList->qxList.at(i).fmindis; + tem.flen = pqxList->qxList.at(i).length; + tem.error_Type = pqxList->qxList.at(i).nqx_type; + + if (pqxList->qxList.at(i).nmindis_BlobIdx >= 0) + { + tem.qx_MisDis_point_pixel = pqxList->qxList.at(pqxList->qxList.at(i).nmindis_BlobIdx).plocatin_pixel; + } + + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "result = NG", "Add New qx,Blob idx %d type %d num %d dis %f len %f ", tem.blobIdx, tem.error_Type, tem.qx_Num, tem.mindis, tem.flen); + + m_reultList.resultList.push_back(tem); + } + } + } + } + } + else + { + + // 数量满足要求 + if (num >= pconfig->num && num > 0 && fmaxarea >= pconfig->sum_area) + { + m_pTemCheck->AddCheckstr(PrintLevel_2, 3, "Num And Dis Judge", "Num = true:Num %d >= %d max_area = true: %f > %f ", num, pconfig->num, fmaxarea, pconfig->sum_area); + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + // 面积 灰阶满足要求 + if (pqxList->qxList.at(i).area >= pconfig->area && + pqxList->qxList.at(i).hj >= pconfig->hj && + pqxList->qxList.at(i).density >= pconfig->density && + pqxList->qxList.at(i).length >= pconfig->len) + { + + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "qx Info", "qx_idx %d / %d idx %d: area %f e %f len %f hj %f", i, (int)pqxList->qxList.size(), + pqxList->qxList.at(i).blobIdx, pqxList->qxList.at(i).area, pqxList->qxList.at(i).energy, pqxList->qxList.at(i).length, pqxList->qxList.at(i).hj); + + int minidx = -1; + bool bdis = true; + double remindis = 0; + + // 对距离有要求 + if (pconfig->dis > 0) + { + double mindis = 99999999999; + + for (int j = 0; j < (int)pqxList->qxList.size(); j++) + { + if (i == j) + { + continue; + } + // 面积 灰阶满足要求 + if (pqxList->qxList.at(j).area >= pconfig->area && + pqxList->qxList.at(j).hj >= pconfig->hj) + { + double dis = CheckUtil::calDis(pqxList->qxList.at(i).plocatin_mm, pqxList->qxList.at(j).plocatin_mm); + if (dis < mindis) + { + mindis = dis; + minidx = j; + } + } + } + // 最小距离 大于 阈值 + if (mindis > pconfig->dis) + { + bdis = false; + } + // m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "QX_Analysis", "mindis %f minidx %d config dis %f ", mindis, minidx, pconfig->dis); + // m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "dis", "dis Is %s -> %f %s %f ", + // BOOL_TO_STR(bdis), mindis, BOOL_TO_ThanLess(bdis), pconfig->dis); + remindis = mindis; + } + else + { + // m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "QX_Analysis", "dis Is true; param :dis == 0;"); + } + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "dis", "dis Is %s -> %f %s %f ", + BOOL_TO_STR(bdis), remindis, BOOL_TO_LessThan(bdis), pconfig->dis); + + // printf("bdis %d pqxList->qxList.at(i).result %d ",bdis, pqxList->qxList.at(i).result); + // 距离满足要求 + if (bdis && pqxList->qxList.at(i).result == 0) + { + pqxList->qxList.at(i).result = 1; + + QX_RESULT tem; + tem.blobIdx = pqxList->qxList.at(i).blobIdx; + tem.qx_Num = num; + tem.mindis = remindis; + if (pconfig->num <= 0 && pconfig->dis <= 0) + { + tem.error_Type = QX_ERROR_TYPE_AREA; + } + else if (pconfig->dis <= 0) + { + tem.error_Type = QX_ERROR_TYPE_NUM; + } + else + { + tem.error_Type = QX_ERROR_TYPE_DIS; + if (minidx >= 0) + { + tem.qx_MisDis_point_pixel = pqxList->qxList.at(minidx).plocatin_pixel; + } + } + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Add New QX", + "result = NG, Add New qx,Blob idx %d -> num %d >= %d is true; dis %f <= %f is true; max_area %f >= %f is true ", + tem.blobIdx, num, pconfig->num, remindis, pconfig->dis, fmaxarea, pconfig->sum_area); + + m_reultList.resultList.push_back(tem); + } + else + { + if (pqxList->qxList.at(i).result != 0) + { + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Num And Dis Judge", "result = NG, old result = %d ", pqxList->qxList.at(i).result); + } + // if (!bdis) + // { + // m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Num And Dis Judge", "Fail,dis %s ", BOOL_TO_STR(bdis)); + // } + } + } + else + { + // m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "preA", "fail"); + } + } + } + else + { + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "result", "fail "); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "num", "%s -> %d %s %d ", + BOOL_TO_STR(num >= pconfig->num), num, BOOL_TO_ThanLess(num >= pconfig->num), pconfig->num); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "num", "%s -> %d %s 0 ", + BOOL_TO_STR(num > 0), num, BOOL_TO_ThanLess(num > 0)); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "max_area", "%s -> %f %s %f ", + BOOL_TO_STR(fmaxarea >= pconfig->sum_area), fmaxarea, BOOL_TO_ThanLess(fmaxarea >= pconfig->sum_area), pconfig->sum_area); + } + } + + return 0; +} + +int QX_Analysis::Analysis_AD_Num(QXAnalysis_Config *pconfig, QX_ALL_List *pqxList, int qx_type) +{ + + // 如果缺陷是暗点, + // 并且 对数量有2个以上要的。因为只有1个要求的话,本身不能满足,那么其他通道也暗点总和一起分析也没意义。 + // 同时对 距离没有要求的。 + if (qx_type == QX_ANALYSIS_AD && !pconfig->bok && (pconfig->num > 1 || pconfig->dis > 1)) + { + // 如果是暗点,那么先忽略暗点对数量的要求,暗点的数量 = RGB 255 多个通道不同位置的暗点数量总和,所以需要 统一放到外面分析。 + // 解决措施,对暗点缺陷有数量要求的,先忽略,先NG, 在在外面进行分析。 + // 对数量有要求。 + m_pTemCheck->AddCheckstr(PrintLevel_2, 3, "Num And Dis Judge", "AD_Num config okparam = %d area %f max_area %f hj %d num %d dis %f len %f", pconfig->bok, pconfig->area, pconfig->sum_area, pconfig->hj, pconfig->num, pconfig->dis, pconfig->len); + + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + + // 当前还是好品的。 + if (pqxList->qxList.at(i).result == 0) + { + bool bsucc = false; + // 面积 灰阶满足要求 + if (pqxList->qxList.at(i).area >= pconfig->area && + pqxList->qxList.at(i).hj >= pconfig->hj && + pqxList->qxList.at(i).density >= pconfig->density && + pqxList->qxList.at(i).length >= pconfig->len) + { + bsucc = true; + } + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "Num deal ", "%d :%s", i, BOOL_TO_STROK(bsucc)); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).area >= pconfig->area), pqxList->qxList.at(i).area, BOOL_TO_ThanLess(pqxList->qxList.at(i).area >= pconfig->area), pconfig->area); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "HJ", "%s -> %f %s %d ", + BOOL_TO_STR(pqxList->qxList.at(i).hj >= pconfig->hj), pqxList->qxList.at(i).hj, BOOL_TO_ThanLess(pqxList->qxList.at(i).hj >= pconfig->hj), pconfig->hj); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).length >= pconfig->len), pqxList->qxList.at(i).length, BOOL_TO_ThanLess(pqxList->qxList.at(i).length >= pconfig->len), pconfig->len); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "md", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).density >= pconfig->density), pqxList->qxList.at(i).density, BOOL_TO_ThanLess(pqxList->qxList.at(i).density >= pconfig->density), pconfig->density); + + if (bsucc) + { + pqxList->qxList.at(i).result = 1; + + QX_RESULT tem; + tem.blobIdx = pqxList->qxList.at(i).blobIdx; + tem.qx_Num = -pconfig->num; + tem.mindis = 0; + tem.error_Type = QX_ERROR_TYPE_NUM_RGB255; + + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Num And Dis Judge", + "result = NG Num RGB255, Add New qx,Blob idx %d ", tem.blobIdx); + + m_reultList.resultList.push_back(tem); + } + } + } + } + + return 0; +} + +int QX_Analysis::Analysis_POL_Num(QXAnalysis_Config *pconfig, QX_ALL_List *pqxList, int qx_type) +{ + // 如果缺陷是暗点, + // 并且 对数量有2个以上要的。因为只有1个要求的话,本身不能满足,那么其他通道也暗点总和一起分析也没意义。 + // 同时对 距离没有要求的。 + if (qx_type == QX_ANALYSIS_POL_CELL && !pconfig->bok && (pconfig->num > 1 || pconfig->dis > 1)) + { + // 如果是暗点,那么先忽略暗点对数量的要求,暗点的数量 = RGB 255 多个通道不同位置的暗点数量总和,所以需要 统一放到外面分析。 + // 解决措施,对暗点缺陷有数量要求的,先忽略,先NG, 在在外面进行分析。 + // 对数量有要求。 + m_pTemCheck->AddCheckstr(PrintLevel_2, 3, "Num And Dis Judge", "POL_Num config okparam = %d area %f max_area %f hj %d num %d dis %f len %f", pconfig->bok, pconfig->area, pconfig->sum_area, pconfig->hj, pconfig->num, pconfig->dis, pconfig->len); + + for (int i = 0; i < (int)pqxList->qxList.size(); i++) + { + + // 当前还是好品的。 + if (pqxList->qxList.at(i).result == 0) + { + bool bsucc = false; + // 面积 灰阶满足要求 + if (pqxList->qxList.at(i).area >= pconfig->area && + pqxList->qxList.at(i).hj >= pconfig->hj && + pqxList->qxList.at(i).density >= pconfig->density && + pqxList->qxList.at(i).length >= pconfig->len) + { + bsucc = true; + } + m_pTemCheck->AddCheckstr(PrintLevel_3, 3, "Num deal ", "%d :%s", i, BOOL_TO_STROK(bsucc)); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Area", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).area >= pconfig->area), pqxList->qxList.at(i).area, BOOL_TO_ThanLess(pqxList->qxList.at(i).area >= pconfig->area), pconfig->area); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "HJ", "%s -> %f %s %d ", + BOOL_TO_STR(pqxList->qxList.at(i).hj >= pconfig->hj), pqxList->qxList.at(i).hj, BOOL_TO_ThanLess(pqxList->qxList.at(i).hj >= pconfig->hj), pconfig->hj); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Len", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).length >= pconfig->len), pqxList->qxList.at(i).length, BOOL_TO_ThanLess(pqxList->qxList.at(i).length >= pconfig->len), pconfig->len); + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "md", "%s -> %f %s %f ", + BOOL_TO_STR(pqxList->qxList.at(i).density >= pconfig->density), pqxList->qxList.at(i).density, BOOL_TO_ThanLess(pqxList->qxList.at(i).density >= pconfig->density), pconfig->density); + + if (bsucc) + { + pqxList->qxList.at(i).result = 1; + + QX_RESULT tem; + tem.blobIdx = pqxList->qxList.at(i).blobIdx; + tem.qx_Num = -pconfig->num; + tem.mindis = 0; + tem.error_Type = QX_ERROR_TYPE_NUM_RGB255; + + m_pTemCheck->AddCheckstr(PrintLevel_4, 3, "Num And Dis Judge", + "result = NG Num RGB255, Add New qx,Blob idx %d ", tem.blobIdx); + + m_reultList.resultList.push_back(tem); + } + } + } + } + + return 0; +} diff --git a/AlgorithmModule/src/SingleGPU.cpp b/AlgorithmModule/src/SingleGPU.cpp new file mode 100644 index 0000000..c429bf4 --- /dev/null +++ b/AlgorithmModule/src/SingleGPU.cpp @@ -0,0 +1,43 @@ +/* + * FileName:CoreLogicFactory.cpp + * Version:V1.0 + * Description: + * Created On:Mon Sep 10 11:13:16 UTC 2018 + * Modified date: + * Author:Sky + */ +#include "SingleGPU.h" + +AI_SingleGPU *AI_SingleGPU::m_pInstance[MAX_GPU_NUMBER] = {nullptr}; + +AI_SingleGPU::CGarbo AI_SingleGPU::m_garbo; +AI_SingleGPU::AI_SingleGPU(int nGpuIdx) +{ + m_nGpuIdx = nGpuIdx; + cout << "AI_SingleGPU GPU:" << m_nGpuIdx << " create succ" << endl; +} + +AI_SingleGPU::~AI_SingleGPU() +{ + // cout << "单例对象销毁!" << endl; + +} + +AI_SingleGPU *AI_SingleGPU::GetInstance(int nGpuIdx) +{ + if (nGpuIdx < 0 || nGpuIdx >= MAX_GPU_NUMBER) + { + return NULL; + } + if (nullptr == m_pInstance[nGpuIdx]) + { + std::mutex mutex_; + mutex_.lock(); // 需要自己采用适当的互斥方式 + if (nullptr == m_pInstance[nGpuIdx]) + { + m_pInstance[nGpuIdx] = new AI_SingleGPU(nGpuIdx); + } + mutex_.unlock(); + } + return m_pInstance[nGpuIdx]; +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a07bf39 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +#限定CMake的版本 +cmake_minimum_required (VERSION 3.5) + +project(rootproject) +set(CHECK_WORK_Value "POL_ET") + +if (DEFINED WORK) + set(CHECK_WORK_Value ${WORK}) +endif() + +# 根据宏设置编译时宏 +add_definitions(-DCHECK_WORK="${CHECK_WORK_Value}") + +message(STATUS "CHECK_WORK: ${CHECK_WORK_Value}") + +find_package( OpenCV REQUIRED ) + +message(STATUS "oPENCV Library status:") +message(STATUS ">version:${OpenCV_VERSION}") +message(STATUS "Include:${OpenCV_INCLUDE_DIRS}") + +set(CMAKE_BUILD_TYPE "release") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) # 要求编译器支持 C++17 +set(CMAKE_CXX_EXTENSIONS OFF) # 禁用 GNU 特定的扩展 + +#set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; --default-stream per-thread) + +add_definitions(-DCUDA_API_PER_THREAD_DEFAULT_STREAM) +# PROJECT_INCLUDE_DIR当作全局头文件变量 +set(PROJECT_INCLUDE_DIR c/include) + +# x86_64,aarch64 +set(BUILD_ARCH x86_64 CACHE STRING "Arch of this project" FORCE) +MESSAGE(STATUS "BUILD_ARCH : ${BUILD_ARCH}") + +MESSAGE(STATUS "CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}") +MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR}) +MESSAGE(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR}) + +#包含通用的编译环境模块到顶层目录 +include(${PROJECT_SOURCE_DIR}/cmake/default_variabes.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/cpp_c_flags.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/print_archs.cmake) + +include_directories(${PROJECT_SOURCE_DIR}/include/) +include_directories(/usr/local/boost/include +/usr/include +${OpenCV_INCLUDE_DIRS} +) +link_directories( +${PROJECT_SOURCE_DIR}/lib/x86_64/ +/usr/local/boost/lib +) + +#下一级的编译目录 + +MESSAGE("build dependent module - start") +#当程序执行命令 ADD_SUBDIRECTORY(src)时进入目录 src 对其中的 CMakeLists.txt 进行解析。 + +add_subdirectory(ConfigModule) +MESSAGE("") + +# CommonUtil +add_subdirectory(AlgorithmModule) +MESSAGE("") + + diff --git a/Common/include/Base_Define.h b/Common/include/Base_Define.h new file mode 100644 index 0000000..97f2c22 --- /dev/null +++ b/Common/include/Base_Define.h @@ -0,0 +1,18 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:49:50 + * @LastEditTime: 2022-09-23 21:51:58 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h + */ +#ifndef Base_Define_H_ +#define Base_Define_H_ +#include +#include + +#define RECT_TO_STRING(rect) \ + "(x=" + std::to_string((rect).x) + ", y=" + std::to_string((rect).y) \ + + ", width=" + std::to_string((rect).width) + ", height=" + std::to_string((rect).height) + ")" + +#endif \ No newline at end of file diff --git a/ConfigModule/CMakeLists.txt b/ConfigModule/CMakeLists.txt new file mode 100644 index 0000000..a797b94 --- /dev/null +++ b/ConfigModule/CMakeLists.txt @@ -0,0 +1,42 @@ +#版本限定 +cmake_minimum_required (VERSION 3.5) + +set(ModuleName "ConfigModule") + +include(${PROJECT_SOURCE_DIR}/cmake/default_variabes.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/cpp_c_flags.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/print_archs.cmake) + + +#头文件 +include_directories( +/usr/local/include +${CMAKE_CURRENT_SOURCE_DIR}/include +) +link_directories( +/usr/local/lib/ +) +# 用set设置变量不能使用*.cpp +file(GLOB SRC_LISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) + +add_library(Config SHARED ${SRC_LISTS}) + +target_link_libraries(Config + ${OpenCV_LIBS} + ) +set(ModuleName "") + +#add_subdirectory(example) + +# make install 安装到/usr/local下 +# 自定义安装前缀 +set(CMAKE_INSTALL_PREFIX /usr/local/polet CACHE PATH "Install path prefix" FORCE) +set(HEADER_FILES include/ConfigBase.h) +# 安装动态库 +install(TARGETS Config + LIBRARY DESTINATION lib # 安装到 CMAKE_INSTALL_PREFIX/lib + ARCHIVE DESTINATION lib/static + RUNTIME DESTINATION bin + PUBLIC_HEADER DESTINATION include) # 安装到 CMAKE_INSTALL_PREFIX/include +# 安装头文件 +install(FILES ${HEADER_FILES} DESTINATION include) \ No newline at end of file diff --git a/ConfigModule/include/CheckConfigDefine.h b/ConfigModule/include/CheckConfigDefine.h new file mode 100644 index 0000000..21315ae --- /dev/null +++ b/ConfigModule/include/CheckConfigDefine.h @@ -0,0 +1,2029 @@ +/* + * @Descripttion: + * @version: + * @Author: sueRimn + * @Date: 2022-03-16 17:09:11 + * @LastEditors: xiewenji 527774126@qq.com + * @LastEditTime: 2025-07-26 12:35:44 + */ +/***********************************************/ +/************ ***************/ +/************金佰利检测算法参数定义**************/ +/************ **************/ +/**********************************************/ +#ifndef _CheckConfigDefine_HPP_ +#define _CheckConfigDefine_HPP_ +#include +#include "ConfigBase.h" +#include + +#define MASK_IMG_STEP 16 +#define MASK_IMG_STARTVALUE 48 + +// 一个检测缺陷 最多有几组参数 +#define MASK_QX_PARAM_NUM 3 +enum REGIONTYPE_ +{ + REGION_TYPE_CHECK, // 检测区域 + REGION_TYPE_SHIELD, // 屏蔽区域 +}; + +// 检测缺陷的种类 +enum CONFIG_QX_NAME_ +{ + CONFIG_QX_NAME_ok_yisi, // 疑似 + CONFIG_QX_NAME_AD_YX, // AD异显(P6873) + CONFIG_QX_NAME_Class_AD_YX, // 分类 AD异显(P6873) + CONFIG_QX_NAME_X_line, // X_line(P3351) + CONFIG_QX_NAME_Y_line, // Y_line(P3452) + CONFIG_QX_NAME_Fangge, // Y_Fangge_line(P3453) 方格 + CONFIG_QX_NAME_Broken_line, // 断线(P3379) + CONFIG_QX_NAME_zara, // ZARA(P1153) + CONFIG_QX_NAME_MTX, // MTX(P1164) + CONFIG_QX_NAME_POL_Cell, // 异物(P1101) + CONFIG_QX_NAME_LD, // 亮点(P1112) + CONFIG_QX_NAME_AD, // 暗点(P1111) + CONFIG_QX_NAME_Scratch_L1, // 一级 轻 划伤(P1557) + CONFIG_QX_NAME_Scratch_L2, // 二级 严重 划伤(P1557) + CONFIG_QX_NAME_Dirty_L0, // 疑似浅层脏污(P0000) + CONFIG_QX_NAME_Dirty_L1, // 轻脏污(P0000) + CONFIG_QX_NAME_Dirty_L2, // 严重脏污(P0000) + CONFIG_QX_NAME_qipao, // 气泡(P0001) + CONFIG_QX_NAME_PS, // ps(P0002) + CONFIG_QX_NAME_Weak_Bright_Mura, // 白GAP(P1654) + CONFIG_QX_NAME_No_Label, // 缺POL(P2833) + CONFIG_QX_NAME_Other, // 缺POL(P2833) + CONFIG_QX_NAME_line, // 缺POL(P3351) + CONFIG_QX_NAME_LD_WTB, // 亮点 WTB(P1112) + CONFIG_QX_NAME_Chess, // Chess 异常 + CONFIG_QX_NAME_127Cell, // 白cell + CONFIG_QX_NAME_white_Cell, // 白cell + CONFIG_QX_NAME_black_Cell, // 白cell + CONFIG_QX_NAME_LD_HS, // 黑闪类画面的亮点 + CONFIG_QX_NAME_LackPOL, // 缺失pol检测 + CONFIG_QX_NAME_count, +}; +// 缺陷项对应在参数中的名称 +static const std::string CONFIG_QX_NAME_Names[] = + { + "ok_yisi", + "AD_YX", + "Class_AD_YX", + "X_line", + "Y_line", + "fangge", + "Broken_line", + "zara", + "MTX", + "Pol_Cell", + "LD", + "AD", + "Scratch_L1", + "Scratch_L2", + "Dirty_L0", + "Dirty_L1", + "Dirty_L2", + "qipao", + "PS", + "Weak_Bright_Mura", + "No_Label", + "qx_Other", + "line", + "LD_WTB", + "qx_Chess", + "Cell127", + "white_Cell", + "black_Cell", + "LD_HS", + "LackPOL"}; + +// web控制检测的缺陷类型, +enum Function_CONFIG_QX_NAME_ +{ + Function_CONFIG_QX_NAME_ok_yisi, // 疑似 + Function_CONFIG_QX_NAME_YX, // AD异显(P6873) + Function_CONFIG_QX_NAME_line, // X_line(P3351) + Function_CONFIG_QX_NAME_zara, // ZARA(P1153) + Function_CONFIG_QX_NAME_MTX, // MTX(P1164) + Function_CONFIG_QX_NAME_POL_Cell, // 异物(P1101) + Function_CONFIG_QX_NAME_LD, // 亮点(P1112) + Function_CONFIG_QX_NAME_AD, // 暗点(P1111) + Function_CONFIG_QX_NAME_Scratch, // 划伤(P1557) + Function_CONFIG_QX_NAME_Dirty, // 脏污(P0000) + Function_CONFIG_QX_NAME_qipao, // 气泡(P0001) + Function_CONFIG_QX_NAME_PS, // ps(P0002) + Function_CONFIG_QX_NAME_Weak_Bright_Mura, // 白GAP(P1654) + Function_CONFIG_QX_NAME_No_Label, // 缺POL(P2833) + Function_CONFIG_QX_NAME_Other, // 缺POL(P2833) + Function_CONFIG_QX_NAME_Chess, // Chess 异常 + Function_CONFIG_QX_NAME_127Cell, // 白cell + Function_CONFIG_QX_NAME_Cell, // 独立检测的黑白cell点 + Function_CONFIG_QX_NAME_count, +}; +// 缺陷项对应在参数中的名称 +static const std::string Function_CONFIG_QX_NAME_Names[] = + { + "OK_Yisi", + "AD_YX", + "Line", + "ZARA", + "MXT", + "POL_Cell", + "LD", + "AnDot", + "Scratch", + "Dirty", + "Qipao", + "PS", + "Weak_Bright_Mura", + "No_Label", + "Other", + "Chess", + "Cell127", + "Cell"}; + +// 通道名称定义 +enum IMG_CHANNEL_ +{ + IMG_CHANNEL_UP, + IMG_CHANNEL_DP, + IMG_CHANNEL_L63, + IMG_CHANNEL_L127, + IMG_CHANNEL_L255, + IMG_CHANNEL_RED, + IMG_CHANNEL_GREEN, + IMG_CHANNEL_BLUE, + IMG_CHANNEL_HS, + IMG_CHANNEL_HB3, + IMG_CHANNEL_HB4, + IMG_CHANNEL_CHESS1, + IMG_CHANNEL_CHESS2, + IMG_CHANNEL_CHESS, + IMG_CHANNEL_AGO, + IMG_CHANNEL_BTW, + IMG_CHANNEL_WTB, + IMG_CHANNEL_TBW, + IMG_CHANNEL_L0, + IMG_CHANNEL_Count, +}; +// 缺陷项对应在参数中的名称 +static const std::string IMG_CHANNEL_NAME[] = + { + "Up-Particle", + "Down-Particle", + "L63", + "L127", + "L255", + "Red", + "Green", + "Blue", + "HS", + "HB3", + "HB4", + "CHESS1", + "CHESS2", + "CHESS", + "AGO", + "BTW", + "WTB", + "TBW", + "L0"}; +// 分析类型 +enum ANALYSIS_TYPE_ +{ + ANALYSIS_TYPE_TF, // 踢废 打标分析 + ANALYSIS_TYPE_YS, // 疑是 分析 + ANALYSIS_TYPE_COUNT, +}; +static const std::string ANALYSIS_TYPE_Names[] = + { + "Check_Param", + "SaveImg_Param"}; + +// 分析类型 +enum QX_RESULT_TYPE_ +{ + QX_RESULT_TYPE_OK, // 踢废 打标分析 + QX_RESULT_TYPE_NG, // 疑是 分析 + QX_RESULT_TYPE_YS, + QX_RESULT_TYPE_COUNT +}; +static const std::string QX_RESULT_TYPE_Names[] = + { + "OK", + "NG", + "YS"}; +// AI模型路径参数 +struct ModelConfigST +{ + std::string defect_model_path = ""; + std::string defect_wtb_model_path = ""; + std::string defect_chess_model_path = ""; + std::string YX_1_model_path = ""; + std::string YX_2_model_path = ""; + std::string zf_model_path = ""; + std::string class_model_path = ""; // 1024dyy-add + std::string class_L0_model_path = ""; // 1024dyy-add + std::string class_L255_model_path = ""; // 1024dyy-add + std::string UP_model_path = ""; // 1024dyy-add + void copy(ModelConfigST tem) + { + this->defect_model_path = tem.defect_model_path; + this->YX_1_model_path = tem.YX_1_model_path; + this->YX_2_model_path = tem.YX_2_model_path; + this->defect_wtb_model_path = tem.defect_wtb_model_path; + this->defect_chess_model_path = tem.defect_chess_model_path; + this->zf_model_path = tem.zf_model_path; + this->class_model_path = tem.class_model_path; // 1024dyy-add + this->class_L0_model_path = tem.class_L0_model_path; // 1024dyy-add + this->class_L255_model_path = tem.class_L255_model_path; // 1024dyy-add + this->UP_model_path = tem.UP_model_path; // 1024dyy-add + } + bool valid() + { + if (defect_model_path != "" && + YX_1_model_path != "" && + class_model_path != "") + { + return true; + } + return false; + } +}; +struct CAM_CONFIGINFO_ +{ + float fscale_x; + float fscale_y; // 相机分辨率 + + CAM_CONFIGINFO_() + { + fscale_x = 0.15f; + fscale_y = 0.15f; + } + void copy(CAM_CONFIGINFO_ tem) + { + this->fscale_x = tem.fscale_x; + this->fscale_y = tem.fscale_y; + } +}; +struct RegionBasicInfo +{ + std::string name; // 区域名称 + int type; // 区域类型 + int lay; // 层级 + std::vector pointArry; // 区域点 + std::vector ChannelArry; // 通道区域 + bool bdraw; // 是否绘制 + RegionBasicInfo() + { + Init(); + } + void Init() + { + name = ""; + type = 0; + lay = 0; + bdraw = false; + pointArry.clear(); + pointArry.shrink_to_fit(); + ChannelArry.clear(); + ChannelArry.shrink_to_fit(); + } + void copy(RegionBasicInfo tem) + { + this->name = tem.name; + this->type = tem.type; + this->lay = tem.lay; + this->bdraw = tem.bdraw; + this->pointArry.assign(tem.pointArry.begin(), tem.pointArry.end()); + this->ChannelArry.assign(tem.ChannelArry.begin(), tem.ChannelArry.end()); + } +}; +struct AandEParam +{ + bool bEnable; // 是否启用 + bool bOk; // 好品条件 + float area; // 面积 + float area_max; // 面积上限 + float energy; // 能量 + float hj; // 灰阶 + float length; // 长度 + int num; // 数量 + float dis; // 距离 + float density; // 密度 + AandEParam() + { + bOk = false; + bEnable = false; + area = -1; + area_max = -1; + energy = -1; + hj = -1; + length = -1; + num = -1; + dis = -1; + density = -1; + } + void print(std::string str) + { + printf("%s bEnable %d bOk %d area %f area_max %f energy %f hj %f length %f num %d dis %f density %f \n", str.c_str(), bEnable, bOk, area, area_max, energy, hj, length, num, dis, density); + } + void copy(AandEParam tem) + { + this->bEnable = tem.bEnable; + this->bOk = tem.bOk; + this->area = tem.area; + this->area_max = tem.area_max; + this->energy = tem.energy; + this->hj = tem.hj; + this->length = tem.length; + this->num = tem.num; + this->dis = tem.dis; + this->density = tem.density; + } +}; + +// 区域的检测参数 +struct CheckConfig_Regions_Param +{ + + std::vector paramArr; + std::string param_name; + int useNum; // 使用个数 + CheckConfig_Regions_Param() + { + paramArr.clear(); + paramArr.shrink_to_fit(); + useNum = 0; + param_name = ""; + } + void addParam(AandEParam param) + { + paramArr.push_back(param); + useNum++; + } +}; +// 不同缺陷类型参数 +struct CheckConfig_Regions_type +{ + std::vector checkConfig_Regions_Param; +}; +// 区域相关参数 +struct RegionConfigST +{ + bool buse; // 是否使用 + RegionBasicInfo basicInfo; // 基础信息 + CheckConfig_Regions_type checkConfig_Regions_type[ANALYSIS_TYPE_COUNT]; + RegionConfigST() + { + buse = false; + } /* data */ +}; +bool compareBylay(const RegionConfigST &a, const RegionConfigST &b); +// 检测参数层级关系 +// 1、区域 +// 2、 检测项目 +// 3、 参数 阈值 + +// 阈值参数系数 +struct THRESHOLD_RATIO +{ + float farea; + float fenergy; + bool bEnable; + THRESHOLD_RATIO() + { + farea = 1; + fenergy = 1; + bEnable = false; + ; + } + void copy(THRESHOLD_RATIO tem) + { + this->farea = tem.farea; + this->fenergy = tem.fenergy; + this->bEnable = tem.bEnable; + } + void printfInfo(std::string str) + { + printf("%s bEnable %d farea %f fenergy %f \n", str.c_str(), bEnable, farea, fenergy); + } +}; + +// 区域无关的基本参数 +struct BasicConfig +{ + std::string strCamearName; + int image_widht; + int Image_height; + int width_min; // 20231122xls-add + int width_max; + int height_min; + int height_max; // 20231122xls-add + bool bDrawShieldRoi; // 绘制屏蔽区域 + bool bShield_ZF; // 屏蔽字符区域,不检测 + bool bDrawPreRoi; // 绘制弱化区域 + float fUP_IOU; + bool bCal_ImageScale; // 是否自动计算成像精度 + float Product_Size_Width_mm; // 产品尺寸 宽度 mm + float Product_Size_Height_mm; // 产品尺寸 高度 mm + float fImage_Scale_x; // 成像精度 + float fImage_Scale_y; // 成像精度 + + float density_R_mm; // 密度计算半径 像素 + BasicConfig() + { + Image_height = 0; + image_widht = 0; + width_min = 0; // 20231122xls-add + width_max = 999999; + height_min = 0; + height_max = 999999; + bDrawShieldRoi = false; + bShield_ZF = false; + bDrawPreRoi = false; + fUP_IOU = 0.9; + bCal_ImageScale = false; + Product_Size_Width_mm = 100; + Product_Size_Height_mm = 1000; + fImage_Scale_x = 0.03; + fImage_Scale_y = 0.03; + density_R_mm = 5; + strCamearName = ""; + } + void copy(BasicConfig tem) + { + this->image_widht = tem.image_widht; + this->Image_height = tem.Image_height; + this->width_min = tem.width_min; // 20231122xls-add + this->width_max = tem.width_max; + this->height_min = tem.height_min; + this->height_max = tem.height_max; + this->bDrawShieldRoi = tem.bDrawShieldRoi; + this->bShield_ZF = tem.bShield_ZF; + this->fUP_IOU = tem.fUP_IOU; + this->bDrawPreRoi = tem.bDrawPreRoi; + + this->bCal_ImageScale = tem.bCal_ImageScale; + this->Product_Size_Width_mm = tem.Product_Size_Width_mm; + this->Product_Size_Height_mm = tem.Product_Size_Height_mm; + this->fImage_Scale_x = tem.fImage_Scale_x; + this->fImage_Scale_y = tem.fImage_Scale_y; + this->density_R_mm = tem.density_R_mm; + this->strCamearName = tem.strCamearName; + } + void print(std::string str = "") + { + printf("============================↓↓↓↓↓↓%s ↓↓↓↓↓↓↓=========================\n", str.c_str(), strCamearName.c_str()); + printf("bCal_ImageScale %d Product_Size_Width =%f Product_Size_Height =%f \n", bCal_ImageScale, Product_Size_Width_mm, Product_Size_Height_mm); + printf("fImage_Scale_x =%f fImage_Scale_y=%f \n", fImage_Scale_x, fImage_Scale_y); + // printf("height_min =%d height_max=%d \n", height_min, height_max); + printf("bDrawShieldRoi %d bShield_ZF %d DrawPreRoi %d fUP_IOU %f density_R_mm %f\n", bDrawShieldRoi, bShield_ZF, bDrawPreRoi, fUP_IOU, density_R_mm); + printf("============================↑↑↑↑↑↑%s↑↑↑↑↑↑=========================\n", str.c_str()); + } +}; +struct NodeBasicConfig +{ + + float calss_conf; // 分类阈值参数,低于这个阈值的不处理, + float calss_area; // 分类阈值参数,低于这个阈值的不处理, + + int img_width; + int img_height; + NodeBasicConfig() + { + + calss_conf = 0.5; + calss_area = 1.0; + } + void copy(NodeBasicConfig tem) + { + + this->calss_conf = tem.calss_conf; + this->calss_area = tem.calss_area; + } + void print(std::string str = "") + { + printf("============================↓↓↓↓↓↓%s↓↓↓↓↓↓↓=========================\n", str.c_str()); + printf("img_width %d img_height %d alss_conf %f calss_area %f \n", img_width, img_height, calss_conf, calss_area); + + printf("============================↑↑↑↑↑↑%s↑↑↑↑↑↑=========================\n", str.c_str()); + } +}; +// 多节点 +struct CommonConfigNodeST +{ + NodeBasicConfig nodebasicConfog; + std::vector regionConfigArr; + cv::Mat mask; + // cv::Mat SheildMask[IMG_CHANNEL_Count]; + void copy(CommonConfigNodeST tem) + { + this->regionConfigArr.assign(tem.regionConfigArr.begin(), tem.regionConfigArr.end()); + this->nodebasicConfog.copy(tem.nodebasicConfog); + if (!tem.mask.empty()) + { + this->mask = tem.mask.clone(); + } + // for (int i = 0; i < IMG_CHANNEL_Count; i++) + // { + // if (!tem.SheildMask[i].empty()) + // { + // this->SheildMask[i] = tem.SheildMask[i].clone(); + // } + // } + } + void InitSheildMask() { + // for (int i = 0; i < IMG_CHANNEL_Count; i++) + // { + // if (!SheildMask[i].empty()) + // { + // SheildMask[i].release(); + // } + // } + }; + void ToSheildMaskImg() + { + // printf("ToSheildMaskImg img_height %d, img_width %d\n", nodebasicConfog.img_height, nodebasicConfog.img_width); + // if (nodebasicConfog.img_width <= 0 || nodebasicConfog.img_height <= 0) + // { + // return; /* code */ + // } + // InitSheildMask(); + + // printf("regionConfigArr.size() %d \n", regionConfigArr.size()); + // std::sort(regionConfigArr.begin(), regionConfigArr.end(), compareBylay); + // for (int i = 0; i < regionConfigArr.size(); i++) + // { + // printf("mask %d / %d type =%d \n", i, regionConfigArr.size(), regionConfigArr.at(i).basicInfo.type); + // if (regionConfigArr.at(i).basicInfo.type == 1) + // { + // for (int ic = 0; ic < regionConfigArr.at(i).basicInfo.ChannelArry.size(); ic++) + // { + // std::string strChannel = regionConfigArr.at(i).basicInfo.ChannelArry.at(ic); + + // int idx = -1; + // for (int pc = 0; pc < IMG_CHANNEL_Count; pc++) + // { + // if (IMG_CHANNEL_NAME[pc] == strChannel) + // { + // idx = pc; + // } + // } + // printf("%d -- %s idx %d\n", ic, strChannel.c_str(), idx); + // if (idx >= 0) + // { + // if (SheildMask[idx].empty()) + // { + // SheildMask[idx] = cv::Mat(nodebasicConfog.img_height, nodebasicConfog.img_width, CV_8U, cv::Scalar(0)); + // } + // cv::fillPoly(SheildMask[idx], regionConfigArr.at(i).basicInfo.pointArry, cv::Scalar(255)); + + // // cv::imwrite(std::to_string(idx)+"_"+strChannel+".png",SheildMask[idx]); + // } + // } + // } + // } + } + void ToMaskImg() + { + + printf("nodebasicConfog.img_height %d, nodebasicConfog.img_width %d\n", nodebasicConfog.img_height, nodebasicConfog.img_width); + if (nodebasicConfog.img_width <= 0 || nodebasicConfog.img_height <= 0) + { + return; /* code */ + } + + mask = cv::Mat(nodebasicConfog.img_height, nodebasicConfog.img_width, CV_8U, cv::Scalar(0)); + + std::sort(regionConfigArr.begin(), regionConfigArr.end(), compareBylay); + for (int i = 0; i < regionConfigArr.size(); i++) + { + // 只绘制检测区域 + if (regionConfigArr.at(i).basicInfo.type != 0) + { + continue; + } + printf("*-*-*-*- %d \n", regionConfigArr.at(i).basicInfo.lay); + + int nv = MASK_IMG_STEP * i + MASK_IMG_STARTVALUE; + if (nv < 0 || nv > 255) + { + nv = 255; + } + cv::fillPoly(mask, regionConfigArr.at(i).basicInfo.pointArry, cv::Scalar(nv)); + // { + // std::vector src_pointArry; // 区域点 + // float src_scale_x = SRCIMG_WIDTH * 1.0f / CHECKIMG_WIDTH; + // float src_scale_y = SRCIMG_HEIGHT * 1.0f / CHECKIMG_HEIGHT; + // for (int j = 0; j < regionConfigArr.at(i).basicInfo.pointArry.size(); j++) + // { + // cv::Point temp; + // temp.x = src_scale_x * regionConfigArr.at(i).basicInfo.pointArry.at(j).x; + // temp.y = src_scale_y * regionConfigArr.at(i).basicInfo.pointArry.at(j).y; + // src_pointArry.push_back(temp); + // // printf("--- %d %d **--- %d %d\n",temp.x,temp.y, regionConfigArr.at(i).basicInfo.pointArry.at(j).x, regionConfigArr.at(i).basicInfo.pointArry.at(j).y); + // } + // cv::fillConvexPoly(Src_mask, src_pointArry, cv::Scalar(nv)); + // } + } + } +}; + +// 和图片相关的参数 +struct CommonCheckConfigST +{ + BasicConfig baseConfig; + // 节点参数数据集 + std::vector nodeConfigArr; + CommonCheckConfigST() + { + nodeConfigArr.clear(); + nodeConfigArr.shrink_to_fit(); + } + void copy(CommonCheckConfigST tem) + { + this->nodeConfigArr.assign(tem.nodeConfigArr.begin(), tem.nodeConfigArr.end()); + this->baseConfig.copy(tem.baseConfig); + } +}; +// 基础检测 +struct Function_Base_Det +{ + bool bOpen; // 是否开启 + std::string strAIMode; // 模型名称 + std::vector DetQXList; // 检测缺陷list + + Function_Base_Det() + { + Init(); + } + void Init() + { + bOpen = false; + strAIMode = ""; + + DetQXList.clear(); + DetQXList.shrink_to_fit(); + } + void copy(Function_Base_Det tem) + { + this->bOpen = tem.bOpen; + this->strAIMode = tem.strAIMode; + this->DetQXList.assign(tem.DetQXList.begin(), tem.DetQXList.end()); + } + void print(std::string str) + { + printf("%s>>bOpen %d strAIMode %s ", str.c_str(), bOpen, strAIMode.c_str()); + + for (int i = 0; i < DetQXList.size(); i++) + { + printf("%s ", DetQXList.at(i).c_str()); + } + printf(" \n"); + } + + std::string GetInfo(std::string str) + { + char buffer[128]; + sprintf(buffer, "%s>>bOpen:%d AIMode:%s ", str.c_str(), bOpen, strAIMode.c_str()); + + std::string str123 = buffer; + + for (int i = 0; i < DetQXList.size(); i++) + { + str123 += DetQXList.at(i) + ";"; + } + str123 += "\n"; + return str123; + } +}; +// 检测功能,使用UP画面的缺陷进行过滤 +struct Function_Use_UP_QX +{ + bool bOpen; // 是否开启 + float fIOU; // IOU 值 + Function_Use_UP_QX() + { + Init(); + } + void Init() + { + bOpen = false; + fIOU = 0.80; + } + void copy(Function_Use_UP_QX tem) + { + this->bOpen = tem.bOpen; + this->fIOU = tem.fIOU; + } + void print(std::string str) + { + printf("%s>>bOpen %d, IOU %f \n", str.c_str(), bOpen, fIOU); + } + std::string GetInfo(std::string str) + { + char buffer[64]; + sprintf(buffer, "%s>>bOpen:%d fIOU:%f \n", str.c_str(), bOpen, fIOU); + std::string str123 = buffer; + return str123; + } +}; +// 只生成Blob不进行分析 +struct Function_OnlyBLob +{ + bool bOpen; // 是否开启 + Function_OnlyBLob() + { + Init(); + } + void Init() + { + bOpen = false; + } + void copy(Function_OnlyBLob tem) + { + this->bOpen = tem.bOpen; + } + void print(std::string str) + { + printf("%s>>bOpen %d\n", str.c_str(), bOpen); + } + std::string GetInfo(std::string str) + { + char buffer[64]; + sprintf(buffer, "%s>>bOpen %d\n", str.c_str(), bOpen); + std::string str123 = buffer; + return str123; + } +}; +// 异显检测 +struct Function_YXDet +{ + bool bOpen; // 是否开启 + std::string strModle; + Function_YXDet() + { + Init(); + } + void Init() + { + bOpen = false; + strModle = ""; + } + void copy(Function_YXDet tem) + { + this->bOpen = tem.bOpen; + this->strModle = tem.strModle; + } + void print(std::string str) + { + printf("%s>>bOpen %d strModle %s\n", str.c_str(), bOpen, strModle.c_str()); + } + std::string GetInfo(std::string str) + { + char buffer[64]; + sprintf(buffer, "%s>>bOpen %d strModle %s\n", str.c_str(), bOpen, strModle.c_str()); + std::string str123 = buffer; + return str123; + } +}; +struct Function_AI_QX +{ + bool bOpen; // 是否开启 + bool bPOLToWhitePOL; // 异物转白异物 + bool bAllToChess; // 所有缺陷转Chess + bool b127WhitePOl_UseDP; // 127 画面的白cell是否依赖dp异物结果。 + float f127WhitePOl_DP_IOU; + Function_AI_QX() + { + Init(); + } + void Init() + { + bOpen = false; + bPOLToWhitePOL = false; + bAllToChess = false; + b127WhitePOl_UseDP = false; + f127WhitePOl_DP_IOU = 0.5; + } + void copy(Function_AI_QX tem) + { + this->bOpen = tem.bOpen; + this->bPOLToWhitePOL = tem.bPOLToWhitePOL; + this->bAllToChess = tem.bAllToChess; + this->b127WhitePOl_UseDP = tem.b127WhitePOl_UseDP; + this->f127WhitePOl_DP_IOU = tem.f127WhitePOl_DP_IOU; + } + void print(std::string str) + { + printf("%s>>bOpen %d POLToWhitePOL %d AllToChess %d 127WhitePOl_UseDP %d 127WhitePOl_DP_IOU %f\n", + str.c_str(), bOpen, bPOLToWhitePOL, bAllToChess, b127WhitePOl_UseDP, f127WhitePOl_DP_IOU); + } + std::string GetInfo(std::string str) + { + char buffer[128]; + sprintf(buffer, "%s>>bOpen %d POLToWhitePOL %d AllToChess %d 127WhitePOl_UseDP %d 127WhitePOl_DP_IOU %f\n", + str.c_str(), bOpen, bPOLToWhitePOL, bAllToChess, b127WhitePOl_UseDP, f127WhitePOl_DP_IOU); + std::string str123 = buffer; + return str123; + } +}; +// 亮点 +struct Function_AI_LD +{ + bool bOpen; // 是否开启 + bool bUseDP; // 是否使用DP检测结果 + bool bWTBLD; // 是否是WTB亮点 + bool bHSLD; // 黑闪类型的亮点 + float fDP_IOU; // DP的IOU + + bool bUseLD_Standard; // 是否使用亮点标准化参数 + float fLD_Area; // 亮点面积 + float fLD_En; // 亮点的能量 + float fLD_HJ; // 亮点灰阶 + float fLD_Len; // 亮点长度 + Function_AI_LD() + { + Init(); + } + void Init() + { + bOpen = false; + bUseDP = false; + bWTBLD = false; + bHSLD = false; + fDP_IOU = 0.1; + fLD_Area = -1; + fLD_En = -1; + fLD_HJ = -1; + fLD_Len = -1; + bUseLD_Standard = false; + } + void copy(Function_AI_LD tem) + { + this->bOpen = tem.bOpen; + this->bUseDP = tem.bUseDP; + this->bWTBLD = tem.bWTBLD; + this->bHSLD = tem.bHSLD; + this->fDP_IOU = tem.fDP_IOU; + this->fLD_Area = tem.fLD_Area; + this->fLD_En = tem.fLD_En; + this->fLD_HJ = tem.fLD_HJ; + this->fLD_Len = tem.fLD_Len; + this->bUseLD_Standard = tem.bUseLD_Standard; + + } + void print(std::string str) + { + printf("%s>>bOpen %d bUseDP %d bWTBLD %d bHSLD %d fDP_IOU %f\n", str.c_str(), bOpen, bUseDP, bWTBLD, bHSLD, fDP_IOU); + } + std::string GetInfo(std::string str) + { + char buffer[64]; + sprintf(buffer, "%s>>bOpen %d bUseDP %d bWTBLD %d bHSLD %d fDP_IOU %f\n", str.c_str(), bOpen, bUseDP, bWTBLD, bHSLD, fDP_IOU); + std::string str123 = buffer; + return str123; + } +}; + +// 大缺陷检测参数 +struct Function_BigQX +{ + bool bOpen; // 是否开启 + float Single_Area; // 单个缺陷的面积 + int Single_HJ; // 单个缺陷的灰机 + float Single_Len; // 单个缺陷的长度 + int Sum_blob_Num; // 总面积统计 blob数量 + float Sum_Area; // 总面积统计 面积参数 + Function_BigQX() + { + Init(); + } + void Init() + { + bOpen = false; + Single_Area = 80; + Single_HJ = 60; + Single_Len = 5; + Sum_blob_Num = 5; + Sum_Area = 100; + } + void copy(Function_BigQX tem) + { + this->bOpen = tem.bOpen; + this->Single_Area = tem.Single_Area; + this->Single_HJ = tem.Single_HJ; + this->Single_Len = tem.Single_Len; + this->Sum_blob_Num = tem.Sum_blob_Num; + this->Sum_Area = tem.Sum_Area; + } + void print(std::string str) + { + printf("%s>>bOpen %d single area %f hj %d len %f sum blob num %d area %f\n", str.c_str(), + bOpen, Single_Area, Single_HJ, Single_Len, Sum_blob_Num, Sum_Area); + } + std::string GetInfo(std::string str) + { + char buffer[128]; + sprintf(buffer, "%s>>bOpen %d single area %f hj %d len %f sum blob num %d area %f\n", str.c_str(), + bOpen, Single_Area, Single_HJ, Single_Len, Sum_blob_Num, Sum_Area); + std::string str123 = buffer; + return str123; + } +}; + +// 屏蔽区域参数 +struct Function_ShieldRegion +{ + bool bOpen; // 是否开启 + + bool bDraw; // 是否绘制 + cv::Mat shieldMask; // 屏蔽区域图片 + std::vector pointArry1; // 区域点 + std::vector pointArry2; // 区域点 + std::vector pointArry3; // 区域点 + std::vector pointArry4; // 区域点 + std::vector pointArry5; // 区域点 + Function_ShieldRegion() + { + Init(); + } + void Init() + { + bOpen = false; + bDraw = true; + + pointArry1.clear(); + pointArry1.shrink_to_fit(); + + pointArry2.clear(); + pointArry2.shrink_to_fit(); + + pointArry3.clear(); + pointArry3.shrink_to_fit(); + + pointArry4.clear(); + pointArry4.shrink_to_fit(); + + pointArry5.clear(); + pointArry5.shrink_to_fit(); + if (!shieldMask.empty()) + { + shieldMask.release(); + } + } + + void copy(Function_ShieldRegion tem) + { + this->bOpen = tem.bOpen; + this->bDraw = tem.bDraw; + this->shieldMask = tem.shieldMask.clone(); + this->pointArry1.assign(tem.pointArry1.begin(), tem.pointArry1.end()); + this->pointArry2.assign(tem.pointArry2.begin(), tem.pointArry2.end()); + this->pointArry3.assign(tem.pointArry3.begin(), tem.pointArry3.end()); + this->pointArry4.assign(tem.pointArry4.begin(), tem.pointArry4.end()); + this->pointArry5.assign(tem.pointArry5.begin(), tem.pointArry5.end()); + } + void ToMaskImg(int img_W, int img_H) + { + if (img_W > 0 && img_H > 0) + { + if (!shieldMask.empty()) + { + shieldMask.release(); + } + + if (!bOpen) + { + return; + } + shieldMask = cv::Mat(img_H, img_W, CV_8U, cv::Scalar(0)); + if (pointArry1.size() > 0) + { + cv::fillPoly(shieldMask, pointArry1, cv::Scalar(255)); + } + if (pointArry2.size() > 0) + { + cv::fillPoly(shieldMask, pointArry2, cv::Scalar(255)); + } + if (pointArry3.size() > 0) + { + cv::fillPoly(shieldMask, pointArry3, cv::Scalar(255)); + } + if (pointArry4.size() > 0) + { + cv::fillPoly(shieldMask, pointArry4, cv::Scalar(255)); + } + if (pointArry5.size() > 0) + { + cv::fillPoly(shieldMask, pointArry5, cv::Scalar(255)); + } + } + } + void print(std::string str) + { + printf("%s>>bOpen %d bDraw %d maskimg empty %d\n", str.c_str(), + bOpen, bDraw, shieldMask.empty()); + } + std::string GetInfo(std::string str) + { + char buffer[128]; + sprintf(buffer, "%s>>bOpen %d bDraw %d maskimg empty %d\n", str.c_str(), + bOpen, bDraw, shieldMask.empty()); + std::string str123 = buffer; + return str123; + } +}; +// 启用127cell 独立检测 +struct Function_Det_127_Cell +{ + bool bOpen; // 是否开启 + Function_Det_127_Cell() + { + Init(); + } + void Init() + { + bOpen = false; + } + void copy(Function_Det_127_Cell tem) + { + this->bOpen = tem.bOpen; + } + void print(std::string str) + { + printf("%s>>bOpen %d \n", str.c_str(), bOpen); + } + std::string GetInfo(std::string str) + { + char buffer[64]; + sprintf(buffer, "%s>>bOpen %d\n", str.c_str(), bOpen); + std::string str123 = buffer; + return str123; + } +}; + +// 检测roi区域参数 +struct Function_EdgeROI +{ + bool bOpen; // 是否开启 + bool Use_DrawROI; // 使用绘制ROI + bool Use_DetEdge; // 使用边缘检测 + bool Use_AIEdge; // 使用AI检测 + bool AI_Fail_UseDraw; // 如果AI 失败使用绘制; + int threshold_value; // 二值化值 + int AI_Erode_Size; // AI 检测 腐蚀的半径。 + cv::Mat EdgeMask; // 边缘区域图片 + std::vector pointArry1; // 区域点 + Function_EdgeROI() + { + Init(); + } + void Init() + { + bOpen = false; + Use_DrawROI = false; + Use_DetEdge = true; + Use_AIEdge = false; + AI_Fail_UseDraw = false; + threshold_value = 11; + AI_Erode_Size = 7; + pointArry1.clear(); + pointArry1.shrink_to_fit(); + if (!EdgeMask.empty()) + { + EdgeMask.release(); + } + } + + void copy(Function_EdgeROI tem) + { + this->bOpen = tem.bOpen; + this->Use_DrawROI = tem.Use_DrawROI; + this->Use_DetEdge = tem.Use_DetEdge; + this->Use_AIEdge = tem.Use_AIEdge; + this->AI_Fail_UseDraw = tem.AI_Fail_UseDraw; + this->threshold_value = tem.threshold_value; + this->AI_Erode_Size = tem.AI_Erode_Size; + this->EdgeMask = tem.EdgeMask.clone(); + this->pointArry1.assign(tem.pointArry1.begin(), tem.pointArry1.end()); + } + void ToMaskImg(int img_W, int img_H) + { + if (img_W > 0 && img_H > 0) + { + if (!EdgeMask.empty()) + { + EdgeMask.release(); + } + if (!bOpen) + { + return; + } + // if (!Use_DrawROI) + // { + // return; + // } + EdgeMask = cv::Mat(img_H, img_W, CV_8U, cv::Scalar(0)); + + if (pointArry1.size() > 0) + { + cv::fillPoly(EdgeMask, pointArry1, cv::Scalar(255)); + } + else + { + printf("pointArry1 == 0 \n\n\n"); + } + } + } + void print(std::string str) + { + printf("%s>>bOpen %d Use_DrawROI %d Use_DetEdge %d Use_AIEdge %d AI_Fail_UseDraw %d threshold_value %d AI_Erode_Size %d EdgeMask empty %d\n", str.c_str(), + bOpen, Use_DrawROI, Use_DetEdge, Use_AIEdge, AI_Fail_UseDraw, threshold_value, AI_Erode_Size, EdgeMask.empty()); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s>>bOpen %d Use_DrawROI %d Use_DetEdge %d Use_AIEdge %d AI_Fail_UseDraw %d threshold_value %d AI_Erode_Size %d EdgeMask empty %d\n", str.c_str(), + bOpen, Use_DrawROI, Use_DetEdge, Use_AIEdge, AI_Fail_UseDraw, threshold_value, AI_Erode_Size, EdgeMask.empty()); + std::string str123 = buffer; + return str123; + } +}; + +// 图片对齐功能 +struct Function_Image_Align +{ + enum RunType + { + type_Use, // 使用 + type_Test, // 仅测试 + }; + bool bOpen; // 是否开启 + bool bDraw; // 是否绘制 + float fscore; // 定位分数 + RunType runType; // 运行模式 + cv::Rect search_Roi; // 搜索区域 + cv::Rect feature_Roi; // 特征区域 + cv::Mat feature_Mask; // 特征mask + cv::Rect Crop_Roi; // 产品裁切区域 + std::vector pointArry1; // 特征区域点 + Function_Image_Align() + { + Init(); + } + void Init() + { + bOpen = false; + bDraw = false; + fscore = 0.9; + search_Roi = cv::Rect(0, 0, 0, 0); + feature_Roi = cv::Rect(0, 0, 0, 0); + Crop_Roi = cv::Rect(0, 0, 0, 0); + pointArry1.clear(); + pointArry1.shrink_to_fit(); + if (!feature_Mask.empty()) + { + feature_Mask.release(); + } + runType = type_Use; + } + // 将枚举值转换为字符串 + std::string colorToString(RunType c) + { + switch (c) + { + case type_Use: + return "Use"; + case type_Test: + return "Test"; + default: + return "Use"; + } + } + void copy(Function_Image_Align tem) + { + this->bOpen = tem.bOpen; + this->bDraw = tem.bDraw; + this->fscore = tem.fscore; + this->search_Roi = tem.search_Roi; + this->feature_Roi = tem.feature_Roi; + this->Crop_Roi = tem.Crop_Roi; + this->feature_Mask = tem.feature_Mask.clone(); + this->pointArry1.assign(tem.pointArry1.begin(), tem.pointArry1.end()); + this->runType = tem.runType; + } + void ToMaskImg(int img_W, int img_H) + { + if (img_W > 0 && img_H > 0) + { + if (!feature_Mask.empty()) + { + feature_Mask.release(); + } + if (!bOpen) + { + return; + } + // cv::Rect boundingRect = cv::boundingRect(pointArry1); + // feature_Roi = boundingRect; + // for (int i = 0; i < pointArry1.size(); i++) + // { + // pointArry1[i].x -= boundingRect.x; + // pointArry1[i].y -= boundingRect.y; + // } + + cv::Mat tem_feature_Mask = cv::Mat(img_H, img_W, CV_8U, cv::Scalar(0)); + + if (pointArry1.size() > 0) + { + cv::fillPoly(tem_feature_Mask, pointArry1, cv::Scalar(255)); + } + else + { + printf("pointArry1 == 0 \n\n\n"); + } + if (feature_Roi.x < 0) + { + feature_Roi.x = 0; + } + if (feature_Roi.y < 0) + { + feature_Roi.y = 0; + } + if (feature_Roi.x + feature_Roi.width > img_W) + { + feature_Roi.width = img_W - feature_Roi.x; + } + if (feature_Roi.y + feature_Roi.height > img_H) + { + feature_Roi.height = img_H - feature_Roi.y; + } + + feature_Mask = tem_feature_Mask(feature_Roi).clone(); + } + } + void print(std::string str) + { + printf("%s>>bOpen %d bDraw %d fscore %f feature_Mask empty %d run type = %s\n", str.c_str(), + bOpen, bDraw, fscore, feature_Mask.empty(), colorToString(runType).c_str()); + } + std::string GetInfo(std::string str) + { + char buffer[128]; + sprintf(buffer, "%s>>bOpen %d bDraw %d fscore %f feature_Mask empty %d run type = %s\n", str.c_str(), + bOpen, bDraw, fscore, feature_Mask.empty(), colorToString(runType).c_str()); + std::string str123 = buffer; + return str123; + } +}; + +// 缺失Pol检测 +struct Function_Detect_LackPol +{ + + bool bOpen; // 是否开启 + + Function_Detect_LackPol() + { + Init(); + } + void Init() + { + bOpen = false; + } + + void copy(Function_Detect_LackPol tem) + { + this->bOpen = tem.bOpen; + } + void print(std::string str) + { + printf("%s>>bOpen %d \n", str.c_str(), + bOpen); + } + std::string GetInfo(std::string str) + { + char buffer[128]; + sprintf(buffer, "%s>>bOpen %d\n", str.c_str(), + bOpen); + std::string str123 = buffer; + return str123; + } +}; + +// 二次精确检测 +struct Function_SecondDet +{ + + bool bOpen; // 是否开启 + + bool andian_Open_area; // 暗点 开启面积检测 + bool andian_Open_len; // 暗点 开启长度检测 + float andian_area_min; // 暗点 面积范围 + float andian_area_max; // 暗点 面积范围 + bool andian_saveProcessImg; // 暗点 存储图片 + + bool pol_Open_area; // pol 开启面积检测 + bool pol_Open_len; // pol 开启长度检测 + float pol_area_min; // pol 面积范围 + float pol_area_max; // pol 面积范围 + bool pol_open_SingleCheck; // pol 开启独立参数分析 + bool pol_open_Create; // pol 可以生成新异物 + bool pol_saveProcessImg; // pol 存储图片 + + Function_SecondDet() + { + Init(); + } + void Init() + { + bOpen = false; + andian_Open_area = false; + andian_Open_len = false; + andian_area_min = 0; + andian_area_max = 0.25; + andian_saveProcessImg = false; + + pol_Open_area = false; + pol_Open_len = false; + pol_area_min = 0; + pol_area_max = 0.25; + pol_open_SingleCheck = false; + pol_open_Create = false; + pol_saveProcessImg = false; + } + + void copy(Function_SecondDet tem) + { + this->bOpen = tem.bOpen; + + this->andian_Open_area = tem.andian_Open_area; + this->andian_Open_len = tem.andian_Open_len; + this->andian_area_min = tem.andian_area_min; + this->andian_area_max = tem.andian_area_max; + this->andian_saveProcessImg = tem.andian_saveProcessImg; + + this->pol_Open_area = tem.pol_Open_area; + this->pol_Open_len = tem.pol_Open_len; + this->pol_area_min = tem.pol_area_min; + this->pol_area_max = tem.pol_area_max; + this->pol_open_SingleCheck = tem.pol_open_SingleCheck; + this->pol_open_Create = tem.pol_open_Create; + this->pol_saveProcessImg = tem.pol_saveProcessImg; + } + void print(std::string str) + { + printf("%s>>bOpen %d andian : Open_area %d Open_len %d bsaveimg %d area_minmax %f-%f\n", str.c_str(), + bOpen, andian_Open_area, andian_Open_len, andian_saveProcessImg, andian_area_min, andian_area_max); + printf("%s>>bOpen %d pol : Open_area %d Open_len %d bsaveimg %d area_minmax %f-%f singlecheck %d create %d\n", str.c_str(), + bOpen, pol_Open_area, pol_Open_len, pol_saveProcessImg, pol_area_min, pol_area_max, pol_open_SingleCheck, pol_open_Create); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s>>bOpen %d andian : Open_area %d Open_len %d bsaveimg %d area_minmax %f-%f pol : Open_area %d Open_len %d bsaveimg %d area_minmax %f-%f singlecheck %d create %d\n", str.c_str(), + bOpen, andian_Open_area, andian_Open_len, andian_saveProcessImg, andian_area_min, andian_area_max, + pol_Open_area, pol_Open_len, pol_saveProcessImg, pol_area_min, pol_area_max, pol_open_SingleCheck, pol_open_Create); + std::string str123 = buffer; + return str123; + } +}; +// 暗点的 S标准 +struct AD_S_Standard +{ + float area; // 面积 + float len; // 长度 + AD_S_Standard() + { + Init(); + } + void Init() + { + area = 0; + len = 0; + } + void copy(AD_S_Standard tem) + { + this->area = tem.area; + this->len = tem.len; + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s:area %f len %f;", str.c_str(), + area, len); + std::string str123 = buffer; + return str123; + } +}; +// 暗点数量分析 +struct AD_Analysisy_Num +{ + bool bOpen; // 是否开启 + int numT; // 数量阈值 + AD_Analysisy_Num() + { + Init(); + } + void Init() + { + bOpen = false; + numT = 0; + } + void copy(AD_Analysisy_Num tem) + { + this->bOpen = tem.bOpen; + this->numT = tem.numT; + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s:bOpen %d num %d;", str.c_str(), + bOpen, numT); + std::string str123 = buffer; + return str123; + } +}; +// 暗点距离分析 +struct AD_Analysisy_Dis +{ + bool bOpen; // 是否开启 + float disT; // 距离阈值 + AD_Analysisy_Dis() + { + Init(); + } + void Init() + { + bOpen = false; + disT = 0; + } + void copy(AD_Analysisy_Dis tem) + { + this->bOpen = tem.bOpen; + this->disT = tem.disT; + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s:bOpen %d dis %f;", str.c_str(), + bOpen, disT); + std::string str123 = buffer; + return str123; + } +}; + +// 暗点S标准分析 +struct AD_Analysisy_S +{ + bool bOpen; // 是否开启 + bool NG_3s; // 直接NG 的 3S 值。 + bool NG_4s; // 直接NG 的 4S 值。 + int Check_s_Value; // 有数量数量要求的s值。 + int Check_s_Num; // 数量要求。 + AD_Analysisy_S() + { + Init(); + } + void Init() + { + bOpen = false; + NG_3s = false; + NG_4s = false; + Check_s_Value = 2; + Check_s_Num = 2; + } + void copy(AD_Analysisy_S tem) + { + this->bOpen = tem.bOpen; + this->NG_3s = tem.NG_3s; + this->NG_4s = tem.NG_4s; + this->Check_s_Value = tem.Check_s_Value; + this->Check_s_Num = tem.Check_s_Num; + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s:bOpen %d s_Value %d s_Num %d NG_3s %d NG_4s %d;", str.c_str(), + bOpen, Check_s_Value, Check_s_Num, NG_3s, NG_4s); + std::string str123 = buffer; + return str123; + } +}; +// 暗点检测功能 +struct Function_AD_Check +{ + + bool bOpen; // 是否开启 + AD_S_Standard S_standard_3s; // 3s 标准 + AD_S_Standard S_standard_2s; // 2s 标准 + AD_S_Standard S_standard_1s; // 1s 标准 + AD_Analysisy_Num analysis_num; // 数量分析 + AD_Analysisy_Dis analysis_dis; // 距离分析 + AD_Analysisy_S analysis_s; // s 标准分析 + + Function_AD_Check() + { + Init(); + } + void Init() + { + bOpen = false; + S_standard_3s.Init(); + S_standard_2s.Init(); + S_standard_1s.Init(); + analysis_num.Init(); + analysis_dis.Init(); + analysis_s.Init(); + } + + void copy(Function_AD_Check tem) + { + this->bOpen = tem.bOpen; + this->S_standard_3s.copy(tem.S_standard_3s); + this->S_standard_2s.copy(tem.S_standard_2s); + this->S_standard_1s.copy(tem.S_standard_1s); + this->analysis_num.copy(tem.analysis_num); + this->analysis_dis.copy(tem.analysis_dis); + this->analysis_s.copy(tem.analysis_s); + } + void print(std::string str) + { + printf("%s>>bOpen %d %s %s %s %s %s %s\n", str.c_str(), + bOpen, S_standard_3s.GetInfo("3S").c_str(), + S_standard_2s.GetInfo("2S").c_str(), + S_standard_1s.GetInfo("1S").c_str(), + analysis_num.GetInfo("analysis_num").c_str(), + analysis_dis.GetInfo("analysis_dis").c_str(), + analysis_s.GetInfo("analysis_s").c_str()); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s>>bOpen %d ", str.c_str(), bOpen); + std::string str123 = buffer; + str123 += S_standard_3s.GetInfo("3S"); + str123 += S_standard_2s.GetInfo("2S"); + str123 += S_standard_1s.GetInfo("1S"); + str123 += analysis_num.GetInfo("analysis_num"); + str123 += analysis_dis.GetInfo("analysis_dis"); + str123 += analysis_s.GetInfo("analysis_s"); + + return str123; + } +}; + +// 异物检测功能 +struct Function_POL_Check +{ + + bool bOpen; // 是否开启 + int numT; // 数量阈值 + Function_POL_Check() + { + Init(); + } + void Init() + { + bOpen = false; + numT = 0; + } + + void copy(Function_POL_Check tem) + { + this->bOpen = tem.bOpen; + this->numT = tem.numT; + } + void print(std::string str) + { + printf("%s>>bOpen %d %d\n", str.c_str(), + bOpen, + numT); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s>>bOpen %d num %d", str.c_str(), bOpen, numT); + std::string str123 = buffer; + + return str123; + } +}; +// 检测功能 +struct CheckFunction +{ + Function_Base_Det f_BaseDet; // 基础检测 + Function_Use_UP_QX f_UseUpQX; // 使用UP画面的缺陷进行过滤 + Function_OnlyBLob f_OnlyBLob; // 只获取blob ,不进行分析 + Function_YXDet f_YXDet; // 异显检测 + Function_AI_QX f_AIQX; // 缺陷分类设置 + Function_AI_LD f_LDConfig; // 亮点参数 + Function_BigQX f_Big_QX; + Function_ShieldRegion f_ShieldRegion; + Function_Det_127_Cell f_Det127Cell; + Function_EdgeROI f_EdgeROI; + Function_Image_Align f_Image_Align; // 图片特征对齐 + Function_Detect_LackPol f_Dectect_LackPol; // 缺失POL检测 + Function_SecondDet f_SecondDetect; // 二次检测分析 + Function_AD_Check f_AD_Check; // 暗点的检测功能 + Function_POL_Check f_POL_Check; // 异物的检测功能 + CheckFunction() + { + Init(); + } + void Init() + { + f_UseUpQX.Init(); + f_BaseDet.Init(); + f_OnlyBLob.Init(); + f_YXDet.Init(); + f_AIQX.Init(); + f_LDConfig.Init(); + f_Big_QX.Init(); + f_ShieldRegion.Init(); + f_Det127Cell.Init(); + f_EdgeROI.Init(); + f_Image_Align.Init(); + f_Dectect_LackPol.Init(); + f_SecondDetect.Init(); + f_AD_Check.Init(); + f_POL_Check.Init(); + } + void copy(CheckFunction tem) + { + + this->f_UseUpQX.copy(tem.f_UseUpQX); + this->f_BaseDet.copy(tem.f_BaseDet); + this->f_OnlyBLob.copy(tem.f_OnlyBLob); + this->f_YXDet.copy(tem.f_YXDet); + this->f_AIQX.copy(tem.f_AIQX); + this->f_LDConfig.copy(tem.f_LDConfig); + this->f_Big_QX.copy(tem.f_Big_QX); + this->f_ShieldRegion.copy(tem.f_ShieldRegion); + this->f_Det127Cell.copy(tem.f_Det127Cell); + this->f_EdgeROI.copy(tem.f_EdgeROI); + this->f_Image_Align.copy(tem.f_Image_Align); + this->f_Dectect_LackPol.copy(tem.f_Dectect_LackPol); + this->f_SecondDetect.copy(tem.f_SecondDetect); + this->f_AD_Check.copy(tem.f_AD_Check); + this->f_POL_Check.copy(tem.f_POL_Check); + } + void print(std::string str) + { + printf("%s>>\n", str.c_str()); + f_BaseDet.print("BaseDet"); + f_UseUpQX.print("UseUpQX"); + f_OnlyBLob.print("OnlyBLob"); + f_YXDet.print("YXDet"); + f_AIQX.print("AIQX"); + f_LDConfig.print("LDConfig"); + f_Big_QX.print("Big_QX"); + f_ShieldRegion.print("ShieldRegion"); + f_Det127Cell.print("Det127Cell"); + f_EdgeROI.print("EdgeROI"); + f_Image_Align.print("Image_Align"); + f_Dectect_LackPol.print("Dectect_LackPol"); + f_SecondDetect.print("SecondDetect"); + f_AD_Check.print("f_AD_Check"); + f_POL_Check.print("f_POL_Check"); + } + std::string GetInfo(std::string str) + { + + std::string str123 = str + ":\n"; + str123 += f_BaseDet.GetInfo("BaseDet"); + str123 += f_UseUpQX.GetInfo("UseUpQX"); + str123 += f_OnlyBLob.GetInfo("f_OnlyBLob"); + str123 += f_YXDet.GetInfo("YXDet"); + str123 += f_AIQX.GetInfo("AIQX"); + str123 += f_LDConfig.GetInfo("LDConfig"); + str123 += f_Big_QX.GetInfo("Big_QX"); + str123 += f_ShieldRegion.GetInfo("ShieldRegion"); + str123 += f_Det127Cell.GetInfo("Det127Cell"); + str123 += f_EdgeROI.GetInfo("EdgeROI"); + str123 += f_Image_Align.GetInfo("Image_Align"); + str123 += f_Dectect_LackPol.GetInfo("Dectect_LackPol"); + str123 += f_SecondDetect.GetInfo("SecondDetect"); + str123 += f_AD_Check.GetInfo("f_AD_Check"); + str123 += f_AD_Check.GetInfo("f_POL_Check"); + return str123; + } +}; +// 单通道检测功能 +struct ChannelCheckFunction +{ + std::string strChannelName; + CheckFunction function; // 使用UP画面的缺陷进行过滤 + ChannelCheckFunction() + { + Init(); + } + void Init() + { + strChannelName = ""; + function.Init(); + } + void copy(ChannelCheckFunction tem) + { + this->strChannelName = tem.strChannelName; + this->function.copy(tem.function); + } + void print(std::string str) + { + printf("%s>> %s\n", str.c_str(), strChannelName.c_str()); + function.print("function"); + } + std::string GetInfo(std::string str) + { + std::string str123 = ""; + str123 += strChannelName + ":\n"; + str123 += function.GetInfo("function"); + // str123 += "\n"; + + return str123; + } +}; + +// 基础检测功能 mark线 +struct Base_Function_MarkLine +{ + + bool bOpen; // 是否开启 + cv::Rect searchRoi; // mark的搜索区域 + int x_sheild_width; + int y_sheild_width; + bool bUse_Roi_Sheild; // 是否开启区域屏蔽 + bool bUse_qx_Sheild; // 是否开启缺陷屏蔽 + std::vector sheil_qx_List; // 屏蔽缺陷list + float qx_sheild_iou; // 屏蔽iou + + Base_Function_MarkLine() + { + Init(); + } + void Init() + { + bOpen = false; + searchRoi = cv::Rect(0, 0, 0, 0); + x_sheild_width = 0; + y_sheild_width = 0; + bUse_Roi_Sheild = false; + bUse_qx_Sheild = false; + sheil_qx_List.clear(); + sheil_qx_List.shrink_to_fit(); + qx_sheild_iou = 0.1; + } + + void copy(Base_Function_MarkLine tem) + { + this->bOpen = tem.bOpen; + this->searchRoi = tem.searchRoi; + this->x_sheild_width = tem.x_sheild_width; + this->y_sheild_width = tem.y_sheild_width; + this->qx_sheild_iou = tem.qx_sheild_iou; + + this->bUse_Roi_Sheild = tem.bUse_Roi_Sheild; + this->bUse_qx_Sheild = tem.bUse_qx_Sheild; + this->sheil_qx_List.assign(tem.sheil_qx_List.begin(), tem.sheil_qx_List.end()); + } + void print(std::string str) + { + printf("%s>>bOpen %d bUse_Roi_Sheild %d bUse_qx_Sheild %d x_sheild_width %d y_sheild_width %d qx_sheild_iou %f search roi %d %d %d %d\n", str.c_str(), + bOpen, bUse_Roi_Sheild, bUse_qx_Sheild, x_sheild_width, y_sheild_width, qx_sheild_iou, searchRoi.x, searchRoi.y, searchRoi.width, searchRoi.height); + + for (int i = 0; i < sheil_qx_List.size(); i++) + { + printf("%s ", sheil_qx_List.at(i).c_str()); + } + printf(" \n"); + } + std::string GetInfo(std::string str) + { + char buffer[256]; + sprintf(buffer, "%s>>bOpen %d bUse_Roi_Sheild %d bUse_qx_Sheild %d x_sheild_width %d y_sheild_width %d qx_sheild_iou %f search roi %d %d %d %d\n", str.c_str(), + bOpen, bUse_Roi_Sheild, bUse_qx_Sheild, x_sheild_width, y_sheild_width, qx_sheild_iou, searchRoi.x, searchRoi.y, searchRoi.width, searchRoi.height); + std::string str123 = buffer; + + for (int i = 0; i < sheil_qx_List.size(); i++) + { + str123 += sheil_qx_List.at(i) + ";"; + } + str123 += "\n"; + return str123; + } +}; +// 基础检测功能 +struct BaseCheckFunction +{ + Base_Function_MarkLine markLine; + BaseCheckFunction() + { + Init(); + } + void Init() + { + markLine.Init(); + } + void copy(BaseCheckFunction tem) + { + this->markLine.copy(tem.markLine); + } + void print(std::string str) + { + markLine.print("markLine"); + } + std::string GetInfo(std::string str) + { + std::string str123 = ""; + str123 += markLine.GetInfo("markLine"); + // str123 += "\n"; + return str123; + } +}; +// 所有通道检测功能 +struct ALLChannelCheckFunction +{ + std::vector channelFunctionArr; // 所有通道的参数。 + ALLChannelCheckFunction() + { + Init(); + } + void Init() + { + channelFunctionArr.clear(); + channelFunctionArr.shrink_to_fit(); + } + void copy(ALLChannelCheckFunction tem) + { + this->channelFunctionArr.assign(tem.channelFunctionArr.begin(), tem.channelFunctionArr.end()); + } + void print(std::string str) + { + printf("%s===========================\n", str.c_str()); + for (int i = 0; i < channelFunctionArr.size(); i++) + { + channelFunctionArr.at(i).print(""); + } + printf("%s===========================\n", str.c_str()); + } +}; + +// 和相机相关的分析参数 +struct AnalysisyConfigST +{ + std::string strSkuName; + CommonCheckConfigST commonCheckConfig; // 和图片相关的参数 + + ALLChannelCheckFunction checkFunction; // 每个通道的检测功能 + + BaseCheckFunction baseFunction; // 检测检测的function + AnalysisyConfigST() + { + strSkuName = ""; + } + void copy(AnalysisyConfigST tem) + { + this->strSkuName = tem.strSkuName; + this->commonCheckConfig.copy(tem.commonCheckConfig); + this->checkFunction.copy(tem.checkFunction); + this->baseFunction.copy(tem.baseFunction); + } + void print(std::string str) + { + printf("%s=============AnalysisyConfigST==============\n", str.c_str()); + checkFunction.print("checkFunction"); + baseFunction.print("baseFunction"); + printf("%s============AnalysisyConfigST===============\n", str.c_str()); + } +}; +// 金佰利 图片亮度值 参数 后来添加的 +struct ImgBrightnessROIConfig +{ + bool bcheck; + cv::Rect imageBrightnessROI; // 图像亮度检测区域 + int minthreshold; // 最小灰度阈值 + int maxthreshold; // 最大灰度阈值 + int alarmSheet; // 检测张数 + ImgBrightnessROIConfig() + { + bcheck = false; + imageBrightnessROI = cv::Rect(0, 0, 0, 0); + minthreshold = 0; + maxthreshold = 0; + alarmSheet = 0; + } + void copy(ImgBrightnessROIConfig tem) + { + this->bcheck = tem.bcheck; + this->imageBrightnessROI = tem.imageBrightnessROI; + this->maxthreshold = tem.maxthreshold; + this->minthreshold = tem.minthreshold; + this->alarmSheet = tem.alarmSheet; + } +}; + +// 预处理图片参数信息 +struct PreDealImgConfig +{ + // 图片预处理: + // 1:cut到指定大小 + // 2、bresize = true, 缩放到模型输入图片尺寸大小 + // 3、bInAI_ImgFflip 输入模型的图片是否要 水平翻转 + // 4、bOutAI_ImgFflip 模型输出的图片是否要 水平翻转 + cv::Rect cutRoi; // 图片裁剪区域信息 + bool bresize; // 是否要resize 到模型输入图尺寸大小 + bool bInAI_ImgFflip; // 模型输入的图片是否翻转 + bool bOutAI_ImgFflip; // 模型输出的图片是否翻转 + PreDealImgConfig() + { + cutRoi.x = 0; + cutRoi.y = 0; + cutRoi.width = 0; + cutRoi.height = 0; + bInAI_ImgFflip = false; + bOutAI_ImgFflip = false; + bresize = false; + } + void copy(PreDealImgConfig tem) + { + this->cutRoi.x = tem.cutRoi.x; + this->cutRoi.y = tem.cutRoi.y; + this->cutRoi.width = tem.cutRoi.width; + this->cutRoi.height = tem.cutRoi.height; + this->bInAI_ImgFflip = tem.bInAI_ImgFflip; + this->bOutAI_ImgFflip = tem.bOutAI_ImgFflip; + this->bresize = tem.bresize; + } +}; + +// 检测基本参数,包括基本信息,和深度学习模型路径参数 +struct CheckConfigST +{ + ImageInfo Srcimg_in; + ImageInfo resultimg_out; + PreDealImgConfig preDealImgConfig; + ModelConfigST modelConfig; // 深度模型参数 + CAM_CONFIGINFO_ camConfig; + CheckConfigST() + { + } + void copy(CheckConfigST tem) + { + this->preDealImgConfig.copy(tem.preDealImgConfig); + this->modelConfig.copy(tem.modelConfig); + this->Srcimg_in.copy(tem.Srcimg_in); + this->resultimg_out.copy(tem.resultimg_out); + this->camConfig.copy(tem.camConfig); + } +}; +struct BLobResult +{ + int nresult; // 最后的结果 + cv::Rect roi; // 位置 + int AI_qx_type; // 缺陷类型, + int area; // Blob- 面积 + int energy; // Blob-能量 + float JudgArea; // Blob- 调整后的面积 平方毫米 + float len; // Blob- 长度 + int maxValue; // Blob- 最大亮度 + float grayDis; // Blob- 灰阶 + float density; // Blob- 密度 + BLobResult() + { + Init(); + } + void Init() + { + nresult = 0; // 最后的结果 + roi = {0, 0, 0, 0}; // 位置 + AI_qx_type = 0; // 缺陷类型, + area = 0; // Blob- 面积 + energy = 0; // Blob-能量 + JudgArea = 0; // Blob- 调整后的面积 平方毫米 + len = 0; // Blob- 长度 + maxValue = 0; // Blob- 最大亮度 + grayDis = 0; // Blob- 灰阶 + density = 0; // Blob- 密度 + } +}; +// 检测结果 +struct DetResultST +{ + std::vector BLobResultList; + DetResultST() + { + Init(); + } + void Init() + { + BLobResultList.erase(BLobResultList.begin(), BLobResultList.end()); + BLobResultList.clear(); + } + void copy(DetResultST tem) + { + this->BLobResultList.assign(tem.BLobResultList.begin(), tem.BLobResultList.end()); + } +}; +#endif //_CORELOGICFACTORY_HPP_ \ No newline at end of file diff --git a/ConfigModule/include/ConfigBase.h b/ConfigModule/include/ConfigBase.h new file mode 100644 index 0000000..72684bb --- /dev/null +++ b/ConfigModule/include/ConfigBase.h @@ -0,0 +1,63 @@ +#ifndef ConfigBase_H_ +#define ConfigBase_H_ +#include + +#define CONFIGBASE_VERSION 4 +enum CONFIG_TYPE_ +{ + ConfigType_Analysisy_Common_XL, + ConfigType_Check_XL, + ConfigType_Image_In, + ConfigType_Image_out, + ConfigType_BloB, + ConfigType_Count, +}; +struct ImageInfo +{ + int width; + int height; + int channels; + ImageInfo() + { + width = 0; + height = 0; + channels = 0; + } + void copy(ImageInfo tem) + { + + this->width = tem.width; + this->height = tem.height; + this->channels = tem.channels; + } + void print(std::string str) + { + printf("%s width=%d height=%d channels=%d\n", str.c_str(), width, height, channels); + } +}; +class ConfigBase +{ +protected: + ConfigBase() {} + +public: + // delete camera interface + ~ConfigBase() {} + static ConfigBase *GetInstance(); + + // 获取参数更新状态 true 有更新 + virtual bool GetConfigUpdataStatus(int nConfigType, int nidx) = 0; + // 复制想使用的参数 + virtual int GetConfig(int nConfigType, void *pconfig) = 0; + + // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 + virtual int UpdateConfig(void *pconfig, int nConfigType) = 0; + virtual int UpdateJSONConfig(void *pconfig, int nConfigType) = 0; + + // 返回检测版本信息 + virtual std::string GetVersion() = 0; + // 返回错误信息 + virtual std::string GetErrorInfo() = 0; +}; + +#endif \ No newline at end of file diff --git a/ConfigModule/include/ConfigInstance.h b/ConfigModule/include/ConfigInstance.h new file mode 100644 index 0000000..c914c7d --- /dev/null +++ b/ConfigModule/include/ConfigInstance.h @@ -0,0 +1,46 @@ +#ifndef ConfigInstance_H_ +#define ConfigInstance_H_ +#include "JsonCoversion.h" +#include +#include +#include +#include "ConfigBase.h" +#include "Define.h" +#include "JsonConfig.h" +#include "CheckConfigDefine.h" +class ConfigInstance : public ConfigBase +{ + +public: + ConfigInstance(); + ~ConfigInstance(); + bool GetConfigUpdataStatus(int nConfigType,int nidx); + // 获取想使用的参数 + int GetConfig(int nConfigType,void *pconfig) ; + // 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常 + int UpdateConfig(void *pconfig, int nConfigType); + int UpdateJSONConfig(void *pconfig, int nConfigType); + // 返回检测版本信息 + std::string GetVersion(); + // 返回错误信息 + std::string GetErrorInfo(); + +private: + // updata analysis cofnig + int Updata_analysis(Json::Value json_value); + int Updata_Check(Json::Value json_value); + //设置 参数更新状态 + int SetStatus( int nConfigType); + // 成员变量 +private: + int m_ErrorValue; //错误代码 + std::mutex mutex_status; + + bool m_USER_ConfigUpdataStatusList[ConfigType_Count][MAX_USER_COUNT]; + + AnalysisyConfigST m_AnalysisyConfig; + CheckConfigST m_CheckConfig; + +}; + +#endif \ No newline at end of file diff --git a/ConfigModule/include/Define.h b/ConfigModule/include/Define.h new file mode 100644 index 0000000..9b511db --- /dev/null +++ b/ConfigModule/include/Define.h @@ -0,0 +1,46 @@ +#ifndef Define_H_ +#define Define_H_ +#include + +// 参数使用最大的用户数 用以更新 参数使用 +#define MAX_USER_COUNT 10 + +enum ERROR_TYPE_Config_ +{ + ERROR_Type_Ok, + ERROR_Type_JsonNull, + ERROR_Type_ConfigType, + ERROR_Type_Count, +}; +static const std::string ERROR_TYPE_Names[] = + { + "OK", + "Json Is Null", + "Config Type Error"}; + +struct CommonParamST +{ + std::string image; + std::string skuName; + std::string value; + CommonParamST() + { + image = ""; + value = ""; + skuName = ""; + } + void copy(CommonParamST tem) + { + this->image = tem.image; + this->value = tem.value; + this->skuName = tem.skuName; + } +}; +enum CHECK_INSTUCT_ +{ + CHECK_INSTUCT_NULL = 1, // 空 + CHECK_INSTUCT_WhiteAndBlack = CHECK_INSTUCT_NULL * 2, // WTB,BTW,HB3,HB4 使用单独检查方法 + +}; + +#endif \ No newline at end of file diff --git a/ConfigModule/include/JsonConfig.h b/ConfigModule/include/JsonConfig.h new file mode 100644 index 0000000..b5d7736 --- /dev/null +++ b/ConfigModule/include/JsonConfig.h @@ -0,0 +1,86 @@ +#ifndef CamConfig_H +#define CamConfig_H + +#include "JsonCoversion.h" +#include +#include +#include "CheckConfigDefine.h" +#include "Define.h" + +class CommonParamJson : public JsonCoversion +{ +public: + CommonParamJson() {} + virtual ~CommonParamJson() {} + +public: + virtual Json::Value toJsonValue(); + virtual void toObjectFromValue(Json::Value root); + int GetConfig(CommonParamST &config); + +private: + CommonParamST _config; +}; + +class CommonParamToCheckConfigJson : public JsonCoversion +{ +public: + CommonParamToCheckConfigJson() {} + virtual ~CommonParamToCheckConfigJson() {} + +public: + virtual Json::Value toJsonValue(); + virtual void toObjectFromValue(Json::Value root); + int GetConfig(CommonCheckConfigST &config); + +private: + CommonCheckConfigST _config; +}; + +class CheckConfigJson : public JsonCoversion +{ +public: + CheckConfigJson() {} + virtual ~CheckConfigJson() {} + +public: + virtual Json::Value toJsonValue(); + virtual void toObjectFromValue(Json::Value root); + int GetConfig(CheckConfigST &config); + +private: + CheckConfigST _config; +}; + +class ChannelFuntonConfigJson : public JsonCoversion +{ +public: + ChannelFuntonConfigJson() {} + virtual ~ChannelFuntonConfigJson() {} + +public: + virtual Json::Value toJsonValue(); + virtual void toObjectFromValue(Json::Value root); + int GetConfig(ALLChannelCheckFunction &config); + int GetFunction(Json::Value value, CheckFunction &function); + +private: + ALLChannelCheckFunction _config; +}; + +class BaseFuntonConfigJson : public JsonCoversion +{ +public: + BaseFuntonConfigJson() {} + virtual ~BaseFuntonConfigJson() {} + +public: + virtual Json::Value toJsonValue(); + virtual void toObjectFromValue(Json::Value root); + int GetConfig(BaseCheckFunction &config); + int GetFunction(Json::Value value); + +private: + BaseCheckFunction _config; +}; +#endif // diff --git a/ConfigModule/include/JsonCoversion.h b/ConfigModule/include/JsonCoversion.h new file mode 100644 index 0000000..5419e33 --- /dev/null +++ b/ConfigModule/include/JsonCoversion.h @@ -0,0 +1,31 @@ +#ifndef JsonCoversion_H +#define JsonCoversion_H +#include +#include +#include +#include "json/json.h" +using namespace std; + +class JsonCoversion +{ + protected: + Json::Value root; + + // Json::FastWriter writer; //弃用 改用StreamWriterBuilder + Json::StreamWriterBuilder writerBuilder; + + // Json::Reader reader; //弃用 改用CharReaderBuilder + Json::CharReaderBuilder readerBuilder; + public: + JsonCoversion(); + virtual ~JsonCoversion(); + protected: + public: + string toJson(); + void toObject(string & strBuf); + protected: + virtual Json::Value toJsonValue() = 0; + virtual void toObjectFromValue(Json::Value root) = 0; +}; + +#endif // JsonCoversion_H diff --git a/ConfigModule/include/json/json-forwards.h b/ConfigModule/include/json/json-forwards.h new file mode 100644 index 0000000..45d2e46 --- /dev/null +++ b/ConfigModule/include/json/json-forwards.h @@ -0,0 +1,346 @@ +/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json-forwards.h" +/// This header provides forward declaration for all JsonCpp types. + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and +The JsonCpp Authors, and is released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED +# define JSON_FORWARD_AMALGAMATED_H_INCLUDED +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED +#include +#include //typedef int64_t, uint64_t +#include //typedef String + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgamated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) // MSVC +#if _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // MSVC 6 + +#if _MSC_VER >= 1500 // MSVC 2008 + /// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#endif // defined(_MSC_VER) + +// In c++11 the override keyword allows you to explicitly define that a function +// is intended to override the base-class version. This makes the code more +// manageable and fixes a set of common hard-to-find bugs. +#if __cplusplus >= 201103L +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT throw() +#if _MSC_VER >= 1800 // MSVC 2013 +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OP_EXPLICIT +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OVERRIDE +#define JSONCPP_NOEXCEPT throw() +#define JSONCPP_OP_EXPLICIT +#endif + +#ifndef JSON_HAS_RVALUE_REFERENCES + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // MSVC >= 2010 + +#ifdef __clang__ +#if __has_feature(cxx_rvalue_references) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // has_feature + +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // GXX_EXPERIMENTAL + +#endif // __clang__ || __GNUC__ + +#endif // not defined JSON_HAS_RVALUE_REFERENCES + +#ifndef JSON_HAS_RVALUE_REFERENCES +#define JSON_HAS_RVALUE_REFERENCES 0 +#endif + +#ifdef __clang__ +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#endif // __clang__ || __GNUC__ + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +#if __GNUC__ >= 6 +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif + +#if !defined(JSON_IS_AMALGAMATION) + +#include "version.h" + +#if JSONCPP_USING_SECURE_MEMORY +#include "allocator.h" //typedef Allocator +#endif + +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef int64_t Int64; +typedef uint64_t UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +#if JSONCPP_USING_SECURE_MEMORY +#define JSONCPP_STRING \ + std::basic_string, Json::SecureAllocator > +#define JSONCPP_OSTRINGSTREAM \ + std::basic_ostringstream, \ + Json::SecureAllocator > +#define JSONCPP_OSTREAM std::basic_ostream > +#define JSONCPP_ISTRINGSTREAM \ + std::basic_istringstream, \ + Json::SecureAllocator > +#define JSONCPP_ISTREAM std::istream +#else +#define JSONCPP_STRING std::string +#define JSONCPP_OSTRINGSTREAM std::ostringstream +#define JSONCPP_OSTREAM std::ostream +#define JSONCPP_ISTRINGSTREAM std::istringstream +#define JSONCPP_ISTREAM std::istream +#endif // if JSONCPP_USING_SECURE_MEMORY +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED diff --git a/ConfigModule/include/json/json.h b/ConfigModule/include/json/json.h new file mode 100644 index 0000000..6d9a0bc --- /dev/null +++ b/ConfigModule/include/json/json.h @@ -0,0 +1,2268 @@ +/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json.h" + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and +The JsonCpp Authors, and is released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_AMALGAMATED_H_INCLUDED +# define JSON_AMALGAMATED_H_INCLUDED +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + +// DO NOT EDIT. This file (and "version") is generated by CMake. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +#define JSON_VERSION_H_INCLUDED + +#define JSONCPP_VERSION_STRING "1.8.4" +#define JSONCPP_VERSION_MAJOR 1 +#define JSONCPP_VERSION_MINOR 8 +#define JSONCPP_VERSION_PATCH 4 +#define JSONCPP_VERSION_QUALIFIER +#define JSONCPP_VERSION_HEXA \ + ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ + (JSONCPP_VERSION_PATCH << 8)) + +#ifdef JSONCPP_USING_SECURE_MEMORY +#undef JSONCPP_USING_SECURE_MEMORY +#endif +#define JSONCPP_USING_SECURE_MEMORY 0 +// If non-zero, the library zeroes any memory that it has allocated before +// it frees its memory. + +#endif // JSON_VERSION_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED +#include +#include //typedef int64_t, uint64_t +#include //typedef String + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgamated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) // MSVC +#if _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // MSVC 6 + +#if _MSC_VER >= 1500 // MSVC 2008 + /// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#endif // defined(_MSC_VER) + +// In c++11 the override keyword allows you to explicitly define that a function +// is intended to override the base-class version. This makes the code more +// manageable and fixes a set of common hard-to-find bugs. +#if __cplusplus >= 201103L +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT throw() +#if _MSC_VER >= 1800 // MSVC 2013 +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OP_EXPLICIT +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1900 +#define JSONCPP_OVERRIDE override +#define JSONCPP_NOEXCEPT noexcept +#define JSONCPP_OP_EXPLICIT explicit +#else +#define JSONCPP_OVERRIDE +#define JSONCPP_NOEXCEPT throw() +#define JSONCPP_OP_EXPLICIT +#endif + +#ifndef JSON_HAS_RVALUE_REFERENCES + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // MSVC >= 2010 + +#ifdef __clang__ +#if __has_feature(cxx_rvalue_references) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // has_feature + +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // GXX_EXPERIMENTAL + +#endif // __clang__ || __GNUC__ + +#endif // not defined JSON_HAS_RVALUE_REFERENCES + +#ifndef JSON_HAS_RVALUE_REFERENCES +#define JSON_HAS_RVALUE_REFERENCES 0 +#endif + +#ifdef __clang__ +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#endif // __clang__ || __GNUC__ + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +#if __GNUC__ >= 6 +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif + +#if !defined(JSON_IS_AMALGAMATION) + +#include "version.h" + +#if JSONCPP_USING_SECURE_MEMORY +#include "allocator.h" //typedef Allocator +#endif + +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef int64_t Int64; +typedef uint64_t UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +#if JSONCPP_USING_SECURE_MEMORY +#define JSONCPP_STRING \ + std::basic_string, Json::SecureAllocator > +#define JSONCPP_OSTRINGSTREAM \ + std::basic_ostringstream, \ + Json::SecureAllocator > +#define JSONCPP_OSTREAM std::basic_ostream > +#define JSONCPP_ISTRINGSTREAM \ + std::basic_istringstream, \ + Json::SecureAllocator > +#define JSONCPP_ISTREAM std::istream +#else +#define JSONCPP_STRING std::string +#define JSONCPP_OSTRINGSTREAM std::ostringstream +#define JSONCPP_OSTREAM std::ostream +#define JSONCPP_ISTRINGSTREAM std::istringstream +#define JSONCPP_ISTREAM std::istream +#endif // if JSONCPP_USING_SECURE_MEMORY +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +#define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_; +}; + +} // namespace Json + +#pragma pack(pop) + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +#define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +#ifndef JSON_USE_CPPTL_SMALLMAP +#include +#else +#include +#endif +#ifdef JSON_USE_CPPTL +#include +#endif + +// Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +#if defined(_MSC_VER) +#define JSONCPP_NORETURN __declspec(noreturn) +#elif defined(__GNUC__) +#define JSONCPP_NORETURN __attribute__((__noreturn__)) +#else +#define JSONCPP_NORETURN +#endif +#endif + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +/** Base class for all exceptions we throw. + * + * We use nothing but these internally. Of course, STL can throw others. + */ +class JSON_API Exception : public std::exception { +public: + Exception(JSONCPP_STRING const& msg); + ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; + char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; + +protected: + JSONCPP_STRING msg_; +}; + +/** Exceptions which the user cannot easily avoid. + * + * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input + * + * \remark derived from Json::Exception + */ +class JSON_API RuntimeError : public Exception { +public: + RuntimeError(JSONCPP_STRING const& msg); +}; + +/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. + * + * These are precondition-violations (user bugs) and internal errors (our bugs). + * + * \remark derived from Json::Exception + */ +class JSON_API LogicError : public Exception { +public: + LogicError(JSONCPP_STRING const& msg); +}; + +/// used internally +JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg); +/// used internally +JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg); + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignment takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : c_str_(czstring) {} + + operator const char*() const { return c_str_; } + + const char* c_str() const { return c_str_; } + +private: + const char* c_str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * Values of an #objectValue or #arrayValue can be accessed using operator[]() + * methods. + * Non-const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resized and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtain default value in the case the + * required element does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + * + * \note #Value string-length fit in size_t, but keys must be < 2^30. + * (The reason is an implementation detail.) A #CharReader will raise an + * exception if a bound is exceeded to avoid security holes in your app, + * but the Value API does *not* check bounds. That is the responsibility + * of the caller. + */ +class JSON_API Value { + friend class ValueIteratorBase; + +public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +#if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + // Required for boost integration, e. g. BOOST_TEST + typedef std::string value_type; + + static const Value& null; ///< We regret this reference to a global instance; + ///< prefer the simpler Value(). + static const Value& nullRef; ///< just a kludge for binary-compatibility; same + ///< as null + static Value const& nullSingleton(); ///< Prefer this to null or nullRef. + + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; +#endif // defined(JSON_HAS_INT64) + + /// Default precision for real value for string representation. + static const UInt defaultRealPrecision; + +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else +private: +#endif +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + class CZString { + public: + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; + CZString(ArrayIndex index); + CZString(char const* str, unsigned length, DuplicationPolicy allocate); + CZString(CZString const& other); +#if JSON_HAS_RVALUE_REFERENCES + CZString(CZString&& other); +#endif + ~CZString(); + CZString& operator=(const CZString& other); + +#if JSON_HAS_RVALUE_REFERENCES + CZString& operator=(CZString&& other); +#endif + + bool operator<(CZString const& other) const; + bool operator==(CZString const& other) const; + ArrayIndex index() const; + // const char* c_str() const; ///< \deprecated + char const* data() const; + unsigned length() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + + struct StringStorage { + unsigned policy_ : 2; + unsigned length_ : 30; // 1GB max + }; + + char const* cstr_; // actually, a prefixed string, unless policy is noDup + union { + ArrayIndex index_; + StringStorage storage_; + }; + }; + +public: +#ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +#else + typedef CppTL::SmallMap ObjectValues; +#endif // ifndef JSON_USE_CPPTL_SMALLMAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. +This is useful since clear() and resize() will not alter types. + + Examples: +\code +Json::Value null_value; // null +Json::Value arr_value(Json::arrayValue); // [] +Json::Value obj_value(Json::objectValue); // {} +\endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) + Value(const char* begin, const char* end); ///< Copy all, incl zeroes. + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * \note This works only for null-terminated strings. (We cannot change the + * size of this class, so we have nowhere to store the length, + * which might be computed later for various operations.) + * + * Example of usage: + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode + */ + Value(const StaticString& value); + Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded + ///< zeroes too. +#ifdef JSON_USE_CPPTL + Value(const CppTL::ConstString& value); +#endif + Value(bool value); + /// Deep copy. + Value(const Value& other); +#if JSON_HAS_RVALUE_REFERENCES + /// Move constructor + Value(Value&& other); +#endif + ~Value(); + + /// Deep copy, then swap(other). + /// \note Over-write existing comments. To preserve comments, use + /// #swapPayload(). + Value& operator=(Value other); + + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + /// copy everything. + void copy(const Value& other); + /// copy values but leave comments and source offsets in place. + void copyPayload(const Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; ///< Embedded zeroes could cause you trouble! +#if JSONCPP_USING_SECURE_MEMORY + unsigned getCStringLength() const; // Allows you to understand the length of + // the CString +#endif + JSONCPP_STRING asString() const; ///< Embedded zeroes are possible. + /** Get raw char* of string-value. + * \return false if !string. (Seg-fault if str or end are NULL.) + */ + bool getString(char const** begin, char const** end) const; +#ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +#endif + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return !isNull() + JSONCPP_OP_EXPLICIT operator bool() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to newSize elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex newSize); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](int index); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](int index) const; + + /// If the array contains at least index+1 elements, returns the element + /// value, + /// otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + +#if JSON_HAS_RVALUE_REFERENCES + Value& append(Value&& value); +#endif + + /// Access an object value by name, create a null member if it does not exist. + /// \note Because of our implementation, keys are limited to 2^30 -1 chars. + /// Exceeding that will cause an exception. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + /// \param key may contain embedded nulls. + Value& operator[](const JSONCPP_STRING& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + /// \param key may contain embedded nulls. + const Value& operator[](const JSONCPP_STRING& key) const; + /** \brief Access an object value by name, create a null member if it does not + exist. + + * If the object has no entry for that name, then the member name used to + store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); +#ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const CppTL::ConstString& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const CppTL::ConstString& key) const; +#endif + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \note key may contain embedded nulls. + Value + get(const char* begin, const char* end, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \param key may contain embedded nulls. + Value get(const JSONCPP_STRING& key, const Value& defaultValue) const; +#ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const CppTL::ConstString& key, const Value& defaultValue) const; +#endif + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of object-mutators. + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. + Value const* demand(char const* begin, char const* end); + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + /// \deprecated + void removeMember(const char* key); + /// Same as removeMember(const char*) + /// \param key may contain embedded nulls. + /// \deprecated + void removeMember(const JSONCPP_STRING& key); + /// Same as removeMember(const char* begin, const char* end, Value* removed), + /// but 'key' is null-terminated. + bool removeMember(const char* key, Value* removed); + /** \brief Remove the named map member. + + Update 'removed' iff removed. + \param key may contain embedded nulls. + \return true iff removed (no exceptions) + */ + bool removeMember(JSONCPP_STRING const& key, Value* removed); + /// Same as removeMember(JSONCPP_STRING const& key, Value* removed) + bool removeMember(const char* begin, const char* end, Value* removed); + /** \brief Remove the indexed array element. + + O(n) expensive operations. + Update 'removed' iff removed. + \return true if removed (no exceptions) + */ + bool removeIndex(ArrayIndex index, Value* removed); + + /// Return true if the object has a member named key. + /// \note 'key' must be null-terminated. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + /// \param key may contain embedded nulls. + bool isMember(const JSONCPP_STRING& key) const; + /// Same as isMember(JSONCPP_STRING const& key)const + bool isMember(const char* begin, const char* end) const; +#ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString& key) const; +#endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif + + /// \deprecated Always pass len. + JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.") + void setComment(const char* comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const char* comment, size_t len, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const JSONCPP_STRING& comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + JSONCPP_STRING getComment(CommentPlacement placement) const; + + JSONCPP_STRING toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(ptrdiff_t start); + void setOffsetLimit(ptrdiff_t limit); + ptrdiff_t getOffsetStart() const; + ptrdiff_t getOffsetLimit() const; + +private: + void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); + + Value& resolveReference(const char* key); + Value& resolveReference(const char* key, const char* end); + + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); + + void setComment(const char* text, size_t len); + + char* comment_; + }; + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; // actually ptr to unsigned, followed by str, unless + // !allocated_ + ObjectValues* map_; + } value_; + ValueType type_ : 8; + unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is + // useless. If not allocated_, string_ must be + // null-terminated. + CommentInfo* comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + ptrdiff_t start_; + ptrdiff_t limit_; +}; + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(const JSONCPP_STRING& key); + +private: + enum Kind { kindNone = 0, kindIndex, kindKey }; + JSONCPP_STRING key_; + ArrayIndex index_; + Kind kind_; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ +class JSON_API Path { +public: + Path(const JSONCPP_STRING& path, + const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const JSONCPP_STRING& path, const InArgs& in); + void addPathInArg(const JSONCPP_STRING& path, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind); + static void invalidPath(const JSONCPP_STRING& path, int location); + + Args args_; +}; + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return other.computeDistance(*this); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value, or -1 if it is not an + /// arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value, or "" if it is not an + /// objectValue. + /// \note Avoid `c_str()` on result, as embedded zeroes are possible. + JSONCPP_STRING name() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + /// \deprecated This cannot be used for UTF-8 strings, since there can be + /// embedded nulls. + JSONCPP_DEPRECATED("Use `key = name();` instead.") + char const* memberName() const; + /// Return the member name of the referenced Value, or NULL if it is not an + /// objectValue. + /// \note Better version than memberName(). Allows embedded nulls. + char const* memberName(char const** end) const; + +protected: + Value& deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; + +public: + // For some reason, BORLAND needs these at the end, rather + // than earlier. No idea why. + ValueIteratorBase(); + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef const Value value_type; + // typedef unsigned int size_t; + // typedef int difference_type; + typedef const Value& reference; + typedef const Value* pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + ValueConstIterator(ValueIterator const& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef Value& reference; + typedef Value* pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + explicit ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +inline void swap(Value& a, Value& b) { a.swap(b); } + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +#define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Unserialize a JSON document into a + *Value. + * + * \deprecated Use CharReader and CharReaderBuilder. + */ +class JSON_API Reader { +public: + typedef char Char; + typedef const Char* Location; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + * + */ + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + JSONCPP_STRING message; + }; + + /** \brief Constructs a Reader allowing all features + * for parsing. + */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set + * for parsing. + */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * \param document UTF-8 encoded string containing the document to read. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + * back during + * serialization, \c false to discard comments. + * This parameter is ignored if + * Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool + parse(const std::string& document, Value& root, bool collectComments = true); + + /** \brief Read a Value from a JSON + document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + back during + * serialization, \c false to discard comments. + * This parameter is ignored if + Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") + JSONCPP_STRING getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + */ + JSONCPP_STRING getFormattedErrorMessages() const; + + /** \brief Returns a vector of structured erros encounted while parsing. + * \return A (possibly empty) vector of StructuredError objects. Currently + * only one error can be returned, but the caller should tolerate + * multiple + * errors. This can occur if the parser recovers from a non-fatal + * parse error and then encounters additional errors. + */ + std::vector getStructuredErrors() const; + + /** \brief Add a semantic error message. + * \param value JSON Value location associated with the error + * \param message The error message. + * \return \c true if the error was successfully added, \c false if the + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const JSONCPP_STRING& message); + + /** \brief Add a semantic error message with extra context. + * \param value JSON Value location associated with the error + * \param message The error message. + * \param extra Additional JSON Value location to contextualize the error + * \return \c true if the error was successfully added, \c false if either + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra); + + /** \brief Return whether there are any errors. + * \return \c true if there are no errors to report \c false if + * errors have occurred. + */ + bool good() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + JSONCPP_STRING message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool + addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static bool containsNewLine(Location begin, Location end); + static JSONCPP_STRING normalizeEOL(Location begin, Location end); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + JSONCPP_STRING document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + JSONCPP_STRING commentsBefore_; + Features features_; + bool collectComments_; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() {} + /** \brief Read a Value from a JSON + document. + * The document must be a UTF-8 encoded string containing the document to + read. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param errs [out] Formatted error messages (if not NULL) + * a user friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + virtual bool parse(char const* beginDoc, + char const* endDoc, + Value* root, + JSONCPP_STRING* errs) = 0; + + class JSON_API Factory { + public: + virtual ~Factory() {} + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + +Usage: +\code + using namespace Json; + CharReaderBuilder builder; + builder["collectComments"] = false; + Value value; + JSONCPP_STRING errs; + bool ok = parseFromStream(builder, std::cin, &value, &errs); +\endcode +*/ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + These are case-sensitive. + Available settings (case-sensitive): + - `"collectComments": false or true` + - true to collect comment and allow writing them + back during serialization, false to discard comments. + This parameter is ignored if allowComments is false. + - `"allowComments": false or true` + - true if comments are allowed. + - `"strictRoot": false or true` + - true if root must be either an array or an object value + - `"allowDroppedNullPlaceholders": false or true` + - true if dropped null placeholders are allowed. (See + StreamWriterBuilder.) + - `"allowNumericKeys": false or true` + - true if numeric object keys are allowed. + - `"allowSingleQuotes": false or true` + - true if '' are allowed for strings (both keys and values) + - `"stackLimit": integer` + - Exceeding stackLimit (recursive depth of `readValue()`) will + cause an exception. + - This is a security issue (seg-faults caused by deeply nested JSON), + so the default is low. + - `"failIfExtra": false or true` + - If true, `parse()` returns false when extra non-whitespace trails + the JSON value in the input string. + - `"rejectDupKeys": false or true` + - If true, `parse()` returns false when a key is duplicated within an + object. + - `"allowSpecialFloats": false or true` + - If true, special float values (NaNs and infinities) are allowed + and their values are lossfree restorable. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + ~CharReaderBuilder() JSONCPP_OVERRIDE; + + CharReader* newCharReader() const JSONCPP_OVERRIDE; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](JSONCPP_STRING key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); +}; + +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream(CharReader::Factory const&, + JSONCPP_ISTREAM&, + Value* root, + std::string* errs); + +/** \brief Read from 'sin' into 'root'. + + Always keep comments from the input JSON. + + This can be used to read a file into a particular sub-object. + For example: + \code + Json::Value root; + cin >> root["dir"]["file"]; + cout << root; + \endcode + Result: + \verbatim + { + "dir": { + "file": { + // The input stream JSON would be nested here. + } + } + } + \endverbatim + \throw std::exception on parse error. + \see Json::operator<<() +*/ +JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_READER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +class Value; + +/** + +Usage: +\code + using namespace Json; + void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { + std::unique_ptr const writer( + factory.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush + } +\endcode +*/ +class JSON_API StreamWriter { +protected: + JSONCPP_OSTREAM* sout_; // not owned; will not delete +public: + StreamWriter(); + virtual ~StreamWriter(); + /** Write Value into document as configured in sub-class. + Do not take ownership of sout, but maintain a reference during function. + \pre sout != NULL + \return zero on success (For now, we always return zero, so check the + stream instead.) \throw std::exception possibly, depending on configuration + */ + virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0; + + /** \brief A simple abstract factory. + */ + class JSON_API Factory { + public: + virtual ~Factory(); + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const = 0; + }; // Factory +}; // StreamWriter + +/** \brief Write into stringstream, then return string, for convenience. + * A StreamWriter will be created from the factory, used, and then deleted. + */ +JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, + Value const& root); + +/** \brief Build a StreamWriter implementation. + +Usage: +\code + using namespace Json; + Value value = ...; + StreamWriterBuilder builder; + builder["commentStyle"] = "None"; + builder["indentation"] = " "; // or whatever you like + std::unique_ptr writer( + builder.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush +\endcode +*/ +class JSON_API StreamWriterBuilder : public StreamWriter::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + Available settings (case-sensitive): + - "commentStyle": "None" or "All" + - "indentation": "". + - Setting this to an empty string also omits newline characters. + - "enableYAMLCompatibility": false or true + - slightly change the whitespace around colons + - "dropNullPlaceholders": false or true + - Drop the "null" string from the writer's output for nullValues. + Strictly speaking, this is not valid JSON. But when the output is being + fed to a browser's JavaScript, it makes for smaller output and the + browser can handle the output just fine. + - "useSpecialFloats": false or true + - If true, outputs non-finite floating point values in the following way: + NaN values as "NaN", positive infinity as "Infinity", and negative + infinity as "-Infinity". + - "precision": int + - Number of precision digits for formatting of real values. + - "precisionType": "significant"(default) or "decimal" + - Type of precision for formatting of real values. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + StreamWriterBuilder(); + ~StreamWriterBuilder() JSONCPP_OVERRIDE; + + /** + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + /** A simple way to update a specific setting. + */ + Value& operator[](JSONCPP_STRING key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults + */ + static void setDefaults(Json::Value* settings); +}; + +/** \brief Abstract class for writers. + * \deprecated Use StreamWriter. (And really, this is an implementation detail.) + */ +class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { +public: + virtual ~Writer(); + + virtual JSONCPP_STRING write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be useful to support feature such as RPC where bandwidth is limited. + * \sa Reader, Value + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter + : public Writer { +public: + FastWriter(); + ~FastWriter() JSONCPP_OVERRIDE {} + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + +private: + void writeValue(const Value& value); + + JSONCPP_STRING document_; + bool yamlCompatibilityEnabled_; + bool dropNullPlaceholders_; + bool omitEndingLineFeed_; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledWriter : public Writer { +public: + StyledWriter(); + ~StyledWriter() JSONCPP_OVERRIDE {} + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const JSONCPP_STRING& value); + void writeIndent(); + void writeWithIndent(const JSONCPP_STRING& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + JSONCPP_STRING document_; + JSONCPP_STRING indentString_; + unsigned int rightMargin_; + unsigned int indentSize_; + bool addChildValues_; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledStreamWriter { +public: + /** + * \param indentation Each level will be indented by this amount extra. + */ + StyledStreamWriter(const JSONCPP_STRING& indentation = "\t"); + ~StyledStreamWriter() {} + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(JSONCPP_OSTREAM& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const JSONCPP_STRING& value); + void writeIndent(); + void writeWithIndent(const JSONCPP_STRING& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + JSONCPP_OSTREAM* document_; + JSONCPP_STRING indentString_; + unsigned int rightMargin_; + JSONCPP_STRING indentation_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(JSON_HAS_INT64) +JSONCPP_STRING JSON_API valueToString(Int value); +JSONCPP_STRING JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +JSONCPP_STRING JSON_API valueToString(LargestInt value); +JSONCPP_STRING JSON_API valueToString(LargestUInt value); +JSONCPP_STRING JSON_API +valueToString(double value, + unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); +JSONCPP_STRING JSON_API valueToString(bool value); +JSONCPP_STRING JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +/** It should not be possible for a maliciously designed file to + * cause an abort() or seg-fault, so these macros are used only + * for pre-condition violations and internal logic errors. + */ +#if JSON_USE_EXCEPTION + +// @todo <= add detail about condition in exception +#define JSON_ASSERT(condition) \ + { \ + if (!(condition)) { \ + Json::throwLogicError("assert json failed"); \ + } \ + } + +#define JSON_FAIL_MESSAGE(message) \ + { \ + JSONCPP_OSTRINGSTREAM oss; \ + oss << message; \ + Json::throwLogicError(oss.str()); \ + abort(); \ + } + +#else // JSON_USE_EXCEPTION + +#define JSON_ASSERT(condition) assert(condition) + +// The call to assert() will show the failure message in debug builds. In +// release builds we abort, for a core-dump or debugger. +#define JSON_FAIL_MESSAGE(message) \ + { \ + JSONCPP_OSTRINGSTREAM oss; \ + oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } + +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_AMALGAMATED_H_INCLUDED diff --git a/ConfigModule/src/ConfigBase.cpp b/ConfigModule/src/ConfigBase.cpp new file mode 100644 index 0000000..0998931 --- /dev/null +++ b/ConfigModule/src/ConfigBase.cpp @@ -0,0 +1,19 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ConfigBase.h" +#include "ConfigInstance.h" + +ConfigBase* ConfigBase::GetInstance() +{ + return (ConfigBase*)new ConfigInstance(); +} +bool compareBylay(const RegionConfigST &a, const RegionConfigST &b) +{ + return a.basicInfo.lay < b.basicInfo.lay; +} \ No newline at end of file diff --git a/ConfigModule/src/ConfigInstance.cpp b/ConfigModule/src/ConfigInstance.cpp new file mode 100644 index 0000000..8bb8478 --- /dev/null +++ b/ConfigModule/src/ConfigInstance.cpp @@ -0,0 +1,213 @@ +/* + * @Author: your name + * @Date: 2022-04-20 15:50:00 + * @LastEditTime: 2022-09-26 16:27:27 + * @LastEditors: sueRimn + * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp + */ +#include "ConfigInstance.h" + +ConfigInstance::ConfigInstance() +{ + m_ErrorValue = ERROR_Type_Ok; +} + +ConfigInstance::~ConfigInstance() +{ +} + +bool ConfigInstance::GetConfigUpdataStatus(int nConfigType, int nidx) +{ + std::lock_guard lock(mutex_status); + + if (nConfigType >= 0 && nConfigType < ConfigType_Count && nidx >= 0 && nidx < MAX_USER_COUNT) + { + m_ErrorValue = ERROR_Type_Ok; + bool status = m_USER_ConfigUpdataStatusList[nConfigType][nidx]; + m_USER_ConfigUpdataStatusList[nConfigType][nidx] = false; + return status; + } + m_ErrorValue = ERROR_Type_ConfigType; + return false; +} + +int ConfigInstance::GetConfig(int nConfigType, void *pconfig) +{ + if (nConfigType >= 0 && nConfigType < ConfigType_Count) + { + } + else + { + m_ErrorValue = ERROR_Type_ConfigType; + return m_ErrorValue; + } + AnalysisyConfigST *p = (AnalysisyConfigST *)pconfig; + CheckConfigST *p1 = (CheckConfigST *)pconfig; + ImageInfo *pimg = (ImageInfo *)pconfig; + switch (nConfigType) + { + case ConfigType_Analysisy_Common_XL: + p->copy(m_AnalysisyConfig); + break; + case ConfigType_Check_XL: + p1->copy(m_CheckConfig); + break; + case ConfigType_Image_In: + pimg->copy(m_CheckConfig.Srcimg_in); + break; + case ConfigType_Image_out: + pimg->copy(m_CheckConfig.resultimg_out); + break; + } + + m_ErrorValue = ERROR_Type_Ok; + return 0; +} + +int ConfigInstance::UpdateConfig(void *pconfig, int nConfigType) +{ + + m_ErrorValue = ERROR_Type_Ok; + return 0; +} + +int ConfigInstance::UpdateJSONConfig(void *pconfig, int nConfigType) +{ + if (pconfig == NULL) + { + m_ErrorValue = ERROR_Type_JsonNull; + return m_ErrorValue; + } + if (nConfigType < 0 || nConfigType >= ConfigType_Count) + { + m_ErrorValue = ERROR_Type_ConfigType; + return m_ErrorValue; + } + + Json::Value *pJsonConfig = (Json::Value *)pconfig; + switch (nConfigType) + { + case ConfigType_Analysisy_Common_XL: + Updata_analysis(*pJsonConfig); + /* code */ + break; + case ConfigType_Check_XL: + /* code */ + Updata_Check(*pJsonConfig); + break; + default: + break; + } + + // getchar(); + m_ErrorValue = ERROR_Type_Ok; + return 0; +} + +std::string ConfigInstance::GetVersion() +{ + m_ErrorValue = ERROR_Type_Ok; + return std::string(); +} + +std::string ConfigInstance::GetErrorInfo() +{ + return ERROR_TYPE_Names[m_ErrorValue]; +} + +int ConfigInstance::Updata_analysis(Json::Value json_value) +{ + + // std::cout << json_value << std::endl; + CommonParamJson configJson; + configJson.toObjectFromValue(json_value); + CommonParamST config; + configJson.GetConfig(config); + + printf("------config.skuName %s \n", config.skuName.c_str()); + + // 解析成对应的 参数 + CommonParamToCheckConfigJson tp; + tp.toObjectFromValue(config.value); + + tp.GetConfig(m_AnalysisyConfig.commonCheckConfig); + m_AnalysisyConfig.strSkuName = config.skuName; + + int img_W = 0; + int img_H = 0; + + for (int i = 0; i < m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size(); i++) + { + if (i == 0) + { + img_W = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).nodebasicConfog.img_width; + img_H = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).nodebasicConfog.img_height; + } + m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).ToMaskImg(); + std::string strpath = "mask_" + std::to_string(i) + ".jpg"; + if (!m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).mask.empty()) + { + cv::imwrite(strpath, m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).mask); + } + } + // for (int i = 0; i < m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size(); i++) + // { + // m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).ToSheildMaskImg(); + // // std::string strpath = "mask_" + std::to_string(i) + ".jpg"; + // // if (!m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).mask.empty()) + // // { + // // cv::imwrite(strpath, m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(i).mask); + // // } + // } + + // 解析成对应的 参数 + ChannelFuntonConfigJson jxjason; + jxjason.toObjectFromValue(config.value); + + jxjason.GetConfig(m_AnalysisyConfig.checkFunction); + for (int i = 0; i < m_AnalysisyConfig.checkFunction.channelFunctionArr.size(); i++) + { + m_AnalysisyConfig.checkFunction.channelFunctionArr.at(i).function.f_ShieldRegion.ToMaskImg(img_W, img_H); + m_AnalysisyConfig.checkFunction.channelFunctionArr.at(i).function.f_EdgeROI.ToMaskImg(img_W, img_H); + m_AnalysisyConfig.checkFunction.channelFunctionArr.at(i).function.f_Image_Align.ToMaskImg(img_W, img_H); + } + + BaseFuntonConfigJson basefjason; + basefjason.toObjectFromValue(config.value); + + basefjason.GetConfig(m_AnalysisyConfig.baseFunction); + + // m_AnalysisyConfig.checkFunction.print("------------ChannelFunction---------------"); + // getchar(); + + // 更新所有状态 + SetStatus(ConfigType_Analysisy_Common_XL); + m_ErrorValue = ERROR_Type_Ok; + return 0; +} + +int ConfigInstance::Updata_Check(Json::Value json_value) +{ + std::cout << json_value << std::endl; + + // 解析成对应的 参数 + CheckConfigJson tp; + tp.toObjectFromValue(json_value); + tp.GetConfig(m_CheckConfig); + // 更新所有状态 + SetStatus(ConfigType_Check_XL); + + m_ErrorValue = ERROR_Type_Ok; + return 0; +} + +int ConfigInstance::SetStatus(int nConfigType) +{ + for (int i = 0; i < MAX_USER_COUNT; i++) + { + m_USER_ConfigUpdataStatusList[nConfigType][i] = true; + } + m_ErrorValue = ERROR_Type_Ok; + return 0; +} diff --git a/ConfigModule/src/Define.cpp b/ConfigModule/src/Define.cpp new file mode 100644 index 0000000..234ceef --- /dev/null +++ b/ConfigModule/src/Define.cpp @@ -0,0 +1 @@ +#include "Define.h" diff --git a/ConfigModule/src/JsonConfig.cpp b/ConfigModule/src/JsonConfig.cpp new file mode 100644 index 0000000..cc960cf --- /dev/null +++ b/ConfigModule/src/JsonConfig.cpp @@ -0,0 +1,1204 @@ +#include "JsonConfig.h" + +Json::Value CommonParamJson::toJsonValue() +{ + return Json::Value(); +} + +void CommonParamJson::toObjectFromValue(Json::Value root) +{ + _config.image = root["image"].asString(); + _config.skuName = root["sku_name"].asString(); + _config.value = root["value"].asString(); +} + +int CommonParamJson::GetConfig(CommonParamST &config) +{ + config.copy(_config); + return 0; +} + +Json::Value CommonParamToCheckConfigJson::toJsonValue() +{ + return Json::Value(); +} + +// 读取和图片相关的参数 +void CommonParamToCheckConfigJson::toObjectFromValue(Json::Value root) +{ + + auto strJson = root.asString(); + Json::CharReaderBuilder builder; + std::unique_ptr reader(builder.newCharReader()); + Json::Value rootvalue; + std::string err; + // std::cout << strJson << std::endl; + auto nSize = strJson.size(); + if (reader->parse(strJson.c_str(), strJson.c_str() + nSize, &rootvalue, &err)) + { + + // 和节点无关参数提取 + { + auto value = rootvalue["base"]; + if (value.isObject()) + { + _config.baseConfig.image_widht = value["image_widht"].asInt(); + _config.baseConfig.Image_height = value["Image_height"].asInt(); + _config.baseConfig.bDrawShieldRoi = value["bDrawShieldRoi"].asBool(); + _config.baseConfig.bDrawPreRoi = value["Draw_PreROI"].asBool(); + _config.baseConfig.bShield_ZF = value["bShield_ZF"].asBool(); + _config.baseConfig.fUP_IOU = value["UP_IOU"].asFloat(); + + _config.baseConfig.bCal_ImageScale = value["bImageScale_Cal"].asBool(); + _config.baseConfig.Product_Size_Width_mm = value["Product_Size_W"].asFloat(); + _config.baseConfig.Product_Size_Height_mm = value["Product_Size_H"].asFloat(); + _config.baseConfig.fImage_Scale_x = value["Image_Scale_X"].asFloat(); + _config.baseConfig.fImage_Scale_y = value["Image_Scale_Y"].asFloat(); + _config.baseConfig.strCamearName = value["CameraName"].asString(); + if (value["Density_R"]) + { + _config.baseConfig.density_R_mm = value["Density_R"].asFloat(); + if (_config.baseConfig.density_R_mm <= 0 || _config.baseConfig.density_R_mm > 99999) + { + _config.baseConfig.density_R_mm = 5; + } + } + + // _config.baseConfig.width_min = value["width_min"].asInt(); // 20231122xls-add + // _config.baseConfig.width_max = value["width_max"].asInt(); + // _config.baseConfig.height_min = value["height_min"].asInt(); + // _config.baseConfig.height_max = value["height_max"].asInt(); // 20231122xls-add + _config.baseConfig.print("baseConfig"); + } + } + // 读取每个节点的参数 + { + auto value_node = rootvalue["node"]; + // 读取每个节点的参数 + for (int i = 0; i < value_node.size(); i++) + { + printf("Node idx %d /%d \n", i, value_node.size()); + + CommonConfigNodeST tem_node; + // 和节点相关基础参数 + { + auto value_node_base = value_node[i]["node_base"]; + // std::cout << value_node_base << std::endl; + + if (value_node_base.isObject()) + { + + tem_node.nodebasicConfog.calss_conf = value_node_base["class_conf"].asFloat(); + tem_node.nodebasicConfog.calss_area = value_node_base["Class_AreaT"].asFloat(); + + tem_node.nodebasicConfog.print("nodebasicConfog"); + } + } + + // 读取当前节点下 的每张图片 一般只读第一张图 + { + auto value_node_imgs = value_node[i]["node_images"]; + + if (value_node_imgs.size() > 0) + { + int img_idx = 0; + tem_node.nodebasicConfog.img_width = value_node_imgs[img_idx]["width"].asInt(); + tem_node.nodebasicConfog.img_height = value_node_imgs[img_idx]["height"].asInt(); + + auto value_node_imgs_region = value_node_imgs[img_idx]["params"]; + printf("tem_node.img_height %d, tem_node.img_width %d region num %d\n", + tem_node.nodebasicConfog.img_height, + tem_node.nodebasicConfog.img_width, + value_node_imgs_region.size()); + + for (int region_idx = 0; region_idx < value_node_imgs_region.size(); region_idx++) + { + printf("region idx %d /%d \n", region_idx, value_node_imgs_region.size()); + + RegionConfigST temRegion; + temRegion.buse = true; + // 1、读取基本参数 + { + auto value_node_imgs_region_base = value_node_imgs_region[region_idx]; + // std::cout< tem_node.nodebasicConfog.img_width) + { + p.x = tem_node.nodebasicConfog.img_width; + } + if (p.y < 0) + { + p.y = 0; + } + if (p.y > tem_node.nodebasicConfog.img_height) + { + p.y = tem_node.nodebasicConfog.img_height; + } + temRegion.basicInfo.pointArry.emplace_back(p); + } + } + } + // 3、读取检测参数 和存图参数 + for (int ParamType_idx = 0; ParamType_idx < ANALYSIS_TYPE_COUNT; ParamType_idx++) + { + if (temRegion.basicInfo.type == 1) + { + continue; + } + + // int param_type = ParamType_idx; + + auto value_node_imgs_region_Check_Param = value_node_imgs_region[region_idx][ANALYSIS_TYPE_Names[ParamType_idx]]; + + if (value_node_imgs_region_Check_Param.isObject()) + { + + for (Json::ValueIterator iter = value_node_imgs_region_Check_Param.begin(); iter != value_node_imgs_region_Check_Param.end(); iter++) + { + CheckConfig_Regions_Param tem_paramValue; + + // const char *name = iter.memberName(); + std::string name = iter.name(); // 新方法,推荐使用 + tem_paramValue.param_name = name; + auto value_node_imgs_region_Check_Param_value = value_node_imgs_region_Check_Param[name]; + + if (value_node_imgs_region_Check_Param_value.isArray()) + { + + for (int idx = 0; idx < value_node_imgs_region_Check_Param_value.size(); idx++) + { + + AandEParam temparam; + temparam.bEnable = value_node_imgs_region_Check_Param_value[idx]["state"].asBool(); + temparam.bOk = value_node_imgs_region_Check_Param_value[idx]["bOK"].asBool(); + if (value_node_imgs_region_Check_Param_value[idx]["area"]) + { + temparam.area = value_node_imgs_region_Check_Param_value[idx]["area"].asFloat(); + } + if (value_node_imgs_region_Check_Param_value[idx]["area_max"]) + { + temparam.area_max = value_node_imgs_region_Check_Param_value[idx]["area_max"].asFloat(); + } + if (value_node_imgs_region_Check_Param_value[idx]["energy"]) + { + temparam.energy = value_node_imgs_region_Check_Param_value[idx]["energy"].asFloat(); + } + + if (value_node_imgs_region_Check_Param_value[idx]["hj"]) + { + temparam.hj = value_node_imgs_region_Check_Param_value[idx]["hj"].asFloat(); + } + + if (value_node_imgs_region_Check_Param_value[idx]["length"]) + { + temparam.length = value_node_imgs_region_Check_Param_value[idx]["length"].asFloat(); + } + + if (value_node_imgs_region_Check_Param_value[idx]["num"]) + { + temparam.num = value_node_imgs_region_Check_Param_value[idx]["num"].asInt(); + } + + if (value_node_imgs_region_Check_Param_value[idx]["dis"]) + { + temparam.dis = value_node_imgs_region_Check_Param_value[idx]["dis"].asFloat(); + } + if (value_node_imgs_region_Check_Param_value[idx]["density"]) + { + temparam.density = value_node_imgs_region_Check_Param_value[idx]["density"].asFloat(); + } + std::string str = ANALYSIS_TYPE_Names[ParamType_idx] + " " + name + " " + std::to_string(idx); + temparam.print(str); + tem_paramValue.addParam(temparam); + } + } + temRegion.checkConfig_Regions_type[ParamType_idx].checkConfig_Regions_Param.push_back(tem_paramValue); + } + } + } + + tem_node.regionConfigArr.push_back(temRegion); + } + } + } + + _config.nodeConfigArr.push_back(tem_node); + } + } + } + else + { + printf("--- ******error json*** \n"); + } +} +int CommonParamToCheckConfigJson::GetConfig(CommonCheckConfigST &config) +{ + config.copy(_config); + return 0; +} + +Json::Value CheckConfigJson::toJsonValue() +{ + return Json::Value(); +} + +void CheckConfigJson::toObjectFromValue(Json::Value root) +{ + { + auto value = root["AI_Model_Path"]; + if (value.isObject()) + { + + _config.modelConfig.defect_model_path = value["defect"].asString(); + _config.modelConfig.YX_1_model_path = value["yx_1"].asString(); + _config.modelConfig.YX_2_model_path = value["yx_2"].asString(); + _config.modelConfig.class_model_path = value["class"].asString(); + _config.modelConfig.defect_wtb_model_path = value["defect_wtb"].asString(); + _config.modelConfig.zf_model_path = value["defect_zf"].asString(); + _config.modelConfig.UP_model_path = value["defect_UP"].asString(); + _config.modelConfig.class_L0_model_path = value["class_L0"].asString(); + _config.modelConfig.class_L255_model_path = value["class_L255"].asString(); + if (value["defect_chess"]) + { + _config.modelConfig.defect_chess_model_path = value["defect_chess"].asString(); + } + + // 1024dyy + std::cout << "_config.modelConfig.defect_model_path=" << _config.modelConfig.defect_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.YX_1_model_path=" << _config.modelConfig.YX_1_model_path << std::endl; // 1126dyy + std::cout << "_config.modelConfig.YX_2_model_path=" << _config.modelConfig.YX_2_model_path << std::endl; // 1126dyy + std::cout << "_config.modelConfig.class_model_path=" << _config.modelConfig.class_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.defect_wtb_model_path=" << _config.modelConfig.defect_wtb_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.defect_chess_model_path=" << _config.modelConfig.defect_chess_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.zf_model_path=" << _config.modelConfig.zf_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.UP_model_path=" << _config.modelConfig.UP_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.class_L0_model_path=" << _config.modelConfig.class_L0_model_path << std::endl; // 1126dyy-add + std::cout << "_config.modelConfig.class_L255_model_path=" << _config.modelConfig.class_L255_model_path << std::endl; // 1126dyy-add + } + } + + { + auto value = root["image_preprocess_param"]; + if (value.isObject()) + { + auto arr = value["crop_roi"]; + if (arr.isArray()) + { + _config.preDealImgConfig.cutRoi.x = arr[0].asInt(); + _config.preDealImgConfig.cutRoi.y = arr[1].asInt(); + _config.preDealImgConfig.cutRoi.width = arr[2].asInt(); + _config.preDealImgConfig.cutRoi.height = arr[3].asInt(); + } + _config.preDealImgConfig.bresize = value["resize"].asBool(); + _config.preDealImgConfig.bInAI_ImgFflip = value["ai_input_image_flip"].asBool(); + _config.preDealImgConfig.bOutAI_ImgFflip = value["ai_output_image_flip"].asBool(); + } + } + { + auto value = root["Camer_param"]; + if (value.isObject()) + { + + _config.camConfig.fscale_x = value["scale_x"].asFloat(); + _config.camConfig.fscale_y = value["scale_y"].asFloat(); + + std::cout << "_config.camConfig.fscale_x=" << _config.camConfig.fscale_x << std::endl; + std::cout << "_config.camConfig.fscale_y=" << _config.camConfig.fscale_y << std::endl; + } + } + { + auto value = root["image_Info"]; + if (value.isObject()) + { + + _config.resultimg_out.width = value["result_image_width"].asInt(); + _config.resultimg_out.height = value["result_image_height"].asInt(); + _config.resultimg_out.channels = value["result_image_channels"].asInt(); + + _config.resultimg_out.print("resultimg_out"); + + _config.Srcimg_in.width = value["src_image_width"].asInt(); + _config.Srcimg_in.height = value["src_image_height"].asInt(); + _config.Srcimg_in.channels = value["src_image_channels"].asInt(); + + _config.Srcimg_in.print("Srcimg_in"); + } + } +} +int CheckConfigJson::GetConfig(CheckConfigST &config) +{ + config.copy(_config); + return 0; +} + +Json::Value ChannelFuntonConfigJson::toJsonValue() +{ + return Json::Value(); +} + +void ChannelFuntonConfigJson::toObjectFromValue(Json::Value root) +{ + auto strJson = root.asString(); + Json::CharReaderBuilder builder; + std::unique_ptr reader(builder.newCharReader()); + Json::Value rootvalue; + std::string err; + std::cout << "ChannelFuntonConfigJson" << std::endl + << std::endl + << std::endl; + // std::cout << strJson << std::endl; + auto nSize = strJson.size(); + + if (reader->parse(strJson.c_str(), strJson.c_str() + nSize, &rootvalue, &err)) + { + // 和节点无关参数提取 + + auto value = rootvalue["checkData"]; + if (value.isArray()) + { + for (int idx = 0; idx < value.size(); idx++) + { + ChannelCheckFunction channel; + if (value[idx]["panelCode"]) + { + channel.strChannelName = value[idx]["panelCode"].asString(); + } + else + { + continue; + } + GetFunction(value[idx]["checkItem"], channel.function); + + // up 特殊处理 + if (channel.strChannelName == "Up-Particle" && channel.function.f_BaseDet.bOpen) + { + channel.function.f_OnlyBLob.bOpen = true; + } + + // channel.print("channel"); + // getchar(); + _config.channelFunctionArr.push_back(channel); + } + // _config.print("channelFunction"); + } + } +} + +int ChannelFuntonConfigJson::GetConfig(ALLChannelCheckFunction &config) +{ + config.copy(_config); + return 0; +} + +int ChannelFuntonConfigJson::GetFunction(Json::Value value, CheckFunction &function) +{ + // std::cout << value << std::endl; + + if (value.isArray()) + { + for (int i = 0; i < value.size(); i++) + { + + std::string strCode = value[i]["itemCode"].asString(); + // std::cout << strCode << std::endl; + // 读取UP 过滤功能 + if ("QX_Detect" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_BaseDet.bOpen = value_f["isOpen"].asBool(); + if (function.f_BaseDet.bOpen) + { + /* code */ + + if (value_f["form"]["Base_Det"]["AI_Model"]) + { + function.f_BaseDet.strAIMode = value_f["form"]["Base_Det"]["AI_Model"].asString(); + } + + auto value_qx = value_f["form"]["Base_Det"]["Det_QX"]; + if (value_qx.isArray()) + { + for (int idx = 0; idx < value_qx.size(); idx++) + { + std::string qx = value_qx[idx].asString(); + function.f_BaseDet.DetQXList.push_back(qx); + } + } + } + else + { + function.f_BaseDet.Init(); + } + } + // 读取UP 过滤功能 + if ("UP_Use" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_UseUpQX.bOpen = value_f["isOpen"].asBool(); + if (function.f_UseUpQX.bOpen) + { + /* code */ + + if (value_f["form"]["UP_QX_Filter"]["IOU"]) + { + function.f_UseUpQX.fIOU = value_f["form"]["UP_QX_Filter"]["IOU"].asFloat(); + } + } + else + { + function.f_UseUpQX.Init(); + } + // function.f_UseUpQX.print("UpQX"); + } + if ("AI_Class" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_AIQX.bOpen = value_f["isOpen"].asBool(); + if (function.f_AIQX.bOpen) + { + /* code */ + + if (value_f["form"]["AI_QX"]["POLToWhitePOL"]) + { + function.f_AIQX.bPOLToWhitePOL = value_f["form"]["AI_QX"]["POLToWhitePOL"].asBool(); + } + if (value_f["form"]["AI_QX"]["UseDP"]) + { + function.f_AIQX.b127WhitePOl_UseDP = value_f["form"]["AI_QX"]["UseDP"].asBool(); + } + if (value_f["form"]["AI_QX"]["DP_IOU"]) + { + function.f_AIQX.f127WhitePOl_DP_IOU = value_f["form"]["AI_QX"]["DP_IOU"].asFloat(); + } + if (value_f["form"]["AI_QX"]["ALLToChess"]) + { + function.f_AIQX.bAllToChess = value_f["form"]["AI_QX"]["ALLToChess"].asBool(); + } + } + else + { + function.f_AIQX.Init(); + } + + // function.f_UseUpQX.print("UpQX"); + } + if ("YX_Detect" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_YXDet.bOpen = value_f["isOpen"].asBool(); + if (value_f["form"]["YX_Det"]["AI_Model"]) + { + function.f_YXDet.strModle = value_f["form"]["YX_Det"]["AI_Model"].asString(); + } + + // function.f_UseUpQX.print("UpQX"); + } + if ("LD_Detect" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_LDConfig.bOpen = value_f["isOpen"].asBool(); + if (function.f_LDConfig.bOpen) + { + /* code */ + + if (value_f["form"]["LD_Det"]["bUseDP"]) + { + function.f_LDConfig.bUseDP = value_f["form"]["LD_Det"]["bUseDP"].asBool(); + } + if (value_f["form"]["LD_Det"]["WTB_LD"]) + { + function.f_LDConfig.bWTBLD = value_f["form"]["LD_Det"]["WTB_LD"].asBool(); + } + if (value_f["form"]["LD_Det"]["HS_LD"]) + { + function.f_LDConfig.bHSLD = value_f["form"]["LD_Det"]["HS_LD"].asBool(); + } + + if (value_f["form"]["LD_Det"]["DP_IOU"]) + { + function.f_LDConfig.fDP_IOU = value_f["form"]["LD_Det"]["DP_IOU"].asFloat(); + } + + if (value_f["form"]["LD_Standard"]["LD_Area"]) + { + function.f_LDConfig.fLD_Area = value_f["form"]["LD_Standard"]["LD_Area"].asFloat(); + } + if (value_f["form"]["LD_Standard"]["LD_En"]) + { + function.f_LDConfig.fLD_En = value_f["form"]["LD_Standard"]["LD_En"].asFloat(); + } + if (value_f["form"]["LD_Standard"]["LD_HJ"]) + { + function.f_LDConfig.fLD_HJ = value_f["form"]["LD_Standard"]["LD_HJ"].asFloat(); + } + if (value_f["form"]["LD_Standard"]["LD_Len"]) + { + function.f_LDConfig.fLD_Len = value_f["form"]["LD_Standard"]["LD_Len"].asFloat(); + } + if (value_f["form"]["LD_Standard"]["bUseLD_Standard"]) + { + function.f_LDConfig.bUseLD_Standard = value_f["form"]["LD_Standard"]["bUseLD_Standard"].asBool(); + } + } + else + { + function.f_LDConfig.Init(); + } + + // function.f_UseUpQX.print("UpQX"); + } + if ("Det_Cell" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_Det127Cell.bOpen = value_f["isOpen"].asBool(); + } + // 大缺陷检测 + if ("BigQX_Detect" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_Big_QX.bOpen = value_f["isOpen"].asBool(); + if (value_f["form"]["SingleConfig"]["Area"]) + { + function.f_Big_QX.Single_Area = value_f["form"]["SingleConfig"]["Area"].asFloat(); + } + if (value_f["form"]["SingleConfig"]["HJ"]) + { + function.f_Big_QX.Single_HJ = value_f["form"]["SingleConfig"]["HJ"].asInt(); + } + if (value_f["form"]["SingleConfig"]["Length"]) + { + function.f_Big_QX.Single_Len = value_f["form"]["SingleConfig"]["Length"].asFloat(); + } + if (value_f["form"]["Sum_Area"]["Blob_Num"]) + { + function.f_Big_QX.Sum_blob_Num = value_f["form"]["Sum_Area"]["Blob_Num"].asInt(); + } + if (value_f["form"]["Sum_Area"]["Area_Sum"]) + { + function.f_Big_QX.Sum_Area = value_f["form"]["Sum_Area"]["Area_Sum"].asFloat(); + } + } + // 屏蔽区域 + if ("ShieldRegion" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_ShieldRegion.bOpen = value_f["isOpen"].asBool(); + if (function.f_ShieldRegion.bOpen) + { + /* code */ + + if (value_f["form"]["ShieldRegionConfig"]["bDraw"]) + { + function.f_ShieldRegion.bDraw = value_f["form"]["ShieldRegionConfig"]["bDraw"].asBool(); + } + { + auto region_coord = value_f["form"]["ShieldRegionConfig"]["region_1"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + function.f_ShieldRegion.pointArry1.emplace_back(p); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + + { + auto region_coord = value_f["form"]["ShieldRegionConfig"]["region_2"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + function.f_ShieldRegion.pointArry2.emplace_back(p); + } + } + // printf(" pointArry2 size %d \n", function.f_ShieldRegion.pointArry2.size()); + } + { + auto region_coord = value_f["form"]["ShieldRegionConfig"]["region_3"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + function.f_ShieldRegion.pointArry3.emplace_back(p); + } + } + // printf(" pointArry3 size %d \n", function.f_ShieldRegion.pointArry3.size()); + } + { + auto region_coord = value_f["form"]["ShieldRegionConfig"]["region_4"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + function.f_ShieldRegion.pointArry4.emplace_back(p); + } + } + // printf(" pointArry4 size %d \n", function.f_ShieldRegion.pointArry4.size()); + } + { + auto region_coord = value_f["form"]["ShieldRegionConfig"]["region_5"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + function.f_ShieldRegion.pointArry5.emplace_back(p); + } + } + // printf(" pointArry5 size %d \n", function.f_ShieldRegion.pointArry5.size()); + } + } + else + { + function.f_ShieldRegion.Init(); + } + } + // 边缘roi + if ("Crop_ROI" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_EdgeROI.bOpen = value_f["isOpen"].asBool(); + if (function.f_EdgeROI.bOpen) + { + /* code */ + + if (value_f["form"]["ROI_Config"]["Use_DrawROI"]) + { + function.f_EdgeROI.Use_DrawROI = value_f["form"]["ROI_Config"]["Use_DrawROI"].asBool(); + } + if (value_f["form"]["ROI_Config"]["Use_DetEdge"]) + { + function.f_EdgeROI.Use_DetEdge = value_f["form"]["ROI_Config"]["Use_DetEdge"].asBool(); + } + if (value_f["form"]["ROI_Config"]["Use_AIEdge"]) + { + function.f_EdgeROI.Use_AIEdge = value_f["form"]["ROI_Config"]["Use_AIEdge"].asBool(); + } + if (value_f["form"]["ROI_Config"]["AI_Fail_UseDraw"]) + { + function.f_EdgeROI.AI_Fail_UseDraw = value_f["form"]["ROI_Config"]["AI_Fail_UseDraw"].asBool(); + } + if (value_f["form"]["ROI_Config"]["threshold_value"]) + { + function.f_EdgeROI.threshold_value = value_f["form"]["ROI_Config"]["threshold_value"].asInt(); + } + if (value_f["form"]["ROI_Config"]["threshold_value"]) + { + function.f_EdgeROI.AI_Erode_Size = value_f["form"]["ROI_Config"]["AI_Erode_Size"].asInt(); + } + { + auto region_coord = value_f["form"]["ROI_Config"]["ROI"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + if (p.x < 0) + { + p.x = 0; + } + if (p.y < 0) + { + p.y = 0; + } + + function.f_EdgeROI.pointArry1.emplace_back(p); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + } + else + { + function.f_EdgeROI.Init(); + } + } + // 边缘roi + if ("Image_Align_T" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_Image_Align.bOpen = value_f["isOpen"].asBool(); + if (function.f_Image_Align.bOpen) + { + /* code */ + + { + auto region_coord = value_f["form"]["Align_Config"]["Edge_TZ"]; + if (region_coord.isArray()) + { + for (int idx = 0; idx < region_coord.size(); idx++) + { + cv::Point p; + p.x = region_coord[idx][0].asInt(); + p.y = region_coord[idx][1].asInt(); + function.f_Image_Align.pointArry1.emplace_back(p); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + { + auto region_roi = value_f["form"]["Align_Config"]["Search_ROI"]; + + { + if (region_roi["x"]) + { + function.f_Image_Align.search_Roi.x = region_roi["x"].asInt(); + } + if (region_roi["y"]) + { + function.f_Image_Align.search_Roi.y = region_roi["y"].asInt(); + } + if (region_roi["width"]) + { + function.f_Image_Align.search_Roi.width = region_roi["width"].asInt(); + } + if (region_roi["height"]) + { + function.f_Image_Align.search_Roi.height = region_roi["height"].asInt(); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + { + auto Kernel_roi = value_f["form"]["Align_Config"]["Kernel_ROI"]; + + { + if (Kernel_roi["x"]) + { + function.f_Image_Align.feature_Roi.x = Kernel_roi["x"].asInt(); + } + if (Kernel_roi["y"]) + { + function.f_Image_Align.feature_Roi.y = Kernel_roi["y"].asInt(); + } + if (Kernel_roi["width"]) + { + function.f_Image_Align.feature_Roi.width = Kernel_roi["width"].asInt(); + } + if (Kernel_roi["height"]) + { + function.f_Image_Align.feature_Roi.height = Kernel_roi["height"].asInt(); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + { + auto crop_roi = value_f["form"]["Align_Config"]["Crop_ROI"]; + + { + if (crop_roi["x"]) + { + function.f_Image_Align.Crop_Roi.x = crop_roi["x"].asInt(); + } + if (crop_roi["y"]) + { + function.f_Image_Align.Crop_Roi.y = crop_roi["y"].asInt(); + } + if (crop_roi["width"]) + { + function.f_Image_Align.Crop_Roi.width = crop_roi["width"].asInt(); + } + if (crop_roi["height"]) + { + function.f_Image_Align.Crop_Roi.height = crop_roi["height"].asInt(); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + { + if (value_f["form"]["Align_Config"]["bDraw"]) + { + function.f_Image_Align.bDraw = value_f["form"]["Align_Config"]["bDraw"].asBool(); + } + } + { + if (value_f["form"]["Align_Config"]["Score"]) + { + float fs = value_f["form"]["Align_Config"]["Score"].asFloat(); + if (fs > 0.01 && fs <= 1) + { + function.f_Image_Align.fscore = fs; + } + } + } + if (value_f["form"]["Align_Config"]["UseType"]) + { + std::string str = value_f["form"]["Align_Config"]["UseType"].asString(); + if (str == "Use") + { + function.f_Image_Align.runType = Function_Image_Align::type_Use; + } + else if (str == "Test") + { + function.f_Image_Align.runType = Function_Image_Align::type_Test; + } + else + { + function.f_Image_Align.runType = Function_Image_Align::type_Use; + } + } + } + else + { + function.f_Image_Align.Init(); + } + } + // 缺pol 检测 + if ("LackPOL_Det" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_Dectect_LackPol.bOpen = value_f["isOpen"].asBool(); + } + + // 二次分类检测 + if ("Second_Det" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_SecondDetect.bOpen = value_f["isOpen"].asBool(); + if (function.f_SecondDetect.bOpen) + { + if (value_f["form"]["Andain_Config"]["Open_Area"]) + { + function.f_SecondDetect.andian_Open_area = value_f["form"]["Andain_Config"]["Open_Area"].asBool(); + } + if (value_f["form"]["Andain_Config"]["Open_Len"]) + { + function.f_SecondDetect.andian_Open_len = value_f["form"]["Andain_Config"]["Open_Len"].asBool(); + } + if (value_f["form"]["Andain_Config"]["Area_min"]) + { + function.f_SecondDetect.andian_area_min = value_f["form"]["Andain_Config"]["Area_min"].asFloat(); + } + if (value_f["form"]["Andain_Config"]["Area_max"]) + { + function.f_SecondDetect.andian_area_max = value_f["form"]["Andain_Config"]["Area_max"].asFloat(); + } + if (value_f["form"]["Andain_Config"]["SaveProcessImg"]) + { + function.f_SecondDetect.andian_saveProcessImg = value_f["form"]["Andain_Config"]["SaveProcessImg"].asBool(); + } + + if (value_f["form"]["POL_Config"]["Open_Area"]) + { + function.f_SecondDetect.pol_Open_area = value_f["form"]["POL_Config"]["Open_Area"].asBool(); + } + if (value_f["form"]["POL_Config"]["Open_Len"]) + { + function.f_SecondDetect.pol_Open_len = value_f["form"]["POL_Config"]["Open_Len"].asBool(); + } + if (value_f["form"]["POL_Config"]["Area_min"]) + { + function.f_SecondDetect.pol_area_min = value_f["form"]["POL_Config"]["Area_min"].asFloat(); + } + if (value_f["form"]["POL_Config"]["Area_max"]) + { + function.f_SecondDetect.pol_area_max = value_f["form"]["POL_Config"]["Area_max"].asFloat(); + } + if (value_f["form"]["POL_Config"]["Open_Single_Check"]) + { + function.f_SecondDetect.pol_open_SingleCheck = value_f["form"]["POL_Config"]["Open_Single_Check"].asBool(); + } + if (value_f["form"]["POL_Config"]["Open_Create_Pol"]) + { + function.f_SecondDetect.pol_open_Create = value_f["form"]["POL_Config"]["Open_Create_Pol"].asBool(); + } + if (value_f["form"]["POL_Config"]["SaveProcessImg"]) + { + function.f_SecondDetect.pol_saveProcessImg = value_f["form"]["POL_Config"]["SaveProcessImg"].asBool(); + } + } + else + { + function.f_SecondDetect.Init(); + } + // getchar(); + } + // 暗点检测 + if ("AD_Check" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_AD_Check.bOpen = value_f["isOpen"].asBool(); + if (function.f_AD_Check.bOpen) + { + if (value_f["form"]["AD_S_Standard"]["AD_3S_Area"]) + { + function.f_AD_Check.S_standard_3s.area = value_f["form"]["AD_S_Standard"]["AD_3S_Area"].asFloat(); + } + if (value_f["form"]["AD_S_Standard"]["AD_3S_Len"]) + { + function.f_AD_Check.S_standard_3s.len = value_f["form"]["AD_S_Standard"]["AD_3S_Len"].asFloat(); + } + + if (value_f["form"]["AD_S_Standard"]["AD_2S_Area"]) + { + function.f_AD_Check.S_standard_2s.area = value_f["form"]["AD_S_Standard"]["AD_2S_Area"].asFloat(); + } + if (value_f["form"]["AD_S_Standard"]["AD_2S_Len"]) + { + function.f_AD_Check.S_standard_2s.len = value_f["form"]["AD_S_Standard"]["AD_2S_Len"].asFloat(); + } + + if (value_f["form"]["AD_S_Standard"]["AD_1S_Area"]) + { + function.f_AD_Check.S_standard_1s.area = value_f["form"]["AD_S_Standard"]["AD_1S_Area"].asFloat(); + } + if (value_f["form"]["AD_S_Standard"]["AD_1S_Len"]) + { + function.f_AD_Check.S_standard_1s.len = value_f["form"]["AD_S_Standard"]["AD_1S_Len"].asFloat(); + } + + if (value_f["form"]["AD_Check_Num"]["Open"]) + { + function.f_AD_Check.analysis_num.bOpen = value_f["form"]["AD_Check_Num"]["Open"].asBool(); + } + if (value_f["form"]["AD_Check_Num"]["Num"]) + { + function.f_AD_Check.analysis_num.numT = value_f["form"]["AD_Check_Num"]["Num"].asInt(); + } + + if (value_f["form"]["AD_Check_Dis"]["Open"]) + { + function.f_AD_Check.analysis_dis.bOpen = value_f["form"]["AD_Check_Dis"]["Open"].asBool(); + } + if (value_f["form"]["AD_Check_Dis"]["Dis"]) + { + function.f_AD_Check.analysis_dis.disT = value_f["form"]["AD_Check_Dis"]["Dis"].asFloat(); + } + + if (value_f["form"]["AD_Check_S"]["Open"]) + { + function.f_AD_Check.analysis_s.bOpen = value_f["form"]["AD_Check_S"]["Open"].asBool(); + } + + if (value_f["form"]["AD_Check_S"]["S_value"]) + { + function.f_AD_Check.analysis_s.Check_s_Value = value_f["form"]["AD_Check_S"]["S_value"].asInt(); + } + if (value_f["form"]["AD_Check_S"]["NG_3s"]) + { + function.f_AD_Check.analysis_s.NG_3s = value_f["form"]["AD_Check_S"]["NG_3s"].asBool(); + } + if (value_f["form"]["AD_Check_S"]["NG_4s"]) + { + function.f_AD_Check.analysis_s.NG_4s = value_f["form"]["AD_Check_S"]["NG_4s"].asBool(); + } + if (value_f["form"]["AD_Check_S"]["Num"]) + { + function.f_AD_Check.analysis_s.Check_s_Num = value_f["form"]["AD_Check_S"]["Num"].asInt(); + } + } + else + { + function.f_AD_Check.Init(); + } + // getchar(); + } + // 异物检测 + if ("POL_Cam" == strCode) + { + auto value_f = value[i]; + // std::cout << value_f << std::endl; + function.f_POL_Check.bOpen = value_f["isOpen"].asBool(); + if (function.f_POL_Check.bOpen) + { + if (value_f["form"]["AnalysisConfig"]["Num"]) + { + function.f_POL_Check.numT = value_f["form"]["AnalysisConfig"]["Num"].asInt(); + } + } + else + { + function.f_POL_Check.Init(); + } + // getchar(); + } + } + } + return 0; +} + +Json::Value BaseFuntonConfigJson::toJsonValue() +{ + return Json::Value(); +} + +void BaseFuntonConfigJson::toObjectFromValue(Json::Value root) +{ + auto strJson = root.asString(); + Json::CharReaderBuilder builder; + std::unique_ptr reader(builder.newCharReader()); + Json::Value rootvalue; + std::string err; + std::cout << "BaseFuntonConfigJson" << std::endl + << std::endl + << std::endl; + // std::cout << strJson << std::endl; + auto nSize = strJson.size(); + + if (reader->parse(strJson.c_str(), strJson.c_str() + nSize, &rootvalue, &err)) + { + // 和节点无关参数提取 + + auto value = rootvalue["baseCheckData"]; + // printf("\n\n\n"); + // std::cout << value << std::endl; + // getchar(); + if (value.isArray()) + { + for (int idx = 0; idx < value.size(); idx++) + { + GetFunction(value[idx]); + } + // _config.print("channelFunction"); + } + } +} + +int BaseFuntonConfigJson::GetConfig(BaseCheckFunction &config) +{ + config.copy(_config); + return 0; +} + +int BaseFuntonConfigJson::GetFunction(Json::Value value) +{ + + // std::cout << value << std::endl; + + std::string strCode = value["itemCode"].asString(); + // std::cout << strCode << std::endl; + // 读取UP 过滤功能 + if ("MarkLine" == strCode) + { + auto value_f = value; + // std::cout << value_f << std::endl; + // getchar(); + _config.markLine.bOpen = value_f["isOpen"].asBool(); + if (_config.markLine.bOpen) + { + + { + auto crop_roi = value_f["form"]["DetConfig"]["SearchROI"]; + + { + if (crop_roi["x"]) + { + _config.markLine.searchRoi.x = crop_roi["x"].asInt(); + } + if (crop_roi["y"]) + { + _config.markLine.searchRoi.y = crop_roi["y"].asInt(); + } + if (crop_roi["width"]) + { + _config.markLine.searchRoi.width = crop_roi["width"].asInt(); + } + if (crop_roi["height"]) + { + _config.markLine.searchRoi.height = crop_roi["height"].asInt(); + } + } + // printf(" pointArry1 size %d \n", function.f_ShieldRegion.pointArry1.size()); + } + if (value_f["form"]["DetConfig"]["x_sheild_width"]) + { + _config.markLine.x_sheild_width = value_f["form"]["DetConfig"]["x_sheild_width"].asInt(); + } + if (value_f["form"]["DetConfig"]["y_sheild_width"]) + { + _config.markLine.y_sheild_width = value_f["form"]["DetConfig"]["y_sheild_width"].asInt(); + } + if (value_f["form"]["DetConfig"]["Use_sheild"]) + { + _config.markLine.bUse_Roi_Sheild = value_f["form"]["DetConfig"]["Use_sheild"].asBool(); + } + if (value_f["form"]["DetConfig"]["Use_QX_sheild"]) + { + _config.markLine.bUse_qx_Sheild = value_f["form"]["DetConfig"]["Use_QX_sheild"].asBool(); + } + if (value_f["form"]["DetConfig"]["qx_sheild_IOU"]) + { + _config.markLine.qx_sheild_iou = value_f["form"]["DetConfig"]["qx_sheild_IOU"].asFloat(); + } + auto value_qx = value_f["form"]["DetConfig"]["qx_sheild"]; + if (value_qx.isArray()) + { + for (int idx = 0; idx < value_qx.size(); idx++) + { + std::string qx = value_qx[idx].asString(); + _config.markLine.sheil_qx_List.push_back(qx); + } + } + } + else + { + _config.markLine.Init(); + } + } + + return 0; +} diff --git a/ConfigModule/src/JsonCoversion.cpp b/ConfigModule/src/JsonCoversion.cpp new file mode 100644 index 0000000..13c1478 --- /dev/null +++ b/ConfigModule/src/JsonCoversion.cpp @@ -0,0 +1,35 @@ +#include "JsonCoversion.h" + +JsonCoversion::JsonCoversion() +{ + //ctor +} + +JsonCoversion::~JsonCoversion() +{ + //dtor +} +string JsonCoversion::toJson() +{ + toJsonValue(); + + std::unique_ptr jsonWriter(writerBuilder.newStreamWriter()); + std::ostringstream os; + std::string jsonStr; + jsonWriter->write(root,&os); + jsonStr = os.str(); + return jsonStr; +} + +void JsonCoversion::toObject(string & strBuf) +{ + std::unique_ptr const jsonReader(readerBuilder.newCharReader()); + + JSONCPP_STRING errs; + bool res = jsonReader->parse(strBuf.c_str(), strBuf.c_str()+strBuf.length(), &root, &errs); + if (!res || !errs.empty()) + { + std::cout << "parseJson err. " << errs << std::endl; + } + toObjectFromValue(root); +} diff --git a/ConfigModule/src/jsoncpp.cpp b/ConfigModule/src/jsoncpp.cpp new file mode 100644 index 0000000..ebd3aa5 --- /dev/null +++ b/ConfigModule/src/jsoncpp.cpp @@ -0,0 +1,5467 @@ +/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json.h" + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and +The JsonCpp Authors, and is released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + + +#include "json/json.h" +#ifndef JSON_IS_AMALGAMATION +#error "Compile with -I PATH_TO_JSON_DIRECTORY" +#endif + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include +#endif + +// Also support old flag NO_LOCALE_SUPPORT +#ifdef NO_LOCALE_SUPPORT +#define JSONCPP_NO_LOCALE_SUPPORT +#endif + +#ifndef JSONCPP_NO_LOCALE_SUPPORT +#include +#endif + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { +static inline char getDecimalPoint() { +#ifdef JSONCPP_NO_LOCALE_SUPPORT + return '\0'; +#else + struct lconv* lc = localeconv(); + return lc ? *(lc->decimal_point) : '\0'; +#endif +} + +/// Converts a unicode code-point to UTF-8. +static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) { + JSONCPP_STRING result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + // printf("-----------------111--cp %d-------\n",cp); + if ((cp >= 0x4E00 && cp <= 0x9FA5) || (cp >= 0xF00 && cp <= 0xFA2D) ) + { + + wchar_t src[2] = { 0 }; + char dest[5] = { 0 }; + src[0] = static_cast(cp); + std::string curLocale = setlocale(LC_ALL,NULL); + setlocale(LC_ALL,"chs"); + wcstombs(dest, src, 5); + result = dest; + setlocale(LC_ALL, curLocale.c_str()); + } + + + return result; +} + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned integer to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = static_cast(value % 10U + static_cast('0')); + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +template Iter fixNumericLocale(Iter begin, Iter end) { + for (; begin != end; ++begin) { + if (*begin == ',') { + *begin = '.'; + } + } + return begin; +} + +template void fixNumericLocaleInput(Iter begin, Iter end) { + char decimalPoint = getDecimalPoint(); + if (decimalPoint == '\0' || decimalPoint == '.') { + return; + } + for (; begin != end; ++begin) { + if (*begin == '.') { + *begin = decimalPoint; + } + } +} + +/** + * Return iterator that would be the new end of the range [begin,end), if we + * were to delete zeros in the end of string, but not the last zero before '.'. + */ +template Iter fixZerosInTheEnd(Iter begin, Iter end) { + for (; begin != end; --end) { + if (*(end - 1) != '0') { + return end; + } + // Don't delete the last zero before the decimal point. + if (begin != (end - 1) && *(end - 2) == '.') { + return end; + } + } + return end; +} + +} // namespace Json + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors +// Copyright (C) 2016 InfoTeCS JSC. All rights reserved. +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include + +#if !defined(snprintf) +#define snprintf std::snprintf +#endif + +#if !defined(sscanf) +#define sscanf std::sscanf +#endif +#else +#include + +#if defined(_MSC_VER) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#if !defined(snprintf) +#define snprintf _snprintf +#endif +#endif +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile +// time to change the stack limit +#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) +#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 +#endif + +static size_t const stackLimit_g = + JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() + +namespace Json { + +#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) +typedef std::unique_ptr CharReaderPtr; +#else +typedef std::auto_ptr CharReaderPtr; +#endif + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_(true), strictRoot_(false), + allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} + +Features Features::all() { return Features(); } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + features.allowDroppedNullPlaceholders_ = false; + features.allowNumericKeys_ = false; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} + +Reader::Reader(const Features& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool Reader::parse(const std::string& document, + Value& root, + bool collectComments) { + document_.assign(document.begin(), document.end()); + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& is, Value& root, bool collectComments) { + // std::istream_iterator begin(is); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since JSONCPP_STRING is reference-counted, this at least does not + // create an extra copy. + JSONCPP_STRING doc; + std::getline(is, doc, (char)EOF); + return parse(doc.data(), doc.data() + doc.size(), root, collectComments); +} + +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + // readValue() may call itself only if it calls readObject() or ReadArray(). + // These methods execute nodes_.push() just before and nodes_.pop)() just + // after calling readValue(). parse() executes one nodes_.push(), so > instead + // of >=. + if (nodes_.size() > stackLimit_g) + throwRuntimeError("Exceeded stackLimit in readValue()."); + + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenFalse: { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNull: { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, + Reader::Location end) { + JSONCPP_STRING normalized; + normalized.reserve(static_cast(end - begin)); + Reader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void Reader::addComment(Location begin, + Location end, + CommentPlacement placement) { + assert(collectComments_); + const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool Reader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void Reader::readNumber() { + const char* p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : '\0'; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } +} + +bool Reader::readString() { + Char c = '\0'; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& token) { + Token tokenName; + JSONCPP_STRING name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name.clear(); + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = JSONCPP_STRING(numberName.asCString()); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); +} + +bool Reader::readArray(Token& token) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token currentToken; + // Accept Comment after last item in the array. + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); + } + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); + } + if (currentToken.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(static_cast(c - '0')); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative && value == maxIntegerValue) + decoded = Value::minLargestInt; + else if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + JSONCPP_STRING buffer(token.start_, token.end_); + JSONCPP_ISTRINGSTREAM is(buffer); + if (!(is >> value)) + return addError("'" + JSONCPP_STRING(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + JSONCPP_STRING decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { + decoded.reserve(static_cast(token.end_ - token.start_ - 2)); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + + //printf("-->>>>>>>>>>>>>>>>>>>1>>>>>>\n"); + + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, current); + if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& ret_unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", token, + current); + int unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, current); + } + ret_unicode = static_cast(unicode); + return true; +} + +bool Reader::addError(const JSONCPP_STRING& message, + Token& token, + Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + size_t const errorCount = errors_.size(); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +// Deprecated. Preserved for backward compatibility +JSONCPP_STRING Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +JSONCPP_STRING Reader::getFormattedErrorMessages() const { + JSONCPP_STRING formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector Reader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + Reader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) { + ptrdiff_t const length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool Reader::pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra) { + ptrdiff_t const length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool Reader::good() const { return !errors_.size(); } + +// exact copy of Features +class OurFeatures { +public: + static OurFeatures all(); + bool allowComments_; + bool strictRoot_; + bool allowDroppedNullPlaceholders_; + bool allowNumericKeys_; + bool allowSingleQuotes_; + bool failIfExtra_; + bool rejectDupKeys_; + bool allowSpecialFloats_; + int stackLimit_; +}; // OurFeatures + +// exact copy of Implementation of class Features +// //////////////////////////////// + +OurFeatures OurFeatures::all() { return OurFeatures(); } + +// Implementation of class Reader +// //////////////////////////////// + +// exact copy of Reader, renamed to OurReader +class OurReader { +public: + typedef char Char; + typedef const Char* Location; + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + JSONCPP_STRING message; + }; + + OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + JSONCPP_STRING getFormattedErrorMessages() const; + std::vector getStructuredErrors() const; + bool pushError(const Value& value, const JSONCPP_STRING& message); + bool pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra); + bool good() const; + +private: + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl + + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenNaN, + tokenPosInf, + tokenNegInf, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + JSONCPP_STRING message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + bool readStringSingleQuote(); + bool readNumber(bool checkInf); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool + addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static JSONCPP_STRING normalizeEOL(Location begin, Location end); + static bool containsNewLine(Location begin, Location end); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + JSONCPP_STRING document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + JSONCPP_STRING commentsBefore_; + + OurFeatures const features_; + bool collectComments_; +}; // OurReader + +// complete copy of Read impl, for OurReader + +bool OurReader::containsNewLine(OurReader::Location begin, + OurReader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +OurReader::OurReader(OurFeatures const& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool OurReader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (features_.failIfExtra_) { + if ((features_.strictRoot_ || token.type_ != tokenError) && + token.type_ != tokenEndOfStream) { + addError("Extra non-whitespace after JSON value.", token); + return false; + } + } + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool OurReader::readValue() { + // To preserve the old behaviour we cast size_t to int. + if (static_cast(nodes_.size()) > features_.stackLimit_) + throwRuntimeError("Exceeded stackLimit in readValue()."); + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenFalse: { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNull: { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNaN: { + Value v(std::numeric_limits::quiet_NaN()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenPosInf: { + Value v(std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNegInf: { + Value v(-std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // else, fall through ... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void OurReader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool OurReader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + break; + } // else fall through + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token.type_ = tokenNumber; + readNumber(false); + break; + case '-': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenNegInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case 'N': + if (features_.allowSpecialFloats_) { + token.type_ = tokenNaN; + ok = match("aN", 2); + } else { + ok = false; + } + break; + case 'I': + if (features_.allowSpecialFloats_) { + token.type_ = tokenPosInf; + ok = match("nfinity", 7); + } else { + ok = false; + } + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void OurReader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool OurReader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool OurReader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, + OurReader::Location end) { + JSONCPP_STRING normalized; + normalized.reserve(static_cast(end - begin)); + OurReader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void OurReader::addComment(Location begin, + Location end, + CommentPlacement placement) { + assert(collectComments_); + const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool OurReader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool OurReader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +bool OurReader::readNumber(bool checkInf) { + const char* p = current_; + if (checkInf && p != end_ && *p == 'I') { + current_ = ++p; + return false; + } + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : '\0'; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + return true; +} +bool OurReader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool OurReader::readStringSingleQuote() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '\'') + break; + } + return c == '\''; +} + +bool OurReader::readObject(Token& token) { + Token tokenName; + JSONCPP_STRING name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name.clear(); + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); + } + if (name.length() >= (1U << 30)) + throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + JSONCPP_STRING msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover(msg, tokenName, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); +} + +bool OurReader::readArray(Token& token) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token currentToken; + // Accept Comment after last item in the array. + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); + } + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); + } + if (currentToken.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool OurReader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(static_cast(c - '0')); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool OurReader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + const int bufferSize = 32; + int count; + ptrdiff_t const length = token.end_ - token.start_; + + // Sanity check to avoid buffer overflow exploits. + if (length < 0) { + return addError("Unable to parse token length", token); + } + size_t const ulength = static_cast(length); + + // Avoid using a string constant for the format control string given to + // sscanf, as this can cause hard to debug crashes on OS X. See here for more + // info: + // + // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html + char format[] = "%lf"; + + if (length <= bufferSize) { + Char buffer[bufferSize + 1]; + memcpy(buffer, token.start_, ulength); + buffer[length] = 0; + fixNumericLocaleInput(buffer, buffer + length); + count = sscanf(buffer, format, &value); + } else { + JSONCPP_STRING buffer(token.start_, token.end_); + count = sscanf(buffer.c_str(), format, &value); + } + + if (count != 1) + return addError("'" + JSONCPP_STRING(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool OurReader::decodeString(Token& token) { + JSONCPP_STRING decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { + decoded.reserve(static_cast(token.end_ - token.start_ - 2)); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + //printf("-->>>>>>>>>>>>>>>>>>2>>>>>>\n"); + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool OurReader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, current); + if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, current); + } + return true; +} + +bool OurReader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& ret_unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", token, + current); + int unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, current); + } + ret_unicode = static_cast(unicode); + return true; +} + +bool OurReader::addError(const JSONCPP_STRING& message, + Token& token, + Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool OurReader::recoverFromError(TokenType skipUntilToken) { + size_t errorCount = errors_.size(); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& OurReader::currentValue() { return *(nodes_.top()); } + +OurReader::Char OurReader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void OurReader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +JSONCPP_STRING OurReader::getFormattedErrorMessages() const { + JSONCPP_STRING formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector OurReader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); ++itError) { + const ErrorInfo& error = *itError; + OurReader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) { + ptrdiff_t length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool OurReader::pushError(const Value& value, + const JSONCPP_STRING& message, + const Value& extra) { + ptrdiff_t length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool OurReader::good() const { return !errors_.size(); } + +class OurCharReader : public CharReader { + bool const collectComments_; + OurReader reader_; + +public: + OurCharReader(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + bool parse(char const* beginDoc, + char const* endDoc, + Value* root, + JSONCPP_STRING* errs) JSONCPP_OVERRIDE { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; + } +}; + +CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } +CharReaderBuilder::~CharReaderBuilder() {} +CharReader* CharReaderBuilder::newCharReader() const { + bool collectComments = settings_["collectComments"].asBool(); + OurFeatures features = OurFeatures::all(); + features.allowComments_ = settings_["allowComments"].asBool(); + features.strictRoot_ = settings_["strictRoot"].asBool(); + features.allowDroppedNullPlaceholders_ = + settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); + features.stackLimit_ = settings_["stackLimit"].asInt(); + features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); + features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); + return new OurCharReader(collectComments, features); +} +static void getValidReaderKeys(std::set* valid_keys) { + valid_keys->clear(); + valid_keys->insert("collectComments"); + valid_keys->insert("allowComments"); + valid_keys->insert("strictRoot"); + valid_keys->insert("allowDroppedNullPlaceholders"); + valid_keys->insert("allowNumericKeys"); + valid_keys->insert("allowSingleQuotes"); + valid_keys->insert("stackLimit"); + valid_keys->insert("failIfExtra"); + valid_keys->insert("rejectDupKeys"); + valid_keys->insert("allowSpecialFloats"); +} +bool CharReaderBuilder::validate(Json::Value* invalid) const { + Json::Value my_invalid; + if (!invalid) + invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidReaderKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + JSONCPP_STRING const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& CharReaderBuilder::operator[](JSONCPP_STRING key) { + return settings_[key]; +} +// static +void CharReaderBuilder::strictMode(Json::Value* settings) { + //! [CharReaderBuilderStrictMode] + (*settings)["allowComments"] = false; + (*settings)["strictRoot"] = true; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = true; + (*settings)["allowSpecialFloats"] = false; + //! [CharReaderBuilderStrictMode] +} +// static +void CharReaderBuilder::setDefaults(Json::Value* settings) { + //! [CharReaderBuilderDefaults] + (*settings)["collectComments"] = true; + (*settings)["allowComments"] = true; + (*settings)["strictRoot"] = false; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = false; + (*settings)["rejectDupKeys"] = false; + (*settings)["allowSpecialFloats"] = false; + //! [CharReaderBuilderDefaults] +} + +////////////////////////////////// +// global functions + +bool parseFromStream(CharReader::Factory const& fact, + JSONCPP_ISTREAM& sin, + Value* root, + JSONCPP_STRING* errs) { + JSONCPP_OSTRINGSTREAM ssin; + ssin << sin.rdbuf(); + JSONCPP_STRING doc = ssin.str(); + char const* begin = doc.data(); + char const* end = begin + doc.size(); + // Note that we do not actually need a null-terminator. + CharReaderPtr const reader(fact.newCharReader()); + return reader->parse(begin, end, root, errs); +} + +JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) { + CharReaderBuilder b; + JSONCPP_STRING errs; + bool ok = parseFromStream(b, sin, &root, &errs); + if (!ok) { + throwRuntimeError(errs); + } + return sin; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() + : current_(), isNull_(true) { +} + +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} + +Value& ValueIteratorBase::deref() const { + return current_->second; +} + +void ValueIteratorBase::increment() { + ++current_; +} + +void ValueIteratorBase::decrement() { + --current_; +} + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { +#ifdef JSON_USE_CPPTL_SMALLMAP + return other.current_ - current_; +#else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +#endif +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +} + +void ValueIteratorBase::copy(const SelfType& other) { + current_ = other.current_; + isNull_ = other.isNull_; +} + +Value ValueIteratorBase::key() const { + const Value::CZString czstring = (*current_).first; + if (czstring.data()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.data())); + return Value(czstring.data(), czstring.data() + czstring.length()); + } + return Value(czstring.index()); +} + +UInt ValueIteratorBase::index() const { + const Value::CZString czstring = (*current_).first; + if (!czstring.data()) + return czstring.index(); + return Value::UInt(-1); +} + +JSONCPP_STRING ValueIteratorBase::name() const { + char const* keey; + char const* end; + keey = memberName(&end); + if (!keey) return JSONCPP_STRING(); + return JSONCPP_STRING(keey, end); +} + +char const* ValueIteratorBase::memberName() const { + const char* cname = (*current_).first.data(); + return cname ? cname : ""; +} + +char const* ValueIteratorBase::memberName(char const** end) const { + const char* cname = (*current_).first.data(); + if (!cname) { + *end = NULL; + return NULL; + } + *end = cname + (*current_).first.length(); + return cname; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() {} + +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueConstIterator::ValueConstIterator(ValueIterator const& other) + : ValueIteratorBase(other) {} + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() {} + +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) { + throwRuntimeError("ConstIterator to Iterator should never be allowed."); +} + +ValueIterator::ValueIterator(const ValueIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +#include +#endif +#include // min() +#include // size_t + +// Disable warning C4702 : unreachable code +#if defined(_MSC_VER) && _MSC_VER >= 1800 // VC++ 12.0 and above +#pragma warning(disable : 4702) +#endif + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +#define ALIGNAS(byte_alignment) +#endif +// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +// const unsigned char& kNullRef = kNull[0]; +// const Value& Value::null = reinterpret_cast(kNullRef); +// const Value& Value::nullRef = null; + +// static +Value const& Value::nullSingleton() { + static Value const nullStatic; + return nullStatic; +} + +// for backwards compatibility, we'll leave these global references around, but +// DO NOT use them in JSONCPP library code any more! +Value const& Value::null = Value::nullSingleton(); +Value const& Value::nullRef = Value::nullSingleton(); + +const Int Value::minInt = Int(~(UInt(-1) / 2)); +const Int Value::maxInt = Int(UInt(-1) / 2); +const UInt Value::maxUInt = UInt(-1); +#if defined(JSON_HAS_INT64) +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); +const UInt64 Value::maxUInt64 = UInt64(-1); +// The constant is hard-coded because some compiler have trouble +// converting Value::maxUInt64 to a double correctly (AIX/xlC). +// Assumes that UInt64 is a 64 bits integer. +static const double maxUInt64AsDouble = 18446744073709551615.0; +#endif // defined(JSON_HAS_INT64) +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + +const UInt Value::defaultRealPrecision = 17; + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + // The casts can lose precision, but we are looking only for + // an approximate range. Might fail on edge cases though. ~cdunn + // return d >= static_cast(min) && d <= static_cast(max); + return d >= min && d <= max; +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + + static_cast(Int64(value & 1)); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, size_t length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= static_cast(Value::maxInt)) + length = Value::maxInt - 1; + + char* newString = static_cast(malloc(length + 1)); + if (newString == NULL) { + throwRuntimeError("in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + } + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/* Record the length as a prefix. + */ +static inline char* duplicateAndPrefixStringValue(const char* value, + unsigned int length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + JSON_ASSERT_MESSAGE(length <= static_cast(Value::maxInt) - + sizeof(unsigned) - 1U, + "in Json::Value::duplicateAndPrefixStringValue(): " + "length too big for prefixing"); + unsigned actualLength = length + static_cast(sizeof(unsigned)) + 1U; + char* newString = static_cast(malloc(actualLength)); + if (newString == 0) { + throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); + } + *reinterpret_cast(newString) = length; + memcpy(newString + sizeof(unsigned), value, length); + newString[actualLength - 1U] = + 0; // to avoid buffer over-run accidents by users later + return newString; +} +inline static void decodePrefixedString(bool isPrefixed, + char const* prefixed, + unsigned* length, + char const** value) { + if (!isPrefixed) { + *length = static_cast(strlen(prefixed)); + *value = prefixed; + } else { + *length = *reinterpret_cast(prefixed); + *value = prefixed + sizeof(unsigned); + } +} +/** Free the string duplicated by + * duplicateStringValue()/duplicateAndPrefixStringValue(). + */ +#if JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { + unsigned length = 0; + char const* valueDecoded; + decodePrefixedString(true, value, &length, &valueDecoded); + size_t const size = sizeof(unsigned) + length + 1U; + memset(value, 0, size); + free(value); +} +static inline void releaseStringValue(char* value, unsigned length) { + // length==0 => we allocated the strings memory + size_t size = (length == 0) ? strlen(value) : length; + memset(value, 0, size); + free(value); +} +#else // !JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { free(value); } +static inline void releaseStringValue(char* value, unsigned) { free(value); } +#endif // JSONCPP_USING_SECURE_MEMORY + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +Exception::Exception(JSONCPP_STRING const& msg) : msg_(msg) {} +Exception::~Exception() JSONCPP_NOEXCEPT {} +char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); } +RuntimeError::RuntimeError(JSONCPP_STRING const& msg) : Exception(msg) {} +LogicError::LogicError(JSONCPP_STRING const& msg) : Exception(msg) {} +JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg) { + throw RuntimeError(msg); +} +JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg) { + throw LogicError(msg); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Value::CommentInfo::CommentInfo() : comment_(0) {} + +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_, 0u); +} + +void Value::CommentInfo::setComment(const char* text, size_t len) { + if (comment_) { + releaseStringValue(comment_, 0u); + comment_ = 0; + } + JSON_ASSERT(text != 0); + JSON_ASSERT_MESSAGE( + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue(text, len); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +// Notes: policy_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} + +Value::CZString::CZString(char const* str, + unsigned length, + DuplicationPolicy allocate) + : cstr_(str) { + // allocate != duplicate + storage_.policy_ = allocate & 0x3; + storage_.length_ = length & 0x3FFFFFFF; +} + +Value::CZString::CZString(const CZString& other) { + cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_); + storage_.policy_ = + static_cast( + other.cstr_ + ? (static_cast(other.storage_.policy_) == + noDuplication + ? noDuplication + : duplicate) + : static_cast(other.storage_.policy_)) & + 3U; + storage_.length_ = other.storage_.length_; +} + +#if JSON_HAS_RVALUE_REFERENCES +Value::CZString::CZString(CZString&& other) + : cstr_(other.cstr_), index_(other.index_) { + other.cstr_ = nullptr; +} +#endif + +Value::CZString::~CZString() { + if (cstr_ && storage_.policy_ == duplicate) { + releaseStringValue(const_cast(cstr_), + storage_.length_ + 1u); // +1 for null terminating + // character for sake of + // completeness but not actually + // necessary + } +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(const CZString& other) { + cstr_ = other.cstr_; + index_ = other.index_; + return *this; +} + +#if JSON_HAS_RVALUE_REFERENCES +Value::CZString& Value::CZString::operator=(CZString&& other) { + cstr_ = other.cstr_; + index_ = other.index_; + other.cstr_ = nullptr; + return *this; +} +#endif + +bool Value::CZString::operator<(const CZString& other) const { + if (!cstr_) + return index_ < other.index_; + // return strcmp(cstr_, other.cstr_) < 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this->cstr_ && other.cstr_); + int comp = memcmp(this->cstr_, other.cstr_, min_len); + if (comp < 0) + return true; + if (comp > 0) + return false; + return (this_len < other_len); +} + +bool Value::CZString::operator==(const CZString& other) const { + if (!cstr_) + return index_ == other.index_; + // return strcmp(cstr_, other.cstr_) == 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + if (this_len != other_len) + return false; + JSON_ASSERT(this->cstr_ && other.cstr_); + int comp = memcmp(this->cstr_, other.cstr_, this_len); + return comp == 0; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +// const char* Value::CZString::c_str() const { return cstr_; } +const char* Value::CZString::data() const { return cstr_; } +unsigned Value::CZString::length() const { return storage_.length_; } +bool Value::CZString::isStaticString() const { + return storage_.policy_ == noDuplication; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType type) { + static char const emptyString[] = ""; + initBasic(type); + switch (type) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + // allocated_ == false, so this is safe. + value_.string_ = const_cast(static_cast(emptyString)); + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; +} + +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; +} +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; +} +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; +} + +Value::Value(const char* value) { + initBasic(stringValue, true); + JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor"); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast(strlen(value))); +} + +Value::Value(const char* begin, const char* end) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(begin, static_cast(end - begin)); +} + +Value::Value(const JSONCPP_STRING& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue( + value.data(), static_cast(value.length())); +} + +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value::Value(const CppTL::ConstString& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast(value.length())); +} +#endif + +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; +} + +Value::Value(const Value& other) { + dupPayload(other); + dupMeta(other); +} + +#if JSON_HAS_RVALUE_REFERENCES +// Move constructor +Value::Value(Value&& other) { + initBasic(nullValue); + swap(other); +} +#endif + +Value::~Value() { + releasePayload(); + + delete[] comments_; + + value_.uint_ = 0; +} + +Value& Value::operator=(Value other) { + swap(other); + return *this; +} + +void Value::swapPayload(Value& other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2 & 0x1; +} + +void Value::copyPayload(const Value& other) { + releasePayload(); + dupPayload(other); +} + +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); +} + +void Value::copy(const Value& other) { + copyPayload(other); + delete[] comments_; + dupMeta(other); +} + +ValueType Value::type() const { return type_; } + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + if (other.value_.string_) + return true; + else + return false; + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, + &other_str); + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, min_len); + if (comp < 0) + return true; + if (comp > 0) + return false; + return (this_len < other_len); + } + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + // if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + return (value_.string_ == other.value_.string_); + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, + &other_str); + if (this_len != other_len) + return false; + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, this_len); + return comp == 0; + } + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + return this_str; +} + +#if JSONCPP_USING_SECURE_MEMORY +unsigned Value::getCStringLength() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + return this_len; +} +#endif + +bool Value::getString(char const** begin, char const** end) const { + if (type_ != stringValue) + return false; + if (value_.string_ == 0) + return false; + unsigned length; + decodePrefixedString(this->allocated_, this->value_.string_, &length, begin); + *end = *begin + length; + return true; +} + +JSONCPP_STRING Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: { + if (value_.string_ == 0) + return ""; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, + &this_str); + return JSONCPP_STRING(this_str, this_len); + } + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +#ifdef JSON_USE_CPPTL +CppTL::ConstString Value::asConstString() const { + unsigned len; + char const* str; + decodePrefixedString(allocated_, value_.string_, &len, &str); + return CppTL::ConstString(str, len); +} +#endif + +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + // This can fail (silently?) if the value is bigger than MAX_FLOAT. + return static_cast(integerToDouble(value_.uint_)); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + // This is kind of strange. Not recommended. + return (value_.real_ != 0.0) ? true : false; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString().empty()) || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; +} + +Value::operator bool() const { return !isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || + type_ == objectValue, + "in Json::Value::clear(): requires complex value"); + start_ = 0; + limit_ = 0; + switch (type_) { + case arrayValue: + case objectValue: + value_.map_->clear(); + break; + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + this->operator[](newSize - 1); + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + JSON_ASSERT(size() == newSize); + } +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) + return nullSingleton(); + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return nullSingleton(); + return (*it).second; +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +void Value::initBasic(ValueType type, bool allocated) { + type_ = type; + allocated_ = allocated; + comments_ = 0; + start_ = 0; + limit_ = 0; +} + +void Value::dupPayload(const Value& other) { + type_ = other.type_; + allocated_ = false; + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::releasePayload() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::dupMeta(const Value& other) { + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment(otherComment.comment_, + strlen(otherComment.comment_)); + } + } else { + comments_ = 0; + } + start_ = other.start_; + limit_ = other.limit_; +} + +// Access an object value by name, create a null member if it does not exist. +// @pre Type of '*this' is object or null. +// @param key is null-terminated. +Value& Value::resolveReference(const char* key) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey(key, static_cast(strlen(key)), + CZString::noDuplication); // NOTE! + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +// @param key is not null-terminated. +Value& Value::resolveReference(char const* key, char const* end) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(key, end): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey(key, static_cast(end - key), + CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &nullSingleton() ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +Value const* Value::find(char const* begin, char const* end) const { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::find(key, end, found): requires " + "objectValue or nullValue"); + if (type_ == nullValue) + return NULL; + CZString actualKey(begin, static_cast(end - begin), + CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return NULL; + return &(*it).second; +} +const Value& Value::operator[](const char* key) const { + Value const* found = find(key, key + strlen(key)); + if (!found) + return nullSingleton(); + return *found; +} +Value const& Value::operator[](JSONCPP_STRING const& key) const { + Value const* found = find(key.data(), key.data() + key.length()); + if (!found) + return nullSingleton(); + return *found; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, key + strlen(key)); +} + +Value& Value::operator[](const JSONCPP_STRING& key) { + return resolveReference(key.data(), key.data() + key.length()); +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value& Value::operator[](const CppTL::ConstString& key) { + return resolveReference(key.c_str(), key.end_c_str()); +} +Value const& Value::operator[](CppTL::ConstString const& key) const { + Value const* found = find(key.c_str(), key.end_c_str()); + if (!found) + return nullSingleton(); + return *found; +} +#endif + +Value& Value::append(const Value& value) { return (*this)[size()] = value; } + +#if JSON_HAS_RVALUE_REFERENCES +Value& Value::append(Value&& value) { + return (*this)[size()] = std::move(value); +} +#endif + +Value Value::get(char const* begin, + char const* end, + Value const& defaultValue) const { + Value const* found = find(begin, end); + return !found ? defaultValue : *found; +} +Value Value::get(char const* key, Value const& defaultValue) const { + return get(key, key + strlen(key), defaultValue); +} +Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const { + return get(key.data(), key.data() + key.length(), defaultValue); +} + +bool Value::removeMember(const char* begin, const char* end, Value* removed) { + if (type_ != objectValue) { + return false; + } + CZString actualKey(begin, static_cast(end - begin), + CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return false; + if (removed) +#if JSON_HAS_RVALUE_REFERENCES + *removed = std::move(it->second); +#else + *removed = it->second; +#endif + value_.map_->erase(it); + return true; +} +bool Value::removeMember(const char* key, Value* removed) { + return removeMember(key, key + strlen(key), removed); +} +bool Value::removeMember(JSONCPP_STRING const& key, Value* removed) { + return removeMember(key.data(), key.data() + key.length(), removed); +} +void Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type_ == nullValue) + return; + + CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); + value_.map_->erase(actualKey); +} +void Value::removeMember(const JSONCPP_STRING& key) { + removeMember(key.c_str()); +} + +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type_ != arrayValue) { + return false; + } + CZString key(index); + ObjectValues::iterator it = value_.map_->find(key); + if (it == value_.map_->end()) { + return false; + } + if (removed) + *removed = it->second; + ArrayIndex oldSize = size(); + // shift left all items left, into the place of the "removed" + for (ArrayIndex i = index; i < (oldSize - 1); ++i) { + CZString keey(i); + (*value_.map_)[keey] = (*this)[i + 1]; + } + // erase the last one ("leftover") + CZString keyLast(oldSize - 1); + ObjectValues::iterator itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); + return true; +} + +#ifdef JSON_USE_CPPTL +Value Value::get(const CppTL::ConstString& key, + const Value& defaultValue) const { + return get(key.c_str(), key.end_c_str(), defaultValue); +} +#endif + +bool Value::isMember(char const* begin, char const* end) const { + Value const* value = find(begin, end); + return NULL != value; +} +bool Value::isMember(char const* key) const { + return isMember(key, key + strlen(key)); +} +bool Value::isMember(JSONCPP_STRING const& key) const { + return isMember(key.data(), key.data() + key.length()); +} + +#ifdef JSON_USE_CPPTL +bool Value::isMember(const CppTL::ConstString& key) const { + return isMember(key.c_str(), key.end_c_str()); +} +#endif + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) { + members.push_back(JSONCPP_STRING((*it).first.data(), (*it).first.length())); + } + return members; +} +// +//# ifdef JSON_USE_CPPTL +// EnumMemberNames +// Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +// EnumValues +// Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type_ == nullValue; } + +bool Value::isBool() const { return type_ == booleanValue; } + +bool Value::isInt() const { + switch (type_) { + case intValue: +#if defined(JSON_HAS_INT64) + return value_.int_ >= minInt && value_.int_ <= maxInt; +#else + return true; +#endif + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type_) { + case intValue: +#if defined(JSON_HAS_INT64) + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); +#else + return value_.int_ >= 0; +#endif + case uintValue: +#if defined(JSON_HAS_INT64) + return value_.uint_ <= maxUInt; +#else + return true; +#endif + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { + switch (type_) { + case intValue: + case uintValue: + return true; + case realValue: +#if defined(JSON_HAS_INT64) + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); +#else + return value_.real_ >= minInt && value_.real_ <= maxUInt && + IsIntegral(value_.real_); +#endif // JSON_HAS_INT64 + default: + break; + } + return false; +} + +bool Value::isDouble() const { + return type_ == intValue || type_ == uintValue || type_ == realValue; +} + +bool Value::isNumeric() const { return isDouble(); } + +bool Value::isString() const { return type_ == stringValue; } + +bool Value::isArray() const { return type_ == arrayValue; } + +bool Value::isObject() const { return type_ == objectValue; } + +void Value::setComment(const char* comment, + size_t len, + CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + if ((len > 0) && (comment[len - 1] == '\n')) { + // Always discard trailing newline, to aid indentation. + len -= 1; + } + comments_[placement].setComment(comment, len); +} + +void Value::setComment(const char* comment, CommentPlacement placement) { + setComment(comment, strlen(comment), placement); +} + +void Value::setComment(const JSONCPP_STRING& comment, + CommentPlacement placement) { + setComment(comment.c_str(), comment.length(), placement); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +JSONCPP_STRING Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; +} + +void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } + +void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } + +ptrdiff_t Value::getOffsetStart() const { return start_; } + +ptrdiff_t Value::getOffsetLimit() const { return limit_; } + +JSONCPP_STRING Value::toStyledString() const { + StreamWriterBuilder builder; + + JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : ""; + out += Json::writeString(builder, *this); + out += '\n'; + + return out; +} + +Value::const_iterator Value::begin() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; + default: + break; + } + return const_iterator(); +} + +Value::const_iterator Value::end() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; + default: + break; + } + return const_iterator(); +} + +Value::iterator Value::begin() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} + +PathArgument::PathArgument(ArrayIndex index) + : key_(), index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) + : key_(key), index_(), kind_(kindKey) {} + +PathArgument::PathArgument(const JSONCPP_STRING& key) + : key_(key.c_str()), index_(), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const JSONCPP_STRING& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.reserve(5); + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *++current != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.' || *current == ']') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(JSONCPP_STRING(beginName, current)); + } + } +} + +void Path::addPathInArg(const JSONCPP_STRING& /*path*/, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg++); + } +} + +void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + return Value::null; + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + return Value::null; + } + node = &((*node)[arg.key_]); + if (node == &Value::nullSingleton()) { + // Error: unable to resolve path (object has no member named '' at + // position...) + return Value::null; + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::nullSingleton()) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include + +#if !defined(isnan) +#define isnan std::isnan +#endif + +#if !defined(isfinite) +#define isfinite std::isfinite +#endif + +#if !defined(snprintf) +#define snprintf std::snprintf +#endif +#else +#include +#include + +#if defined(_MSC_VER) +#if !defined(isnan) +#include +#define isnan _isnan +#endif + +#if !defined(isfinite) +#include +#define isfinite _finite +#endif + +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#if !defined(snprintf) +#define snprintf _snprintf +#endif +#endif + +#if defined(__sun) && defined(__SVR4) // Solaris +#if !defined(isfinite) +#include +#define isfinite finite +#endif +#endif + +#if defined(__hpux) +#if !defined(isfinite) +#if defined(__ia64) && !defined(finite) +#define isfinite(x) \ + ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) +#endif +#endif +#endif + +#if !defined(isnan) +// IEEE standard states that NaN values will not compare to themselves +#define isnan(x) (x != x) +#endif + +#if !defined(isfinite) +#define isfinite finite +#endif +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) +typedef std::unique_ptr StreamWriterPtr; +#else +typedef std::auto_ptr StreamWriterPtr; +#endif + +JSONCPP_STRING valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + if (value == Value::minLargestInt) { + uintToString(LargestUInt(Value::maxLargestInt) + 1, current); + *--current = '-'; + } else if (value < 0) { + uintToString(LargestUInt(-value), current); + *--current = '-'; + } else { + uintToString(LargestUInt(value), current); + } + assert(current >= buffer); + return current; +} + +JSONCPP_STRING valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +JSONCPP_STRING valueToString(Int value) { + return valueToString(LargestInt(value)); +} + +JSONCPP_STRING valueToString(UInt value) { + return valueToString(LargestUInt(value)); +} + +#endif // # if defined(JSON_HAS_INT64) + +namespace { +JSONCPP_STRING valueToString(double value, + bool useSpecialFloats, + unsigned int precision, + PrecisionType precisionType) { + // Print into the buffer. We need not request the alternative representation + // that always has a decimal point because JSON doesn't distinguish the + // concepts of reals and integers. + if (!isfinite(value)) { + static const char* const reps[2][3] = { { "NaN", "-Infinity", "Infinity" }, + { "null", "-1e+9999", "1e+9999" } }; + return reps[useSpecialFloats ? 0 : 1] + [isnan(value) ? 0 : (value < 0) ? 1 : 2]; + } + + JSONCPP_STRING buffer(size_t(36), '\0'); + while (true) { + int len = snprintf( + &*buffer.begin(), buffer.size(), + (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", + precision, value); + assert(len >= 0); + size_t wouldPrint = static_cast(len); + if (wouldPrint >= buffer.size()) { + buffer.resize(wouldPrint + 1); + continue; + } + buffer.resize(wouldPrint); + break; + } + + buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); + + // strip the zero padding from the right + if (precisionType == PrecisionType::decimalPlaces) { + buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end()); + } + + // try to ensure we preserve the fact that this was given to us as a double on + // input + if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { + buffer += ".0"; + } + return buffer; +} +} // namespace + +JSONCPP_STRING valueToString(double value, + unsigned int precision, + PrecisionType precisionType) { + return valueToString(value, false, precision, precisionType); +} + +JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; } + +static bool isAnyCharRequiredQuoting(char const* s, size_t n) { + assert(s || !n); + + char const* const end = s + n; + for (char const* cur = s; cur < end; ++cur) { + if (*cur == '\\' || *cur == '\"' || *cur < ' ' || + static_cast(*cur) < 0x80) + return true; + } + return false; +} + +static unsigned int utf8ToCodepoint(const char*& s, const char* e) { + const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; + + unsigned int firstByte = static_cast(*s); + + if (firstByte < 0x80) + return firstByte; + + if (firstByte < 0xE0) { + if (e - s < 2) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = + ((firstByte & 0x1F) << 6) | (static_cast(s[1]) & 0x3F); + s += 1; + // oversized encoded characters are invalid + return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF0) { + if (e - s < 3) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x0F) << 12) | + ((static_cast(s[1]) & 0x3F) << 6) | + (static_cast(s[2]) & 0x3F); + s += 2; + // surrogates aren't valid codepoints itself + // shouldn't be UTF-8 encoded + if (calculated >= 0xD800 && calculated <= 0xDFFF) + return REPLACEMENT_CHARACTER; + // oversized encoded characters are invalid + return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF8) { + if (e - s < 4) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x07) << 18) | + ((static_cast(s[1]) & 0x3F) << 12) | + ((static_cast(s[2]) & 0x3F) << 6) | + (static_cast(s[3]) & 0x3F); + s += 3; + // oversized encoded characters are invalid + return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; + } + + return REPLACEMENT_CHARACTER; +} + +static const char hex2[] = "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + +static JSONCPP_STRING toHex16Bit(unsigned int x) { + const unsigned int hi = (x >> 8) & 0xff; + const unsigned int lo = x & 0xff; + JSONCPP_STRING result(4, ' '); + result[0] = hex2[2 * hi]; + result[1] = hex2[2 * hi + 1]; + result[2] = hex2[2 * lo]; + result[3] = hex2[2 * lo + 1]; + return result; +} + +static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { + if (value == NULL) + return ""; + + if (!isAnyCharRequiredQuoting(value, length)) + return JSONCPP_STRING("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to JSONCPP_STRING is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL + JSONCPP_STRING result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + char const* end = value + length; + for (const char* c = value; c != end; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something.) + // blep notes: actually escaping \/ may be useful in javascript to avoid = 0x20) + result += static_cast(cp); + else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane + result += "\\u"; + result += toHex16Bit(cp); + } else { // codepoint is not in Basic Multilingual Plane + // convert to surrogate pair first + cp -= 0x10000; + result += "\\u"; + result += toHex16Bit((cp >> 10) + 0xD800); + result += "\\u"; + result += toHex16Bit((cp & 0x3FF) + 0xDC00); + } + } break; + //default: { + // result += *c; + //}break; + //xwj --------------- + } + } + result += "\""; + return result; +} + +JSONCPP_STRING valueToQuotedString(const char* value) { + return valueToQuotedStringN(value, static_cast(strlen(value))); +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() {} + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false), + omitEndingLineFeed_(false) {} + +void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } + +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } + +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } + +JSONCPP_STRING FastWriter::write(const Value& root) { + document_.clear(); + writeValue(root); + if (!omitEndingLineFeed_) + document_ += '\n'; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + document_ += valueToQuotedStringN(str, static_cast(end - str)); + break; + } + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + ArrayIndex size = value.size(); + for (ArrayIndex index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); + } + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const JSONCPP_STRING& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedStringN(name.data(), + static_cast(name.length())); + document_ += yamlCompatibilityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_(74), indentSize_(3), addChildValues_() {} + +JSONCPP_STRING StyledWriter::write(const Value& root) { + document_.clear(); + addChildValues_ = false; + indentString_.clear(); + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += '\n'; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const JSONCPP_STRING& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultilineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultilineArray(const Value& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const JSONCPP_STRING& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { + indentString_ += JSONCPP_STRING(indentSize_, ' '); +} + +void StyledWriter::unindent() { + assert(indentString_.size() >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += '\n'; + writeIndent(); + const JSONCPP_STRING& comment = root.getComment(commentBefore); + JSONCPP_STRING::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + document_ += *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + writeIndent(); + ++iter; + } + + // Comments are stripped of trailing newlines, so add one here + document_ += '\n'; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + document_ += '\n'; + document_ += root.getComment(commentAfter); + document_ += '\n'; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(const JSONCPP_STRING& indentation) + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_(), indented_(false) {} + +void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_.clear(); + indented_ = true; + writeCommentBeforeValue(root); + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const JSONCPP_STRING& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultilineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultilineArray(const Value& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) { + if (!indented_) + writeIndent(); + *document_ << value; + indented_ = false; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) + writeIndent(); + const JSONCPP_STRING& comment = root.getComment(commentBefore); + JSONCPP_STRING::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *document_ << *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would include newline + *document_ << indentString_; + ++iter; + } + indented_ = false; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << ' ' << root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *document_ << root.getComment(commentAfter); + } + indented_ = false; +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +////////////////////////// +// BuiltStyledStreamWriter + +/// Scoped enums are not available until C++11. +struct CommentStyle { + /// Decide whether to write comments. + enum Enum { + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. + }; +}; + +struct BuiltStyledStreamWriter : public StreamWriter { + BuiltStyledStreamWriter(JSONCPP_STRING const& indentation, + CommentStyle::Enum cs, + JSONCPP_STRING const& colonSymbol, + JSONCPP_STRING const& nullSymbol, + JSONCPP_STRING const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision, + PrecisionType precisionType); + int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE; + +private: + void writeValue(Value const& value); + void writeArrayValue(Value const& value); + bool isMultilineArray(Value const& value); + void pushValue(JSONCPP_STRING const& value); + void writeIndent(); + void writeWithIndent(JSONCPP_STRING const& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(Value const& root); + void writeCommentAfterValueOnSameLine(Value const& root); + static bool hasCommentForValue(const Value& value); + + typedef std::vector ChildValues; + + ChildValues childValues_; + JSONCPP_STRING indentString_; + unsigned int rightMargin_; + JSONCPP_STRING indentation_; + CommentStyle::Enum cs_; + JSONCPP_STRING colonSymbol_; + JSONCPP_STRING nullSymbol_; + JSONCPP_STRING endingLineFeedSymbol_; + bool addChildValues_ : 1; + bool indented_ : 1; + bool useSpecialFloats_ : 1; + unsigned int precision_; + PrecisionType precisionType_; +}; +BuiltStyledStreamWriter::BuiltStyledStreamWriter( + JSONCPP_STRING const& indentation, + CommentStyle::Enum cs, + JSONCPP_STRING const& colonSymbol, + JSONCPP_STRING const& nullSymbol, + JSONCPP_STRING const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision, + PrecisionType precisionType) + : rightMargin_(74), indentation_(indentation), cs_(cs), + colonSymbol_(colonSymbol), nullSymbol_(nullSymbol), + endingLineFeedSymbol_(endingLineFeedSymbol), addChildValues_(false), + indented_(false), useSpecialFloats_(useSpecialFloats), + precision_(precision), precisionType_(precisionType) {} +int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout) { + sout_ = sout; + addChildValues_ = false; + indented_ = true; + indentString_.clear(); + writeCommentBeforeValue(root); + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *sout_ << endingLineFeedSymbol_; + sout_ = NULL; + return 0; +} +void BuiltStyledStreamWriter::writeValue(Value const& value) { + switch (value.type()) { + case nullValue: + pushValue(nullSymbol_); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, + precisionType_)); + break; + case stringValue: { + // Is NULL is possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + JSONCPP_STRING const& name = *it; + Value const& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedStringN( + name.data(), static_cast(name.length()))); + *sout_ << colonSymbol_; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); + if (isMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + Value const& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *sout_ << "["; + if (!indentation_.empty()) + *sout_ << " "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *sout_ << ((!indentation_.empty()) ? ", " : ","); + *sout_ << childValues_[index]; + } + if (!indentation_.empty()) + *sout_ << " "; + *sout_ << "]"; + } + } +} + +bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + Value const& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *sout_ << value; +} + +void BuiltStyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + + if (!indentation_.empty()) { + // In this case, drop newlines too. + *sout_ << '\n' << indentString_; + } +} + +void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) { + if (!indented_) + writeIndent(); + *sout_ << value; + indented_ = false; +} + +void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } + +void BuiltStyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { + if (cs_ == CommentStyle::None) + return; + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) + writeIndent(); + const JSONCPP_STRING& comment = root.getComment(commentBefore); + JSONCPP_STRING::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *sout_ << *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would write extra newline + *sout_ << indentString_; + ++iter; + } + indented_ = false; +} + +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( + Value const& root) { + if (cs_ == CommentStyle::None) + return; + if (root.hasComment(commentAfterOnSameLine)) + *sout_ << " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *sout_ << root.getComment(commentAfter); + } +} + +// static +bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +/////////////// +// StreamWriter + +StreamWriter::StreamWriter() : sout_(NULL) {} +StreamWriter::~StreamWriter() {} +StreamWriter::Factory::~Factory() {} +StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } +StreamWriterBuilder::~StreamWriterBuilder() {} +StreamWriter* StreamWriterBuilder::newStreamWriter() const { + JSONCPP_STRING indentation = settings_["indentation"].asString(); + JSONCPP_STRING cs_str = settings_["commentStyle"].asString(); + JSONCPP_STRING pt_str = settings_["precisionType"].asString(); + bool eyc = settings_["enableYAMLCompatibility"].asBool(); + bool dnp = settings_["dropNullPlaceholders"].asBool(); + bool usf = settings_["useSpecialFloats"].asBool(); + unsigned int pre = settings_["precision"].asUInt(); + CommentStyle::Enum cs = CommentStyle::All; + if (cs_str == "All") { + cs = CommentStyle::All; + } else if (cs_str == "None") { + cs = CommentStyle::None; + } else { + throwRuntimeError("commentStyle must be 'All' or 'None'"); + } + PrecisionType precisionType(significantDigits); + if (pt_str == "significant") { + precisionType = PrecisionType::significantDigits; + } else if (pt_str == "decimal") { + precisionType = PrecisionType::decimalPlaces; + } else { + throwRuntimeError("precisionType must be 'significant' or 'decimal'"); + } + JSONCPP_STRING colonSymbol = " : "; + if (eyc) { + colonSymbol = ": "; + } else if (indentation.empty()) { + colonSymbol = ":"; + } + JSONCPP_STRING nullSymbol = "null"; + if (dnp) { + nullSymbol.clear(); + } + if (pre > 17) + pre = 17; + JSONCPP_STRING endingLineFeedSymbol; + return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, + endingLineFeedSymbol, usf, pre, + precisionType); +} +static void getValidWriterKeys(std::set* valid_keys) { + valid_keys->clear(); + valid_keys->insert("indentation"); + valid_keys->insert("commentStyle"); + valid_keys->insert("enableYAMLCompatibility"); + valid_keys->insert("dropNullPlaceholders"); + valid_keys->insert("useSpecialFloats"); + valid_keys->insert("precision"); + valid_keys->insert("precisionType"); +} +bool StreamWriterBuilder::validate(Json::Value* invalid) const { + Json::Value my_invalid; + if (!invalid) + invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidWriterKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + JSONCPP_STRING const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& StreamWriterBuilder::operator[](JSONCPP_STRING key) { + return settings_[key]; +} +// static +void StreamWriterBuilder::setDefaults(Json::Value* settings) { + //! [StreamWriterBuilderDefaults] + (*settings)["commentStyle"] = "All"; + (*settings)["indentation"] = "\t"; + (*settings)["enableYAMLCompatibility"] = false; + (*settings)["dropNullPlaceholders"] = false; + (*settings)["useSpecialFloats"] = false; + (*settings)["precision"] = 17; + (*settings)["precisionType"] = "significant"; + //! [StreamWriterBuilderDefaults] +} + +JSONCPP_STRING writeString(StreamWriter::Factory const& factory, + Value const& root) { + JSONCPP_OSTRINGSTREAM sout; + StreamWriterPtr const writer(factory.newStreamWriter()); + writer->write(root, &sout); + return sout.str(); +} + +JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) { + StreamWriterBuilder builder; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c14c1fe --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ + +# 阿加犀工业检测算法调用通用库 + +## 介绍 +京东方 检测算法so + +## 环境 +1、opencv +2、tensorRT + +## 使用 +1、把本地的TensorRT 头文件拷贝到 include文件下中。/home/aidlux/drivers/tensorrt/TensorRT-8.2.1.8/samples/common/ +2、修改模型输入、输出尺寸。ImgCheckConfig.h AI_IN_IMAGE_WIDTH AI_IN_IMAGE_HEIGHT AI_OUT_IMAGE_WIDTH AI_OUT_IMAGE_HEIGHT +3、修改模型输入参数宏定义 作为变量初始化参数 + + +### 最近更新 Update + +### Notes ++ 1、如果不能正确显示中文,有可能系统没有安装中文字符 sudo apt-get install language-pack-zh-hans + +### Author +- [谢文吉] diff --git a/cmake/cpp_c_flags.cmake b/cmake/cpp_c_flags.cmake new file mode 100644 index 0000000..1523dca --- /dev/null +++ b/cmake/cpp_c_flags.cmake @@ -0,0 +1,41 @@ +if(CMAKE_BUILD_TYPE MATCHES "(Release|RELEASE|release)") + # release mode + set(CMAKE_BUILD_TYPE "release") +else() + set(CMAKE_BUILD_TYPE "debug") + # debug mode + if(NOT (${CMAKE_C_FLAGS} MATCHES "-g")) + add_compile_options(-g) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + endif() + if(NOT (${CMAKE_CXX_FLAGS} MATCHES "-g")) + add_compile_options(-g) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") + endif() +endif() +#--------------------------------------------------------------------------------------------------- + + +#++++++add c++11 standard and c99 standard +if(NOT (${CMAKE_C_FLAGS} MATCHES "-std=")) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") +endif() + +if(NOT (${CMAKE_CXX_FLAGS} MATCHES "-std=")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +endif() +#--------------------------------------------------------------------------------------------------- + + +#++++++add path of link library +if(NOT (${CMAKE_C_FLAGS} MATCHES "-Wl,-rpath,")) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-rpath,.:lib/:lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/HK/:../lib/${BUILD_ARCH}/HK/HCNetSDKCom") +endif() + +if(NOT (${CMAKE_CXX_FLAGS} MATCHES "-Wl,-rpath,")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-rpath,.:lib/:lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/:../lib/${BUILD_ARCH}/HK/:../lib/${BUILD_ARCH}/HK/HCNetSDKCom") +endif() +#--------------------------------------------------------------------------------------------------- + +# message(STATUS "CMAKE_CXX_FLAGS:${CMAKE_CXX_FLAGS}") \ No newline at end of file diff --git a/cmake/default_variabes.cmake b/cmake/default_variabes.cmake new file mode 100644 index 0000000..d685cd3 --- /dev/null +++ b/cmake/default_variabes.cmake @@ -0,0 +1,15 @@ +if(NOT DEFINED ModuleName OR ModuleName EQUAL "") + set(ModuleName "DefaultModule") +endif() + +# BUILD_ARCH:x86_64 aarch64 参考 gcc -v 结果的 Target +if(NOT DEFINED BUILD_ARCH) + set(BUILD_ARCH x86_64 CACHE STRING "Arch of this project") +endif() + +if(NOT "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" STREQUAL "${CMAKE_BINARY_DIR}/../lib/${BUILD_ARCH}/") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${BUILD_ARCH}/) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${BUILD_ARCH}/) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) +endif() +link_directories(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) \ No newline at end of file diff --git a/cmake/print_archs.cmake b/cmake/print_archs.cmake new file mode 100644 index 0000000..008ba76 --- /dev/null +++ b/cmake/print_archs.cmake @@ -0,0 +1,2 @@ +message(STATUS "build <${ModuleName}>") +message(STATUS " ARCH type:${BUILD_ARCH} Mode:${CMAKE_BUILD_TYPE}") \ No newline at end of file