Files
eUi/include/simpleAlgo.h
T
2025-07-09 16:03:18 +08:00

768 lines
25 KiB
C++

#include <HalconCpp.h>
#include <opencv.hpp>
#include <ios>
#include <handleAI.h>
#pragma once
using namespace HalconCpp;
struct MatchResult {
cv::Rect boundingRect;
double confidence;
};
// 简单的图像相关算法
//融合两张图片白色区域
static cv::Mat mergeBinaryMats(const cv::Mat& mat1, const cv::Mat& mat2)
{
// 确保两个输入图像具有相同的尺寸
if (mat1.size() != mat2.size()) {
std::cerr << "Error: Input images must have the same size." << std::endl;
return cv::Mat();
}
// 创建一个输出图像,初始化为全黑
cv::Mat merged = cv::Mat::zeros(mat1.size(), CV_8U);
// 将两个输入图像中的白色部分合并到输出图像
cv::bitwise_or(mat1, mat2, merged);
return merged;
}
//Rect相加
static cv::Rect rectPlusRect(cv::Rect world, cv::Rect rect)
{
return cv::Rect(rect.x + world.x, rect.y + world.y, rect.width, rect.height);
}
static cv::Rect findMaxAreaContour(cv::Mat src)
{
int maxIndex = 0, maxArea = 0;
std::vector<std::vector<cv::Point>>contours;
cv::findContours(src, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
if (contours.size() == 0)
return cv::Rect(0, 0, 0, 0);
for (int i = 0; i < contours.size(); i++)
{
int Area = cv::contourArea(contours[i]);
if (Area > maxArea)
{
maxArea = Area;
maxIndex = i;
}
}
if (contours.size() != 0)
return cv::boundingRect(contours[maxIndex]);
return cv::Rect(0, 0, 0, 0);
}
static cv::Rect findMaxAreaContour(cv::Mat src, int& indexReturn)
{
int maxIndex = 0, maxArea = 0;
std::vector<std::vector<cv::Point>>contours;
cv::findContours(src, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
if (contours.size() == 0)
return cv::Rect(0, 0, 0, 0);
for (int i = 0; i < contours.size(); i++)
{
int Area = cv::contourArea(contours[i]);
if (Area > maxArea)
{
maxArea = Area;
maxIndex = i;
}
}
if (contours.size() != 0)
{
indexReturn = maxIndex;
return cv::boundingRect(contours[maxIndex]);
}
}
static cv::Mat cutImg2Cls(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128));
static cv::Mat cutImg2Cls(std::vector<cv::Point> contour, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128));
static std::vector<cv::Mat> cutImg2ClsVec(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize = cv::Size(128, 128))
{
std::vector<cv::Mat> result;
if (boundingBox.width <= 0 || boundingBox.height <= 0 || imgInput.empty()) {
std::cerr << "Invalid bounding box or empty input image." << std::endl;
return result;
}
int minSide = getMin(boundingBox.width, boundingBox.height);
if (minSide == 0) {
std::cerr << "Bounding box has zero width or height." << std::endl;
return result;
}
int splitCount = getMax(1, getMax(boundingBox.width, boundingBox.height) / minSide);
if (splitCount > 2) {
if (boundingBox.width > boundingBox.height) { // 横向裁
for (int i = 0; i < splitCount; i++) {
int x = boundingBox.x + boundingBox.height * i;
if (x + boundingBox.height > boundingBox.x + boundingBox.width)
break;
result.emplace_back(cutImg2Cls(cv::Rect(x, boundingBox.y, boundingBox.height, boundingBox.height), imgInput, targetSize));
}
// 确保最右边包含
result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x + boundingBox.width - boundingBox.height, boundingBox.y, boundingBox.height, boundingBox.height), imgInput, targetSize));
}
else { // 纵向裁
for (int i = 0; i < splitCount; i++) {
int y = boundingBox.y + boundingBox.width * i;
if (y + boundingBox.width > boundingBox.y + boundingBox.height)
break;
result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, y, boundingBox.width, boundingBox.width), imgInput, targetSize));
}
result.emplace_back(cutImg2Cls(cv::Rect(boundingBox.x, boundingBox.y + boundingBox.height - boundingBox.width, boundingBox.width, boundingBox.width), imgInput, targetSize));
}
}
else {
result.emplace_back(cutImg2Cls(boundingBox, imgInput, targetSize));
}
return result;
}
static cv::Mat cutImg2Cls(std::vector<cv::Point> contour, cv::Mat imgInput, cv::Size targetSize)
{
if (contour.empty() || imgInput.empty()) {
std::cerr << "Empty contour or input image." << std::endl;
return cv::Mat();
}
cv::Rect boundingBox = cv::boundingRect(contour);
return cutImg2Cls(boundingBox, imgInput, targetSize);
}
static cv::Mat cutImg2Cls(cv::Rect boundingBox, cv::Mat imgInput, cv::Size targetSize)
{
if (boundingBox.width <= 0 || boundingBox.height <= 0 || imgInput.empty()) {
std::cerr << "Invalid bounding box or empty input image." << std::endl;
return cv::Mat();
}
cv::Point mid(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2);
int sideLength = getMax(getMax(boundingBox.width, boundingBox.height), 128);
// 生成一个空的正方形黑图
cv::Mat squareImage(sideLength, sideLength, imgInput.type(), cv::Scalar(0, 0, 0));
// 从原图中取的期望矩形区域
cv::Rect expectRect(mid.x - sideLength / 2, mid.y - sideLength / 2, sideLength, sideLength);
int xOffset = 0;
int yOffset = 0;
// 调整 expectRect 防止越界
if (expectRect.x < 0) {
expectRect.width += expectRect.x;
xOffset -= expectRect.x;
expectRect.x = 0;
}
if (expectRect.y < 0) {
expectRect.height += expectRect.y;
yOffset -= expectRect.y;
expectRect.y = 0;
}
if (expectRect.x + expectRect.width > imgInput.cols)
expectRect.width = imgInput.cols - expectRect.x;
if (expectRect.y + expectRect.height > imgInput.rows)
expectRect.height = imgInput.rows - expectRect.y;
if (expectRect.width <= 0 || expectRect.height <= 0) {
std::cerr << "Adjusted region is invalid after clipping." << std::endl;
return cv::Mat();
}
imgInput(expectRect).copyTo(squareImage(cv::Rect(xOffset, yOffset, expectRect.width, expectRect.height)));
cv::resize(squareImage, squareImage, targetSize);
return squareImage;
}
static cv::Mat HObject2Mat(HObject& Hobj) //HObject类型转Mat类型
{
HTuple htCh;
HString cType;
cv::Mat Image;
ConvertImageType(Hobj, &Hobj, "byte");
CountChannels(Hobj, &htCh);
Hlong wid = 0;
Hlong hgt = 0;
if (htCh[0].I() == 1)
{
HImage hImg(Hobj);
void* ptr = hImg.GetImagePointer1(&cType, &wid, &hgt);//GetImagePointer1(Hobj, &ptr, &cType, &wid, &hgt);
int W = wid;
int H = hgt;
Image.create(H, W, CV_8UC1);
unsigned char* pdata = static_cast<unsigned char*>(ptr);
memcpy(Image.data, pdata, W * H);
}
else if (htCh[0].I() == 3)
{
void* Rptr;
void* Gptr;
void* Bptr;
HImage hImg(Hobj);
hImg.GetImagePointer3(&Rptr, &Gptr, &Bptr, &cType, &wid, &hgt);
int W = wid;
int H = hgt;
Image.create(H, W, CV_8UC3);
std::vector<cv::Mat> VecM(3);
VecM[0].create(H, W, CV_8UC1);
VecM[1].create(H, W, CV_8UC1);
VecM[2].create(H, W, CV_8UC1);
unsigned char* R2 = (unsigned char*)Rptr;
unsigned char* G = (unsigned char*)Gptr;
unsigned char* B = (unsigned char*)Bptr;
memcpy(VecM[2].data, R2, W * H);
memcpy(VecM[1].data, G, W * H);
memcpy(VecM[0].data, B, W * H);
cv::merge(VecM, Image);
}
return Image;
}
enum MatsToHObjectEnum
{
horizontal,
vertical
};
static HalconCpp::HObject MatsToHObject(cv::Mat* img1, cv::Mat* img2, MatsToHObjectEnum type)
{
auto start3 = std::chrono::high_resolution_clock::now();
HalconCpp::HObject Hobj;
int height = 0;
int width = 0;
switch (type)
{
case horizontal:
width = img1->cols;
height = img1->rows + img2->rows;
break;
case vertical:
width = img1->cols + img2->cols;
height = img1->rows;
break;
}
if (img1->type() == CV_8UC1)
{
unsigned char* imgData = new unsigned char[width * height];
memcpy(imgData, img1->data, img1->rows * img1->cols);
memcpy(img1->rows * img1->cols + imgData, img2->data, img1->rows * img1->cols);
GenImage1(&Hobj, "byte", width, height, (Hlong)imgData);
delete[]imgData;
imgData = nullptr;
}
auto end3 = std::chrono::high_resolution_clock::now();
auto duration3 = std::chrono::duration_cast<std::chrono::milliseconds>(end3 - start3);
std::cout << "Time taken by functionxxx: " << duration3.count() << " milliseconds" << std::endl;
return Hobj;
}
static HalconCpp::HObject MatsToHObject(cv::Mat& img1, cv::Mat& img2, MatsToHObjectEnum type)
{
auto start3 = std::chrono::high_resolution_clock::now();
HalconCpp::HObject Hobj;
int height = 0;
int width = 0;
switch (type)
{
case horizontal:
width = img1.cols;
height = img1.rows + img2.rows;
break;
case vertical:
width = img1.cols + img2.cols;
height = img1.rows;
break;
}
if (img1.type() == CV_8UC1)
{
unsigned char* imgData = new unsigned char[width * height];
//#pragma omp parallel for
//for (int i = 0; i < 2; i++)
//{
// switch (i)
// {
// case 0:
// memcpy(imgData, img1.data, img1.rows * img1.cols);
// break;
// case 1:
// memcpy(img1.rows * img1.cols + imgData, img2.data, img1.rows * img1.cols);
// break;
// }
//}
memcpy(imgData, img1.data, img1.rows * img1.cols);
memcpy(img1.rows * img1.cols + imgData, img2.data, img1.rows * img1.cols);
GenImage1(&Hobj, "byte", width, height, (Hlong)imgData);
delete[]imgData;
imgData = nullptr;
}
auto end3 = std::chrono::high_resolution_clock::now();
auto duration3 = std::chrono::duration_cast<std::chrono::milliseconds>(end3 - start3);
std::cout << "Time taken by functionxxx: " << duration3.count() << " milliseconds" << std::endl;
return Hobj;
}
static void MatToHObjectV(cv::Mat& image, HalconCpp::HObject* Hobj)
{
int hgt = image.rows;
int wid = image.cols;
int i;
if (image.type() == CV_8UC3)
{
HalconCpp::HImage himage = HalconCpp::HImage();
std::vector<cv::Mat> imgchannel;
split(image, imgchannel);
cv::Mat imgB = imgchannel[0];
cv::Mat imgG = imgchannel[1];
cv::Mat imgR = imgchannel[2];
uchar* dataR = new uchar[hgt * wid];
uchar* dataG = new uchar[hgt * wid];
uchar* dataB = new uchar[hgt * wid];
for (i = 0; i < hgt; i++)
{
memcpy(dataR + wid * i, imgR.data + imgR.step * i, wid);
memcpy(dataG + wid * i, imgG.data + imgG.step * i, wid);
memcpy(dataB + wid * i, imgB.data + imgB.step * i, wid);
}
himage.GenImage3("byte", wid, hgt, dataR, dataG, dataB);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPtR, * hImgPtG, * hImgPtB;
himage.GetImagePointer3(&hImgPtR, &hImgPtG, &hImgPtB, &tmpType, &tmpW, &tmpH);
GenImage3(Hobj, "byte", wid, hgt, (Hlong)hImgPtR, (Hlong)hImgPtG, (Hlong)hImgPtB);
delete[]dataR;
delete[]dataG;
delete[]dataB;
dataR = NULL;
dataG = NULL;
dataB = NULL;
}
else if (image.type() == CV_8UC1)
{
//HalconCpp::HImage himage = HalconCpp::HImage();
////uchar* data = new uchar[hgt * wid];
////for (i = 0; i < hgt; i++)
////{
//// memcpy(data + wid * i, image.data + image.step * i, wid);
////}
////gen_image_const
//himage.GenImage1("byte", wid, hgt, image.data);
//HalconCpp::HString tmpType;
//Hlong tmpW, tmpH;
//void* hImgPt;
//hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
//GenImage1(&Hobj, "byte", wid, hgt, (Hlong)hImgPt);
GenImage1(Hobj, "byte", wid, hgt, (Hlong)image.data);
/* delete[] data;
data = NULL;*/
}
else if (image.type() == CV_16UC1)
{
HalconCpp::HImage himage = HalconCpp::HImage();
ushort* data = new ushort[hgt * wid * 2];
memcpy(data, image.data, hgt * wid * 2);
himage.GenImage1("uint2", wid, hgt, data);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPt;
hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
GenImage1(Hobj, "uint2", wid, hgt, (Hlong)hImgPt);
delete[] data;
data = NULL;
}
else if (image.type() == CV_16SC1)
{
HalconCpp::HImage himage = HalconCpp::HImage();
short* data = new short[hgt * wid * 2];
memcpy(data, image.data, hgt * wid * 2);
himage.GenImage1("int2", wid, hgt, data);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPt;
hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
GenImage1(Hobj, "int2", wid, hgt, (Hlong)hImgPt);
delete[] data;
data = NULL;
}
}
static HalconCpp::HObject MatToHObject(cv::Mat& image)
{
HalconCpp::HObject Hobj;
int hgt = image.rows;
int wid = image.cols;
int i;
if (image.type() == CV_8UC3)
{
HalconCpp::HImage himage = HalconCpp::HImage();
std::vector<cv::Mat> imgchannel;
split(image, imgchannel);
cv::Mat imgB = imgchannel[0];
cv::Mat imgG = imgchannel[1];
cv::Mat imgR = imgchannel[2];
uchar* dataR = new uchar[hgt * wid];
uchar* dataG = new uchar[hgt * wid];
uchar* dataB = new uchar[hgt * wid];
for (i = 0; i < hgt; i++)
{
memcpy(dataR + wid * i, imgR.data + imgR.step * i, wid);
memcpy(dataG + wid * i, imgG.data + imgG.step * i, wid);
memcpy(dataB + wid * i, imgB.data + imgB.step * i, wid);
}
himage.GenImage3("byte", wid, hgt, dataR, dataG, dataB);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPtR, * hImgPtG, * hImgPtB;
himage.GetImagePointer3(&hImgPtR, &hImgPtG, &hImgPtB, &tmpType, &tmpW, &tmpH);
GenImage3(&Hobj, "byte", wid, hgt, (Hlong)hImgPtR, (Hlong)hImgPtG, (Hlong)hImgPtB);
delete[]dataR;
delete[]dataG;
delete[]dataB;
dataR = NULL;
dataG = NULL;
dataB = NULL;
}
else if (image.type() == CV_8UC1)
{
//HalconCpp::HImage himage = HalconCpp::HImage();
////uchar* data = new uchar[hgt * wid];
////for (i = 0; i < hgt; i++)
////{
//// memcpy(data + wid * i, image.data + image.step * i, wid);
////}
////gen_image_const
//himage.GenImage1("byte", wid, hgt, image.data);
//HalconCpp::HString tmpType;
//Hlong tmpW, tmpH;
//void* hImgPt;
//hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
//GenImage1(&Hobj, "byte", wid, hgt, (Hlong)hImgPt);
GenImage1(&Hobj, "byte", wid, hgt, (Hlong)image.data);
/* delete[] data;
data = NULL;*/
}
else if (image.type() == CV_16UC1)
{
HalconCpp::HImage himage = HalconCpp::HImage();
ushort* data = new ushort[hgt * wid * 2];
memcpy(data, image.data, hgt * wid * 2);
himage.GenImage1("uint2", wid, hgt, data);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPt;
hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
GenImage1(&Hobj, "uint2", wid, hgt, (Hlong)hImgPt);
delete[] data;
data = NULL;
}
else if (image.type() == CV_16SC1)
{
HalconCpp::HImage himage = HalconCpp::HImage();
short* data = new short[hgt * wid * 2];
memcpy(data, image.data, hgt * wid * 2);
himage.GenImage1("int2", wid, hgt, data);
HalconCpp::HString tmpType;
Hlong tmpW, tmpH;
void* hImgPt;
hImgPt = himage.GetImagePointer1(&tmpType, &tmpW, &tmpH);
GenImage1(&Hobj, "int2", wid, hgt, (Hlong)hImgPt);
delete[] data;
data = NULL;
}
return Hobj;
}
//获取两点之间的直线距离
static double getDistance(cv::Point pointO, cv::Point pointA)
{
double distance;
distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
distance = sqrtf(distance);
return distance;
}
//获取点到线段之间的直线距离
static double pointToLineDistance(const cv::Point& point, const cv::Point& lineStart, const cv::Point& lineEnd) {
double numerator = std::abs((lineEnd.y - lineStart.y) * point.x - (lineEnd.x - lineStart.x) * point.y + lineEnd.x * lineStart.y - lineEnd.y * lineStart.x);
double denominator = std::sqrt(std::pow(lineEnd.y - lineStart.y, 2) + std::pow(lineEnd.x - lineStart.x, 2));
return numerator / denominator;
}
//计算角度,pt2为顶点
static double calculateAngle(cv::Point pt1, cv::Point pt2, cv::Point pt3)
{
// 计算两个向量
cv::Point vector1 = pt1 - pt2;
cv::Point vector2 = pt3 - pt2;
// 计算两个向量的长度
double length1 = norm(vector1);
double length2 = norm(vector2);
// 计算两个向量的点积
double dotProduct = vector1.dot(vector2);
// 计算夹角的余弦值
double cosAngle = dotProduct / (length1 * length2);
// 计算夹角的弧度
double angleRadians = acos(cosAngle);
// 将弧度转换为度数
double angleDegrees = angleRadians * 180 / CV_PI;
return angleDegrees;
}
//计算角度偏移量,pt1,pt2为第一条线段,pt3,pt4为第二条线段
static double calculateAngleOffset(cv::Point pt11, cv::Point pt12, cv::Point pt21, cv::Point pt22)
{
// 计算第一条线段的向量
cv::Point vec1(pt12.x - pt11.x, pt12.y - pt11.y);
// 计算第二条线段的向量
cv::Point vec2(pt22.x - pt21.x, pt22.y - pt21.y);
// 计算向量的叉乘
double crossProduct = vec1.x * vec2.y - vec1.y * vec2.x;
// 计算角度偏移量
double angleOffset = atan2(crossProduct, vec1.dot(vec2));
// 将弧度转换为度数
angleOffset = angleOffset * 180 / CV_PI;
return angleOffset;
}
//通过角度计算圆上点的位置
static cv::Point calculatePointOnCircle(cv::Point center, double radius, double angleDegrees)
{
// 将角度转换为弧度
double angleRadians = angleDegrees * CV_PI / 180.0;
// 计算点的坐标
int x = static_cast<int>(center.x + radius * cos(angleRadians));
int y = static_cast<int>(center.y + radius * sin(angleRadians));
return cv::Point(x, y);
}
/// <summary>
/// 模板匹配,以MatchResult返回
/// </summary>
/// <param name="originalImage">图像</param>
/// <param name="templateImage">模板图像</param>
/// <returns></returns>
static MatchResult templateMatching(const cv::Mat& originalImage, const cv::Mat& templateImage) {
MatchResult result;
// 创建结果图像
int resultCols = originalImage.cols - templateImage.cols + 1;
int resultRows = originalImage.rows - templateImage.rows + 1;
cv::Mat resultImg(resultRows, resultCols, CV_32FC1);
// 进行模板匹配
cv::matchTemplate(originalImage, templateImage, resultImg, cv::TM_CCOEFF_NORMED);
// 归一化结果图像
cv::normalize(resultImg, resultImg, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
// 寻找最佳匹配位置
double minVal, maxVal;
cv::Point minLoc, maxLoc;
cv::minMaxLoc(resultImg, &minVal, &maxVal, &minLoc, &maxLoc);
// 设置矩形框和可信度
result.boundingRect = cv::Rect(maxLoc.x, maxLoc.y, templateImage.cols, templateImage.rows);
result.confidence = maxVal;
return result;
}
/// <summary>
/// 模板匹配,返回Rect以及分数
/// </summary>
/// <param name="templateImg">模板图像</param>
/// <param name="srcImg">匹配图像</param>
/// <param name="sorce">分数</param>
/// <returns></returns>
static cv::Rect doMatchTemplate(const cv::Mat& templateImg, const cv::Mat& srcImg, double* sorce)
{
cv::Mat resultImage;
matchTemplate(srcImg, templateImg, resultImage, cv::TM_CCOEFF_NORMED);
double minVal = 0, maxVal = 0;
cv::Point minLoc(0, 0), maxLoc(0, 0);
minMaxLoc(resultImage, &minVal, &maxVal, &minLoc, &maxLoc);
*sorce = maxVal;
cv::Rect rect(maxLoc.x, maxLoc.y, templateImg.cols, templateImg.rows);
return rect;
}
//计算contour是否重叠
static bool isContoursOverlap(const std::vector<cv::Point>& contour1, const std::vector<cv::Point>& contour2, double thresholdPercent = 0) {
cv::Rect rect1 = cv::boundingRect(contour1);
cv::Rect rect2 = cv::boundingRect(contour2);
cv::Size tempImgSize(getMax(rect1.x + rect1.width, rect2.x + rect2.width), getMax(rect1.y + rect1.height, rect2.y + rect2.height));
cv::Mat binaryImage = cv::Mat::zeros(tempImgSize, CV_8U);
// 画出目标轮廓
drawContours(binaryImage, std::vector<std::vector<cv::Point>>{contour2}, 0, cv::Scalar(255), -1);
double totalOverlap = 0.0;
// 创建一个临时的二值图像
cv::Mat tempBinaryImage = cv::Mat::zeros(tempImgSize, CV_8U);
// 画出当前轮廓
drawContours(tempBinaryImage, std::vector<std::vector<cv::Point>>{contour1}, 0, cv::Scalar(255), -1);
// 计算重叠的像素数
cv::Mat intersection = binaryImage & tempBinaryImage;
int overlapPixelCount = countNonZero(intersection);
// 计算当前轮廓的重叠百分比
double overlapPercentage = static_cast<double>(overlapPixelCount) / countNonZero(tempBinaryImage);
return overlapPercentage * 100.0 > thresholdPercent; // 将结果转换为百分比
}
//计算rect是否重叠
static bool isRectOverlap(const cv::Rect& rect1, const cv::Rect& rect2, double thresholdPercent = 0) {
// 计算两个矩形的重叠区域
cv::Rect intersection = rect1 & rect2;
if (thresholdPercent != 0)//如果有阈值
{
int maxCnotourArea = getMax(rect1.area(), rect2.area());
if (intersection.area() / maxCnotourArea < thresholdPercent)
return false;
}
// 如果重叠区域的面积大于0,则说明两个矩形重叠
return intersection.area() > 0;
}
//将两个contour的区域合并
static std::vector<cv::Point> contourPlusContour(const std::vector<cv::Point>& contour1, const std::vector<cv::Point>& contour2)
{
std::vector<cv::Point>res;
res.insert(res.end(), contour1.begin(), contour1.end());
res.insert(res.end(), contour2.begin(), contour2.end());
return res;
}
static cv::Rect BboxToRect(handdleAI::Bbox input)
{
return cv::Rect(input.x - input.w / 2, input.y - input.h / 2, input.w, input.h);
}
enum ngTypeEnum
{
OK,
huaHeng,
aoKeng,
zangWu
};
struct rectAndData
{
cv::Rect rect;
double defectHeight;
double defectWidth;
int badType = 0;
bool result;
ngTypeEnum ngType;
std::vector<cv::Point> contour;
rectAndData(cv::Rect rectInput, double defectHeightInput, double defectWidthInput, bool resultInput)
{
rect = rectInput;
defectHeight = defectHeightInput;
defectWidth = defectWidthInput;
result = resultInput;
}
rectAndData(cv::Rect rectInput, double defectHeightInput, double defectWidthInput, int n, bool resultInput)
{
rect = rectInput;
defectHeight = defectHeightInput;
defectWidth = defectWidthInput;
badType = n;
result = resultInput;
}
rectAndData(cv::Rect rectInput, double defectHeightInput, double defectWidthInput, int n, bool resultInput, std::vector<cv::Point>& contourInput)
{
rect = rectInput;
defectHeight = defectHeightInput;
defectWidth = defectWidthInput;
badType = n;
result = resultInput;
contour = contourInput;
}
rectAndData(cv::Rect rectInput, double defectHeightInput, double defectWidthInput, int n, bool resultInput, std::vector<cv::Point>& contourInput, ngTypeEnum inputNgType)
{
rect = rectInput;
defectHeight = defectHeightInput;
defectWidth = defectWidthInput;
badType = n;
result = resultInput;
contour = contourInput;
ngType = inputNgType;
}
};
;
//平铺图像
static cv::Mat tiledImages(std::vector<cv::Mat>& imgs)
{
if (imgs.size() == 0)
return cv::imread("./noimg.png",-1);
if (imgs.size() == 1)
return imgs[0];
for (auto& img : imgs)
{
if (img.channels() == 1)
cv::cvtColor(img, img, cv::COLOR_GRAY2BGR);
}
//总图像大小 平铺显示
int matWidth = 0, matHeight = 0;
for (auto& mat : imgs)
{
matHeight = getMax(mat.rows, matHeight);
matWidth += mat.cols;
}
cv::Mat showMat(matHeight, matWidth, CV_8UC3);
//平铺图像
int withCnt = 0;
for (auto& resultMat : imgs)
{
resultMat.copyTo(showMat(cv::Rect(withCnt, 0, resultMat.cols, resultMat.rows)));
withCnt += resultMat.cols;
}
return showMat;
};