bool CTabPage1DlgTest::running(int useWindow, int modelType, const CString& circlePath, const CString& rectanglePath)
{
if (!m_pMainDlg)
{
AfxMessageBox(_T("主对话框指针未设置,初始化失败!"), MB_ICONERROR);
return false;
}
int cameraIndex = useWindow - 1;
//if (m_selectedCameraWindow != 4)
//{
// if (m_selectedCamera != m_selectedCameraWindow)
// {
// AfxMessageBox(_T("选择的相机与当前窗口不匹配,无法操作!"));
// m_bThreadRunning[cameraIndex] = FALSE;
// TRACE("running中 m_bThreadRunning[%d] = FALSE;\n", cameraIndex);
// return false;
// }
//}
// 开始计时
LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
bool isOK = true;//判断是否合格
HObject image;
int camName = 0;
if (useWindow == 1) camName = 1;
else if(useWindow == 2) camName = 2;
else if (useWindow == 3) camName = 3;
else if (useWindow == 4) camName = 4;
// 安全获取图像
{
CSingleLock lock(&m_imageLock[cameraIndex], TRUE);
if (m_imageBuf[cameraIndex].IsInitialized()) {
CopyObj(m_imageBuf[cameraIndex], &image, 1, 1);
}
else {
if (cameraIndex >= 0 && cameraIndex < 4)
{
m_bThreadRunning[cameraIndex] = FALSE;
}
AfxMessageBox(_T("图像未就绪!"));
return false;
}
}
// 显示图像
switch (cameraIndex) {
case 0: m_myHalcon->LoadImageCam1(image); break;
case 1: m_myHalcon->LoadImageCam2(image); break;
case 2: m_myHalcon->LoadImageCam3(image); break;
case 3: m_myHalcon->LoadImageCam4(image); break;
}
// 触发图像处理完成事件
switch (cameraIndex) {
case 0: m_haiKang1.SetImageProcessed(); break;
case 1: m_haiKang2.SetImageProcessed(); break;
case 2: m_haiKang3.SetImageProcessed(); break;
case 3: m_haiKang4.SetImageProcessed(); break;
}
//for (int i = 0; i <= 30; i++)
//{
// Sleep(100);
//}
// 显示当前时间和统计结果
SYSTEMTIME st;
GetLocalTime(&st);
int millisecond = st.wMilliseconds;
int second = st.wSecond;
int minute = st.wMinute;
int hour = st.wHour;
bool isModel = false;
switch (modelType) {
case 0:
{
int clickCount = 0;
switch (cameraIndex)
{
case 0: clickCount = m_clickCountCam1++; break;
case 1: clickCount = m_clickCountCam2++; break;
case 2: clickCount = m_clickCountCam3++; break;
case 3: clickCount = m_clickCountCam4++; break;
}
m_myHalcon->ClearDisplayRegion(useWindow);
CString mBigModel;
int bigModelCount = 0;
bigModelCount = GetPrivateProfileString("glueStandard", "bigModel", "0.0", mBigModel.GetBuffer(256), 256, circlePath);
mBigModel.ReleaseBuffer();
bigModelCount = _ttoi(mBigModel);
//
CString mSmallModel;
int smallModelCount = 0;
smallModelCount = GetPrivateProfileString("glueStandard", "smallModel", "0.0", mSmallModel.GetBuffer(256), 256, circlePath);
mSmallModel.ReleaseBuffer();
smallModelCount = _ttoi(mSmallModel);
//
CString mRectangleModelMark;
double modelMark = 0;
GetPrivateProfileString("glueStandard", "modelMark", "0.0", mRectangleModelMark.GetBuffer(256), 256, circlePath);
mRectangleModelMark.ReleaseBuffer();
modelMark = _tstof(mRectangleModelMark);
//
CString mModelNumber;
int modelNumber = 0;
GetPrivateProfileString("glueStandard", "model", "0", mModelNumber.GetBuffer(256), 256, circlePath);
mModelNumber.ReleaseBuffer();
modelNumber = _ttoi(mModelNumber);
//
CString mChipAlarm;
int alarmCount = 0;
GetPrivateProfileString("glueStandard", "alarmCount", "0.0", mChipAlarm.GetBuffer(256), 256, circlePath);
mChipAlarm.ReleaseBuffer();
alarmCount = _tstoi(mChipAlarm);
//
CString mglue;
float glue = 0.0;
GetPrivateProfileString("glueStandard", "glueStandardData", "0.0", mglue.GetBuffer(256), 256, circlePath);
mglue.ReleaseBuffer();
glue = _tstof(mglue);
//
CString mgluePercent;
float gluePercent = 0.0;
GetPrivateProfileString("glueStandard", "gulePercentage", "0.0", mgluePercent.GetBuffer(256), 256, circlePath);
mgluePercent.ReleaseBuffer();
gluePercent = _tstof(mgluePercent);
//
CString horizontalCoordinates, verticalCoordinates;
double horizontal = 0; double vertical = 0;
GetPrivateProfileString("glueStandard", "horizontalCoordinates", "0.0", horizontalCoordinates.GetBuffer(256), 256, circlePath);
GetPrivateProfileString("glueStandard", "verticalCoordinates", "0.0", verticalCoordinates.GetBuffer(256), 256, circlePath);
horizontalCoordinates.ReleaseBuffer();
verticalCoordinates.ReleaseBuffer();
horizontal = _ttof(horizontalCoordinates);
vertical = _ttof(verticalCoordinates);
//
CString mAllowMistakeNumber;
int allowMistake = 0;
GetPrivateProfileString("glueStandard", "allowMistake", "0.0", mAllowMistakeNumber.GetBuffer(256), 256, circlePath);
mAllowMistakeNumber.ReleaseBuffer();
allowMistake = _tstoi(mAllowMistakeNumber);
//
CString mFlowNumber;
int flowNumber = 0;
GetPrivateProfileString("glueStandard", "flowNumber", "0.0", mFlowNumber.GetBuffer(256), 256, circlePath);
mFlowNumber.ReleaseBuffer();
flowNumber = _tstoi(mFlowNumber);
if (gluePercent == 0)
{
if (cameraIndex >= 0 && cameraIndex < 4)
{
m_bThreadRunning[cameraIndex] = FALSE;
}
AfxMessageBox(_T("请输入胶量检测百分比系数或者配置文件不存在!"), MB_ICONWARNING);
return false;
}
if (gluePercent < 0 || gluePercent >= 1)
{
if (cameraIndex >= 0 && cameraIndex < 4)
{
m_bThreadRunning[cameraIndex] = FALSE;
}
AfxMessageBox(_T("百分比系数需在 0 到 1 之间(如 0.1 表示 10%)!"), MB_ICONERROR);
return false;
}
double lowerBound = glue * (1 - gluePercent);//胶量百分比
double upperBound = glue * (1 + gluePercent);
// 定义模板句柄和位置信息
HTuple modelHandle, tuple;
//创建区域和圆的容器
HObject* bigModel = new HObject[bigModelCount];
HObject** smallModel = new HObject * [bigModelCount];
// 读取模板
CString modelPath;
modelPath.Format(m_debugPath + R"(\config\Camera%d\circle\model\model.shm)", cameraIndex + 1);
// 读取模板位置元组
CString tuplePath;
tuplePath.Format(m_debugPath + R"(\config\Camera%d\circle\model\tuple.tup)" , cameraIndex + 1);
// 检查文件是否存在
CFileStatus fileStatus;
if (!CFile::GetStatus(modelPath, fileStatus) || !CFile::GetStatus(tuplePath, fileStatus))
{
if (cameraIndex >= 0 && cameraIndex < 4)
{
m_bThreadRunning[cameraIndex] = FALSE;
}
AfxMessageBox(_T("圆模板文件不存在!"), MB_ICONWARNING);
// 释放资源并返回
delete[] smallModel;
delete[] bigModel;
return false;
}
modelHandle = m_myHalcon->readShapeModel(modelPath);
tuple = m_myHalcon->readTuple(tuplePath);
if (tuple.Length() >= 3)
{
produceModel.row = ((const HTuple&)tuple)[0];
produceModel.column = ((const HTuple&)tuple)[1];
produceModel.angle = ((const HTuple&)tuple)[2];
}
else
{
// 如果元组数据不完整,使用默认值
produceModel.row = 0;
produceModel.column = 0;
produceModel.angle = 0;
}
for (int i = 0; i < bigModelCount; i++)
{
smallModel[i] = new HObject[bigModelCount];
}
CString rangeInfo;
rangeInfo.Format(_T("当前范围:[%.1f, %.1f](基准值±%d%%),第%d次拍照"), lowerBound, upperBound, static_cast<int>(gluePercent * 100), clickCount +1);
CString displayText;
displayText.AppendFormat(_T("===== 相机%d胶量检测结果 =====\r\n"), camName);
displayText += rangeInfo + _T("\r\n\r\n");
HTuple homMat2D;
int successCount = 0, failedCount = 0;
for (int regIdx = 0; regIdx < bigModelCount; regIdx++)
{
displayText.AppendFormat(_T("【区域 %d】\r\n"), regIdx + 1);
CString regionPath;
regionPath.Format(m_debugPath + R"(\config\Camera%d\circle\bigModel\newRegion%d.hobj)", cameraIndex + 1,regIdx + 1);
bigModel[regIdx] = m_myHalcon->readRegion(regionPath);
// 检查文件是否存在
CFileStatus fileStatus;
if (!CFile::GetStatus(regionPath, fileStatus))
{
CString msg;
msg.Format(_T("圆区域文件不存在: %s"), (LPCSTR)regionPath);
AfxMessageBox(msg, MB_ICONWARNING);
continue;
}
HObject reduceDomainRegions = m_myHalcon->reduceDomain(image, bigModel[regIdx]);
auto findModel = m_myHalcon->findModel(reduceDomainRegions, modelHandle, 360, modelMark, 0);
if (findModel.row.Length() > 0)
{
m_myHalcon->setColor(useWindow, "green");
m_myHalcon->dispObj(bigModel[regIdx], useWindow);
ModelData currentFindModel;
//
currentFindModel.row = findModel.row[0];
currentFindModel.column = findModel.column[0];
currentFindModel.angle = findModel.angle[0];
homMat2D = m_myHalcon->vectorAngleToRigid(produceModel, currentFindModel);
isModel = true;
}
else
{
m_myHalcon->setColor(useWindow, "red");
m_myHalcon->dispObj(bigModel[regIdx], useWindow);
}
try
{
// 读取该区域内的所有圆
for (int smallModelIdx = 0; smallModelIdx < smallModelCount; smallModelIdx++)
{
CString circlePath;
circlePath.Format(m_debugPath + R"(\config\Camera%d\circle\smallModel\Region%d_Circle%d.hobj)", cameraIndex + 1,regIdx + 1, smallModelIdx + 1);
if (CFile::GetStatus(circlePath, fileStatus))
{
double deltaR = 0;
double deltaC = 0;
HTuple areaCenterGlue;
//m_myHalcon->setColor(useWindow, "red");
smallModel[regIdx][smallModelIdx] = m_myHalcon->readRegion(circlePath);
m_myHalcon->dispObj(smallModel[regIdx][smallModelIdx], useWindow);
//m_myHalcon->saveRegion(smallModel[regIdx][smallModelIdx], "red", useWindow);
/*if (regIdx == 2 && smallModelIdx == 2)
{
int a = 10;
}*/
if (isModel)
{
double glueArea = -1.0;
double glueRow = -1.0;
double glueCol = -1.0;
HTuple areaCenter = m_myHalcon->areaCenter(smallModel[regIdx][smallModelIdx]);
double circleRow = areaCenter[1].D();
double circleCol = areaCenter[2].D();
HObject reduceDomainCircle = m_myHalcon->reduceDomain(image, smallModel[regIdx][smallModelIdx]);
HObject thresholdSubPix = m_myHalcon->thresholdSubPix(reduceDomainCircle, 128);
// 检查边缘是否有效
HTuple isEmpty;
CountObj(thresholdSubPix, &isEmpty);
if (isEmpty.D() == 0)
{
TRACE("区域 %d 未检测到边缘!\n");
glueArea = -1;
deltaR = -1;
deltaC = -1;
failedCount++;
CString circleInfo;
circleInfo.AppendFormat(_T(" 圆 %d: 胶量=%.2f, 偏移=(R=%.2f, C=%.2f), 状态=%s\r\n"), smallModelIdx + 1, glueArea, deltaR, deltaC, _T("NG"));
displayText += circleInfo;
continue;
}
// 检测到边缘,计算轮廓面积
HTuple areas, row, col, pointOrder;
HTuple allAreas, validAreas;
HTuple validRows, validCols;
HTuple allRows, allCols;
//
if (regIdx == 1 && smallModelIdx == 1)
{
int a = 10;
}
// 提取所有轮廓面积
for (int i = 1; i <= isEmpty.I(); i++)
{
HObject singleContour;
SelectObj(thresholdSubPix, &singleContour, i);
AreaCenterXld(singleContour, &areas, &row, &col, &pointOrder);
//TRACE("区域 %d 圆 %d 轮廓 %d 的面积:%f\n", regIdx + 1, smallModelIdx + 1, i, areas.D());
//TRACE("中心点坐标: row=%.2f, col=%.2f\n", row.D(), col.D());
allAreas.Append(areas);
allRows.Append(row);
allCols.Append(col);
}
// 筛选有效面积(阈值可调整)
double minAreaThreshold = 0.0;
for (int i = 0; i < allAreas.Length(); i++)
{
if (allAreas[i].D() > minAreaThreshold)
{
validAreas.Append(allAreas[i]);
validRows.Append(allRows[i]);
validCols.Append(allCols[i]);
}
}
// 检查是否有有效轮廓
if (validAreas.Length() > 0)
{
// 获取最大面积
glueArea = m_myHalcon->tupleMax(validAreas).D();
//TRACE("区域 %d 圆 %d 的最大有效面积:%.2f\n", regIdx + 1, smallModelIdx + 1, glueArea);
// 查找最大面积的索引
int maxIndex = 0;
for (int i = 0; i < validAreas.Length(); i++)
{
if (validAreas[i].D() == glueArea)
{
maxIndex = i;
break;
}
}
// 获取最大面积对应的坐标
if (maxIndex != -1)
{
//glueArea = maxArea;
glueRow = validRows[maxIndex].D();
glueCol = validCols[maxIndex].D();
//TRACE("最大面积对应的坐标: glueRow=%.2f, glueCol=%.2f\n", glueRow, glueCol);
}
}
if (validAreas.Length() == 0)
{
m_myHalcon->setColor(useWindow, "red");
row = -1;
col = -1;
failedCount++;
}
//
bool isGlueValid = (glueArea >= lowerBound && glueArea <= upperBound);
if (isGlueValid)
{
deltaR = areaCenter[1].D() - glueRow;
deltaC = areaCenter[2].D() - glueCol;
}
bool coordinates = false;
double sssas = deltaR;
double sssasss = deltaC;
if ((deltaC > -horizontal && deltaC < horizontal) && (deltaR > -vertical && deltaR < vertical))
{
if (deltaC == -1 && deltaR == -1)
{
coordinates = false;
}
coordinates = true;
}
//如果胶量和位置都合格则进入
int isPass = false;
if (isGlueValid && coordinates)
{
m_myHalcon->setColor(useWindow, "green");
m_myHalcon->dispObj(smallModel[regIdx][smallModelIdx], useWindow);
//m_myHalcon->saveRegion(smallModel[regIdx][smallModelIdx], "green", useWindow);
isPass = true;
}
else
{
m_myHalcon->setColor(useWindow, "red");
m_myHalcon->dispObj(smallModel[regIdx][smallModelIdx], useWindow);
//m_myHalcon->dispObj(thresholdSubPix, useWindow);
//m_myHalcon->saveRegion(smallModel[regIdx][smallModelIdx], "red", useWindow);
deltaR = -1;
deltaC = -1;
failedCount++;
isPass = false;
}
CString circleInfo;
circleInfo.AppendFormat("圆 %d: 胶量=%.2f, 偏移=(R=%.2f, C=%.2f), 状态=%s\r\n", smallModelIdx + 1, glueArea, deltaR, deltaC, isPass ? "OK" : "NG");
//circleInfo.AppendFormat("范围 %d, 区域 %d, %.2f, %.2f, %s\r\n", regIdx, smallModelIdx + 1, deltaR, deltaC, isPass ? "OK" : "NG");
displayText += circleInfo;
}
}
else
{
CString msg;
msg.Format(_T("圆文件不存在: %s"), (LPCSTR)circlePath);
}
}
}
catch (const HalconCpp::HException& ex)
{
CString errorMsg;
errorMsg.Format(_T("读取区域或圆时出错: %s"), ex.ErrorMessage().Text());
AfxMessageBox(errorMsg, MB_ICONERROR);
}
displayText += _T("\r\n");
}
m_myHalcon->displayRegion(useWindow);
//允许不合格的次数范围
if (failedCount > allowMistake)
{
m_chipAlarmCount++;
isOK = false;
if (m_chipAlarmCount == alarmCount)
{
m_chipAlarmCount = 0;
AfxMessageBox("芯片报警次数已达到!", MB_ICONWARNING);
}
}
CString displayTextData;
displayTextData.Format("%02d时%02d分%02d秒", hour, minute, second);
int boardCount;
switch (cameraIndex)
{
case 0: boardCount = m_clickCountCam1 / flowNumber; break;
case 1: boardCount = m_clickCountCam2 / flowNumber; break;
case 2: boardCount = m_clickCountCam3 / flowNumber; break;
case 3: boardCount = m_clickCountCam4 / flowNumber; break;
}
if (boardCount > 0)
{
switch (cameraIndex)
{
case 0: m_currentBoardClick = m_cam1FinishProduceCount; m_cam1FinishProduceCount++; break;
case 1: m_currentBoardClick = m_cam2FinishProduceCount; m_cam2FinishProduceCount++; break;
case 2: m_currentBoardClick = m_cam3FinishProduceCount; m_cam3FinishProduceCount++; break;
case 3: m_currentBoardClick = m_cam4FinishProduceCount; m_cam4FinishProduceCount++; break;
}
CString displayTexts;
m_currentBoardClick++;
displayTexts.Format("%02d时%02d分%02d秒 - 相机%d -点胶板完成%d个产品", hour, minute, second, camName, m_currentBoardClick);
m_pMainDlg->PrintToMainEditMessage(displayTexts);
}
//m_pMainDlg->PrintToMainEditState(m_clickCountCam1, displayTextData, displayText);
switch (cameraIndex)
{
case 0: m_pMainDlg->PrintToMainEditState(0, m_clickCountCam1, displayTextData, displayText); break;
case 1: m_pMainDlg->PrintToMainEditState(0, m_clickCountCam2, displayTextData, displayText); break;
case 2: m_pMainDlg->PrintToMainEditState(0, m_clickCountCam3, displayTextData, displayText); break;
case 3: m_pMainDlg->PrintToMainEditState(0,m_clickCountCam4, displayTextData, displayText); break;
}
if (boardCount > 0)
{
//m_clickCountCam1 = 0;
switch (cameraIndex)
{
case 0: m_clickCountCam1 = 0; break;
case 1: m_clickCountCam2 = 0; break;
case 2: m_clickCountCam3 = 0; break;
case 3: m_clickCountCam4 = 0; break;
}
}
if (failedCount > allowMistake || !isModel)
{
isOK = false;//判断检测是否合格
}
// 清理内存
for (int i = 0; i < bigModelCount; i++)
{
delete[] smallModel[i];
}
delete[] smallModel;
delete[] bigModel;
break;
}
case 1:
{
int clickCount = 0;
switch (cameraIndex)
{
case 0: clickCount = m_clickCountCam1++; break;
case 1: clickCount = m_clickCountCam2++; break;
case 2: clickCount = m_clickCountCam3++; break;
case 3: clickCount = m_clickCountCam4++; break;
}
CString mBigModel;
int bigModelCount = 0;
bigModelCount = GetPrivateProfileString("glueStandard", "bigModel", "0.0", mBigModel.GetBuffer(256), 256, rectanglePath);
mBigModel.ReleaseBuffer();
bigModelCount = _ttoi(mBigModel);
//
CString mRectangleModelMark;
double modelMark = 0;
GetPrivateProfileString("glueStandard", "modelMark", "0.0", mRectangleModelMark.GetBuffer(256), 256, rectanglePath);
mRectangleModelMark.ReleaseBuffer();
modelMark = _tstof(mRectangleModelMark);
//
CString mModelNumber;
int modelNumber = 0;
GetPrivateProfileString("glueStandard", "modelCount", "0", mModelNumber.GetBuffer(256), 256, rectanglePath);
mModelNumber.ReleaseBuffer();
modelNumber = _ttoi(mModelNumber);
//
CString mChipAlarm;
int alarmCount = 0;
GetPrivateProfileString("glueStandard", "alarmCount", "0.0", mChipAlarm.GetBuffer(256), 256, rectanglePath);
mChipAlarm.ReleaseBuffer();
alarmCount = _tstoi(mChipAlarm);
//
CString horizontalCoordinates, verticalCoordinates;
double horizontal = 0; double vertical = 0;
GetPrivateProfileString("glueStandard", "horizontalCoordinates", "0.0", horizontalCoordinates.GetBuffer(256), 256, rectanglePath);
GetPrivateProfileString("glueStandard", "verticalCoordinates", "0.0", verticalCoordinates.GetBuffer(256), 256, rectanglePath);
horizontalCoordinates.ReleaseBuffer();
verticalCoordinates.ReleaseBuffer();
horizontal = _ttof(horizontalCoordinates);
vertical = _ttof(verticalCoordinates);
//
CString mAllowMistakeNumber;
int allowMistake = 0;
GetPrivateProfileString("glueStandard", "allowMistake", "0.0", mAllowMistakeNumber.GetBuffer(256), 256, rectanglePath);
mAllowMistakeNumber.ReleaseBuffer();
allowMistake = _tstoi(mAllowMistakeNumber);
//
CString mFlowNumber;
int flowNumber = 0;
GetPrivateProfileString("glueStandard", "flowNumber", "0.0", mFlowNumber.GetBuffer(256), 256, rectanglePath);
mFlowNumber.ReleaseBuffer();
flowNumber = _tstoi(mFlowNumber);
//
CString mthreshold;
int thresholdXld = 0;
GetPrivateProfileString("glueStandard", "Threashold", "0.0", mthreshold.GetBuffer(256), 256, rectanglePath);
mthreshold.ReleaseBuffer();
thresholdXld = _tstoi(mthreshold);
//
HTuple* modelHandles = new HTuple[modelNumber];
for (int i = 0; i < modelNumber; i++)
{
CString modelPath;
modelPath.Format(m_debugPath + R"(\config\Camera%d\rectangle\model\model%d.shm)", cameraIndex + 1, i + 1);
modelHandles[i] = m_myHalcon->readShapeModel(modelPath);
}
int successCount = 0, failedCount = 0;
CString displayText;
CString failedRegions; // 用于存储失败区域的编号
for (int regIdx = 0; regIdx < bigModelCount; regIdx++)
{
int regionNum = regIdx + 1;
int productNum = regionNum;
// 读取区域
CString regionPath;
regionPath.Format(m_debugPath + R"(\config\Camera%d\rectangle\bigModel\newRegion%d.hobj)", cameraIndex + 1,regionNum);
HObject region = m_myHalcon->readRegion(regionPath);
// 检查区域是否存在
CFileStatus fileStatus;
if (!CFile::GetStatus(regionPath, fileStatus))
{
if (cameraIndex >= 0 && cameraIndex < 4)
{
m_bThreadRunning[cameraIndex] = FALSE;
}
CString errorMsg;
errorMsg.Format("区域文件不存在: %s", (LPCTSTR)regionPath);
AfxMessageBox(errorMsg, MB_ICONWARNING);
return false;
}
HObject reduceDomain = m_myHalcon->reduceDomain(image, region);
bool matched = false; // 判断是否匹配成功
HTuple deltaR, deltaC;
deltaR = HTuple(0.0); // 初始化 deltaR
deltaC = HTuple(0.0); // 初始化 deltaC
for (int i = 0; i < modelNumber; i++)
{
HObject thresholdSubPix, selectShapeXld;
HTuple areaCenterXLD, tuple, areaCenter;
double xldRow = -1.0;
double xldCol = -1.0;
double xldArea = -1.0;
auto result = m_myHalcon->findModel(reduceDomain, modelHandles[i], 360, modelMark, 1);
if (result.row > 0)
{
areaCenter = m_myHalcon->areaCenter(reduceDomain);
double regionRow = areaCenter[1].D();
double regionCol = areaCenter[2].D();
CString str;
str.Format(_T("thresholdXld = %d"), thresholdXld);
//TRACE(str);
HObject thresholdSubPix = m_myHalcon->thresholdSubPix(reduceDomain, thresholdXld);
// 检查边缘是否有效
HTuple isEmpty;
CountObj(thresholdSubPix, &isEmpty);
// 检测到边缘,计算轮廓面积
HTuple areas, row, col, pointOrder;
HTuple allAreas, validAreas;
HTuple validRows, validCols;
HTuple allRows, allCols;
for (int i = 1; i <= isEmpty.I(); i++)
{
HObject singleContour;
SelectObj(thresholdSubPix, &singleContour, i);
AreaCenterXld(singleContour, &areas, &row, &col, &pointOrder);
allAreas.Append(areas);
allRows.Append(row);
allCols.Append(col);
}
// 筛选有效面积
double minAreaThreshold = 0.0;
for (int i = 0; i < allAreas.Length(); i++)
{
if (allAreas[i].D() > minAreaThreshold)
{
validAreas.Append(allAreas[i]);
validRows.Append(allRows[i]);
validCols.Append(allCols[i]);
}
}
// 检查是否有有效轮廓
if (validAreas.Length() > 0)
{
xldArea = m_myHalcon->tupleMax(validAreas).D();
// 查找最大面积的索引
int maxIndex = 0;
for (int i = 0; i < validAreas.Length(); i++)
{
if (validAreas[i].D() == xldArea)
{
maxIndex = i;
break;
}
}
// 获取最大面积对应的坐标
if (maxIndex != -1)
{
xldRow = validRows[maxIndex].D();
xldCol = validCols[maxIndex].D();
}
deltaR = areaCenter[1].D() - xldRow;
deltaC = areaCenter[2].D() - xldCol;
//判断区域中心和芯片中心的偏差值是否大于设定值
if (deltaR > vertical || deltaR < -vertical || deltaC > horizontal || deltaC < -horizontal)
{
deltaR = -1;
deltaC = -1;
break;
}
}
matched = true;
}
if (matched == false)
{
deltaR = -1;
deltaC = -1;
}
}
double dDeltaR = deltaR.D();
double dDeltaC = deltaC.D();
CString regionResult;
CString rang = "-";
//regionResult.Format("范围%s, 区域%d, %.2f, %.2f, %s\r\n", rang, regionNum, dDeltaR, dDeltaC, matched ? "OK" : "NG");
regionResult.Format(_T("区域%d (产品%d): (ΔR=%.2f, ΔC=%.2f) %s \r\n"), regionNum, productNum, dDeltaR, dDeltaC, matched ? _T("OK") : _T("NG"));
displayText += regionResult;
// 显示结果
m_myHalcon->setColor(useWindow, matched ? "green" : "red");
m_myHalcon->dispObj(region, useWindow);
if (!matched)
{
if (!failedRegions.IsEmpty())
failedRegions.Append(_T(","));
CString temp;
temp.Format(_T("%d"), regionNum);
failedRegions.Append(temp);
}
matched ? successCount++ : failedCount++;
}
// 清理模板
for (int i = 0; i < modelNumber; i++)
{
ClearShapeModel(modelHandles[i]);
}
delete[] modelHandles;
CString displayInfo;
displayInfo.Format("%02d时%02d分%02d秒 -第%d次点击- 成功%d/失败%d - 相机%d - 失败区域: %s", hour, minute, second, clickCount + 1, successCount, failedCount, camName, failedRegions.GetBuffer(0));
//displayInfo.Format("成功%d/失败%d - 相机%d - 失败区域: %s", successCount, failedCount, camName, failedRegions.GetBuffer(0));
if (failedCount > allowMistake)
{
m_chipAlarmCount++;
if (m_chipAlarmCount == alarmCount)
{
m_chipAlarmCount = 0;
AfxMessageBox("芯片报警次数已达到!", MB_ICONWARNING);
}
}
int boardCount = 0;
switch (cameraIndex)
{
case 0: boardCount = m_clickCountCam1 / flowNumber; break;
case 1: boardCount = m_clickCountCam2 / flowNumber; break;
case 2: boardCount = m_clickCountCam3 / flowNumber; break;
case 3: boardCount = m_clickCountCam4 / flowNumber; break;
}
switch (cameraIndex)
{
case 0: m_currentBoardClick = m_cam1FinishProduceCount; break;
case 1: m_currentBoardClick = m_cam2FinishProduceCount; break;
case 2: m_currentBoardClick = m_cam3FinishProduceCount; break;
case 3: m_currentBoardClick = m_cam4FinishProduceCount; break;
}
if (boardCount > 0)
{
switch (cameraIndex)
{
case 0: m_currentBoardClick = m_cam1FinishProduceCount; m_cam1FinishProduceCount++; break;
case 1: m_currentBoardClick = m_cam2FinishProduceCount; m_cam2FinishProduceCount++; break;
case 2: m_currentBoardClick = m_cam3FinishProduceCount; m_cam3FinishProduceCount++; break;
case 3: m_currentBoardClick = m_cam4FinishProduceCount; m_cam4FinishProduceCount++; break;
}
CString displayTexts;
m_currentBoardClick++;
displayTexts.Format("%02d时%02d分%02d秒 - 相机%d - 芯片板完成%d个产品", hour, minute, second, cameraIndex + 1, m_currentBoardClick);
m_pMainDlg->PrintToMainEditMessage(displayTexts);
}
switch (cameraIndex)
{
case 0: m_pMainDlg->PrintToMainEditState(1, m_clickCountCam1, displayInfo, displayText); break;
case 1: m_pMainDlg->PrintToMainEditState(1, m_clickCountCam2, displayInfo, displayText); break;
case 2: m_pMainDlg->PrintToMainEditState(1, m_clickCountCam3, displayInfo, displayText); break;
case 3: m_pMainDlg->PrintToMainEditState(1, m_clickCountCam4, displayInfo, displayText); break;
}
if (failedCount > allowMistake || isModel )
{
isOK = false;//判断检测是否合格
}
//流程中的检测结果全部显示完成后再清空计数
if (boardCount > 0)
{
switch (cameraIndex)
{
case 0: m_clickCountCam1 = 0; break;
case 1: m_clickCountCam2 = 0; break;
case 2: m_clickCountCam3 = 0; break;
case 3: m_clickCountCam4 = 0; break;
}
}
}}
if (cameraIndex >= 0 && cameraIndex < 4)
{
m_bThreadRunning[cameraIndex] = FALSE;
//TRACE("running中 m_bThreadRunning[%d] = FALSE;\n", cameraIndex);
}
else
{
TRACE("警告:cameraIndex = %d 超出有效范围(0~3)\n", cameraIndex);
}
//结束计时并计算耗时(毫秒)
QueryPerformanceCounter(&end);
double elapsedTime = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
CString msg;
msg.Format("相机%d执行完成,耗时: %.2f 毫秒", cameraIndex, elapsedTime);
//AfxMessageBox(msg, MB_ICONINFORMATION);
m_pMainDlg->PrintToMainEditMessage(msg);
return isOK;这是检测程序,通过传入相机序号来调用,现在只调用相机1耗时在100ms,多个相机同时调用就在2-300之间
最新发布