From b17e09fe2d2f1a8f7665031da254bff24b68e9b8 Mon Sep 17 00:00:00 2001 From: RCi <15089880081@163.com> Date: Thu, 27 Nov 2025 00:36:14 +0800 Subject: [PATCH] =?UTF-8?q?V20251127-2.2.7=20=E4=BF=AE=E5=A4=8DCLS?= =?UTF-8?q?=E5=88=87=E5=9B=BE=E5=87=BD=E6=95=B0=E3=80=82=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=9C=80=E6=96=B0=E7=9A=84=E7=9B=B8=E6=9C=BA=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/global.h | 2 +- include/simpleAlgo.h | 92 ++- src/cutImage/main.cpp | 18 +- .../CMakeLists.txt | 71 --- .../Hd_CameraModule_3DKeyence.cpp | 567 ------------------ .../Hd_CameraModule_3DKeyence.h | 108 ---- .../Hd_CameraModule_3DKeyence_test/readme.txt | 3 - .../Hd_CameraModule_HIK_General.cpp | 70 ++- .../Hd_CameraModule_HIK_PCIE.cpp | 38 +- 9 files changed, 162 insertions(+), 807 deletions(-) delete mode 100644 subModule/Hd_CameraModule_3DKeyence_test/CMakeLists.txt delete mode 100644 subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.cpp delete mode 100644 subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.h delete mode 100644 subModule/Hd_CameraModule_3DKeyence_test/readme.txt diff --git a/include/global.h b/include/global.h index 26bbe27..30d084b 100644 --- a/include/global.h +++ b/include/global.h @@ -11,7 +11,7 @@ #include #pragma execution_character_set("utf-8") -const std::string softwareVersion = "20251125-2.2.6"; +const std::string softwareVersion = "20251127-2.2.7"; const std::string euiJsonVersion = "1.0.6"; #define globalDatabasePth "./sqlDatabase/eui_db.db" //全局数据库路径 #define saveImgEnable 1 diff --git a/include/simpleAlgo.h b/include/simpleAlgo.h index 2e7b1db..d1c69be 100644 --- a/include/simpleAlgo.h +++ b/include/simpleAlgo.h @@ -126,49 +126,79 @@ static std::vector cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput } if (boundingBox.width < targetSize.width && boundingBox.height < targetSize.height) return { cutImg2Cls(boundingBox, imgInput, targetSize) }; - const int w = boundingBox.width; const int h = boundingBox.height; + const bool splitHoriz = (w > h);// 横向长 -> 沿X方向切 const int targetMinSide = std::max(1, std::min(targetSize.width, targetSize.height)); - int minSide = std::min(w, h); - minSide = std::max(minSide, targetMinSide); + int minSide = std::max(std::min(w, h), targetMinSide); if (minSide <= 0) { std::cerr << "Bounding box has zero width or height." << std::endl; return result; } + const int longSide = splitHoriz ? w : h; + const int step = minSide; + //根据长宽是否小于targetsize来分开处理 + // 沿长边切分为若干个 size=minSide 的方块,覆盖到末端且避免重复最后一块 + if (w < targetSize.width || h < targetSize.height) { + + const int beginCoord = splitHoriz ? boundingBox.x - targetSize.height / 2 + boundingBox.height / 2 : boundingBox.y - targetSize.width / 2 + boundingBox.width / 2; + const int endCoord = beginCoord + longSide; - // 沿长边切分为若干个 size=minSide 的方块,覆盖到末端且避免重复最后一块 - const bool splitHoriz = (w > h); // 横向长 -> 沿X方向切 - const int longSide = splitHoriz ? w : h; - const int step = minSide; - const int beginCoord = splitHoriz ? boundingBox.x - targetSize.height / 2 + boundingBox.height / 2 : boundingBox.y - targetSize.width / 2 + boundingBox.width / 2; - const int endCoord = beginCoord + longSide + (splitHoriz ? targetSize.width / 2 : targetSize.height / 2); - - // 计算切块起点列表 - std::vector starts; - starts.reserve((longSide + step - 1) / step); - for (int s = beginCoord; s + step <= endCoord; s += step) { - starts.emplace_back(s); - } - // 确保包含末端(避免遗漏),同时避免与最后一个重复 - const int lastStart = std::max(beginCoord, endCoord - step); - if (starts.empty() || starts.back() != lastStart) { - starts.emplace_back(lastStart); - } - - result.reserve(starts.size()); - if (splitHoriz) { - int y = boundingBox.y - targetSize.width / 2 + boundingBox.height / 2; - for (int x : starts) { - result.emplace_back(cutImg2Cls(cv::Rect(x, y, minSide, minSide), imgInput, targetSize)); + // 计算切块起点列表 + std::vector starts; + starts.reserve((longSide + step - 1) / step); + for (int s = beginCoord; s + step <= endCoord; s += step) { + starts.emplace_back(s); } - } else { - int x = boundingBox.x - targetSize.width / 2 + boundingBox.width / 2; - for (int y : starts) { - result.emplace_back(cutImg2Cls(cv::Rect(x, y, minSide, minSide), imgInput, targetSize)); + // 确保包含末端(避免遗漏),同时避免与最后一个重复 + const int lastStart = std::max(beginCoord, endCoord - step); + if (starts.empty() || starts.back() != lastStart) { + starts.emplace_back(lastStart); + } + + result.reserve(starts.size()); + if (splitHoriz) { + int y = boundingBox.y - targetSize.width / 2 + boundingBox.height / 2; + for (int x : starts) { + result.emplace_back(cutImg2Cls(cv::Rect(x, y, minSide, minSide), imgInput, targetSize)); + } + } + else { + int x = boundingBox.x - targetSize.width / 2 + boundingBox.width / 2; + for (int y : starts) { + result.emplace_back(cutImg2Cls(cv::Rect(x, y, minSide, minSide), imgInput, targetSize)); + } } } + else { + const int beginCoord = splitHoriz ? boundingBox.x : boundingBox.y ; + const int endCoord = beginCoord + longSide; + + // 计算切块起点列表 + std::vector starts; + starts.reserve((longSide + step - 1) / step); + for (int s = beginCoord; s + step <= endCoord; s += step) { + starts.emplace_back(s); + } + // 确保包含末端(避免遗漏),同时避免与最后一个重复 + const int lastStart = std::max(beginCoord, endCoord - step); + if (starts.empty() || starts.back() != lastStart) { + starts.emplace_back(lastStart); + } + + result.reserve(starts.size()); + if (splitHoriz) { + for (int x : starts) { + result.emplace_back(cutImg2Cls(cv::Rect(x, boundingBox.y, minSide, minSide), imgInput, targetSize)); + } + } + else { + for (int y : starts) { + result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, y, minSide, minSide), imgInput, targetSize)); + } + } + } return result; } diff --git a/src/cutImage/main.cpp b/src/cutImage/main.cpp index c983028..0c3a822 100644 --- a/src/cutImage/main.cpp +++ b/src/cutImage/main.cpp @@ -6,8 +6,20 @@ int main(int argc, char* argv[]) //rlj_hanyin("D:\\º¸ӡImage\\11.20\\T\\NG", "bmp", "./outputs/", cv::Size(300, 300)); //yuhan_hanqian("D:\\testImage\\OK", "bmp", "./outputs/" , cv::Size(300, 300)); // yuhan_hanqian("D:\\testImg\\L", "bmp", "./outputs/", cv::Size(50, 50)); - cv::Mat img = cv::imread("D:\\testImage\\04QCB82602000JFBN00206BN_Camera3_ORI_0_09-42-34-710.bmp", -1); - //755 4300 60 300 - auto imgs = cutImg2ClsVec(cv::Rect(8120, 4850, 1007, 129), img); + cv::Mat img = cv::imread("D:\\testImage\\cutImageTest (2).bmp", -1); + img(cv::Rect(1000, 1500, 2350, 1020)).copyTo(img); + cv::Mat imgR = cv::imread("D:\\testImage\\cutImageTest (1).bmp", -1); + std::vector> contours; + cv::findContours(imgR, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + std::vector> allCutImgs; + std::vector samples; + for (auto& contour : contours) { + //755 4300 60 300 + auto imgs = cutImg2ClsVec(cv::boundingRect(contour), img); + allCutImgs.push_back(imgs); + samples.push_back(img(cv::boundingRect(contour))); + } + auto imgs = cutImg2ClsVec(cv::Rect(370, 320, 384, 70), img); + cv::Mat sa = img(cv::Rect(370, 320, 384, 70)); return 1; } \ No newline at end of file diff --git a/subModule/Hd_CameraModule_3DKeyence_test/CMakeLists.txt b/subModule/Hd_CameraModule_3DKeyence_test/CMakeLists.txt deleted file mode 100644 index 8533141..0000000 --- a/subModule/Hd_CameraModule_3DKeyence_test/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# 获取获取当前目录名 -get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME) -string(TIMESTAMP RUN_TIME) -message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME}) - -set(DLL_NAMES "keyence3D" "opencv") -foreach(child ${DLL_NAMES}) - - LIST(APPEND ENV_INCLUDE ${${child}_include}) - LIST(APPEND ENV_LIB ${${child}_lib}) - LIST(APPEND ENV_TARGET ${${child}_target_link}) -endforeach() -message(" ENV_INCLUDE : " ${ENV_INCLUDE} ) -message(" ENV_LIB : " ${ENV_LIB} ) -message(" ENV_TARGET : " ${ENV_TARGET} ) -include_directories( - - ${ENV_INCLUDE} - ) - -link_directories ( - ${ENV_LIB} - - ) - - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_CXX_STANDARD 11) -SET(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC OFF) -set(CMAKE_AUTORCC ON) - -FILE(GLOB HEAD_FILES "./*.h" ) -FILE(GLOB SRC_FILES "./*.cpp") -FILE(GLOB UI_FILES "./*.ui") - - -#find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) - -add_library(${CURRENT_FOLDER} SHARED - ${HEAD_FILES} - ${SRC_FILES} - ${UI_FILES} - ) - - - -set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} - ) - - -target_link_libraries(${CURRENT_FOLDER} PRIVATE - ${ENV_TARGET} - Qt${QT_VERSION_MAJOR}::Core - ) - - -# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY) - - - - -string(TIMESTAMP RUN_TIME) -message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME}) diff --git a/subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.cpp b/subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.cpp deleted file mode 100644 index 2e1d3fc..0000000 --- a/subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.cpp +++ /dev/null @@ -1,567 +0,0 @@ -#include "Hd_CameraModule_3DKeyence.h" -#include -#include -#include -#include -#include - -int G_xImageSize = 0; // Number of X points. -int G_yImageSize = 0; // Number of Y lines. -//const int MAX_LJXA_XDATANUM = 3200; -//const unsigned int BUFFER_FULL_COUNT = 30000; -// -//int _imageAvailable[MAX_LJXA_DEVICENUM] = { 0 }; -//unsigned short* _luminanceBuf[MAX_LJXA_DEVICENUM] = { 0 }; -//unsigned short* _heightBuf[MAX_LJXA_DEVICENUM] = { 0 }; -//int _lastImageSizeHeight[MAX_LJXA_DEVICENUM]; -int imgTakeNum = 0, imgTarget = 1; -int imgIndex = 0; -int getImageTimeOut = 3000; -QString lastError; -QMutex* m_mutex = nullptr; -std::mutex bufferMutex; -QQueue< cv::Mat> heightMatS;//高度图 -QQueue luminanceMatS;//灰度图 -//data == "rest_newProductIn"时要结束run;机台报警,取图超时,复位后重新拍的情况。 -bool ifBreak = false; -//ifRunning减少ifBreak的判断;"rest_newProductIn"时,Logic_camera_thread框架会结束未处理完的相相机取图 -bool ifRunning = false; -QString byteArrayToUnicode(const QByteArray array) { - - // state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功 - // 如果转换成功,则值为0,如果值大于0,则说明转换失败 - QTextCodec::ConverterState state; - // 先尝试使用utf-8的方式把QByteArray转换成QString - QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state); - // 如果转换时无效字符数量大于0,说明编码格式不对 - if (state.invalidChars > 0) - { - // 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了) - text = QTextCodec::codecForName("GBK")->toUnicode(array); - } - return text; -} - -bool JumpFlag = false; -int yCounts; -void myCallbackFunc(LJX8IF_PROFILE_HEADER* pProfileHeaderArray, WORD* pHeightProfileArray, WORD* pLuminanceProfileArray, DWORD dwLuminanceEnable, DWORD dwProfileDataCount, DWORD dwCount, DWORD dwNotify, DWORD dwUser) -{ - try - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " --> Enter callback function"; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "dwProfileDataCount = " << dwProfileDataCount; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "dwCount = " << dwCount; - std::cout << "dwCount->" << dwCount <<" dwProfileDataCount"<< dwProfileDataCount << "dwNotify = " << dwNotify<< std::endl; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "dwNotify = " << dwNotify; - //if (dwCount < 1000)return; - /* if ((dwNotify != 0) || (dwNotify & 0x10000) != 0) - { - return; - }*/ - std::lock_guard lock(bufferMutex); - if (dwCount == 0) - { - return; - } - if (_imageAvailable[dwUser] == 1) - { - return; - } - - - - // _heightBuf 代表的含义:程序里的高度缓存区,pHeightProfileArray 回调函数里的数据 - // 此处崩溃的可能性:xImageSize 配置文件中设置的值和3D相机调试软件设置的值不一致,会崩溃。 - if (JumpFlag) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "JumpFlag"; - return; - } - if (_heightBuf[dwUser] == NULL) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_heightBuf[dwUser] == NULL"; - _heightBuf[dwUser] = (unsigned short*)malloc(G_yImageSize * MAX_LJXA_XDATANUM * 2); - //return; - } - if (pHeightProfileArray == NULL) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "pHeightProfileArray== NULL"; - return; - } - - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_heightBuf[dwUser]: " << _heightBuf[dwUser]; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "pHeightProfileArray: " << pHeightProfileArray; - - //判断内存是否重叠 - if (_heightBuf[dwUser] <= pHeightProfileArray || (unsigned short*)_heightBuf[dwUser] >= (WORD*)pHeightProfileArray + dwProfileDataCount * dwCount * 2) - { - memcpy(&_heightBuf[dwUser][0], pHeightProfileArray, dwProfileDataCount * dwCount * 2); - } - else - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "first memcpy _heightBuf error"; - if (_heightBuf[dwUser] != NULL) - { - free(_heightBuf[dwUser]); - _heightBuf[dwUser] = NULL; - } - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " memcpy _heightBuf again "; - _heightBuf[dwUser] = (unsigned short*)malloc(yCounts * MAX_LJXA_XDATANUM * 2); - memcpy(&_heightBuf[dwUser][0], pHeightProfileArray, dwProfileDataCount * dwCount * 2); - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Second memcpy _heightBuf success "; - - } - - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_luminanceBuf[dwUser]: " << _luminanceBuf[dwUser]; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "pLuminanceProfileArray: " << pLuminanceProfileArray; - if (dwLuminanceEnable == 1) - { - if (_luminanceBuf[dwUser] == NULL) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "_luminanceBuf[dwUser]== NULL"; - //return; - _luminanceBuf[dwUser] = (unsigned short*)malloc(G_yImageSize * MAX_LJXA_XDATANUM * 2); - } - if (_luminanceBuf[dwUser] <= pLuminanceProfileArray || (unsigned short*)_luminanceBuf[dwUser] >= (WORD*)pLuminanceProfileArray + dwProfileDataCount * dwCount * 2) - memcpy(&_luminanceBuf[dwUser][0], pLuminanceProfileArray, dwProfileDataCount * dwCount * 2); - else - qDebug() << __FUNCTION__ << " line:" << __LINE__ << "memcpy _luminanceBuf error"; - } - _imageAvailable[dwUser] = 1; // 图像获取成功 dwUser 和 deviceId 一致 - _lastImageSizeHeight[dwUser] = dwCount; // 扫描的行数, dwCount 和 yImageSize 一致 - } - catch (std::exception e) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " --> execute callback function error"; - } -} - -int Hd_CameraModule_3DKeyence::LJXA_ACQ_OpenDevice(int lDeviceId, LJX8IF_ETHERNET_CONFIG* EthernetConfig, int HighSpeedPortNo) -{ - int errCode = LJX8IF_EthernetOpen(lDeviceId, EthernetConfig); - - _ethernetConfig[lDeviceId] = *EthernetConfig; - _highSpeedPortNo[lDeviceId] = HighSpeedPortNo; - - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Open device ! errCode:" << errCode; - return errCode; -} - -void Hd_CameraModule_3DKeyence::LJXA_ACQ_CloseDevice(int lDeviceId) -{ - LJX8IF_FinalizeHighSpeedDataCommunication(lDeviceId); - LJX8IF_CommunicationClose(lDeviceId); - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Close device!"; -} - - -bool Hd_CameraModule_3DKeyence::decodeInitData(QByteArray byteArray,QVector &vector_data) -{ - while (!byteArray.isEmpty()) - { - int type = 0; - QByteArray m_type = byteArray.mid(0,4); - memcpy((void*)&type,(void*)m_type.data(), 4); - byteArray.remove(0,4); - - int len = 0; - QByteArray m_len = byteArray.mid(0,4); - memcpy((void*)&len,(void*)m_len.data(), 4); - byteArray.remove(0,4); - - QByteArray mm_data = byteArray.mid(0,len); - vector_data.append(mm_data); - byteArray.remove(0,len); - } - return true; -} - -Hd_CameraModule_3DKeyence* create() -{ - qDebug() << __FUNCTION__ << "line:" << __LINE__ << " Hd_CameraModule_3DKeyence create success!" ; - return new Hd_CameraModule_3DKeyence; -} - -void destory(Hd_CameraModule_3DKeyence * ptr) -{ - if (ptr) - { - delete ptr; - ptr = nullptr; - } - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Hd_CameraModule_3DKeyence destory success!"; -} - -Hd_CameraModule_3DKeyence::Hd_CameraModule_3DKeyence() -{ - m_mutex = new QMutex; -} - - -Hd_CameraModule_3DKeyence::~Hd_CameraModule_3DKeyence() -{ - if (isopen) - { - isopen = false; - - // Stop HighSpeed - errCode = LJX8IF_StopHighSpeedDataCommunication(deviceId); - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Stop HighSpeed errCode:" << errCode; - - LJXA_ACQ_CloseDevice(deviceId); - qDebug() << __FUNCTION__ << "line:" << __LINE__ << " CloseDevice success!"; - if (heightImage) - { - free(heightImage); - - } - if (luminanceImage) - { - free(luminanceImage); - } - } - - // Free memory - if (_heightBuf[deviceId] != NULL) - { - free(_heightBuf[deviceId]); - } - - if (_luminanceBuf[deviceId] != NULL) - { - free(_luminanceBuf[deviceId]); - } - - if (startReq_ptr) - { - delete startReq_ptr; - startReq_ptr = nullptr; - } - - if (profileInfo_ptr) - { - delete profileInfo_ptr; - profileInfo_ptr = nullptr; - } - - if (setParam_Ptr) - { - delete setParam_Ptr; - setParam_Ptr = nullptr; - } - - if (getParam_Ptr) - { - delete getParam_Ptr; - getParam_Ptr = nullptr; - } - if (m_mutex) - { - delete m_mutex; - m_mutex = nullptr; - } - qDebug() << __FUNCTION__ << "line:" << __LINE__ << " delete success!"; -} - -bool Hd_CameraModule_3DKeyence::readData(std::vector &mats,QByteArray &data) -{ - Q_UNUSED(data); - - QMutexLocker locker(m_mutex); - if (luminanceMatS.empty() || heightMatS.empty()) - { - qDebug() << " [Error] " << " srcImage is null"; - return false; - } - for (int i = 0; i < imgTarget; i++) { - if (heightMatS.size() >= 1 && luminanceMatS.size() >= 1) { - mats.push_back(luminanceMatS.dequeue()); - mats.push_back(heightMatS.dequeue()); - } - else { - mats.push_back(cv::Mat(G_xImageSize, G_yImageSize, CV_8UC1, cv::Scalar(0, 0, 0))); - mats.push_back(cv::Mat(G_xImageSize, G_yImageSize, CV_8UC1, cv::Scalar(0, 0, 0))); - } - } - imgTakeNum = 0; - qCritical() << " [info] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg readData,deviceId" << deviceId << " imgIndex" << imgIndex; - return true; -} - -bool Hd_CameraModule_3DKeyence::writeData(std::vector &mat,QByteArray &data) -{ - if (data == "clearCahce") { - QMutexLocker locker(m_mutex); - heightMatS.clear(); - luminanceMatS.clear(); - } - //2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值 - //if (data == "rest_newProductIn") - //{ - // //根据实际项目,设置初始值:曝光、增益,ROI区域等 - // /*{ - // if (expourseTimeList.size() > 0) - // SetExposureTime(expourseTimeList[0]); - // if (gainList.size() > 0) - // SetGain(gainList[0]); - // } - // getImageNum = 0;*/ - // if (luminanceMatS.size() > 0 || heightMatS.size() > 0) - // { - // m_mutex->lock(); - // luminanceMatS.clear(); - // heightMatS.clear(); - // m_mutex->unlock(); - // std::cout << "rest_newProductIn , queuePic.size() > 0 ,signal maybe too fast " << camera_name.toStdString() << std::endl; - // qWarning() << __FUNCTION__ << " line: " << __LINE__ << "rest_newProductIn , queuePic.size() > 0 ,signal maybe too fast " << camera_name; - // } - // if (ifRunning == true) - // { - // ifBreak = true; - // Sleep(10); - // } - // imgIndex = 0; - // //getImageNum = 0; - // return true; - //} - - - return true; -} - -//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1... -bool Hd_CameraModule_3DKeyence::initParas(QByteArray& initData) -{ - QByteArrayList valueList = initData.split('#'); - if (valueList.size() < 6) { - qDebug() << "[Error] " << " Hd_CameraModule_HIK initParas fail--params error!参数数量不满足"; - lastError = "参数数量不满足"; - return false; - } - EthernetConfig.wPortNo = 24691; - - camera_name = valueList[0]; - auto valueL1 = valueList[0].split('.'); - if (valueL1.size() == 4) - { - EthernetConfig.abyIpAddress[0] = valueL1.at(0).toInt(); - EthernetConfig.abyIpAddress[1] = valueL1.at(1).toInt(); - EthernetConfig.abyIpAddress[2] = valueL1.at(2).toInt(); - EthernetConfig.abyIpAddress[3] = valueL1.at(3).toInt(); - } - - deviceId = valueList[1].toInt(); - - xImageSize = valueList[2].toInt(); - G_xImageSize = valueList[2].toInt(); - - yImageSize = valueList[3].toInt(); - G_yImageSize = valueList[3].toInt(); - - imgTarget = valueList[4].toInt(); - - getImageTimeOut = valueList[5].toInt(); - yCounts = yImageSize; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " camera_name:" << camera_name << " paras init is success!"; - - // 初始化申请空间 20230214 - startReq_ptr = new LJX8IF_HIGH_SPEED_PRE_START_REQ; - profileInfo_ptr = new LJX8IF_PROFILE_INFO; - startReq_ptr->bySendPosition = 2; - - setParam_Ptr = new LJXA_ACQ_SETPARAM; - getParam_Ptr = new LJXA_ACQ_GETPARAM; - - setParam_Ptr->y_linenum = yImageSize; - setParam_Ptr->y_pitch_um = y_pitch_um; - setParam_Ptr->timeout_ms = timeout_ms; - setParam_Ptr->use_external_batchStart = use_external_batchStart; - - // Allocate user memory - heightImage = (unsigned short*)malloc(sizeof(unsigned short) * xImageSize * yImageSize); - luminanceImage = (unsigned short*)malloc(sizeof(unsigned short) * xImageSize * yImageSize); - - errCode = LJXA_ACQ_OpenDevice(deviceId, &EthernetConfig, HighSpeedPortNo); - if ( errCode != LJX8IF_RC_OK ) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Failed to open device "; - //Free user memory - if ( heightImage ) - { - free(heightImage); - } - - if ( luminanceImage ) - { - free(luminanceImage); - } - return false; - } - - isopen = true; - - // Allocate memory - _heightBuf[deviceId] = (unsigned short*)malloc(yImageSize * MAX_LJXA_XDATANUM * 2); - if (_heightBuf[deviceId] == NULL) - { - return LJX8IF_RC_ERR_NOMEMORY; - } - - _luminanceBuf[deviceId] = (unsigned short*)malloc(yImageSize * MAX_LJXA_XDATANUM * 2); - if (_luminanceBuf[deviceId] == NULL) - { - return LJX8IF_RC_ERR_NOMEMORY; - } - - // Initialize - if (!InitHighSpeed()) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " InitHighSpeed error! " ; - } - return true; -} -bool Hd_CameraModule_3DKeyence::InitHighSpeed() -{ - try - { - if ( startReq_ptr == nullptr ) - { - startReq_ptr = new LJX8IF_HIGH_SPEED_PRE_START_REQ; - startReq_ptr->bySendPosition = 2; - qWarning() << __FUNCTION__ << " line: " << __LINE__ << " startReq_ptr is null! "; - } - if ( profileInfo_ptr == nullptr ) - { - profileInfo_ptr = new LJX8IF_PROFILE_INFO; - qWarning() << __FUNCTION__ << " line: " << __LINE__ << " profileInfo_ptr is null! "; - } - errCode = LJX8IF_InitializeHighSpeedDataCommunicationSimpleArray(deviceId, &_ethernetConfig[deviceId], _highSpeedPortNo[deviceId], &myCallbackFunc, yImageSize, deviceId); // 初始化高速通讯 - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " errCode:" << errCode; - errCode = LJX8IF_PreStartHighSpeedDataCommunication(deviceId, startReq_ptr, profileInfo_ptr); // 预开始启动高速通信,作用 做预连接 - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " errCode:" << errCode; - - // zUnit - errCode = LJX8IF_GetZUnitSimpleArray(deviceId, &zUnit); - if (errCode != 0 || zUnit == 0) - { - qCritical() << __FUNCTION__ << " line:" << __LINE__ << " Failed to acquire zunit! "; - return false; - } - errCode = LJX8IF_StartHighSpeedDataCommunication(deviceId); // 正式开始高速通讯 - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " errCode: " << errCode; - - //Start HighSpeed - _imageAvailable[deviceId] = 0; - _lastImageSizeHeight[deviceId] = 0; - } - catch (const QString ev) - { - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " ev: " << ev; - return false; - } - return true; - -} - -bool Hd_CameraModule_3DKeyence::run() -{ - - ifRunning = true; - ifBreak = false; - if ( !isopen ) - { - qCritical() << __FUNCTION__ << " line:" << __LINE__ << " device is not opened! "; - return false; - } - - try - { - while (imgTakeNum != imgTarget) - { - int sleepMs = 10; - int cnt = 0; - int timeoutCnt = getImageTimeOut / sleepMs; - while (_imageAvailable[deviceId] != 1 ) - { - QThread::msleep(10); - if (cnt++ >= timeoutCnt) - { - heightMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0))); - luminanceMatS.push_back(cv::Mat(G_yImageSize, G_xImageSize, CV_8UC1, cv::Scalar(0, 0, 0))); - imgTakeNum++; - qDebug() << "imgGetERROR insert blank img cameraID:" << camera_name; - continue; - } - } - - - std::lock_guard lock(bufferMutex); - _getParam[deviceId].luminance_enabled = profileInfo_ptr->byLuminanceOutput; - _getParam[deviceId].x_pointnum = profileInfo_ptr->wProfileDataCount; - _getParam[deviceId].y_linenum_acquired = _lastImageSizeHeight[deviceId]; - _getParam[deviceId].x_pitch_um = profileInfo_ptr->lXPitch / 100.0f; - _getParam[deviceId].y_pitch_um = y_pitch_um; - _getParam[deviceId].z_pitch_um = zUnit / 100.0f; - - *getParam_Ptr = _getParam[deviceId]; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " getPara Finished: "; - int xDataNum = _getParam[deviceId].x_pointnum; - - unsigned short* dwHeightBuf = (unsigned short*)&_heightBuf[deviceId][0]; - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " dwHeightBuf Init Finished: "; - memcpy(heightImage, dwHeightBuf, xDataNum * yImageSize * 2); - - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Height Img memcpy Finished: "; - std::vectorpoits(xDataNum * yImageSize * 2, 0); - if (_getParam[deviceId].luminance_enabled > 0) - { - unsigned short* dwLuminanceBuf = (unsigned short*)&_luminanceBuf[deviceId][0]; - memcpy(luminanceImage, dwLuminanceBuf, xDataNum * yImageSize * 2); - } - // Free memory - if (_heightBuf[deviceId] != NULL) - { - free(_heightBuf[deviceId]); - _heightBuf[deviceId] = NULL; - } - - if (_luminanceBuf[deviceId] != NULL) - { - free(_luminanceBuf[deviceId]); - _luminanceBuf[deviceId] = NULL; - } - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " Free memory Finished: "; - - m_mutex->lock(); - cv::Mat luminanceMat; - if(_lastImageSizeHeight[deviceId] != 0) - luminanceMat = cv::Mat(_lastImageSizeHeight[deviceId], xImageSize, CV_16UC1, luminanceImage); - else - luminanceMat = cv::Mat(yImageSize, xImageSize, CV_16UC1, luminanceImage); - cv::normalize(luminanceMat, luminanceMat, 0, 255, cv::NORM_MINMAX); - cv::convertScaleAbs(luminanceMat, luminanceMat); - - luminanceMatS.enqueue(luminanceMat); - - cv::Mat heightImg; - if (_lastImageSizeHeight[deviceId] != 0) - cv::Mat(_lastImageSizeHeight[deviceId], xImageSize, CV_16UC1, heightImage).copyTo(heightImg); - else - cv::Mat(yImageSize, xImageSize, CV_16UC1, heightImage).copyTo(heightImg); - heightMatS.enqueue(heightImg); - m_mutex->unlock(); - qDebug() << __FUNCTION__ << " line:" << __LINE__ << " success to acquire 3d image! camera_name: " << camera_name; - //Start HighSpeed - _imageAvailable[deviceId] = 0; - _lastImageSizeHeight[deviceId] = 0; - imgTakeNum++; - } - qDebug() << camera_name <<"Finish"; - return true; - } - catch (QString ev) - { - qCritical() << __FUNCTION__ << " line: " << __LINE__ << " ev: " << ev; - return false; - } -} diff --git a/subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.h b/subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.h deleted file mode 100644 index ccdf9fc..0000000 --- a/subModule/Hd_CameraModule_3DKeyence_test/Hd_CameraModule_3DKeyence.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef Hd_CameraModule_3DKeyence_H -#define Hd_CameraModule_3DKeyence_H - -#include -#include -#include -#include -#include - -#include "LJX8_IF.h" -#include "LJX8_ErrorCode.h" - -#include - -#pragma comment(lib, "winmm.lib") -#pragma execution_character_set("utf-8") - -typedef struct { - int y_linenum; - float y_pitch_um; - int timeout_ms; - int use_external_batchStart; -} LJXA_ACQ_SETPARAM; - -typedef struct { - int luminance_enabled; - int x_pointnum; - int y_linenum_acquired; - float x_pitch_um; - float y_pitch_um; - float z_pitch_um; -} LJXA_ACQ_GETPARAM; - - -const int MAX_LJXA_DEVICENUM = 6; -const int MAX_LJXA_XDATANUM = 3200; -const unsigned int BUFFER_FULL_COUNT = 30000; - -static int _imageAvailable[MAX_LJXA_DEVICENUM] = { 0 }; -static unsigned short* _luminanceBuf[MAX_LJXA_DEVICENUM] = { 0 }; -static unsigned short* _heightBuf[MAX_LJXA_DEVICENUM] = { 0 }; -static int _lastImageSizeHeight[MAX_LJXA_DEVICENUM]; - -class Hd_CameraModule_3DKeyence :public dsModuleBase -{ -public: - Hd_CameraModule_3DKeyence(); - virtual ~Hd_CameraModule_3DKeyence(); - //从类中读数据到实例对象 - bool readData(std::vector& mats, QByteArray& data); - //实例对象把数据写入到类 - bool writeData(std::vector& mat, QByteArray& data); - bool initParas(QByteArray& initData); - bool run(); - - int LJXA_ACQ_OpenDevice(int lDeviceId, LJX8IF_ETHERNET_CONFIG* EthernetConfig, int HighSpeedPortNo); - //int LJXA_ACQ_StartAsync(int lDeviceId, LJXA_ACQ_SETPARAM* setParam); - //int LJXA_ACQ_AcquireAsync(int lDeviceId, unsigned short* heightImage, unsigned short* luminanceImage, LJXA_ACQ_SETPARAM* setParam, LJXA_ACQ_GETPARAM* getParam); - void LJXA_ACQ_CloseDevice(int lDeviceId); - - bool decodeInitData(QByteArray byteArray, QVector& vector_data); - bool InitHighSpeed(); -private: - //int LJXA_ACQ_Acquire(int lDeviceId, unsigned short* heightImage, unsigned short* luminanceImage, LJXA_ACQ_SETPARAM* setParam, LJXA_ACQ_GETPARAM* getParam); - LJX8IF_HIGH_SPEED_PRE_START_REQ* startReq_ptr = nullptr; - LJX8IF_PROFILE_INFO* profileInfo_ptr = nullptr; - - // Static variable - LJX8IF_ETHERNET_CONFIG _ethernetConfig[MAX_LJXA_DEVICENUM]; - int _highSpeedPortNo[MAX_LJXA_DEVICENUM]; - - LJXA_ACQ_GETPARAM _getParam[MAX_LJXA_DEVICENUM]; - - int deviceId = 0; // Set "0" if you use only 1 head. - int xImageSize = 0; // Number of X points. - int yImageSize = 0; // Number of Y lines. - float y_pitch_um = 0; // Data pitch of Y data. (e.g. your encoder setting) - int timeout_ms = 0; // Timeout value for the acquiring image (in milisecond). - int use_external_batchStart = 1; // Set "1" if you controll the batch start timing externally. (e.g. terminal input) 0内部触发,1外部触发 - std::string outputFilePath1 = "sample_height.csv"; - std::string outputFilePath2 = "sample_height.tif"; - std::string outputFilePath3 = "sample_luminance.tif"; - - //std::vector< cv::Mat> vector_mat; - unsigned short zUnit = 0; - - unsigned short* heightImage = nullptr; // Height image - unsigned short* luminanceImage = nullptr; // Luminance image - - LJXA_ACQ_SETPARAM* setParam_Ptr = nullptr; - LJXA_ACQ_GETPARAM* getParam_Ptr = nullptr; - int HighSpeedPortNo = 24692; // Port number for high-speed communication - bool isopen = false; - int errCode; - - LJX8IF_ETHERNET_CONFIG EthernetConfig; - - QString camera_name; // 相机名称 - int recontimeout_ms = 3000; -}; - -extern "C" -{ - Q_DECL_EXPORT Hd_CameraModule_3DKeyence* create(); - Q_DECL_EXPORT void destory(Hd_CameraModule_3DKeyence* ptr); -} - -#endif // HD_MVCAMERA_MODULE_H diff --git a/subModule/Hd_CameraModule_3DKeyence_test/readme.txt b/subModule/Hd_CameraModule_3DKeyence_test/readme.txt deleted file mode 100644 index 7a69391..0000000 --- a/subModule/Hd_CameraModule_3DKeyence_test/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -基恩士3D相机 -初始化格式 IP#DEVICE-ID(手动按照初始化的顺序从0开始递增)#图像宽(X)#图像高(Y)#取图次数#超时时间 -192.168.31.1#0#3200#850#1#1000 \ No newline at end of file diff --git a/subModule/Hd_CameraModule_HIK_General/Hd_CameraModule_HIK_General.cpp b/subModule/Hd_CameraModule_HIK_General/Hd_CameraModule_HIK_General.cpp index bce840f..833a111 100644 --- a/subModule/Hd_CameraModule_HIK_General/Hd_CameraModule_HIK_General.cpp +++ b/subModule/Hd_CameraModule_HIK_General/Hd_CameraModule_HIK_General.cpp @@ -15,7 +15,9 @@ enum triggerModeEnum { HARDWARE, EMPTY }; -statusEnum cameraStatus = DISCONNECTED; +std::atomic cameraStatus(DISCONNECTED); +std::atomic reconnecting(false); +std::mutex handleMutex; triggerModeEnum triggerMode = HARDWARE; int getImageTimeOut = 3000; bool runFlag = true; @@ -77,11 +79,14 @@ bool connectDevice() lastError = "找不到相机" + QString::fromStdString(Username); return false; } + + std::lock_guard lock(handleMutex); if (handle != NULL) { MV_CC_StopGrabbing(handle); MV_CC_CloseDevice(handle); MV_CC_DestroyHandle(handle); + handle = NULL; } //打开相机 @@ -111,7 +116,7 @@ bool connectDevice() if (MV_OK != nRet)return false; MV_CC_StartGrabbing(handle); - cameraStatus = CONNECTED; + cameraStatus.store(CONNECTED); return true; } void SetExposureTime(float exposureValue) @@ -133,27 +138,42 @@ void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser){ qDebug() << "[Error] " << " MV camera disconnects!"; - if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT && cameraStatus == CONNECTED){ - - cameraStatus = RECONNECTING; + if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT && cameraStatus.load() == CONNECTED){ + + // 防止重复启动重连线程 + bool expected = false; + if (!reconnecting.compare_exchange_strong(expected, true)) { + qDebug() << "[Warning] Reconnect already in progress, skipping duplicate request"; + return; + } + + cameraStatus.store(RECONNECTING); // 启动后台线程负责重连,避免在回调线程中长时间阻塞 std::thread([]() { - qDebug() << "[Info] start reconnect thread"; + qDebug() << QString::fromStdString(Username) << " start reconnect thread"; // 确保设备资源关闭 CloseDevice(); int times = 0; while (runFlag) { - qDebug() << "[Info] reconnect times:" << times++; + qDebug() << QString::fromStdString(Username) << " reconnect attempt:" << times++; if (connectDevice()) { - qWarning() << "[Hd_CameraModule_HIK] reconnect success!"; - cameraStatus = CONNECTED; + qWarning() << QString::fromStdString(Username) << " reconnect success!"; + cameraStatus.store(CONNECTED); + reconnecting.store(false); return; } - + + qDebug() << QString::fromStdString(Username) << " reconnect failed, waiting 1 seconds before retry..."; + std::this_thread::sleep_for(std::chrono::seconds(1)); } + + // 如果runFlag为false,线程退出 + qDebug() << "[Info] reconnect thread stopped (runFlag=false)"; + cameraStatus.store(DISCONNECTED); + reconnecting.store(false); }).detach(); } } @@ -234,21 +254,43 @@ void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFra //关闭设备 void CloseDevice() { - + std::lock_guard lock(handleMutex); + // 如果 handle 已经为空,直接返回 if (handle == nullptr) return; // 使用 SDK 正确的停止/关闭/销毁流程,避免使用 CloseHandle 等不匹配的 API - MV_CC_StopGrabbing(handle); - MV_CC_CloseDevice(handle); - MV_CC_DestroyHandle(handle); + int nRet = MV_CC_StopGrabbing(handle); + if (MV_OK != nRet) { + qDebug() << "[Warning] MV_CC_StopGrabbing failed, nRet=" << nRet; + } + + nRet = MV_CC_CloseDevice(handle); + if (MV_OK != nRet) { + qDebug() << "[Warning] MV_CC_CloseDevice failed, nRet=" << nRet; + } + + nRet = MV_CC_DestroyHandle(handle); + if (MV_OK != nRet) { + qDebug() << "[Warning] MV_CC_DestroyHandle failed, nRet=" << nRet; + } + handle = nullptr; } Hd_CameraModule_HIK_General::~Hd_CameraModule_HIK_General() { runFlag = false; + + // 等待重连线程结束 + int waitCount = 0; + while (reconnecting.load() && waitCount < 50) { // 最多等待5秒 + qDebug() << "[Info] Waiting for reconnect thread to finish..."; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + waitCount++; + } + CloseDevice(); if (n_mutex) { diff --git a/subModule/Hd_CameraModule_HIK_PCIE/Hd_CameraModule_HIK_PCIE.cpp b/subModule/Hd_CameraModule_HIK_PCIE/Hd_CameraModule_HIK_PCIE.cpp index 5c6b4dc..9506ca6 100644 --- a/subModule/Hd_CameraModule_HIK_PCIE/Hd_CameraModule_HIK_PCIE.cpp +++ b/subModule/Hd_CameraModule_HIK_PCIE/Hd_CameraModule_HIK_PCIE.cpp @@ -15,7 +15,9 @@ enum triggerModeEnum { HARDWARE, EMPTY }; -statusEnum cameraStatus = DISCONNECTED; +std::atomic cameraStatus(DISCONNECTED); +std::atomic reconnecting(false); +std::mutex handleMutex; triggerModeEnum triggerMode = HARDWARE; int getImageTimeOut = 3000; bool runFlag = true; @@ -90,8 +92,9 @@ bool connectDevice() if (handle != NULL) { MV_CC_StopGrabbing(handle); - MV_CC_CloseDevice(handle); - MV_CC_DestroyHandle(handle); + handle = NULL; + //MV_CC_CloseDevice(handle); + //MV_CC_DestroyHandle(handle); } //打开相机 @@ -113,6 +116,7 @@ bool connectDevice() if (MV_OK != nRet) return false; MV_CC_StartGrabbing(handle); + cameraStatus.store(CONNECTED); return true; } void SetExposureTime(float exposureValue) @@ -133,27 +137,42 @@ void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser) { qDebug() << "[Error] " << " MV camera disconnects!"; - if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT && cameraStatus == CONNECTED) { + if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT && cameraStatus.load() == CONNECTED) { - cameraStatus = RECONNECTING; + // 防止重复启动重连线程 + bool expected = false; + if (!reconnecting.compare_exchange_strong(expected, true)) { + qDebug() << "[Warning] Reconnect already in progress, skipping duplicate request"; + return; + } + + cameraStatus.store(RECONNECTING); // 启动后台线程负责重连,避免在回调线程中长时间阻塞 std::thread([]() { - qDebug() << "[Info] start reconnect thread"; + qDebug() << QString::fromStdString(Username) << " start reconnect thread"; // 确保设备资源关闭 CloseDevice(); int times = 0; while (runFlag) { - qDebug() << "[Info] reconnect times:" << times++; + qDebug() << QString::fromStdString(Username) << " reconnect attempt:" << times++; if (connectDevice()) { - qWarning() << "[Hd_CameraModule_HIK] reconnect success!"; - cameraStatus = CONNECTED; + qWarning() << QString::fromStdString(Username) << " reconnect success!"; + cameraStatus.store(CONNECTED); + reconnecting.store(false); return; } + qDebug() << QString::fromStdString(Username) << " reconnect failed, waiting 1 seconds before retry..."; + std::this_thread::sleep_for(std::chrono::seconds(1)); } + + // 如果runFlag为false,线程退出 + qDebug() << "[Info] reconnect thread stopped (runFlag=false)"; + cameraStatus.store(DISCONNECTED); + reconnecting.store(false); }).detach(); } } @@ -249,6 +268,7 @@ void CloseDevice() //MV_CC_CloseDevice(handle); //MV_CC_DestroyHandle(handle); } + handle = NULL; //nRet = MV_CC_CloseDevice(handle); //nRet = MV_CC_DestroyHandle(handle); }