Compare commits

...

18 Commits

@ -44,6 +44,7 @@ public:
static int SizeRect(cv::Rect &roi, int img_w, int img_h, int addw, int addh);
static int CalHj(const cv::Mat &img, const cv::Mat &mask, int b_value);
static int CalHj(const cv::Mat &img, const cv::Mat &mask, const cv::Mat &backgroundimg);
static int CalHjWeighted(const cv::Mat &img, const cv::Mat &mask, int b_value, float power = 2.0f);
static float CalRoi2RoiPre(cv::Rect rect1, cv::Rect rect2);
// 计算平均灰度
static float CalImgBrightness(cv::Mat imgRoi);

@ -73,6 +73,9 @@ public:
// 获取检测库 状态信息 返回CHECK_THREAD_RUN_STATUS
int GetStatus();
// 计算blob的密度
int CalBlobDensity_QX();
// 更新参数 pconfig 参数指针nConfigType 需要更新的参数类型 返回0 成功 其他异常
int UpdateConfig(void *pconfig, int nConfigType);

@ -2,7 +2,7 @@
#define ImgCheckBase_H_
#include <string>
#include <memory>
#define ALL_INTERFACE_VERSION 6
#define ALL_INTERFACE_VERSION 7
#define MAX_GPU_NUM 4
enum CHECK_THREAD_RUN_STATUS

