From 479a65f7e29c06766a426756e1f5b9b7de498fa1 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期四, 10 七月 2025 14:38:27 +0800
Subject: [PATCH] 修复:Notch测量坐标异常导致崩溃的问题,增强日志输出。 - 在 Notch_Process_Calculate 函数中,增加对坐标有效性的检查,避免非法坐标(如 -1, -1)导致 OpenCV 函数异常崩溃; - 当发现坐标异常时,记录错误日志,并跳过该测量点,防止程序崩溃; - 增加超大测量值的日志记录(Dimension 或 Chamfer 大于 2000 um),进一步提高程序的稳定性;
---
EdgeInspector_App/Process/InspectCamera.cpp | 192 +++++++++++++++++++-----------------------------
1 files changed, 76 insertions(+), 116 deletions(-)
diff --git a/EdgeInspector_App/Process/InspectCamera.cpp b/EdgeInspector_App/Process/InspectCamera.cpp
index 7c6fa50..88ff302 100644
--- a/EdgeInspector_App/Process/InspectCamera.cpp
+++ b/EdgeInspector_App/Process/InspectCamera.cpp
@@ -3720,13 +3720,6 @@
BOOL CInspectCamera::Notch_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame)
{
- //CTime tCurrentTime = CTime::GetCurrentTime();
- //CTime tLimitTime = CTime(2023,3,31,11,59,59);
- //CTimeSpan tSpanTime = tLimitTime - tCurrentTime;
-
- //if(tSpanTime.GetTotalSeconds() < 0)
- // return FALSE;
-
if(m_pGlassData == NULL)
return FALSE;
@@ -3782,24 +3775,20 @@
pEdgeImage = cvCloneImage(pOriginImage);
pBinImage = cvCloneImage(pOriginImage);
- g_pLog->DisplayMessage(_T("1. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
-
// 1. Image PreProcess..
+ g_pLog->DisplayMessage(_T("1. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
Notch_Process_PreProcess(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
- // Notch_Process_PreProcess_2(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
-
- g_pLog->DisplayMessage(_T("2. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
// 2. Notch Dimension/Chamfer Find..
+ g_pLog->DisplayMessage(_T("2. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
Notch_Process_Measure(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
- g_pLog->DisplayMessage(_T("3. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
-
// 3. Notch Dimension/Chamfer Calculate Result..
+ g_pLog->DisplayMessage(_T("3. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
bool bResult = Notch_Process_Calculate(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
- g_pLog->DisplayMessage(_T("4. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
// 4. Notch Dimension/Chamfer Judge
+ g_pLog->DisplayMessage(_T("4. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
Notch_Process_Judge(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
if (!bResult)
@@ -3822,21 +3811,19 @@
pSideData->m_bNotchInspection_Complete = TRUE;
-
-
return FALSE;
}
- g_pLog->DisplayMessage(_T("5. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
// 5. Notch Defect Inspect (Chip/Crack)
+ g_pLog->DisplayMessage(_T("5. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
Notch_Process_Defect(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
- g_pLog->DisplayMessage(_T("6. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
// 6. Notch Find Circle
+ g_pLog->DisplayMessage(_T("6. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
Notch_Process_FindCircle(emDim, stFrame, i);
+ // 7. Notch Process End
g_pLog->DisplayMessage(_T("7. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
-
cvReleaseImageHeader(&pOriginImage);
cvReleaseImage(&pEdgeImage);
cvReleaseImage(&pBinImage);
@@ -3844,79 +3831,47 @@
pSideData->m_bNotchInspection_Complete = TRUE;
- g_pLog->DisplayMessage(_T("7. Notch_Process End %s : %d"),g_SideName[(int) emDim], stFrame.nFrameIdx);
-
return TRUE;
}
void CInspectCamera::Notch_Process_PreProcess(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI)
{
- if(m_pRecipe == NULL)
+ if (m_pRecipe == nullptr) {
return;
+ }
- if(nNotchIdx < 0 || MAX_SIDE_NOTCH_COUNT <= nNotchIdx)
+ if (nNotchIdx < 0 || nNotchIdx >= MAX_SIDE_NOTCH_COUNT) {
return;
+ }
- CString strTemp;
+ // 中值滤波器大小,用于去噪,必须为奇数(若偶数会自动减1)
+ const int nSmoothFilter = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
- int sigma1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
- int sigma2 = 7;
+ // 磨边区域阈值,控制反二值化阈值,主要用于提取 Notch 边缘特征
+ const int nGrindThreshold = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold;
- if(sigma1 % 2 == 0)
- sigma1 = sigma1 - 1;
+ // 玻璃区域阈值,控制正二值化阈值,用于提取玻璃主体区域
+ const int nGlassThreshold = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold;
- if(1 < sigma1)
- cvSmooth(scr,img_Bin,CV_MEDIAN,sigma1);
+ // 确保奇数滤波器大小
+ int nFilterSize = (nSmoothFilter % 2 == 0) ? (nSmoothFilter - 1) : nSmoothFilter;
-// double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold * 10;
-// double th2 = 40.0;
-// int sigma=5;
-//
-// cvCanny(img_Bin,img_Edge,th1,th2,sigma);
+ if (nFilterSize > 1) {
+ // 中值滤波降噪
+ cvSmooth(scr, img_Bin, CV_MEDIAN, nFilterSize);
+ }
- double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold;
+ // Edge图:反二值化阈值处理
+ cvThreshold(scr, img_Edge, nGrindThreshold, 255, CV_THRESH_BINARY_INV);
+ CString strEdgeFileName;
+ strEdgeFileName.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx);
+ SaveDebugImage(emDim, stFrame, img_Edge, strEdgeFileName);
- cvThreshold(scr,img_Edge,th1,255,CV_THRESH_BINARY_INV);
-
- strTemp.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx);
- SaveDebugImage(emDim, stFrame, img_Edge, strTemp);
-
- th1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold;
-
- cvThreshold(scr,img_Bin,th1,255,CV_THRESH_BINARY);
-
- strTemp.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx);
- SaveDebugImage(emDim, stFrame, img_Bin, strTemp);
-}
-
-void CInspectCamera::Notch_Process_PreProcess_2(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI)
-{
- if(m_pRecipe == NULL)
- return;
-
- if(nNotchIdx < 0 || MAX_SIDE_NOTCH_COUNT <= nNotchIdx)
- return;
-
- int sigma1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
-
- CString strTemp;
- cvThreshold(scr,img_Edge,sigma1,255,CV_THRESH_BINARY_INV);
-
- double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold;
- double th2 = 40.0;
- int sigma=5;
-
- cvCanny(img_Edge, img_Edge,th1,th2,sigma);
-
- strTemp.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx);
- SaveDebugImage(emDim, stFrame, img_Edge, strTemp);
-
- th1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold;
-
- cvThreshold(scr,img_Bin,th1,255,CV_THRESH_BINARY);
-
- strTemp.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx);
- SaveDebugImage(emDim, stFrame, img_Bin, strTemp);
+ // Bin图:正常二值化
+ cvThreshold(scr, img_Bin, nGlassThreshold, 255, CV_THRESH_BINARY);
+ CString strBinFileName;
+ strBinFileName.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx);
+ SaveDebugImage(emDim, stFrame, img_Bin, strBinFileName);
}
void CInspectCamera::Notch_Process_Measure(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr,IplImage* img_Edge,IplImage* img_Bin, CRect rtROI)
@@ -4088,7 +4043,6 @@
break;
}
-
if(bEdgeCheck == FALSE && (bEdgeFind == TRUE || bBinEdgeFind == TRUE))
{
if(bFindEdge == FALSE && bEdgeFind == TRUE)
@@ -4156,6 +4110,21 @@
CPoint ptDim_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx];
CPoint ptChamfer_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx];
+ if (ptRef_pxl.x < 0 || ptRef_pxl.y < 0) {
+ g_pLog->DisplayMessage(_T("[ERROR] Invalid Ref Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptRef_pxl.x, ptRef_pxl.y);
+ continue;
+ }
+
+ if (ptDim_pxl.x < 0 || ptDim_pxl.y < 0) {
+ g_pLog->DisplayMessage(_T("[ERROR] Invalid Dim Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptDim_pxl.x, ptDim_pxl.y);
+ continue;
+ }
+
+ if (ptChamfer_pxl.x < 0 || ptChamfer_pxl.y < 0) {
+ g_pLog->DisplayMessage(_T("[ERROR] Invalid Chamfer Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptChamfer_pxl.x, ptChamfer_pxl.y);
+ continue;
+ }
+
// Dimension
double dX_dim_um = (double)(ptRef_pxl.x - ptDim_pxl.x) * m_dPixelSizeX;
double dY_dim_um = (double)(ptRef_pxl.y - ptDim_pxl.y) * m_dPixelSizeY;
@@ -4169,9 +4138,9 @@
m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx] = dChamfer;
- if (dDimension > 2000 && dChamfer > 2000)
- {
- return FALSE;
+ if (dDimension > 2000.0 && dChamfer > 2000.0) {
+ g_pLog->DisplayMessage(_T("[ERROR] Abnormal Dimension & Chamfer too large at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Dimension: %.2f, Chamfer: %.2f"), nNotchIdx, nMeasureIdx, dDimension, dChamfer);
+ continue;
}
}
@@ -4242,8 +4211,7 @@
//选取测量研磨尺寸最大值
if (m_nChamferOffset_um < dChamfer_um)
{
- m_nChamferOffset_um = dChamfer_um;
-
+ m_nChamferOffset_um = dChamfer_um;
}
m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Result_Diff_um[nNotchIdx][nMeasureIdx] = dChamfer_std_um - dChamfer_um;
m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] = dChamfer_std_um;
@@ -4308,7 +4276,6 @@
CString strTemp;
-
int nSide = (int) emDim;
int nThreshold = pNotchParam->m_nNotch_Inspect_Defect_Threshold;
int nOffset = pNotchParam->m_nNotch_Inspect_Defect_Offset;
@@ -4353,8 +4320,7 @@
vecDefectCandidateList.push_back(defectInfo);
}
m_pDefectControl->ExtractDefect_Notch(emDim, m_iCamera, stFrame.nScanIdx, nNotchIdx, &vecDefectCandidateList);
-#else
-
+#else
nOffset = m_nChamferOffset_um / m_pGlassData->GetSideData(emDim)->m_dPixelSizeX;
nOffset += pNotchParam->m_nNotch_Inspect_Defect_Offset;
m_nChamferOffset_um = 0;
@@ -4518,27 +4484,21 @@
CRect rtSet_Area = pNotchParam->m_rtNotch_Circle_Area_pxl[nCircleIdx];
CRect rtRotateArea;
-
- if(GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
+ if (GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE) {
+ g_pLog->DisplayMessage(_T("Notch Circle %d Rotate Area Error"), nCircleIdx);
continue;
+ }
CRect rtROI = rtRotateArea;
+ if (rtROI.Width() <= 0 || rtROI.Height() <= 0) {
+ g_pLog->DisplayMessage(_T("Invalid ROI size: %d x %d"), rtROI.Width(), rtROI.Height());
+ continue;
+ }
pSideData->m_rtNotchCircleArea_pxl[nNotchIdx][nCircleIdx] = rtROI;
VectorDouble vectorX;
VectorDouble vectorY;
VectorDouble vectorR;
-
- /*
- for(int nMeasureIdx=0; nMeasureIdx<MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
- {
- if(pSideData->m_nNotch_Dimension_Edge_Judge[nMeasureIdx] ==0)
- continue;
-
- vectorX.push_back((double) pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x);
- vectorY.push_back((double) pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y);
- }
- */
// 2. Get Edge Line
int nThreshold = m_pRecipe->m_SideParam[(int) emDim].m_nChamferLineThreshold;
@@ -4548,22 +4508,27 @@
IplImage* pEdgeImage = cvCreateImage(cvSize(rtROI.Width(), rtROI.Height()), 8, 1);
IplImage* pCannyEdgeImage = cvCreateImage(cvSize(rtROI.Width(), rtROI.Height()), 8, 1);
- for(int i=0; i<rtROI.Height(); i++)
- memcpy(&pEdgeImage->imageData[(i*pEdgeImage->widthStep)], (pFrameBuffer + ((rtROI.top+i)*m_nFrameWidth) + rtROI.left), rtROI.Width());
+ for (int i = 0; i < rtROI.Height(); i++) {
+ memcpy(&pEdgeImage->imageData[(i * pEdgeImage->widthStep)], (pFrameBuffer + ((rtROI.top + i) * m_nFrameWidth) + rtROI.left), rtROI.Width());
+ }
- int sigma1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
+ int nMedianFilterSize = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
+ nMedianFilterSize = std::max(3, std::min(nMedianFilterSize, 31));
+ if (nMedianFilterSize % 2 == 0) {
+ nMedianFilterSize--;
+ }
+ cvSmooth(pEdgeImage, pEdgeImage, CV_MEDIAN, nMedianFilterSize);
- if(sigma1 % 2 == 0)
- sigma1 = sigma1 - 1;
+ double th1 = 40.0;
+ double th2 = std::max(1.0, std::min((double)m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold * 10, 255.0));
- if(1 < sigma1)
- cvSmooth(pEdgeImage,pEdgeImage,CV_MEDIAN,sigma1);
+ if (th1 > th2) {
+ std::swap(th1, th2);
+ }
- double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold * 10;
- double th2 = 40.0;
- int sigma=5;
+ g_pLog->DisplayMessage(_T("Smooth Filter: %d, Canny th1: %.1f, th2: %.1f"), nMedianFilterSize, th1, th2);
- cvCanny(pEdgeImage,pCannyEdgeImage,th1,th2,sigma);
+ cvCanny(pEdgeImage, pCannyEdgeImage, th1, th2, nMedianFilterSize);
CString strTemp;
strTemp.Format(_T("Notch\\Notch_%d_Circle_%d_Ori.jpg"), nNotchIdx, nCircleIdx);
@@ -4647,7 +4612,6 @@
{
sprintf(pSideData->m_strNotchCircle_Radius_Comment[nNotchIdx][nCircleIdx], "Rad. [OK] %.1f um / %.1f um", dRadiuse_um, dResult_um);
}
-
}
}
}
@@ -5565,8 +5529,6 @@
return TRUE;
}
-
-
BOOL CInspectCamera::Measure_TopCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
{
if(m_pGlassData == NULL || m_pRecipe == NULL)
@@ -5938,13 +5900,11 @@
BOOL CInspectCamera::OnThreadEnd(int iThread, CInspectThread *pInspectThread)
{
-
return TRUE;
}
BOOL CInspectCamera::OnThreadEndAll()
{
-
return TRUE;
}
--
Gitblit v1.9.3