You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
7.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2022-04-28 10:41:42
* @LastEditors: xiewenji 527774126@qq.com
* @LastEditTime: 2025-08-03 21:32:02
*/
/*
* 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 <iostream>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <mutex>
#include <vector>
#include <thread>
#include <opencv2/opencv.hpp>
using namespace std;
// 掩膜主体(圆角矩形)外的凸起区域(如把手)的描述
struct Mask_Protrusion_
{
int nCorner; // 就近角(产品主轴坐标系):0 左上 1 右上 2 左下 3 右下
cv::Rect roi; // 凸起外接矩形(输入图坐标系,已裁剪到图像范围内)
cv::Point2f ptCenter; // 凸起质心(输入图坐标系)
float fAngle; // 边缘倾角(度,日志排查用)
float fLen; // 凸起外接矩形长边(像素)
float fDepth; // 凸起相对主体直边的最大伸出深度(像素)
float fArea; // 凸起面积(掩膜像素数)
float fFillRatio; // 凸起外接矩形内掩膜像素占比
Mask_Protrusion_()
{
nCorner = 0;
ptCenter = cv::Point2f(0.0f, 0.0f);
fAngle = 0.0f;
fLen = 0.0f;
fDepth = 0.0f;
fArea = 0.0f;
fFillRatio = 0.0f;
}
};
class CheckUtil
{
public:
static long getcurTime();
static std::string getCurrentDate();
static std::string getCurTimeHMS();
static std::string Op_float2String(float nvalue);
static int64_t getSnowId();
// 当前日期(年月日, 8 位纯数字), 形如 "20261029", 便于存图文件名检索/排序
static std::string getCurrentDateYMD();
// 生成不重名的存图完整路径 = strDir + strPrefix + [ "_序号" ] + "_" + strName + strExt
static std::string GetUniqueImgPath(const std::string &strDir, const std::string &strPrefix, const std::string &strName, const std::string &strExt);
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 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 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 CalImgBrightness(cv::Mat imgRoi);
// 计算角度
static float Cal2PointAngle(cv::Point p_left, cv::Point p_right);
// 获取 RotatedRect 长轴的方向角(归一化到 [0, 180) 度)
static float getLongAxisAngle(const cv::RotatedRect rect);
// 排序RotatedRect的四个顶点
static std::vector<cv::Point2f> sort_vertices(cv::RotatedRect rrect);
// 找图片的最大外轮廓
static std::vector<cv::Point> getLargestContourROI(const cv::Mat &binaryImg, bool &found);
// 从外轮廓掩膜(outer定位mask)中分离凸起区域(如把手):
// 主体是圆角矩形、把手基本出现在四角附近:逐行/逐列扫描掩膜边界,为每条边缘搜索带内点数最多的直线;
// 掩膜中超出四条边缘(超过容差带)的像素按连通域切分成凸起区域(含就近角/质心/面积/深度/填充率)。
// binMask:掩膜(非零为前景,兼容 0/1 与 0/255);protrusions:输出的凸起列表(按面积从大到小)
// 可调参数(应对实际情况):
// nMinDepth:凸起最小深度(输入图像素;<=0 时按掩膜短边/150 自动取值,下限 6)
// 调大:只报明显外凸的把手,浅把手会漏检,可压住边缘毛刺/噪声;
// 调小:浅凸起与噪声都易报出(误报变多)。mask 由模型输出放大而来时直边带量化台阶
// (台阶高≈量化步长),建议取 2 个量化步长左右(调用方见 CheckHandleByBigMask)。
// nMinArea:凸起最小面积(输入图像素²;<=0 时按 nMinDepth² 自动取值)
// 调大:小碎块被过滤,把手很小或被遮挡一部分时可能漏检;
// 调小:碎块残留为候选的几率变大(仍会被 nMinDepth 再过滤一遍)。
// nEdgeMargin:边缘外扩量(输入图像素;<=0 时自动取“最小深度的一半”)
// 把四条边缘线整体向外推该距离后再判凸起,等效于把凸起区域相应减小:
// 调大:边缘顺边毛刺/线条偏差被吞掉,凸起区域更小更干净;过大时浅把手漏检;
// 调小:更灵敏,但边缘毛刺容易连进凸起区域。
// 边缘拟合的细节参数(带宽容差/斜率上限)见 FitEdgeLine 注释。
// pBodyQuad:可选输出,拟合出的主体四边形(左上/右上/右下/左下,输入图坐标),仅 -s 存图观察用
// 返回:0 成功、1 掩膜为空、2 无有效前景
static int GetMaskProtrusions(const cv::Mat &binMask, std::vector<Mask_Protrusion_> &protrusions,
int nMinDepth = 0, int nMinArea = 0, std::vector<cv::Point2f> *pBodyQuad = NULL,
int nEdgeMargin = 0);
static std::string GetRectString(cv::Rect rect);
//创建目录
static int CreateDir(const std::string &dir);
// 异步存图
static int SaveImgAsync(const std::string &path, const cv::Mat &img);
// 点的距离是否过小
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<cv::Rect> &samllRoiList, cv::Rect config_roi, int config_SmallImg_Width, int config_SmallImg_Height, int config_MinOverlap_Width, int config_MinOverlap_Height);
static cv::Point2f transformPoint(const cv::Point2f &point, const cv::Mat &transform_matrix);
// 依目标图像通道数返回可用的绘制颜色:
// 1 通道(灰度) -> 统一白色,保证可见
// 4 通道(BGRA) -> 补 alpha = 255
// 3 通道 -> 原样返回
static inline cv::Scalar GetDrawColor(const cv::Mat &img, const cv::Scalar &color)
{
if (img.channels() == 1)
{
return cv::Scalar(255);
}
if (img.channels() == 4)
{
return cv::Scalar(color[0], color[1], color[2], 255);
}
return color;
}
};
// 无参数重载:直接返回原字符串,避免 -Wformat-security 警告
static inline std::string str_Format(const std::string &format)
{
return format;
}
template <typename... Args>
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<char[]> 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_