暂时稳定的一个版本

This commit is contained in:
2024-06-24 17:38:21 +08:00
parent b37e1005df
commit e929cbfa1d
109 changed files with 370 additions and 280 deletions
@@ -1,6 +1,6 @@
#include <FrontendBackendBridge.h>
#include <uiModule/uiModule_switchProduct.h>
#include <appConfig/appConfig.hpp>
fbBridge bridge;
//INIT
backEnd::backEnd(QObject* parent)
@@ -109,4 +109,4 @@ std::vector<productDataStruct> switchProductWidgetDataPtr::getAllProductData()
result = *productDatasPtr;
mutex->unlock();
return result;
}
}
@@ -49,7 +49,6 @@ class fbBridge :public QObject
{
Q_OBJECT
public:
appConfig* _appConfig = nullptr;
switchProductWidgetDataPtr _switchProductWidgetDataPtr;
frontEnd front;
backEnd back;
@@ -62,6 +61,9 @@ public:
{
}
appConfig* _appConfig = nullptr;
private:
};
+46 -65
View File
@@ -285,10 +285,6 @@ void test()
QThread::msleep(100);
}
CorrectionPoints oldPoints;
double originX = -125.3, originY = -450.4, originZ = -233.8;
double originRx = -0.278863, originRy = 0.142551, originRz = -0.676582;
//-726.5 -1104.1 -33989.4 -24.6389 14.1795 -0.660849
void createModbusStrs(const int startPos,double& Value, std::shared_ptr <detData> data)
{
data->writeBack("short", startPos, QString::number(Value < 0 ? 2 : 1));
@@ -297,31 +293,65 @@ void createModbusStrs(const int startPos,double& Value, std::shared_ptr <detData
data->writeBack("short", startPos + 2, QString::number(static_cast<int>(abs(pvalue * 100))));
}
correctionStruct* correctionData1x = new correctionStruct();
double doubleLmit(double input, int num)
{
std::ostringstream out;
out << std::fixed << std::setprecision(num) << input;
return std::stod(out.str());
}
void ALGO_Correction(std::shared_ptr <detData> data)
{
test();
correctionData1x->in_X_X0Y = { 344.7,503.1,684.49 };
correctionData1x->in_Y_X0Y = { -1213.81,-1313.8,-1213.81 };
correctionData1x->in_Z_X0Y = { -130.5,-130.58,-130.46 };
correctionData1x->in_Z_X0Y_Value = { -77.8479,-78.1794,-76.3074 };
correctionData1x->in_X_X0Z = { 615.2,197.49,197.38 };
correctionData1x->in_Y_X0Z = { -372.67,-372.84,-372.87 };
correctionData1x->in_Z_X0Z = { -922.86,-933.44,-1004.16 };
correctionData1x->in_Y_X0Z_Value = { -74.139,-77.8869,-78.1404 };
correctionData1x->in_X_Y0Z = { -213.84,-213.9,-213.86 };
correctionData1x->in_Y_Y0Z = { -1007.81,-1072.32,-999.51 };
correctionData1x->in_Z_Y0Z = { -601.31,-601.35,-693.32 };
correctionData1x->in_X_Y0Z_Value = { 81.1083,80.4141,80.9913 };
data->correctionData = correctionData1x;
if (data->correctionData == nullptr)
return;
CorrectionPoints resultPoints;
HalconCorrection(data->correctionData, resultPoints);
Point3d point = getRPY(resultPoints);
std::cout << "ox:" << resultPoints.Origin[0] << "oy:" << resultPoints.Origin[1] << "oz:" << resultPoints.Origin[2] << std::endl;
std::cout << "Rx:" << point.x << "Ry:" << point.y << "Rz:" << point.z << std::endl;
//std::cout << "ox:" << oldPoints.Origin[0] << "oy:" << oldPoints.Origin[1] << "oz:" << oldPoints.Origin[2] << std::endl;
//std::cout << "Rx:" << rotationAnglesx.x << "Ry:" << rotationAnglesx.y << "Rz:" << rotationAnglesx.z << std::endl;
double offsetX = originX - resultPoints.Origin[0];
double offsetY = originY - resultPoints.Origin[1];
double offsetZ = originZ - resultPoints.Origin[2];
double offsetRx = originRx - point.x;
double offsetRy = originRy - point.y;
double offsetRz = originRz - point.z;
//Point3d RPYResult = getRPYOffset(oldPoints, resultPoints);
//Point3d oriResult = getOriginPointOffset(oldPoints, resultPoints);
int baseOffsetX = data->_productDataStruct.basePos[0] - resultPoints.Origin[0];
int baseOffsetY = data->_productDataStruct.basePos[1] - resultPoints.Origin[1];
int baseOffsetZ = data->_productDataStruct.basePos[2] - resultPoints.Origin[2];
double offsetRx = data->_productDataStruct.baseRad[0] - point.x;
double offsetRy = data->_productDataStruct.baseRad[1] - point.y;
double offsetRz = data->_productDataStruct.baseRad[2] - point.z;
cv::Vec3d radIn1({ 0,0,0 });
cv::Vec3d radIn2({ degToRad(offsetRx),degToRad(offsetRy),degToRad(offsetRz) });
cv::Mat coords = (cv::Mat_<double>(3, 1) << data->_productDataStruct.basePos[0], data->_productDataStruct.basePos[1], data->_productDataStruct.basePos[2]);
cv::Mat newCoords = transform_coordinates(coords, radIn1, radIn2);
cv::Mat coordsOffset = (cv::Mat_<double>(3, 1) << coords.at<double>(0, 0) - newCoords.at<double>(0, 0), coords.at<double>(1, 0) - newCoords.at<double>(1, 0), coords.at<double>(2, 0) - newCoords.at<double>(2, 0));
double offsetX = doubleLmit(coordsOffset.at<double>(0, 0) + baseOffsetX,3);
double offsetY = doubleLmit(coordsOffset.at<double>(1, 0) + baseOffsetY,3);
double offsetZ = doubleLmit(coordsOffset.at<double>(2, 0) + baseOffsetZ,3);
offsetRx = doubleLmit(offsetRx, 3);
offsetRy = doubleLmit(offsetRy, 3);
offsetRz = doubleLmit(offsetRz, 3);
std::cout << "offsetX:" << offsetX << "offsetY:" << offsetY << "offsetZ:" << offsetZ << std::endl;
std::cout << "offsetRx:" << offsetRx << "offsetRy:" << offsetRy << "offsetRz:" << offsetRz << std::endl;
//int pValueBounus = 100;
createModbusStrs(310, offsetX,data);
createModbusStrs(313, offsetY, data);
createModbusStrs(316, offsetZ, data);
@@ -331,53 +361,4 @@ void ALGO_Correction(std::shared_ptr <detData> data)
createModbusStrs(325, offsetRz, data);
data->writeBack("short", 274, "1");
#if 0
//originX
data->writeBack("short", 310, QString::number(out_Origin[0] < 0 ? 2 : 1));
data->writeBack("short", 311, QString::number(abs(static_cast<int>(out_Origin[0]))));
double pvalue = out_Origin[0] - static_cast<int>(out_Origin[0]);
data->writeBack("short", 312, QString::number(abs(pvalue * pValueBounus)));
//originY
data->writeBack("short", 313, QString::number(out_Origin[1] < 0 ? 2 : 1));
data->writeBack("short", 314, QString::number(abs(static_cast<int>(out_Origin[1]))));
pvalue = out_Origin[1] - static_cast<int>(out_Origin[1]);
data->writeBack("short", 315, QString::number(abs(pvalue * pValueBounus)));
//originZ
data->writeBack("short", 316, QString::number(out_Origin[2] < 0 ? 2 : 1));
data->writeBack("short", 317, QString::number(abs(static_cast<int>(out_Origin[2]))));
pvalue = out_Origin[2] - static_cast<int>(out_Origin[2]);
data->writeBack("short", 318, QString::number(abs(pvalue * pValueBounus)));
//originX1
data->writeBack("short", 319, QString::number(out_Result_X[0] < 0 ? 2 : 1));
data->writeBack("short", 320, QString::number(abs(static_cast<int>(out_Result_X[0]))));
pvalue = out_Result_X[0] - static_cast<int>(out_Result_X[0]);
data->writeBack("short", 321, QString::number(abs(pvalue * pValueBounus)));
//originX2
data->writeBack("short", 322, QString::number(out_Result_X[1] < 0 ? 2 : 1));
data->writeBack("short", 323, QString::number(abs(static_cast<int>(out_Result_X[1]))));
pvalue = out_Result_X[1] - static_cast<int>(out_Result_X[1]);
data->writeBack("short", 324, QString::number(abs(pvalue * pValueBounus)));
//originX3
data->writeBack("short", 325, QString::number(out_Result_X[2] < 0 ? 2 : 1));
data->writeBack("short", 326, QString::number(abs(static_cast<int>(out_Result_X[2]))));
pvalue = out_Result_X[2] - static_cast<int>(out_Result_X[2]);
data->writeBack("short", 327, QString::number(abs(pvalue * pValueBounus)));
//originY1
data->writeBack("short", 328, QString::number(out_Result_Y[0] < 0 ? 2 : 1));
data->writeBack("short", 329, QString::number(abs(static_cast<int>(out_Result_Y[0]))));
pvalue = out_Result_Y[0] - static_cast<int>(out_Result_Y[0]);
data->writeBack("short", 330, QString::number(abs(pvalue * pValueBounus)));
//originY2
data->writeBack("short", 331, QString::number(out_Result_Y[1] < 0 ? 2 : 1));
data->writeBack("short", 332, QString::number(abs(static_cast<int>(out_Result_Y[1]))));
pvalue = out_Result_Y[1] - static_cast<int>(out_Result_Y[1]);
data->writeBack("short", 333, QString::number(abs(pvalue * pValueBounus)));
//originY3
data->writeBack("short", 334, QString::number(out_Result_Y[2] < 0 ? 2 : 1));
data->writeBack("short", 335, QString::number(abs(static_cast<int>(out_Result_Y[2]))));
pvalue = out_Result_Y[2] - static_cast<int>(out_Result_Y[2]);
data->writeBack("short", 336, QString::number(abs(pvalue * pValueBounus)));
data->writeBack("short", 274, "1");
#endif
}
+35 -58
View File
@@ -8,11 +8,12 @@ cv::Mat pinHandleAiEvaluate(std::shared_ptr <detData> data, cv::Mat& src,
bool pinHalconEvaluate(cv::Rect& Result, cv::Mat& src, cv::Mat& out, int productType);
//公头定位
std::vector<handdleAI::Bbox> pinDetEvaluate(cv::Mat& src, handleAiModelManager* _handleAiModelManager)
std::vector<handdleAI::Bbox> pinDetEvaluate(std::shared_ptr <detData> data ,cv::Mat& src, handleAiModelManager* _handleAiModelManager)
{
cv::Mat resultImg;
std::vector<handdleAI::Bbox> result;
_handleAiModelManager->smalDet->Evaluate(src, result);
handleAiModelDet* detPtr = _handleAiModelManager->getDetModel(data->_productDataStruct.handleAiData.detModelName);
detPtr->Evaluate(src, result);
detPtr = nullptr;
return result;
}
std::vector<handdleAI::Bbox> getpinHandleAiEvaluateRect(std::shared_ptr <detData> data, cv::Mat& src, std::vector<handdleAI::Bbox>& detResult)
@@ -120,44 +121,10 @@ bool pinHalconEvaluate(cv::Rect& Result, cv::Mat& src,cv::Mat& out,int productTy
// ));
//}
}
//缺陷检测
void handleAiEvaluate(std::shared_ptr <detData> data, handleAiModelManager* _handleAiModelManager, std::vector<handdleAI::Bbox>connectorPos, std::vector<cv::Mat>&aiImgResult)
{
cv::Mat src = data->oriImgs[0];
for (auto box : connectorPos)
{
cv::Mat handleAiMat;
bool processed = false;
switch (box.classes)
{
case 0://AFront
handleAiMat = pinHandleAiEvaluate(data, src(BboxToRect(box)),
_handleAiModelManager->largeSeg, _handleAiModelManager->largeCls);
aiImgResult.push_back(handleAiMat);//AI检测结果
break;
case 1://ABack
handleAiMat = pinHandleAiEvaluate(data, src(BboxToRect(box)),
_handleAiModelManager->largeSeg, _handleAiModelManager->largeCls);
aiImgResult.push_back(handleAiMat);//AI检测结果
break;
case 2://B
handleAiMat = pinHandleAiEvaluate(data, src(BboxToRect(box)),
_handleAiModelManager->midSeg, _handleAiModelManager->midCls);
aiImgResult.push_back(handleAiMat);//AI检测结果
break;
case 3://C
handleAiMat = pinHandleAiEvaluate(data, src(BboxToRect(box)),
_handleAiModelManager->smallSeg, _handleAiModelManager->smallCls);
aiImgResult.push_back(handleAiMat);//AI检测结果
break;
default:
data->segOriginImgs.push_back(src(BboxToRect(box)));//AI检测结果
aiImgResult.push_back(src(BboxToRect(box)));//AI检测结果
break;
}
}
}
cv::Mat pinHandleAiEvaluate(std::shared_ptr <detData> data, cv::Mat& src,
cv::Size minPin(30, 30), maxPin(200, 200);
cv::Mat pinHandleAiEvaluate(std::shared_ptr <detData> data, cv::Mat& src,
handleAiModelSeg* segPtr, handleAiModelCls* clsPtr)
{
//结果图
@@ -177,41 +144,47 @@ cv::Mat pinHandleAiEvaluate(std::shared_ptr <detData> data, cv::Mat& src,
for (auto contour : contours)
{
cv::Rect originRect = cv::boundingRect(contour);
if (originRect.width < 30 || originRect.height < 30)
if (originRect.width < minPin.width || originRect.height < minPin.height || originRect.width > maxPin.width || originRect.height > maxPin.height)
continue;
cv::Rect rect = originRect;
int maxHeightOrWidth = max(rect.width, rect.height);
int exHeight = max(maxHeightOrWidth - rect.height, 0);
int exWidth = max(maxHeightOrWidth - rect.width, 0);
rect += cv::Size(exWidth, exHeight);
//判断左上是否越界
rect.x = max(0, rect.x);
rect.y = max(0, rect.y);
//判断右下是否越界
rect.x = min(src.cols - rect.width, rect.x);
rect.y = min(src.rows - rect.height, rect.y);
cv::Mat clsImg;
src(rect).copyTo(clsImg);
cv::resize(clsImg, clsImg, cv::Size(128, 128));
cv::Mat clsImg = cutImg2Cls(rect, src);
int clsRes = clsPtr->Evaluate(clsImg);
cv::Scalar color = cv::Scalar(0, 0, 255, 30);
std::string clsFileName;
switch (clsRes)
{
case 0:
color = cv::Scalar(0, 255, 0, 30);
clsFileName = "OK";
break;
case 1:
color = cv::Scalar(0, 0, 255, 30);
clsFileName = "NG1";
break;
default:
clsFileName = std::to_string(clsRes);
}
data->clsOriginImgs.push_back(std::make_pair(clsFileName, clsImg));
cv::rectangle(Paint, originRect, color, 2);
data->clsOriginImgs.push_back(std::make_pair(clsImg, clsRes));
}
//返回结果图
return Paint;
}
void handleAiEvaluate(std::shared_ptr <detData> data, handleAiModelManager* _handleAiModelManager, std::vector<handdleAI::Bbox>connectorPos, std::vector<cv::Mat>&aiImgResult)
{
cv::Mat src = data->oriImgs[0];
for(auto& handleAiData: data->_productDataStruct.handleAiData.detResultHandle)
{
handleAiModelSeg* segPtr = _handleAiModelManager->getSegModel(handleAiData.segModelName);
handleAiModelCls* clsPtr = _handleAiModelManager->getClsModel(handleAiData.clsModelName);
for (auto box : connectorPos)
{
cv::Mat handleAiMat = pinHandleAiEvaluate(data, src(BboxToRect(box)),
segPtr, clsPtr);
aiImgResult.push_back(handleAiMat);//AI检测结果
}
}
}
//主函数
int ALGO_InspectionErrorCheck(std::shared_ptr <detData> data)
{
@@ -240,7 +213,11 @@ void ALGO_Inspection(std::shared_ptr <detData> data, handleAiModelManager* _hand
}
cv::Mat src = data->oriImgs[0];
//使用det获取每个公头的位置
std::vector<handdleAI::Bbox> detResult = pinDetEvaluate(src, _handleAiModelManager);
std::vector<handdleAI::Bbox> detResult = pinDetEvaluate(data,src, _handleAiModelManager);
if (detResult.size() == 0)
{
return;
}
//过滤结果,获取用于handleAi/HALCON检测的rect
std::vector<handdleAI::Bbox> pinPos = getpinHandleAiEvaluateRect(data,src, detResult);
+1 -1
View File
@@ -640,7 +640,7 @@ static std::vector<cv::Point> contourPlusContour(const std::vector<cv::Point>& c
return res;
}
static Rect BboxToRect(handdleAI::Bbox input)
static cv::Rect BboxToRect(handdleAI::Bbox input)
{
return Rect(input.x - input.w / 2, input.y - input.h / 2, input.w, input.h);
}
@@ -7,7 +7,7 @@
#include <simpleTools/stringAlgo.h>
#include <handleAi/handleAiSimpleDet.h>
#include <uiModule/components/fancyWarnWindow.h>
#include <simpleTools/fileManager.h>
#pragma region 数据结构
struct productDataStruct
{
@@ -26,7 +26,7 @@ struct productDataStruct
bool disableHandleAiConfig = false;
bool enableCodedAlgo = false;
int codedAlgoIndex = -1;
std::vector<handleAiSimpleDet>handleAiDatas;
handleAiSimpleDet handleAiData;
};
struct lightSourceStruct
{
@@ -95,33 +95,36 @@ public:
{
productData.lightSetting.insert(std::make_pair(std::stoi(it.key()), it.value()));
}
for (auto data : res["HandleAi"])
if (res["HandleAi"].empty() == false)
{
handleAiSimpleDet handleAiData;
handleAiData.detModelName = data["detModelName"];
handleAiData.detResultIndex = std::vector<int>(data["detResultIndex"].begin(), data["detResultIndex"].end());
handleAiData.detGpuIndex = data["detGpuIndex"];
handleAiData.segModelName = data["segModelName"];
handleAiData.segNgIndex = std::vector<int>(data["segNgIndex"].begin(), data["segNgIndex"].end());
handleAiData.segGpuIndex = data["segGpuIndex"];
handleAiData.clsModelName = data["clsModelName"];
handleAiData.clsNgIndex = std::vector<int>(data["clsNgIndex"].begin(), data["clsNgIndex"].end());
handleAiData.segGpuIndex = data["segGpuIndex"];
for (auto it = data["clsResultHandle"].begin(); it != data["clsResultHandle"].end(); ++it)
productData.handleAiData.detModelName = res["HandleAi"]["detModelName"];
productData.handleAiData.detGpuIndex = res["HandleAi"]["detGpuIndex"];
for (auto& data : res["HandleAi"]["segHandle"])
{
std::vector<std::string> result = split(it.value(), ',');
if (result.size() != 4)
detResultHandleStruct detResultHandle;
detResultHandle.detResultIndex = std::vector<int>(data["detResultIndex"].begin(), data["detResultIndex"].end());
detResultHandle.segModelName = data["segModelName"];
detResultHandle.segNgIndex = std::vector<int>(data["segNgIndex"].begin(), data["segNgIndex"].end());
detResultHandle.segGpuIndex = data["segGpuIndex"];
detResultHandle.clsModelName = data["clsModelName"];
detResultHandle.clsNgIndex = std::vector<int>(data["clsNgIndex"].begin(), data["clsNgIndex"].end());
detResultHandle.segGpuIndex = data["segGpuIndex"];
for (auto it = data["clsResultHandle"].begin(); it != data["clsResultHandle"].end(); ++it)
{
fancyWarnWindow* warn = new fancyWarnWindow
(fancyWarnWindow::Warning, QString("在%1中的clsResultHandle发现格式错误").arg(QString::fromStdString(fileManager::getFileName(file))),
QString("%1").arg(QString::fromStdString(it.value())));
continue;
std::vector<std::string> result = split(it.value(), ',');
if (result.size() != 4)
{
fancyWarnWindow* warn = new fancyWarnWindow
(fancyWarnWindow::Warning, QString("在%1中的clsResultHandle发现格式错误").arg(QString::fromStdString(fileManager::getFileName(file))),
QString("%1").arg(QString::fromStdString(it.value())));
continue;
}
detResultHandle.clsResultHandle.insert(std::make_pair(std::stoi(it.key()), std::make_pair(result[0], cv::Scalar(std::stoi(result[3]), std::stoi(result[2]), std::stoi(result[1])))));
}
handleAiData.clsResultHandle.insert(std::make_pair(std::stoi(it.key()), std::make_pair(result[0], cv::Scalar(std::stoi(result[3]), std::stoi(result[2]), std::stoi(result[1])))));
productData.handleAiData.detResultHandle.push_back(detResultHandle);
}
productData.handleAiDatas.push_back(handleAiData);
}
productDatas.push_back(productData);
}
@@ -153,5 +156,4 @@ public:
}
#pragma endregion
};
#pragma once
@@ -9,6 +9,7 @@
#include <FrontendBackendBridge.h>
#include <uiModule/uiModule_switchProduct.h>
#include <appConfig/appConfig.hpp>
#include <manualDetThread.h>
backEndManager::backEndManager(appConfig* appData)
{
@@ -21,6 +22,7 @@ backEndManager::backEndManager(appConfig* appData)
_triggerManager = new triggerManager();
_cameraManager = new cameraManager();
_threadManager = new threadManager();
_manualDetThread = new manualDetThread(this);
}
void backEndManager::run()
{
@@ -81,17 +83,9 @@ backEndManager::~backEndManager()
}
void backEndManager::startManualDetSlot(cv::Mat* mats, int algoIndex)
void backEndManager::startManualDetSlot(std::string path, int index)
{
std::shared_ptr <detData> data = _detDataManager->insertDetData("Manual", "Manual", 0, 1);
data->productType = algoIndex;
data->resShowIndex = 0;
data->oriImgMutex.lock();
data->oriImgs.push_back(mats->clone());
data->oriImgMutex.unlock();
delete mats;
_threadManager->addTask(data);//Ìí¼ÓÈÎÎñ
_manualDetThread->startDet(path, index);
}
void backEndManager::writeArmStartSignal(int productTypeIn)
@@ -13,6 +13,7 @@ class threadManager;
class detDataManager;
class imgSaveThreadManager;
class appConfig;
class manualDetThread;
class backEndManager :public QThread
{
Q_OBJECT
@@ -32,7 +33,7 @@ public:
triggerManager* _triggerManager = nullptr;//触发器
cameraManager* _cameraManager = nullptr;//
threadManager* _threadManager = nullptr;
manualDetThread* _manualDetThread = nullptr;
//
std::string productTypeStr;
int productType = -1;
@@ -44,7 +45,7 @@ public slots:
isInit = NotInit;
this->start();
}
void startManualDetSlot(cv::Mat* mats, int algoIndex);
void startManualDetSlot(std::string path, int index);
void writeArmStartSignal(int productType);
private:
void run();
@@ -59,6 +60,5 @@ signals:
void switchStartBtnStatusSignal(int);
void addShowPerformanceWidgetData(int index,int timeCost);
void resetShowPerformanceWidget();
};
#endif
+11 -5
View File
@@ -5,6 +5,7 @@
#include <random>
#include <chrono>
#include <qmutex.h>
#include <appConfig/appConfig.hpp>
//所有检测需要的数据均放在这里
class detDataManager;
class detData
@@ -65,7 +66,7 @@ public:
//algoThreadIndex = _struct.threadIndex;
//resShowIndex = _struct.showIndex;
}
productDataStruct _productDataStruct;
//结果
bool aiDetOK = false;
bool halconOK = false;
@@ -73,7 +74,7 @@ public:
QMutex resultMutex;//结果图锁
std::vector<cv::Mat> resultImgs;//结果图
std::vector<cv::Mat> segOriginImgs;//seg检测原图,共用结果图锁
std::vector<std::pair<cv::Mat,int>> clsOriginImgs;//cls检测原图,共用结果图锁
std::vector<std::pair<std::string,cv::Mat>> clsOriginImgs;//cls检测原图,共用结果图锁
QMutex oriImgMutex;//原图锁
std::vector<cv::Mat> oriImgs;//原图
@@ -88,10 +89,14 @@ public:
}
~detData()
{
for (auto img : oriImgs)
for (auto& img : oriImgs)
img.release();
for (auto img : resultImgs)
for (auto& img : resultImgs)
img.release();
for (auto& img : segOriginImgs)
img.release();
for (auto& img : clsOriginImgs)
img.second.release();
}
};
class detDataManager
@@ -149,4 +154,5 @@ public:
return false;
}
};
};
#pragma once
@@ -5,6 +5,7 @@
#include <qdatetime.h>
#include <backStruct.h>
#include <threadPoolManager.h>
#include <uiModule/components/fancyWarnWindow.h>
class backEndManager;
enum imgSaveThreadType
{
@@ -26,12 +27,28 @@ public:
std::pair<std::string, cv::Mat> data = imgQueue.dequeue();
mutex.unlock();
cv::imwrite(data.first, data.second);
data.second.release();
}
}
void addData(std::string str, cv::Mat mat)
void addData(std::string str, cv::Mat& mat)
{
try
{
if (mat.data == nullptr || mat.empty())
{
qDebug() << "在存图线程中发现无效图像";
return;
}
}
catch(...)
{
qDebug() << "在存图线程中发现无效图像";
return;
}
mutex.lock();
imgQueue.append(std::make_pair(str, mat));
cv::Mat img;
mat.copyTo(img);
imgQueue.append(std::make_pair(str, img));
mutex.unlock();
this->start();
}
@@ -106,7 +123,7 @@ public:
break;
case clsImg:
for (int i = 0; i < data->clsOriginImgs.size(); i++)
resultFileNames.push_back(fileName + "CLS_RES" + getCurrentDateTime() + "_" + std::to_string(data->clsOriginImgs[i].second) + "_Count" + std::to_string(i) + ".bmp");
resultFileNames.push_back(fileName + "CLS_RES" + getCurrentDateTime() + "_" + data->clsOriginImgs[i].first + "_Count" + std::to_string(i) + ".bmp");
break;
}
return resultFileNames;
@@ -124,23 +141,23 @@ public:
{
std::string fileSavePath = genDirName(data, resImg);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
std::string segAndClsPath= fileSavePath + "detImgs//" + getCurrentDateTime() + "//";
createDirectoryIfNotExists(segAndClsPath);//不存在此文件夹则创建
std::string segAndClsPath = fileSavePath + "detImgs//" + getCurrentDateTime() + "//";
//结果图保存
std::vector<std::string>resFileNames = genFileNmaes(data, resImg);
for (int index = 0; index < resFileNames.size(); index++)
saveThread.addData(fileSavePath + resFileNames[index], data->resultImgs[index]);
//seg
std::vector<std::string>segFileNames = genFileNmaes(data, segImg);
if (segFileNames.size() > 0)
createDirectoryIfNotExists(segAndClsPath);//不存在此文件夹则创建
for (int index = 0; index < segFileNames.size(); index++)
saveThread.addData(segAndClsPath + segFileNames[index], data->segOriginImgs[index]);
//cls
std::vector<std::string>clsFileNames = genFileNmaes(data, clsImg);
for (int index = 0; index < clsFileNames.size(); index++)
saveThread.addData(segAndClsPath + clsFileNames[index], data->resultImgs[index]);
saveThread.addData(segAndClsPath + clsFileNames[index], data->clsOriginImgs[index].second);
}
private:
std::string path = "";
@@ -0,0 +1,67 @@
#include <QThread>
#include <QObject>
#include <opencv.hpp>
#include <threadPoolManager.h>
#include <detData.h>
#include <appConfig/appConfig.hpp>
class manualDetThread :public QThread
{
Q_OBJECT
public:
backEndManager* _backEndManager;
detDataManager* _detDataManager;
threadManager* _threadManager;
appConfig* _appConfig;
//检测参数
std::string imgPathStr = "";
int algoIndex = 0;
manualDetThread(backEndManager* _backEndManager)
{
_backEndManager = _backEndManager;
_detDataManager = _backEndManager->_detDataManager;
_threadManager = _backEndManager->_threadManager;
_appConfig = _backEndManager->_appConfig;
}
void run()
{
std::vector<std::shared_ptr<cv::Mat>> mats;
std::vector<std::string>files;
fileManager::getAllFiles(imgPathStr, files, "jpg");
for (auto file : files)
{
std::shared_ptr <detData> data = _detDataManager->insertDetData("Manual", "Manual", 0, 1);
data->productType = algoIndex;
data->resShowIndex = 0;
data->oriImgMutex.lock();
data->oriImgs.push_back(cv::imread(file, -1));
data->oriImgMutex.unlock();
data->_productDataStruct = _appConfig->productDatas[algoIndex];
_threadManager->addTask(data);//添加任务
}
files.clear();
fileManager::getAllFiles(imgPathStr, files, "bmp");
for (auto file : files)
{
std::shared_ptr <detData> data = _detDataManager->insertDetData("Manual", "Manual", 0, 1);
data->productType = algoIndex;
data->resShowIndex = 0;
data->oriImgMutex.lock();
data->oriImgs.push_back(cv::imread(file, -1));
data->oriImgMutex.unlock();
data->_productDataStruct = _appConfig->productDatas[algoIndex];
_threadManager->addTask(data);//添加任务
}
emit finishImgReadSignal();
}
void startDet(std::string path,int index)
{
imgPathStr = path;
algoIndex = index;
this->start();
}
signals:
void finishImgReadSignal();
//void startManualDetSignal(cv::Mat*, int);
};
#pragma once
@@ -0,0 +1,66 @@
#include <QThread>
#include <QObject>
#include <opencv.hpp>
#include <threadPoolManager.h>
#include <detData.h>
#include <appConfig/appConfig.hpp>
class manualDetThread :public QThread
{
Q_OBJECT
public:
backEndManager* _backEndManager;
detDataManager* _detDataManager;
threadManager* _threadManager;
appConfig* _appConfig;
//检测参数
std::string imgPathStr = "";
int algoIndex = 0;
manualDetThread(backEndManager* _backEndManager)
{
_backEndManager = _backEndManager;
_detDataManager = _backEndManager->_detDataManager;
_threadManager = _backEndManager->_threadManager;
_appConfig = _backEndManager->_appConfig;
}
void run()
{
std::vector<std::shared_ptr<cv::Mat>> mats;
std::vector<std::string>files;
fileManager::getAllFiles(imgPathStr, files, "jpg");
for (auto file : files)
{
std::shared_ptr <detData> data = _detDataManager->insertDetData("Manual", "Manual", 0, 1);
data->productType = algoIndex;
data->resShowIndex = 0;
data->oriImgMutex.lock();
data->oriImgs.push_back(cv::imread(file, -1));
data->oriImgMutex.unlock();
data->_productDataStruct = _appConfig->productDatas[algoIndex];
_threadManager->addTask(data);//添加任务
}
files.clear();
fileManager::getAllFiles(imgPathStr, files, "bmp");
for (auto file : files)
{
std::shared_ptr <detData> data = _detDataManager->insertDetData("Manual", "Manual", 0, 1);
data->productType = algoIndex;
data->resShowIndex = 0;
data->oriImgMutex.lock();
data->oriImgs.push_back(cv::imread(file, -1));
data->oriImgMutex.unlock();
data->_productDataStruct = _appConfig->productDatas[algoIndex];
_threadManager->addTask(data);//添加任务
}
emit _backEndManager->finishImgReadSignal();
}
void startDet(std::string path,int index)
{
imgPathStr = path;
algoIndex = index;
this->start();
}
signals:
};
#pragma once
@@ -91,8 +91,6 @@ void threadManager::process()
}
void threadManager::resultHandle(std::shared_ptr <detData> data)
{
//储存结果图
std::async(std::launch::async, &imgSaveThreadManager::saveRes, _imgSaveThreadManager, data);
//发送图片
if (data->resultImgs.size() > 0)
{
@@ -123,7 +121,9 @@ void threadManager::resultHandle(std::shared_ptr <detData> data)
for (auto writeBackStr : data->writeBackData)
_triggerManager->sendFinsMsg(writeBackStr);
//提交清理申请
//储存结果图
std::async(std::launch::async, &imgSaveThreadManager::saveRes, _imgSaveThreadManager, data);
//删除 不再持有
detDataManager* dManager = data->dManager;
data->dManager->deleteDetData(data->timeCode);
}
@@ -23,7 +23,6 @@ class algoThread;
class subThread;
class detDataManager;
class triggerManager;
class backEndManager;
class sncodeCls
@@ -12,6 +12,7 @@ static correctionStruct* correctionData;
void triggerManager::initialization(backEndManager* input)
{
_backEndManager = input;
_appConfig = _backEndManager->_appConfig;
dManager = _backEndManager->_detDataManager;
_cameraManager = _backEndManager->_cameraManager;
_threadManager = _backEndManager->_threadManager;
@@ -129,6 +130,7 @@ void triggerManager::decodeCameraCMD(QByteArray byte)
//correctionData->in_Z_Y0Z = { 118.15,-228.19,-256.5 };
//correctionData->in_X_Y0Z_Value = { -36.652200,-36.7302,41.0436 };
std::shared_ptr <detData> data = dManager->insertDetData("181964", "TEST", 0, 0);
data->_productDataStruct = _appConfig->productDatas[0];
data->imgAmountMin = 0;
data->correctionData = correctionData;
_threadManager->addTask(data);//添加任务
@@ -297,11 +299,12 @@ void triggerManager::decodeCameraCMD(QByteArray byte)
if (armPos == 9)
{
std::shared_ptr <detData> data = dManager->insertDetData("181964", "TEST", 0 , 0);
data->productType = _backEndManager->productType;
data->_productDataStruct = _appConfig->productDatas[_backEndManager->productType];
data->imgAmountMin = 0;
data->correctionData = correctionData;
_threadManager->addTask(data);//添加任务
correctionData = nullptr;
}
}
@@ -316,10 +319,11 @@ void triggerManager::decodeCameraCMD(QByteArray byte)
std::cout << "arm @Pos:" << Pos;
std::shared_ptr <detData> data = dManager->insertDetData("Camera1", "TEST", 1, 1);
data->productType = _backEndManager->productType;
data->oriShowIndex = 0;
data->resShowIndex = 0;
data->armPos = Pos;
data->productType = _backEndManager->productType;
data->_productDataStruct = _appConfig->productDatas[_backEndManager->productType];
auto camera = _cameraManager->getCamera("Camera1");//查找相机
if (camera != nullptr)
camera->captureImage(data);//拍照
@@ -6,6 +6,7 @@
#include <qlibrary.h>
#include <globalStruct.h>
#include <backStruct.h>
#include <appConfig/appConfig.hpp>
class backEndManager;
class cameraManager;
@@ -64,6 +65,7 @@ private:
class triggerManager : public QThread
{
public:
appConfig* _appConfig;
bool armIsRunning = false;
bool initFlag = false;
QString triggerFileName;
+10 -1
View File
@@ -15,6 +15,7 @@ public:
QMovie* movie = nullptr;
QTextEdit* initLog = nullptr;
fancyButtonText* retryBtn = new fancyButtonText(100,50,"重试","重新进行初始化");
fancyButtonText* manualBtn = new fancyButtonText(180, 50, "离线模式", "离线模式");
QGridLayout* glayout = new QGridLayout(this);
QVBoxLayout* vlayout = new QVBoxLayout(this);
loadingWidget()
@@ -23,6 +24,7 @@ public:
connect(retryBtn, &QPushButton::clicked, [=]()
{
retryBtn->setDisabled(true);
manualBtn->setDisabled(true);
start();
});
}
@@ -54,8 +56,13 @@ public:
initLog->append("正在初始化...");
vlayout->addWidget(initLog);
vlayout->addWidget(retryBtn);
QHBoxLayout* btnLayout = new QHBoxLayout();
btnLayout->setAlignment(Qt::AlignLeft);
btnLayout->addWidget(retryBtn);
retryBtn->hide();
btnLayout->addWidget(manualBtn);
manualBtn->hide();
vlayout->addLayout(btnLayout);
glayout->addWidget(sign, 0, 0);
glayout->addLayout(vlayout, 1, 0);
@@ -89,6 +96,8 @@ public:
sign->setPixmap(QPixmap(":/topBar/icon/error.png"));
retryBtn->show();
retryBtn->setEnabled(true);
manualBtn->show();
manualBtn->setEnabled(true);
}
}
protected:
@@ -1,30 +0,0 @@
#include <front/pages/manualDetWidget.h>
#include <back/detData.h>
#include <simpleTools/fileManager.h>
void manualDetThread::run()
{
std::string imgPathStr = imgPathEdit->text().toStdString() + "\\";
int algoIndex = algoSelect->currentIndex();
std::vector<std::shared_ptr<cv::Mat>> mats;
std::vector<std::string>files;
fileManager::getAllFiles(imgPathStr, files, "jpg");
for (auto file : files)
{
emit startManualDetSignal(new cv::Mat(cv::imread(file,-1)), algoIndex);
//mats.push_back(std::shared_ptr<cv::Mat>(std::make_shared<cv::Mat>(cv::imread(file))));
logWidget->append(u8"¼ì²âµ½Í¼Æ¬:" + QString::fromStdString(file));
}
fileManager::getAllFiles(imgPathStr, files, "bmp");
for (auto file : files)
{
emit startManualDetSignal(new cv::Mat(cv::imread(file, -1)), algoIndex);
//mats.push_back(std::shared_ptr<cv::Mat>(std::make_shared<cv::Mat>(cv::imread(file))));
logWidget->append(u8"¼ì²âµ½Í¼Æ¬:" + QString::fromStdString(file));
}
emit finishImgReadSignal();
}
void manualDetThread::manualDetSlot()
{
this->start();
}
@@ -9,26 +9,9 @@
#include <QThread>
#include <qlineedit.h>
#include <qtextedit.h>
class manualDetThread :public QThread
{
Q_OBJECT
public:
manualDetThread(QLineEdit* imgPathEditIn, QComboBox* algoSelectIn, QTextEdit* logWidgetIn)
{
imgPathEdit = imgPathEditIn;
algoSelect = algoSelectIn;
logWidget = logWidgetIn;
}
QTextEdit* logWidget = nullptr;
QLineEdit* imgPathEdit = nullptr;
QComboBox* algoSelect = nullptr;
void run();
public slots:
void manualDetSlot();
signals:
void finishImgReadSignal();
void startManualDetSignal(cv::Mat*,int);
};
#include <FrontendBackendBridge.h>
#include <appConfig/appConfig.hpp>
class manualDetWidget : public QWidget
{
Q_OBJECT
@@ -48,7 +31,7 @@ public:
QLineEdit* imgPathEdit = new QLineEdit(this);
QComboBox* algoSelect = new QComboBox(this);
QTextEdit* logWidget = new QTextEdit(this);
manualDetThread* _manualDetThread = new manualDetThread(imgPathEdit, algoSelect, logWidget);
//manualDetThread* _manualDetThread = new manualDetThread(imgPathEdit, algoSelect, logWidget);
fancyButtonText* startEvaluateBtn = new fancyButtonText(100,60,"检测","");
void titleInit()
{
@@ -106,9 +89,10 @@ public:
algoSelect->setFont(font);
algoSelect->setPalette(palette);
algoSelect->setFixedWidth(componentsWidth);
algoSelect->addItem("小产品");
algoSelect->addItem("中产品");
algoSelect->addItem("大产品");
for (auto data : bridge._appConfig->productDatas)
{
algoSelect->addItem(QString::fromStdString(data.name));
}
leftMainLayout->addWidget(algoSelect);
leftMainLayout->addWidget(startEvaluateBtn);
@@ -126,19 +110,21 @@ public:
leftMainLayout->setAlignment(Qt::AlignTop);
mainLayout->addLayout(rightMainLayout);
connect(startEvaluateBtn, &QPushButton::clicked, _manualDetThread, &manualDetThread::manualDetSlot);
connect(startEvaluateBtn, &QPushButton::clicked, this, [=]() {emit startManualDetSignal(imgPathEdit->text().toStdString(), algoSelect->currentIndex()); });
connect(startEvaluateBtn, &QPushButton::clicked, this, [=]() {startEvaluateBtn->setDisabled(true); });
connect(_manualDetThread, &manualDetThread::finishImgReadSignal,this, &manualDetWidget::finishImgReadSlot);
//connect(_manualDetThread, &manualDetThread::finishImgReadSignal,this, &manualDetWidget::finishImgReadSlot);
}
~manualDetWidget()
{
delete _manualDetThread;
//delete _manualDetThread;
}
public slots:
void finishImgReadSlot()
{
startEvaluateBtn->setEnabled(true);
}
signals:
void startManualDetSignal(std::string path, int index);
};
#pragma once
+2
View File
@@ -103,4 +103,6 @@ static void cvMatToQPixMap(cv::Mat& src,QPixmap& pixmap)
}
Q_DECLARE_METATYPE(imgWidgetShowType)
Q_DECLARE_METATYPE(cv::Mat*)
Q_DECLARE_METATYPE(cv::Mat)
Q_DECLARE_METATYPE(std::string)
#pragma once
@@ -1,19 +1,19 @@
#include <handleAi/handleAiModel.h>
#include <appConfig/appConfig.hpp>
handleAiModelManager::handleAiModelManager(appConfig* appData)
handleAiModelManager::handleAiModelManager(appConfig* _appConfig)
{
gpuMutex = std::vector<std::mutex*>(gpuCnt, new std::mutex());
appData->productDatasMutex.lock();
this->basePath = appData->handleAiModelPath + "/";
for (auto& productData : appData->productDatas)
_appConfig->productDatasMutex.lock();
this->basePath = _appConfig->handleAiModelPath + "/";
for (auto& productData : _appConfig->productDatas)
{
for (auto& handleAiData : productData.handleAiDatas)
insertDetModelPath(productData.handleAiData.detModelName, productData.handleAiData.detGpuIndex);
for (auto& handleAiData : productData.handleAiData.detResultHandle)
{
insertDetModelPath(handleAiData.detModelName, handleAiData.detGpuIndex);
insertSegModelPath(handleAiData.segModelName, handleAiData.segGpuIndex);
insertClsModelPath(handleAiData.clsModelName, handleAiData.clsGpuIndex);
}
}
appData->productDatasMutex.unlock();
_appConfig->productDatasMutex.unlock();
}
@@ -129,9 +129,7 @@ public:
handleAiModelCls* smallCls;
handleAiModelDet* smalDet;
std::string basePath;
////////模型放这里///////
handleAiModelManager(appConfig*);
///////////END/////////
bool insertSegModelPath(std::string modelName,int gpuIndex)
{
auto mapResult = segModels.find(modelName);
@@ -157,29 +155,26 @@ public:
clsModels.insert(std::make_pair(modelName, clsModel));
}
//
bool getSegModel(std::string modelName, handleAiModelSeg* seg)
handleAiModelSeg* getSegModel(std::string modelName)
{
auto mapResult = segModels.find(modelName);
if (mapResult != segModels.end())//已有数据
return false;
seg = mapResult->second;
return true;
if (mapResult == segModels.end())//已有数据
return nullptr;
return mapResult->second;
}
bool getDetModel(std::string modelName, handleAiModelDet* det)
handleAiModelDet* getDetModel(std::string modelName)
{
auto mapResult = detModels.find(modelName);
if (mapResult != detModels.end())//已有数据
return false;
det = mapResult->second;
return true;
if (mapResult == detModels.end())//已有数据
return nullptr;
return mapResult->second;
}
bool getClsModel(std::string modelName, handleAiModelCls* cls)
handleAiModelCls* getClsModel(std::string modelName)
{
auto mapResult = clsModels.find(modelName);
if (mapResult != clsModels.end())//已有数据
return false;
cls = mapResult->second;
return true;
if (mapResult == clsModels.end())//已有数据
return nullptr;
return mapResult->second;
}
void initialization(backEndManager* _backEndManagerIn)
{
@@ -223,7 +218,7 @@ private:
std::unordered_map<std::string, handleAiModelSeg*> segModels;
std::unordered_map<std::string, handleAiModelCls*> clsModels;
std::unordered_map<std::string, handleAiModelDet*> detModels;
std::vector<std::mutex*>gpuMutex;
std::vector<std::mutex*>gpuMutex = std::vector<std::mutex*>(6, new std::mutex());
int gpuCnt = 1;//gpu数量
};
#endif
@@ -2,14 +2,9 @@
#include <vector>
#include <opencv.hpp>
#include <unordered_map>
struct handleAiSimpleDet
struct detResultHandleStruct
{
//最后调用模型时是使用路径去查找,请保证规则一致
std::string detModelName;//重复时将不会重复初始化
std::vector<int> detResultIndex;//本产品对应det模型训练时的序号
int detGpuIndex = 0;
std::string segModelName;//重复时将不会重复初始化
std::vector<int>segNgIndex;//NG的将会进入cls检测
@@ -20,6 +15,14 @@ struct handleAiSimpleDet
int clsGpuIndex = 0;
//int为Cls的分类结果 string为文本 Scalar为颜色
std::unordered_map<int,std::pair<std::string,cv::Scalar>>clsResultHandle;//结果绘制
std::unordered_map<int, std::pair<std::string, cv::Scalar>>clsResultHandle;//结果绘制
};
struct handleAiSimpleDet
{
//最后调用模型时是使用路径去查找,请保证规则一致
std::string detModelName;//重复时将不会重复初始化
int detGpuIndex = 0;
std::vector<detResultHandleStruct>detResultHandle;
};
#pragma once
+6 -4
View File
@@ -15,8 +15,7 @@
#include <back/logmsg.h>
#include <FrontendBackendBridge.h>
#include <mutex>
#include <appConfig/appConfig.hpp>
#include <back/manualDetThread.h>
void connectSignalAndSlots(MainWindow* front, backEndManager* back)
{
QObject::connect(back, &backEndManager::sendPixmapImageWidget, front, &MainWindow::recvPixmapImageWidget);
@@ -26,11 +25,12 @@ void connectSignalAndSlots(MainWindow* front, backEndManager* back)
QObject::connect(back, &backEndManager::addHistoryDataSignal, front, &MainWindow::addDetHistoryData);
QObject::connect(back, &backEndManager::switchStartBtnStatusSignal,
front->_displayWidget->_switchProductWidget, &switchProductWidget::switchStartBtnStatus);
QObject::connect(back->_manualDetThread, &manualDetThread::finishImgReadSignal,
front->_manualDetWidget, &manualDetWidget::finishImgReadSlot);
QObject::connect(front, &MainWindow::reInitSignal, back, &backEndManager::initialization);
QObject::connect(front->_loadingWidget.retryBtn, &QPushButton::clicked, back, &backEndManager::initialization);
QObject::connect(front->_manualDetWidget->_manualDetThread, &manualDetThread::startManualDetSignal,
QObject::connect(front->_manualDetWidget, &manualDetWidget::startManualDetSignal,
back, &backEndManager::startManualDetSlot);
QObject::connect(front->_displayWidget->_switchProductWidget, &switchProductWidget::startArmProgramSignal,
back, &backEndManager::writeArmStartSignal);
@@ -55,6 +55,8 @@ int main(int argc, char* argv[])
qRegisterMetaType<imgWidgetShowType>("imgWidgetShowType");
qRegisterMetaType<showImgPack>("showImgPack");
qRegisterMetaType<cv::Mat*>("matPtr");
qRegisterMetaType<cv::Mat>("mat");
qRegisterMetaType<std::string>("stdString");
appConfig _appConfig;
MainWindow w(&_appConfig);
w.show();
+1
View File
@@ -58,6 +58,7 @@ MainWindow::MainWindow(appConfig* appData, QWidget* parent)
blurEffectAnimation->start();
showMaximized();
QObject::connect(_loadingWidget.manualBtn, &QPushButton::clicked, this, &MainWindow::switchToManulMode);
}
MainWindow::~MainWindow()
+5
View File
@@ -98,6 +98,11 @@ private:
public slots:
void switchToManulMode()
{
_displayWidget->setDisabled(true);
loading(false);
}
void minimizeWindow()
{
showMinimized();
@@ -5,7 +5,7 @@
#include <qtimer.h>
#include <qlabel.h>
#include <uiModule/components/fancyButton.h>
#include <qdatetime.h>
class fancyWarnWindow :public QDialog
{
public:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Some files were not shown because too many files have changed in this diff Show More