@ -25,6 +25,7 @@
#include <vector>
#include <mutex>
#include <algorithm>
#include <ctime>
static std::mutex g_ngImgSave_mutex;
static std::vector<std::future<void>> g_ngImgSave_futures;
@ -724,6 +725,10 @@ int CameraCheckAnalysisy::preDet_BQ(const cv::Mat &L255CutImg, std::shared_ptr<I
for (int i = 0; i < m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.size(); i++)
{
cv::Rect boundingRect = m_pCheck_Result->cameraBaseResult->pBQ_Result->pBQ_roiList.at(i);
boundingRect.x -= 5;
boundingRect.y -= 5;
boundingRect.width += 10;
boundingRect.height += 10;
detImg_mask(boundingRect).setTo(255);
}
if (L255->result->in_shareImage->bDebugsaveImg)
@ -1235,43 +1240,52 @@ int CameraCheckAnalysisy::ngImgSave() {
auto result_copy = m_pCheck_Result;
std::string save_path_root = "/home/aidlux/BOE/FOG/cloud/";
auto task = std::async(std::launch::async, [result_copy, save_path_root]() {
// 生成当天日期字符串,用于按天组织存储目录
time_t now = time(nullptr);
struct tm tm_now;
localtime_r(&now, &tm_now);
char date_buf[16];
strftime(date_buf, sizeof(date_buf), "%Y-%m-%d", &tm_now);
std::string date_str(date_buf);
auto task = std::async(std::launch::async, [result_copy, save_path_root, date_str]() {
try {
if (!result_copy) return;
// ---------- 目录清理(加锁防止并发删除)----------
// 只保留最近 2 天的数据(今天 + 昨天),删除更早的日期目录
{
static std::mutex cleanup_mutex; // 静态锁,所有实例共享
std::lock_guard<std::mutex> lock(cleanup_mutex);
// 计算 1 天前的日期作为清理截止线(保留今天和昨天共 2 天)
time_t now_cleanup = time(nullptr);
time_t cutoff_time = now_cleanup - 1 * 24 * 3600;
struct tm tm_cutoff;
localtime_r(&cutoff_time, &tm_cutoff);
char cutoff_buf[16];
strftime(cutoff_buf, sizeof(cutoff_buf), "%Y-%m-%d", &tm_cutoff);
std::string cutoff_str(cutoff_buf);
DIR* dir = opendir(save_path_root.c_str());
if (dir) {
std::vector<std::pair<std::string, time_t>> dirs;
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
std::string name = entry->d_name;
if (name == "." || name == "..") continue;
std::string full_path = save_path_root + name;
struct stat st;
if (stat(full_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
struct stat lst;
if (lstat(full_path.c_str(), &lst) == 0 && !S_ISLNK(lst.st_mode)) {
dirs.emplace_back(full_path, st.st_mtime);
// 检查是否为日期格式目录 YYYY-MM-DD
if (name.length() == 10 && name[4] == '-' && name[7] == '-') {
// ISO 日期格式可按字典序直接比较
if (name < cutoff_str) {
std::string full_path = save_path_root + name;
struct stat st;
if (stat(full_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
CheckUtil::DeleteDir(full_path);
}
}
}
}
closedir(dir);
if (dirs.size() > 100) {
std::sort(dirs.begin(), dirs.end(),
[](auto& a, auto& b) { return a.second < b.second; });
const std::string& oldest_dir = dirs.front().first;
if (!oldest_dir.empty() && oldest_dir != save_path_root) {
CheckUtil::DeleteDir(oldest_dir);
}
}
} else {
cerr << ("ERROR: cannot open root directory for cleanup");
}
}
@ -1300,8 +1314,8 @@ int CameraCheckAnalysisy::ngImgSave() {
!m_CheckResult_shareP->resultimg.empty() &&
!m_CheckResult_shareP->cutSrcimg.empty()) {
// 构建保存目录(使用净化后的组件
std::string save_dir = save_path_root + "/" + safe_product + "/" + safe_camera + "/";
// 构建保存目录(使用净化后的组件,包含日期子目录
std::string save_dir = save_path_root + date_str + "/" + safe_product + "/" + safe_camera + "/";
if (CheckUtil::CreateDir(save_dir) != 0) {
cerr << ("Failed to create directory: " + save_dir);
continue;
@ -1316,7 +1330,7 @@ int CameraCheckAnalysisy::ngImgSave() {
// cv::imwrite(save_dir + safe_channel + "_AIMask.png", mask_img);
// cv::imwrite(save_dir + safe_channel + "_Resultimg.png", result_img);
// cv::imwrite(save_dir + safe_channel + "_CutImg.png", cut_img);
writeLog(save_dir+ safe_channel + "log", m_CheckResult_shareP->det_LogList);
writeLog(save_dir+ safe_channel + "_log", m_CheckResult_shareP->det_LogList);
} catch (const cv::Exception& e) {
cerr << ("OpenCV exception: " + std::string(e.what()));
} catch (const std::exception& e) {

@ -457,6 +457,32 @@ int CheckUtil::CalHj(const cv::Mat &img, const cv::Mat &mask, const cv::Mat &bac
return meanValue123[0];
}
int CheckUtil::CalHjWeighted(const cv::Mat &img, const cv::Mat &mask, int b_value, float power)
{
cv::Mat imgf;
if (img.type() != CV_32F)
img.convertTo(imgf, CV_32F);
else
imgf = img;
cv::Mat absDiff = cv::abs(imgf - b_value);
cv::Mat weight;
cv::pow(absDiff, power, weight);
cv::Mat maskedDiff, maskedWeight;
absDiff.copyTo(maskedDiff, mask);
weight.copyTo(maskedWeight, mask);
cv::Scalar weightedSum = cv::sum(maskedDiff.mul(weight));
cv::Scalar weightSum = cv::sum(maskedWeight);
if (weightSum[0] < 1e-6)
return 0;
return static_cast<int>(weightedSum[0] / weightSum[0]);
}
float CheckUtil::CalRoi2RoiPre(cv::Rect rect1, cv::Rect rect2)
{
// 计算交集区域

@ -415,6 +415,7 @@ int ImageResultJudge::ResultJudge(std::shared_ptr<ImageAllResult> pImageResult)
Judge_Status = true;
checkFlage = ANALYSIS_TYPE_TF;
nerrortype = 1;
bNG_Status = true;
}
}
// 暗点 3S 分析 对 好品 或者 是 疑是的缺陷进行3S分析。S数量分析。 3S的暗点直接NG.
@ -626,7 +627,9 @@ int ImageResultJudge::ResultJudge(std::shared_ptr<ImageAllResult> pImageResult)
m_CheckResult_shareP->nresult = nqx_type;
}
#ifdef AI_Time
GetAIDetImg(pImageResult, pCenter, tem.AI_in_Img, tem.AI_out_img);
#endif
m_CheckResult_shareP->qxImageResult.push_back(tem);
}
else
@ -637,7 +640,9 @@ int ImageResultJudge::ResultJudge(std::shared_ptr<ImageAllResult> pImageResult)
m_CheckResult_shareP->nYS_result = nqx_type;
}
#ifdef AI_Time
GetAIDetImg(pImageResult, pCenter, tem.AI_in_Img, tem.AI_out_img);
#endif
m_CheckResult_shareP->YS_ImageResult.push_back(tem);
}
@ -885,7 +890,9 @@ int ImageResultJudge::MergeResult(std::shared_ptr<ImageAllResult> pImageResult,
{
m_CheckResult_shareP->nresult = nqx_type;
}
#ifdef AI_Time
GetAIDetImg(pImageResult, pCenter, tem.AI_in_Img, tem.AI_out_img);
#endif
m_CheckResult_shareP->qxImageResult.push_back(tem);
}
}

@ -170,7 +170,7 @@ int ImgCheckAnalysisy::GetStatus()
std::string ImgCheckAnalysisy::GetVersion()
{
return std::string("BOE_1.2.0");
return std::string("BOE_1.2.4_" + std::string(__DATE__) + "_" + std::string(__TIME__));
}
std::string ImgCheckAnalysisy::GetErrorInfo()
@ -332,7 +332,7 @@ cv::Scalar ImgCheckAnalysisy::calc_blob_info_withstats(cv::Mat &img, const cv::M
// 计算 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)
@ -381,7 +381,7 @@ double ImgCheckAnalysisy::CalBlobHJ(cv::Mat &img, const cv::Mat &mask, cv::Rect
// 计算 hj差异图像大于0的像素均值
// double hj = std::abs(fbk - fdet);
double hj = CheckUtil::CalHj(cimg, cmask, fbk);
double hj = CheckUtil::CalHjWeighted(cimg, cmask, fbk, 2.0f);
static int kkk = 0;
unsigned char *pErrordata = (unsigned char *)cimg.data;
@ -589,6 +589,7 @@ int ImgCheckAnalysisy::SetNewConfig()
m_pRegionAnalysisyParam = &m_pCommonAnalysisyConfig->regionConfigArr.at(0);
GetParamidx();
UpdateImgageScale();
UPdateLDConfig();
if (true)
{
printf("SetNewConfig m_nConfigIdx %d m_CheckConfig.strSkuName %s \n", m_nConfigIdx, m_AnalysisyConfig.strSkuName.c_str());
@ -1448,6 +1449,9 @@ int ImgCheckAnalysisy::GetCheckResultBLob()
BLobToDetResult();
// 计算缺陷密度
CalBlobDensity_QX();
return 0;
}
@ -2482,6 +2486,11 @@ int ImgCheckAnalysisy::AI_Detect_QX()
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, strBaseLog, "=======model use Chess");
pAI_Model = AI_Factory->AI_defect_Chess;
}
else if (m_pFuntion->function.f_BaseDet.strAIMode == "RGB-HGRAY")
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, strBaseLog, "=======model use RE_RGBHGRAY");
pAI_Model = AI_Factory->AI_defect_RE_RGBHGRAY;
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, strBaseLog, "=======model use base");
@ -3356,17 +3365,17 @@ int ImgCheckAnalysisy::BLobToDetResult()
config_qx_type == CONFIG_QX_NAME_Other ||
config_qx_type == CONFIG_QX_NAME_LD)
{
std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type];
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 = LDJudge(config_qx_type, roi, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, pQxlog);
int detre = 1;
//int detre = 1;
// 表示L0 和 DP 都有的 亮的
if (dbresult == 1)
{
config_qx_type = CONFIG_QX_NAME_LD;
qx_name = CONFIG_QX_NAME_Names[config_qx_type];
}
pQxlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, " LD Judge ", "%s qx %s ", Re_TO_STR_False(detre), qx_name.c_str());
pQxlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, " LD Judge ", "%s qx %s ", Re_TO_STR_Pass_1(dbresult), qx_name.c_str());
}
// 如果是chess 画面缺陷类型直接是chess异常。
if (m_pFuntion->function.f_AIQX.bAllToChess)
@ -3450,7 +3459,7 @@ int ImgCheckAnalysisy::BLobToDetResult()
bool ban = JudgeQXAnalysis(config_qx_type, pQxlog);
if (!ban)
{
std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type];
qx_name = CONFIG_QX_NAME_Names[config_qx_type];
pQxlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "Judge QX", "qx function close, config_qx_type %s Not Det",
qx_name.c_str());
@ -3467,7 +3476,7 @@ int ImgCheckAnalysisy::BLobToDetResult()
isMarksheildQX = Judge_MarkLine_QX(config_qx_type, roi, pQxlog);
if (isMarksheildQX)
{
std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type];
qx_name = CONFIG_QX_NAME_Names[config_qx_type];
pQxlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "MarkLine_QX", "MarkLine_QX close, config_qx_type %s Not Det",
qx_name.c_str());
@ -4432,4 +4441,105 @@ bool ImgCheckAnalysisy::JudgeQXAnalysis(int nqx_configType, std::shared_ptr<DetL
pQxlog->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;
}
}
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 (!m_pDetResult || !m_pDetResult->pQx_ErrorList || m_pDetResult->pQx_ErrorList->size() <= 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Density_QX", "pQx_ErrorList is empty, skip density calc");
return 0;
}
m_pdetlog->AddCheckstr(PrintLevel_1, "Density_QX", "Start: dis_T=%.1fmm qx_count=%zu", dis_T, m_pDetResult->pQx_ErrorList->size());
for (int i = 0; i < m_pDetResult->pQx_ErrorList->size(); i++)
{
m_pDetResult->pQx_ErrorList->at(i).density = 1;
if (m_pDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_MTX ||
m_pDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_POL_Cell ||
m_pDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_LD ||
m_pDetResult->pQx_ErrorList->at(i).nconfig_qx_type == CONFIG_QX_NAME_AD)
{
/* code */
}
else
{
continue;
}
cv::Rect roi = m_pDetResult->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_pDetResult->pQx_ErrorList->size(); j++)
{
if (i == j)
{
continue;
}
if (m_pDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_MTX ||
m_pDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_POL_Cell ||
m_pDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_LD ||
m_pDetResult->pQx_ErrorList->at(j).nconfig_qx_type == CONFIG_QX_NAME_AD)
{
/* code */
}
else
{
continue;
}
cv::Rect roi123 = m_pDetResult->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;
}
float avdis = dis_T;
if (num > 1)
{
avdis = sum_dis / (num - 1);
}
float fScore = (dis_T - avdis) / dis_T;
double fD = num + fScore;
m_pDetResult->pQx_ErrorList->at(i).density = fD;
m_pdetlog->AddCheckstr(PrintLevel_2, "Density_QX", " idx=%d type=%d(%s) roi[%d,%d,%d,%d] near_num=%d avgDis=%.2f score=%.3f density=%.2f",
i,
m_pDetResult->pQx_ErrorList->at(i).nconfig_qx_type,
m_pDetResult->pQx_ErrorList->at(i).qx_name.c_str(),
roi.x, roi.y, roi.width, roi.height,
num, avdis, fScore, fD);
}
m_pdetlog->AddCheckstr(PrintLevel_1, "Density_QX", "End: processed %zu defects", m_pDetResult->pQx_ErrorList->size());
return 0;
}

