|
|
/*
|
|
|
* 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));
|
|
|
} |