| | |
| | | g_pLog->DisplayMessage(_T("[APP]Measure Side Edge Start, StartEdge = %d, EndEdge = %d, Width = %d"), nTopEdge, nBottomEdge, imgWidth); |
| | | |
| | | stFrameIndex stFrame = m_pGrabber->GetGrabFrame(); |
| | | CRIP_THICKNESS_PARM& rip = m_pRecipe->m_SideParam[eDim].m_RipThk; |
| | | CSIDE_PARM parm = m_pRecipe->m_SideParam[eDim]; |
| | | CRIP_THICKNESS_PARM& rip = parm.m_RipThk; |
| | | if (rip.m_bUseInspect != TRUE) { |
| | | return TRUE; |
| | | } |
| | | |
| | | int inspectNum = 36; |
| | | |
| | | //输入参数 |
| | | int topOffset = rip.m_nTopOffset; //T Offset |
| | |
| | | int leftEdge = rip.m_nRectLeft; //Rect L |
| | | int rightEdge = rip.m_nRectRight; //Rect R |
| | | int leftThres = rip.m_nLeftThres; //Left Thres |
| | | int rightThres = rip.m_nRightThres; //Right Thres |
| | | int rightThres = rip.m_nRightThres; //Right Thres |
| | | int gassThres = rip.m_nGlassThres; //Gas Thres |
| | | |
| | | int inspectNum = 36; |
| | | |
| | | int startY = nTopEdge + topOffset; |
| | | int endY = nBottomEdge - botOffset; |
| | | int step = (int)((endY - startY) / inspectNum); |
| | | g_pLog->DisplayMessage(_T("[APP]Measure Side Edge, (startY, endY, step) = (%d, %d, %d)"), startY, endY, step); |
| | | |
| | | int nStep = max(1, (endY - startY) / inspectNum); // 防 0 |
| | | auto SpecDiff = [](double v, double vMin, double vMax)->double { |
| | | if (v <= 0) return 0.0; // 无效值 |
| | | if (v < vMin) return v - vMin; // 负:低于下限 |
| | | if (v > vMax) return v - vMax; // 正:高于上限 |
| | | return 0.0; // 在规格内 |
| | | }; |
| | | auto judge = [](double v_um, double vMin, double vMax)->int { |
| | | if (v_um <= 0) return 0; |
| | | return (v_um < vMin || v_um > vMax) ? 2 : 1; |
| | | }; |
| | | auto MakeBaseInfo = [&](CPoint pt, CRect rt, DefectLocation loc)->CDefect_Info { |
| | | CDefect_Info info; |
| | | info.m_iFrameIdx = stFrame.nFrameIdx; |
| | | info.m_nCamID = m_iCamera; |
| | | info.m_nScanIdx = stFrame.nScanIdx; |
| | | info.m_nGlassStartLine = pSideData->m_nGlassStartLine; |
| | | info.m_nSideIdx = (int)eDim; |
| | | info.m_ptDefectPos_pxl = pt; |
| | | info.m_rtDefectPos_pxl = rt; |
| | | info.m_DefectLoc = loc; |
| | | return info; |
| | | }; |
| | | |
| | | #if 1 |
| | | int nMeasureCount = parm.m_nSideDimensionCount; |
| | | for (int nMeasurePointIdx = 0; nMeasurePointIdx < nMeasureCount; nMeasurePointIdx++) { |
| | | if (nMeasurePointIdx == MAX_SIDE_DIMENSION_MEASURE_COUNT) { |
| | | break; |
| | | } |
| | | |
| | | if (parm.m_bSideDimension_Use[nMeasurePointIdx] != TRUE) { |
| | | continue; |
| | | } |
| | | |
| | | //这里做一个测试 |
| | | int inputY = (int)(parm.m_nSideDimensionPos_TopMarkToDistance_um[nMeasurePointIdx] * m_dPixelSizeY); //这个是输入参数,距离StartLine的距离, um |
| | | int targetY = (int)(inputY / m_dPixelSizeY); |
| | | int x1 = leftEdge; |
| | | int y1 = nTopEdge + targetY - 50; |
| | | int x2 = rightEdge; |
| | | int y2 = nTopEdge + targetY + 50; |
| | | |
| | | double dist_ret = 0.0f; //输出结果 |
| | | double left_dist_Gass = 0.0f; //输出结果 |
| | | double right_dist_Gass; //输出结果 |
| | | double xMinEdge_px = 0.0f; //输出结果 |
| | | double yMinEdge_px = 0.0f; //输出结果 |
| | | double xMaxEdge_px = 0.0f; //输出结果 |
| | | double yMaxEdge_px = 0.0f; //输出结果 |
| | | double xMinGas_px = 0.0f; //输出结果 |
| | | double yMinGas_px = 0.0f; //输出结果 |
| | | double xMaxGas_px = 0.0f; //输出结果 |
| | | double yMaxGas_px = 0.0f; //输出结果 |
| | | MeasureSideEdge_POS_1(eDim, x1, y1, x2, y2, leftThres, rightThres, gassThres, |
| | | xMinEdge_px, yMinEdge_px, xMaxEdge_px, yMaxEdge_px, |
| | | xMinGas_px, yMinGas_px, xMaxGas_px, yMaxGas_px, |
| | | dist_ret, left_dist_Gass, right_dist_Gass); |
| | | |
| | | g_pLog->DisplayMessage(_T("[APP]Measure Result: LeftEdge = (%.1f, %.1f), LeftGas = (%.1f, %.1f), rightGas = (%.1f, %.1f), RightEdge = (%.1f, %.1f), (Dist, LeftGass, RightGass) = (%.1f, %.1f, %.1f)"), |
| | | xMinEdge_px, yMinEdge_px, |
| | | xMinGas_px, yMinGas_px, |
| | | xMaxGas_px, yMaxGas_px, |
| | | xMaxEdge_px, yMaxEdge_px, |
| | | dist_ret, left_dist_Gass, right_dist_Gass); |
| | | |
| | | dist_ret *= m_dPixelSizeX; |
| | | left_dist_Gass *= m_dPixelSizeX; |
| | | right_dist_Gass *= m_dPixelSizeX; |
| | | |
| | | const int nGlassState = judge(dist_ret, rip.m_nGlassSizeMin_um, rip.m_nGlassSizeMax_um); |
| | | const int nLeftState = judge(left_dist_Gass, rip.m_nLeftRipSizeMin_um, rip.m_nLeftRipSizeMax_um); |
| | | const int nRightState = judge(right_dist_Gass, rip.m_nRightRipSizeMin_um, rip.m_nRightRipSizeMax_um); |
| | | |
| | | if (nMeasurePointIdx < MAX_RIP_SAMPLE_COUNT) { |
| | | // Glass 线段 |
| | | pSideData->m_ptSideRip_Glass_pxl[nMeasurePointIdx][0] = CPoint((int)xMinEdge_px, (int)yMinEdge_px); |
| | | pSideData->m_ptSideRip_Glass_pxl[nMeasurePointIdx][1] = CPoint((int)xMaxEdge_px, (int)yMaxEdge_px); |
| | | pSideData->m_dSideRip_Glass_um[nMeasurePointIdx] = dist_ret; |
| | | pSideData->m_nSideRip_Glass_Status[nMeasurePointIdx] = nGlassState; |
| | | |
| | | // Left 线段 |
| | | pSideData->m_ptSideRip_Left_pxl[nMeasurePointIdx][0] = CPoint((int)xMinEdge_px, (int)yMinEdge_px); |
| | | pSideData->m_ptSideRip_Left_pxl[nMeasurePointIdx][1] = CPoint((int)xMinGas_px, (int)yMinGas_px); |
| | | pSideData->m_dSideRip_Left_um[nMeasurePointIdx] = left_dist_Gass; |
| | | pSideData->m_nSideRip_Left_Status[nMeasurePointIdx] = nLeftState; |
| | | |
| | | // Right 线段 |
| | | pSideData->m_ptSideRip_Right_pxl[nMeasurePointIdx][0] = CPoint((int)xMaxGas_px, (int)yMaxGas_px); |
| | | pSideData->m_ptSideRip_Right_pxl[nMeasurePointIdx][1] = CPoint((int)xMaxEdge_px, (int)yMaxEdge_px); |
| | | pSideData->m_dSideRip_Right_um[nMeasurePointIdx] = right_dist_Gass; |
| | | pSideData->m_nSideRip_Right_Status[nMeasurePointIdx] = nRightState; |
| | | } |
| | | |
| | | // Glass NG |
| | | if (nGlassState == 2) { |
| | | CRect rt( |
| | | (int)min(min(xMinEdge_px, xMinGas_px), min(xMaxEdge_px, xMaxGas_px)), |
| | | (int)min(min(yMinEdge_px, yMinGas_px), min(yMaxEdge_px, yMaxGas_px)), |
| | | (int)max(max(xMinEdge_px, xMinGas_px), max(xMaxEdge_px, xMaxGas_px)), |
| | | (int)max(max(yMinEdge_px, yMinGas_px), max(yMaxEdge_px, yMaxGas_px)) |
| | | ); |
| | | CPoint pt((rt.left + rt.right) / 2, (rt.top + rt.bottom) / 2); |
| | | CDefect_Info defect = MakeBaseInfo(pt, rt, DefectLoc_Rip_Thickness_Glass); |
| | | double dDiff = SpecDiff(dist_ret, rip.m_nGlassSizeMin_um, rip.m_nGlassSizeMax_um); |
| | | m_pDefectControl->ExtractDefect_RipThickness(eDim, m_iCamera, stFrame.nScanIdx, defect, dist_ret, dDiff); |
| | | } |
| | | // Left NG |
| | | if (nLeftState == 2) { |
| | | CRect rt( |
| | | (int)min(xMinEdge_px, xMinGas_px), |
| | | (int)min(yMinEdge_px, yMinGas_px), |
| | | (int)max(xMinEdge_px, xMinGas_px), |
| | | (int)max(yMinEdge_px, yMinGas_px) |
| | | ); |
| | | CPoint pt((rt.left + rt.right) / 2, (rt.top + rt.bottom) / 2); |
| | | CDefect_Info defect = MakeBaseInfo(pt, rt, DefectLoc_Rip_Thickness_Left); |
| | | double dDiff = SpecDiff(left_dist_Gass, rip.m_nLeftRipSizeMin_um, rip.m_nLeftRipSizeMax_um); |
| | | m_pDefectControl->ExtractDefect_RipThickness(eDim, m_iCamera, stFrame.nScanIdx, defect, left_dist_Gass, dDiff); |
| | | } |
| | | // Right NG |
| | | if (nRightState == 2) { |
| | | CRect rt( |
| | | (int)min(xMaxEdge_px, xMaxGas_px), |
| | | (int)min(yMaxEdge_px, yMaxGas_px), |
| | | (int)max(xMaxEdge_px, xMaxGas_px), |
| | | (int)max(yMaxEdge_px, yMaxGas_px) |
| | | ); |
| | | CPoint pt((rt.left + rt.right) / 2, (rt.top + rt.bottom) / 2); |
| | | CDefect_Info defect = MakeBaseInfo(pt, rt, DefectLoc_Rip_Thickness_Right); |
| | | double dDiff = SpecDiff(right_dist_Gass, rip.m_nRightRipSizeMin_um, rip.m_nRightRipSizeMax_um); |
| | | m_pDefectControl->ExtractDefect_RipThickness(eDim, m_iCamera, stFrame.nScanIdx, defect, right_dist_Gass, dDiff); |
| | | } |
| | | } |
| | | #else |
| | | double dist_array[36]; //输出结果 |
| | | double left_dist_Gass_array[36]; //输出结果 |
| | | double right_dist_Gass_array[36]; //输出结果 |
| | |
| | | double xMaxGas_array_px[36]; //输出结果 |
| | | double yMaxGas_array_px[36]; //输出结果 |
| | | |
| | | int startY = nTopEdge + topOffset; |
| | | int endY = nBottomEdge - botOffset; |
| | | int step = (int)((endY - startY) / inspectNum); |
| | | g_pLog->DisplayMessage(_T("[APP]Measure Side Edge, (startY, endY, step) = (%d, %d, %d)"), startY, endY, step); |
| | | |
| | | for (int i = 0; i < inspectNum; i++) { |
| | | int x1 = leftEdge; |
| | | int y1 = startY + i * step; |
| | |
| | | x1, y1, x2, y2, |
| | | leftThres, rightThres, gassThres, |
| | | xMinEdge_array_px[i], yMinEdge_array_px[i], xMaxEdge_array_px[i], yMaxEdge_array_px[i], |
| | | xMinGas_array_px[i], yMinGas_array_px[i], xMaxGas_array_px[i], yMaxGas_array_px[i], |
| | | xMinGas_array_px[i], yMinGas_array_px[i], xMaxGas_array_px[i], yMaxGas_array_px[i], |
| | | szDist, leftGassDist, rightGassDist); |
| | | |
| | | dist_array[i] = m_dPixelSizeX * szDist; |
| | |
| | | right_dist_Gass_array[i] = m_dPixelSizeX * rightGassDist; |
| | | |
| | | g_pLog->DisplayMessage(_T("[APP]Measure Result %d: LeftEdge = (%.1f, %.1f), LeftGas = (%.1f, %.1f), rightGas = (%.1f, %.1f), RightEdge = (%.1f, %.1f), (Dist, LeftGass, RightGass) = (%.1f, %.1f, %.1f)"), |
| | | i + 1, |
| | | xMinEdge_array_px[i], yMinEdge_array_px[i], |
| | | xMinGas_array_px[i], yMinGas_array_px[i], |
| | | xMaxGas_array_px[i], yMaxGas_array_px[i], |
| | | xMaxEdge_array_px[i], yMaxEdge_array_px[i], |
| | | i + 1, |
| | | xMinEdge_array_px[i], yMinEdge_array_px[i], |
| | | xMinGas_array_px[i], yMinGas_array_px[i], |
| | | xMaxGas_array_px[i], yMaxGas_array_px[i], |
| | | xMaxEdge_array_px[i], yMaxEdge_array_px[i], |
| | | dist_array[i], left_dist_Gass_array[i], right_dist_Gass_array[i]); |
| | | |
| | | // 添加缺陷 |
| | |
| | | } |
| | | } |
| | | } |
| | | #endif |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | void CInspectCamera::MeasureSideEdge_POS_1(DimensionDir eDim, |
| | | int x1, int y1, int x2, int y2, |
| | | int leftThres, int rightThres, int gassThres, |
| | | double& minEdgeX, double& minEdgeY, double& maxEdgeX, double& maxEdgeY, |
| | | double& minGasX, double& minGasY, double& maxGasX, double& maxGasY, |
| | | double& szDist, double& leftGassDist, double& rightGassDist) { |
| | | /* code */ |
| | | szDist = 0.0f; |
| | | leftGassDist = 0.0f; |
| | | rightGassDist = 0.0f; |
| | | int width = x2 - x1 + 1; |
| | | int height = y2 - y1 + 1; |
| | | uchar* imgData = new uchar[width * height]; |
| | | try { |
| | | CutImageROI(imgData, eDim, x1, y1, x2, y2); |
| | | |
| | | MeasurePoint dotResult1[100]; |
| | | MeasurePoint dotResult2[100]; |
| | | MeasurePoint dotResult3[100]; |
| | | int dotNum1 = 0; |
| | | int dotNum2 = 0; |
| | | int dotNum3 = 0; |
| | | CVisionMeasureClass doExec; |
| | | double sigma = 2.5f; //输入参数, 增加参数 |
| | | doExec.doMeasurePosB(imgData, width, height, sigma, |
| | | dotResult1, dotNum1, |
| | | dotResult2, dotNum2, |
| | | dotResult3, dotNum3); |
| | | for (int i = 0; i < dotNum1; i++) { |
| | | dotResult1[i].x += x1; |
| | | dotResult1[i].y += y1; |
| | | } |
| | | for (int i = 0; i < dotNum2; i++) { |
| | | dotResult2[i].x += x1; |
| | | dotResult2[i].y += y1; |
| | | } |
| | | for (int i = 0; i < dotNum3; i++) { |
| | | dotResult3[i].x += x1; |
| | | dotResult3[i].y += y1; |
| | | } |
| | | |
| | | int fzDist = 4.5; //输入参数, 增加参数 |
| | | |
| | | double xMinResult[3] = { -1 }; |
| | | double yMinResult[3] = { -1 }; |
| | | double xMaxResult[3] = { -1 }; |
| | | double yMaxResult[3] = { -1 }; |
| | | double xMinGassResult[3] = { -1 }; |
| | | double yMinGassResult[3] = { -1 }; |
| | | double xMaxGassResult[3] = { -1 }; |
| | | double yMaxGassResult[3] = { -1 }; |
| | | MeasureResultProc(dotResult1, dotNum1, leftThres, rightThres, gassThres, fzDist, |
| | | xMinResult[0], yMinResult[0], xMaxResult[0], yMaxResult[0], |
| | | xMinGassResult[0], yMinGassResult[0], xMaxGassResult[0], yMaxGassResult[0]); |
| | | MeasureResultProc(dotResult2, dotNum2, leftThres, rightThres, gassThres, fzDist, |
| | | xMinResult[1], yMinResult[1], xMaxResult[1], yMaxResult[1], |
| | | xMinGassResult[1], yMinGassResult[1], xMaxGassResult[1], yMaxGassResult[1]); |
| | | MeasureResultProc(dotResult3, dotNum3, leftThres, rightThres, gassThres, fzDist, |
| | | xMinResult[2], yMinResult[2], xMaxResult[2], yMaxResult[2], |
| | | xMinGassResult[2], yMinGassResult[2], xMaxGassResult[2], yMaxGassResult[2]); |
| | | |
| | | std::vector<double> vDist, vLeftGass, vRightGass; |
| | | for (int i = 0; i < 3; i++) { |
| | | if (xMinResult[i] > 0 && xMaxResult[i] > 0) { |
| | | double dx = xMaxResult[i] - xMinResult[i]; |
| | | double dy = yMaxResult[i] - yMinResult[i]; |
| | | double dist = sqrt(dx * dx + dy * dy); |
| | | vDist.push_back(dist); |
| | | } |
| | | if (xMinResult[i] > 0 && xMinGassResult[i] > 0) { |
| | | double dx = xMinGassResult[i] - xMinResult[i]; |
| | | double dy = yMinGassResult[i] - yMinResult[i]; |
| | | double dist = sqrt(dx * dx + dy * dy); |
| | | vLeftGass.push_back(dist); |
| | | } |
| | | if (xMaxResult[i] > 0 && xMaxGassResult[i] > 0) { |
| | | double dx = xMaxResult[i] - xMaxGassResult[i]; |
| | | double dy = yMaxResult[i] - yMaxGassResult[i]; |
| | | double dist = sqrt(dx * dx + dy * dy); |
| | | vRightGass.push_back(dist); |
| | | } |
| | | } |
| | | |
| | | double avgDist = 0.0f; |
| | | int sz = (int)(vDist.size()); |
| | | if (sz > 2) { |
| | | for (int i = 0; i < sz - 1; i++) { |
| | | for (int j = i + 1; j < sz; j++) { |
| | | if (vDist[i] > vDist[j]) { |
| | | double tmp = vDist[i]; |
| | | vDist[i] = vDist[j]; |
| | | vDist[j] = tmp; |
| | | } |
| | | } |
| | | } |
| | | double avg = 0.0f; |
| | | for (int i = 1; i < sz - 1; i++) { |
| | | avg += vDist[i]; |
| | | } |
| | | avgDist = avg / (sz - 2); |
| | | } |
| | | double avgLeftGass = 0.0f; |
| | | sz = (int)(vLeftGass.size()); |
| | | if (sz > 2) { |
| | | for (int i = 0; i < sz - 1; i++) { |
| | | for (int j = i + 1; j < sz; j++) { |
| | | if (vLeftGass[i] > vLeftGass[j]) { |
| | | double tmp = vLeftGass[i]; |
| | | vLeftGass[i] = vLeftGass[j]; |
| | | vLeftGass[j] = tmp; |
| | | } |
| | | } |
| | | } |
| | | double avg = 0.0f; |
| | | for (int i = 1; i < sz - 1; i++) { |
| | | avg += vLeftGass[i]; |
| | | } |
| | | avgLeftGass = avg / (sz - 2); |
| | | } |
| | | |
| | | double avgRightGass = 0.0f; |
| | | sz = (int)(vRightGass.size()); |
| | | if (sz > 2) { |
| | | for (int i = 0; i < sz - 1; i++) { |
| | | for (int j = i + 1; j < sz; j++) { |
| | | if (vRightGass[i] > vRightGass[j]) { |
| | | double tmp = vRightGass[i]; |
| | | vRightGass[i] = vRightGass[j]; |
| | | vRightGass[j] = tmp; |
| | | } |
| | | } |
| | | } |
| | | double avg = 0.0f; |
| | | for (int i = 1; i < sz - 1; i++) { |
| | | avg += vRightGass[i]; |
| | | } |
| | | avgRightGass = avg / (sz - 2); |
| | | } |
| | | |
| | | szDist = avgDist; |
| | | leftGassDist = avgLeftGass; |
| | | rightGassDist = avgRightGass; |
| | | |
| | | minEdgeX = xMinResult[1]; |
| | | minEdgeY = yMinResult[1]; |
| | | maxEdgeX = xMaxResult[1]; |
| | | maxEdgeY = yMaxResult[1]; |
| | | minGasX = minEdgeX + leftGassDist - 1; |
| | | minGasY = minEdgeY; |
| | | maxGasX = maxEdgeX - rightGassDist + 1; |
| | | maxGasY = maxEdgeY; |
| | | |
| | | delete[] imgData; |
| | | imgData = nullptr; |
| | | } |
| | | catch (...) { |
| | | delete[] imgData; |
| | | imgData = nullptr; |
| | | } |
| | | } |
| | | |
| | | void CInspectCamera::MeasureSideEdge_POS(DimensionDir eDim, |
| | | int x1, int y1, int x2, int y2, |
| | | int leftThres, int rightThres, int gassThres, |