@ -972,6 +972,7 @@ int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
}
A_2S_num += AD_list.at(ad_i).num_2s;
A_3S_num += AD_list.at(ad_i).num_3s;
if(AD_list.at(ad_i).num_1s >= 3) A_3S_num++;
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "AD_list %d %s",
ad_i, AD_list.at(ad_i).GetInfo().c_str());
}
@ -1028,7 +1029,7 @@ int QX_Merge_Analysis::Analysis_AD(ALL_Qx_DataList *pALLTypeqxList, int qx_idx)
}
else
{
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "3S Analysis --> %s result NG 3S %d < 1",
m_pMergedetlog->AddCheckstr(PrintLevel_2, 3, "AD RGBL255", "3S Analysis --> %s result OK 3S %d < 1",
pQXChannelList->channel_name.c_str(), A_3S_num);
}
}

@ -213,6 +213,7 @@ int ConfigInstance::Updata_Check(Json::Value json_value)
int ConfigInstance::SetStatus(int nConfigType)
{
std::lock_guard<std::mutex> lock(mutex_status);
for (int i = 0; i < MAX_USER_COUNT; i++)
{
m_USER_ConfigUpdataStatusList[nConfigType][i] = true;

@ -22,62 +22,6 @@ ConfigManager::~ConfigManager()
{
}
std::vector <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"};
std::vector <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",
};
int ReadFlawCodeConfig(std::string json_path)
{
m_FlawCodeList.erase(m_FlawCodeList.begin(), m_FlawCodeList.end());
@ -203,6 +147,7 @@ int ConfigManager::UpdateConfig()
if (!std::filesystem::exists(strConfigPath)) {
strConfigPath = m_strConfigRootPath + "/param.json";
}
printf("read param %s\n", strConfigPath.c_str());
std::shared_ptr<ConfigBase> temConfig = ConfigBase::GetInstance();
re = LoadParamConfig(temConfig, strConfigPath);
if (re != 0)
@ -218,7 +163,12 @@ int ConfigManager::UpdateConfig()
printf("Error >>>> camear Name is empty \n");
continue;
}
Config_instances_[p.commonCheckConfig.baseConfig.strCamearName] = temConfig;
auto it = Config_instances_.find(p.commonCheckConfig.baseConfig.strCamearName);
if (it != Config_instances_.end() && it->second) {
LoadParamConfig(it->second, strConfigPath);
} else {
Config_instances_[p.commonCheckConfig.baseConfig.strCamearName] = temConfig;
}
}
// getchar();

@ -32,7 +32,7 @@ void CommonParamToCheckConfigJson::toObjectFromValue(Json::Value root)
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::Value rootvalue;
std::string err;
// std::cout << strJson << std::endl;
std::cout << strJson << std::endl;
auto nSize = strJson.size();
if (reader->parse(strJson.c_str(), strJson.c_str() + nSize, &rootvalue, &err))
{
@ -48,7 +48,8 @@ void CommonParamToCheckConfigJson::toObjectFromValue(Json::Value root)
if ( _config.baseConfig.strConfigVersion == "")
{
_config.baseConfig.strConfigVersion = "NULL";
}
}
_config.baseConfig.image_widht = value["image_widht"].asInt();
_config.baseConfig.Image_height = value["Image_height"].asInt();
_config.baseConfig.bDrawShieldRoi = value["bDrawShieldRoi"].asBool();

Loading…
Cancel
Save