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.

792 lines
19 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.

/*
* 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 <sys/time.h>
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <sstream>
#include <sys/statfs.h>
#include <stdlib.h>
#include <fstream>
#include <thread>
#include "snowflake.hpp"
#include <dirent.h>
#include <errno.h>
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;
}
static int _remove_dir_recursive_(const std::string &dir_path) {
DIR *dir = opendir(dir_path.c_str());
if (!dir) {
// 如果目录不存在,视为成功(因为目标是不存在)
if (errno == ENOENT) return 0;
printf("opendir[%s] error: %s\n", dir_path.c_str(), strerror(errno));
return -1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != nullptr) {
std::string name = entry->d_name;
// 跳过 . 和 ..
if (name == "." || name == "..") {
continue;
}
std::string full_path = dir_path + "/" + name;
struct stat st;
// 获取文件状态,使用 lstat 以处理符号链接
if (lstat(full_path.c_str(), &st) == -1) {
printf("lstat[%s] error: %s\n", full_path.c_str(), strerror(errno));
continue;
}
// 如果是目录,递归删除
if (S_ISDIR(st.st_mode)) {
if (_remove_dir_recursive_(full_path) != 0) {
closedir(dir);
return -1;
}
// 删除空子目录
if (rmdir(full_path.c_str()) != 0) {
printf("rmdir[%s] error: %s\n", full_path.c_str(), strerror(errno));
closedir(dir);
return -1;
}
} else {
// 如果是文件(或符号链接等),直接删除
if (remove(full_path.c_str()) != 0) {
printf("remove[%s] error: %s\n", full_path.c_str(), strerror(errno));
closedir(dir);
return -1;
}
}
}
closedir(dir);
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::getCurrentDate()
{
struct timeval tv;
gettimeofday(&tv, NULL); // 获取当前时间
// 将 tv_sec 转换为 time_t 类型代表自1970年1月1日起的秒数
time_t raw_time = tv.tv_sec;
// 使用 localtime 将 time_t 转换为 tm 结构体
struct tm *time_info = localtime(&raw_time);
// 使用字符串流格式化为 "YYYY-MM-DD"
std::ostringstream oss;
oss << (time_info->tm_year + 1900) << "-" // tm_year 是从1900年开始的
<< (time_info->tm_mon + 1) << "-" // tm_mon 是从0开始的
<< time_info->tm_mday; // tm_mday 是当前月的天数
return oss.str(); // 返回日期字符串
}
std::string CheckUtil::getCurTimeHMS()
{
struct timeval tv;
gettimeofday(&tv, NULL); // 获取当前时间
time_t raw_time = tv.tv_sec;
struct tm *time_info = localtime(&raw_time);
int millisec = tv.tv_usec / 1000; // 微秒转毫秒
std::ostringstream oss;
oss << std::setfill('0') << std::setw(2) << time_info->tm_hour << ":"
<< std::setfill('0') << std::setw(2) << time_info->tm_min << ":"
<< std::setfill('0') << std::setw(2) << time_info->tm_sec << "."
<< std::setfill('0') << std::setw(3) << millisec;
return oss.str(); // 返回格式 "HH:MM:SS.mmm"
}
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::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;
}
int CheckUtil::CalHj(const cv::Mat &img, const cv::Mat &mask, int b_value)
{
cv::Mat imgf;
if (img.type() != CV_32F)
img.convertTo(imgf, CV_32F);
else
imgf = img;
// 2. 减去常数并取绝对值
cv::Mat absDiff = cv::abs(imgf - b_value);
// 3. 用 mask 计算平均值
cv::Scalar meanValue123 = cv::mean(absDiff, mask);
int nonZeroCount = cv::countNonZero(mask);
// printf("===========1== hj %f nonZeroCount %d\n", meanValue123[0], nonZeroCount);
if (nonZeroCount > 100)
{
cv::Mat element;
if (nonZeroCount > 1500)
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(11, 11));
}
else if (nonZeroCount > 1000)
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7));
}
else if (nonZeroCount > 500)
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
}
else
{
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
}
// 进行腐蚀操作
cv::Mat erodedMask;
cv::erode(mask, erodedMask, element);
int nonZeroCount111 = cv::countNonZero(erodedMask);
if (nonZeroCount111 > 100)
{
meanValue123 = cv::mean(absDiff, erodedMask);
// printf("========2===== hj %f nonZeroCount %d\n", meanValue123[0], nonZeroCount111);
}
}
// if (meanValue123[0] > 100)
// {
// // 打印 32F 像素值
// for (int i = 0; i < absDiff.rows; ++i)
// {
// for (int j = 0; j < absDiff.cols; ++j)
// {
// std::cout << "Pixel value at (" << i << ", " << j << "): "
// << absDiff.at<float>(i, j) << std::endl;
// }
// }
// }
return meanValue123[0];
}
int CheckUtil::CalHj(const cv::Mat &img, const cv::Mat &mask, const cv::Mat &backgroundimg)
{
cv::Mat imgf;
if (img.type() != CV_32F)
img.convertTo(imgf, CV_32F);
else
imgf = img;
cv::Scalar meanValue = cv::mean(backgroundimg);
int b_value = meanValue[0];
// 2. 减去常数并取绝对值
cv::Mat absDiff = cv::abs(imgf - b_value);
// 3. 用 mask 计算平均值
cv::Scalar meanValue123 = cv::mean(absDiff, mask);
return meanValue123[0];
}
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::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<double>(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<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> 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;
}
int CheckUtil::DeleteDir(const std::string &dir)
{
if (dir.empty()) {
return -1;
}
// 检查路径是否存在
struct stat st;
if (stat(dir.c_str(), &st) != 0) {
// 目录不存在,视为成功
return 0;
}
// 如果不是目录,可能是文件,尝试直接删除
if (!S_ISDIR(st.st_mode)) {
if (remove(dir.c_str()) == 0) {
return 0;
} else {
printf("remove file[%s] error: %s\n", dir.c_str(), strerror(errno));
return -1;
}
}
// 是目录,先递归清空内容
if (_remove_dir_recursive_(dir) != 0) {
return -1;
}
// 最后删除空目录本身
if (rmdir(dir.c_str()) != 0) {
printf("rmdir[%s] error: %s\n", dir.c_str(), strerror(errno));
return -1;
}
// printf("remove dir[%s] success.\n", dir.c_str());
return 0;
}
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::Point2f p1, cv::Point2f 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<cv::Rect> &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;
}
cv::Point2f CheckUtil::transformPoint(const cv::Point2f &point, const cv::Mat &transform_matrix)
{
// 验证变换矩阵有效性
if (transform_matrix.empty() || transform_matrix.rows != 2 || transform_matrix.cols != 3)
{
std::cerr << "Error: Invalid transformation matrix! Returning original point." << std::endl;
return point;
}
// 使用矩阵乘法进行点变换
cv::Mat point_mat = (cv::Mat_<double>(3, 1) << point.x, point.y, 1);
cv::Mat result_mat = transform_matrix * point_mat;
return cv::Point2f(result_mat.at<double>(0), result_mat.at<double>(1));
}