List <DlafFovDetectResult> _lstFovResults = new List <DlafFovDetectResult>(); //保存当前料片的测试结果 public void OnCustomizeMsg(string msgCategory, object[] msgParams) //其他自定义消息 { BeginInvoke(new Action(() => { if (msgCategory == DLAFOfflineSetectStation.SCM_PieceStart) //开始了一个料片检测 { if (_currRecipe == null) { _currRecipe = (JFHubCenter.Instance.RecipeManager as JFDLAFRecipeManager).GetRecipe("Product", cbRecipeID.Text) as JFDLAFProductRecipe; } _lstFovResults.Clear(); mapDetectCells.InitaialDieState(); rchDetectInfo.Text = ""; rchDetectInfo.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + " 开始检测"); _currICRow = -1; //当前显示的ICRow _currICCol = -1; _currFov = null; //当前显示的Fov _picFolder = msgParams[0] as string; } else if (msgCategory == DLAFOfflineSetectStation.SCM_PieceEnd) //一个料片检测完成 { } else if (msgCategory == DLAFOfflineSetectStation.SCM_FovDetectResult) //一个Fov检测完成 , 显示结果 { if (null != _currTaskImgs) { foreach (HObject ho in _currTaskImgs) { ho.Dispose(); } _currTaskImgs = null; } _currTaskImgs = msgParams[0] as List <HObject>; //从Fov中读出的原图 DlafFovDetectResult fdr = (msgParams[1] as DlafFovDetectResult).Clone(); _lstFovResults.Add(fdr); _currICRow = fdr.ICRow; _currICCol = fdr.ICCol; _currFov = fdr.FovName; ShowFovImageResult(); //画图 UpdateErrorDataGrid(fdr); //将错误信息更新到DatagridView UpdateDetectMapping(fdr); //将检测结果更新到Map控件 rchDetectInfo.AppendText("ICRow:" + fdr.ICRow + " ICCol:" + fdr.ICCol + " Fov:" + fdr.FovName + "-----\n"); rchDetectInfo.AppendText("检测" + (fdr.IsDetectSuccess ? "完成" : ("失败:" + fdr.DetectErrorInfo)) + "\n"); } })); }
/// <summary> /// 设置产品信号/批次号 /// </summary> /// <param name="recipeID"></param> /// <param name="lotID"></param> /// <param name="errorInfo"></param> /// <returns></returns> public bool SetRecipeLot(string recipeID, string lotID, out string errorInfo) { if (string.IsNullOrEmpty(recipeID)) { errorInfo = "参数RecipeID为空字串"; _recipeID = null; return(false); } JFDLAFRecipeManager rm = JFHubCenter.Instance.RecipeManager as JFDLAFRecipeManager; if (null == rm || !rm.IsInitOK) { errorInfo = "配方管理器未设置/未初始化!"; _recipeID = null; return(false); } string[] allRecipeIDS = rm.AllRecipeIDsInCategoty("Product"); if (null == allRecipeIDS || !allRecipeIDS.Contains(recipeID)) { errorInfo = "RecipeID:\"" + recipeID + "\"在配方管理器中不存在!"; _recipeID = null; return(false); } _recipeID = recipeID; _recipe = rm.GetRecipe("Product", _recipeID) as JFDLAFProductRecipe; if (string.IsNullOrEmpty(lotID)) { _lotID = null; errorInfo = "参数项LotID为空值"; return(false); } _lotID = lotID; int fovCountInPiece = _recipe.FovCount * _recipe.ICCount;//料片所有Fov数量 _fovResults = new DlafFovDetectResult[fovCountInPiece]; _fovCounteds = new bool[fovCountInPiece]; errorInfo = "Success"; return(true); }
void UpdateTaskNameButtons(DlafFovDetectResult fdr) { if (null == _currRecipe) { return; } string[] taskNames = fdr.TaskNames; int i = 0; for (i = 0; i < taskNames.Length; i++) { if (i < _rbTaskNames.Length) { _rbTaskNames[i].Visible = true; _rbTaskNames[i].Enabled = true; _rbTaskNames[i].Text = taskNames[i]; } } for (; i < _rbTaskNames.Length; i++) { _rbTaskNames[i].Visible = false; } }
/// <summary> /// 输入一条Fov的检测结果 /// </summary> /// <param name="fovResult">Fov检测结果</param> public void EntryFovResult(DlafFovDetectResult fr /*, out bool isLastFovInPiece*/) { if (null == fr) { return; } int fovIndexInDie = 0; string[] allFovNames = _recipe.FovNames(); for (int i = 0; i < allFovNames.Length; i++) { if (fr.FovName == allFovNames[i]) { fovIndexInDie = i; break; } } int idx = (fr.ICRow * _recipe.ColCount + fr.ICCol) * _recipe.FovCount + fovIndexInDie; _fovResults[idx] = fr; _fovCounteds[idx] = false; }
/// <summary> /// 将错误信息更新到列表中 /// </summary> /// <param name="fdr"></param> void UpdateErrorDataGrid(DlafFovDetectResult fdr) { bool _isShowAllItems = chkShowAllItems.Checked; lbSelectedInfo.Text = "选中单元: Row=" + (fdr.ICRow + 1) + " Col=" + (fdr.ICCol + 1) + " FovName:" + fdr.FovName + " 结果:" + (fdr.IsFovOK ? "合格" : "不合格"); dgvInspectResultsInFov.Rows.Clear(); int dieIndex = 0; int dieCount = fdr.CurrColCount * fdr.CurrRowCount; if (dieCount <= 0)//Fov只是Die的一部分 { dieCount = 1; } //表格行 : Die/检测项/检测结果/检测标准数据/检测结果数据/备注 for (dieIndex = 0; dieIndex < dieCount; dieIndex++) { if (!fdr.IsDetectSuccess) //视觉算子出错 { DataGridViewRow row = new DataGridViewRow(); DataGridViewTextBoxCell dieIndexCell = new DataGridViewTextBoxCell(); dieIndexCell.Style.BackColor = Color.Red; dieIndexCell.Value = dieIndex + 1; row.Cells.Add(dieIndexCell); DataGridViewTextBoxCell detectItemCell = new DataGridViewTextBoxCell(); detectItemCell.Value = "---"; detectItemCell.Style.ForeColor = Color.Red; row.Cells.Add(detectItemCell); DataGridViewTextBoxCell dieErrorCell = new DataGridViewTextBoxCell(); dieErrorCell.Value = "检测出错:" + fdr.DetectErrorInfo; dieErrorCell.Style.ForeColor = Color.Red; row.Cells.Add(dieErrorCell); DataGridViewTextBoxCell dieRefVelCell = new DataGridViewTextBoxCell(); dieRefVelCell.Value = "---"; dieRefVelCell.Style.ForeColor = Color.Red; row.Cells.Add(dieRefVelCell); DataGridViewTextBoxCell dieDetectVelCell = new DataGridViewTextBoxCell(); dieDetectVelCell.Value = "---"; dieDetectVelCell.Style.ForeColor = Color.Red; row.Cells.Add(dieDetectVelCell); DataGridViewTextBoxCell dieRemarksCell = new DataGridViewTextBoxCell(); string rowColInfo = "Die:" + (dieIndex + 1) + " 行:" + (dieIndex / dieCount + 1) + " 列:" + (dieIndex % dieCount + 1); dieRemarksCell.Value = rowColInfo; dieRemarksCell.Style.ForeColor = Color.Red; row.Cells.Add(dieRemarksCell); dgvInspectResultsInFov.Rows.Add(row); } else //检测成功,列出每个检测项 { for (int i = 0; i < fdr.DieInspectResults[dieIndex].Length; i++) { if (!_isShowAllItems && fdr.DieInspectResults[dieIndex][i].IsDetectOK()) { continue; } DataGridViewRow row = new DataGridViewRow(); Color txtColor = Color.DarkGreen; if (!DlafFovDetectResult.IsInspectItemsOK(fdr.DieInspectResults[dieIndex])) { txtColor = Color.DarkRed; } DataGridViewTextBoxCell dieIndexCell = new DataGridViewTextBoxCell(); dieIndexCell.Style.ForeColor = txtColor; dieIndexCell.Value = dieIndex + 1; row.Cells.Add(dieIndexCell); DataGridViewTextBoxCell detectItemCell = new DataGridViewTextBoxCell(); detectItemCell.Value = fdr.DieInspectResults[dieIndex][i].InspectID; detectItemCell.Style.ForeColor = fdr.DieInspectResults[dieIndex][i].IsDetectOK() ? Color.DarkGreen : Color.DarkRed; row.Cells.Add(detectItemCell); DataGridViewTextBoxCell dieErrorCell = new DataGridViewTextBoxCell(); dieErrorCell.Value = string.Join(" ", fdr.DieInspectResults[dieIndex][i].ErrorTexts); dieErrorCell.Style.ForeColor = fdr.DieInspectResults[dieIndex][i].IsDetectOK() ? Color.DarkGreen : Color.DarkRed; row.Cells.Add(dieErrorCell); DataGridViewTextBoxCell dieRefVelCell = new DataGridViewTextBoxCell(); dieRefVelCell.Value = fdr.DieInspectResults[dieIndex][i].QualifiedDescript; //dieRefVelCell.Style.ForeColor = fdr.DieInspectResults[dieIndex][i].IsDetectOK() ? Color.DarkGreen : Color.DarkRed; row.Cells.Add(dieRefVelCell); DataGridViewTextBoxCell dieDetectVelCell = new DataGridViewTextBoxCell(); dieDetectVelCell.Value = fdr.DieInspectResults[dieIndex][i].ResultDescript; row.Cells.Add(dieDetectVelCell); DataGridViewTextBoxCell dieRemarksCell = new DataGridViewTextBoxCell(); string rowColInfo = "Die:" + (dieIndex + 1) + " 行:" + (dieIndex / dieCount + 1) + " 列:" + (dieIndex % dieCount + 1); dieRemarksCell.Value = rowColInfo; row.Cells.Add(dieRemarksCell); dgvInspectResultsInFov.Rows.Add(row); } } } }
//显示图像/以及测试结果 void ShowFovImageResult() { if (null == _currRecipe) { return; } if (null == _currTaskImgs) { return; } int idxInRetList = (_currICRow * _currRecipe.ColCount + _currICCol) * _currRecipe.FovCount + _FovNameIndex(_currFov); if (null == _lstFovResults || idxInRetList >= _lstFovResults.Count) { //htDetectImg.RefreshWindow(_currTaskImgs[_currTask], null, "fit"); return; } DlafFovDetectResult fdr = _lstFovResults[idxInRetList]; #if false //老版本算子的显示 htDetectImg.ColorName = "green"; bool isShowImg = fdr.WireRegion != null; //fdr.DetectIterms != null && fdr.DetectIterms.ContainsKey("WireRegions"); if (isShowImg) { htDetectImg.RefreshWindow(_currTaskImgs[_currTask], fdr.WireRegion, "fit"); } htDetectImg.ColorName = "yellow"; HObject OKRegion = null; HOperatorSet.GenEmptyRegion(out OKRegion); if (fdr.DetectIterms != null) { foreach (KeyValuePair <string, HObject> kvRegion in fdr.DetectIterms) { if (kvRegion.Key == "WireRegions") { continue; } if (null != kvRegion.Value) { HOperatorSet.ConcatObj(OKRegion, kvRegion.Value, out OKRegion); } } if (!isShowImg) { htDetectImg.RefreshWindow(_currTaskImgs[_currTask], OKRegion, "fit"); isShowImg = true; } else { htDetectImg.DispRegion(OKRegion); } } //显示ErrorRegion htDetectImg.ColorName = "red"; HObject hoFailedRegion = null; HOperatorSet.GenEmptyRegion(out hoFailedRegion); if (null != fdr.DiesErrorRegions) { foreach (HObject[] hoRegs in fdr.DiesErrorRegions) { if (null != hoRegs) { foreach (HObject hoReg in hoRegs) { if (null != hoReg) { HOperatorSet.ConcatObj(hoFailedRegion, hoReg, out hoFailedRegion); } } } } } if (null != hoFailedRegion) { if (!isShowImg) { htDetectImg.RefreshWindow(_currTaskImgs[_currTask], hoFailedRegion, "fit"); } else { htDetectImg.DispRegion(hoFailedRegion); } } #endif bool _isShowAllItem = chkShowAllItems.Checked; htDetectImg.RefreshWindow(_currTaskImgs[_currTask], null, "fit"); if (!fdr.IsDetectSuccess || null == fdr.DieInspectResults) { return; } HObject errRegion = null;//所有错误区域 HOperatorSet.GenEmptyRegion(out errRegion); HObject bondRegion = null; HOperatorSet.GenEmptyRegion(out bondRegion); HObject wireRegion = null; HOperatorSet.GenEmptyRegion(out wireRegion); HObject epoxyRegion = null; HOperatorSet.GenEmptyRegion(out epoxyRegion); foreach (InspectResultItem[] dieItems in fdr.DieInspectResults) { foreach (InspectResultItem item in dieItems) { if (!item.IsDetectOK()) { HOperatorSet.ConcatObj(errRegion, item.ResultRegion, out errRegion); } if (!_isShowAllItem) { continue; } switch (item.InspectCategoty) { case InspectResultItem.Categoty.Frame: break; case InspectResultItem.Categoty.IC: break; case InspectResultItem.Categoty.Bond: HOperatorSet.ConcatObj(bondRegion, item.ResultRegion, out bondRegion); break; case InspectResultItem.Categoty.Wire: HOperatorSet.ConcatObj(wireRegion, item.ResultRegion, out wireRegion); break; case InspectResultItem.Categoty.Epoxy: HOperatorSet.ConcatObj(epoxyRegion, item.ResultRegion, out epoxyRegion); break; } } } if (_isShowAllItem) { htDetectImg.ColorName = "green"; htDetectImg.DispRegion(wireRegion); htDetectImg.ColorName = "yellow"; htDetectImg.DispRegion(bondRegion); htDetectImg.ColorName = "blue"; htDetectImg.DispRegion(epoxyRegion); } htDetectImg.ColorName = "red"; htDetectImg.DispRegion(errRegion); }
/// <summary> /// 更新Map控件 /// </summary> /// <param name="fdr"></param> void UpdateDetectMapping(DlafFovDetectResult fdr) { int colInMap = fdr.ICCol * _currRecipe.FovCount + _FovNameIndex(fdr.FovName); mapDetectCells.SetDieState(fdr.ICRow, colInMap, fdr.IsFovOK ? "合格" : "不合格"); }
public DlafFovDetectResult Clone() { DlafFovDetectResult ret = new DlafFovDetectResult(); ret.ICRow = ICRow; ret.ICCol = ICCol; ret.FovName = FovName; ret.DetectDiesRows = DetectDiesRows; ret.DetectDiesCols = DetectDiesCols; ret.DiesErrorCodes = DiesErrorCodes; ret.DiesErrorTaskNames = DiesErrorTaskNames; //非托管对象 if (null != DiesErrorRegions) { ret.DiesErrorRegions = new HObject[DiesErrorRegions.Length][]; for (int i = 0; i < DiesErrorRegions.Length; i++) { if (DiesErrorRegions[i] == null) { ret.DiesErrorRegions[i] = null; } else { ret.DiesErrorRegions[i] = new HObject[DiesErrorRegions[i].Length]; for (int j = 0; j < DiesErrorRegions[i].Length; j++) { ret.DiesErrorRegions[i][j] = DiesErrorRegions[i][j].CopyObj(1, -1);//Clone(); } } } } else { ret.DiesErrorRegions = DiesErrorRegions; } if (null != DetectIterms) { ret.DetectIterms = new Dictionary <string, HObject>(); foreach (string key in DetectIterms.Keys) { HObject val = DetectIterms[key]; if (null == val) { ret.DetectIterms.Add(key, null); } else { ret.DetectIterms.Add(key, val.Clone()); } } } else { ret.DetectIterms = null; } if (null != DetectDiesImages) { ret.DetectDiesImages = new HObject[DetectDiesImages.Length]; for (int i = 0; i < DetectDiesImages.Length; i++) { ret.DetectDiesImages[i] = DetectDiesImages[i].Clone(); } } else { ret.DetectDiesImages = null; } if (null != WireRegion) { ret.WireRegion = WireRegion.Clone(); } else { ret.WireRegion = null; } return(ret); }
protected override void RunLoopInWork() { NotifyCustomizeMsg(SCM_PieceStart, new object[] { _currPiecePicFolder }); //Inspect_Node inpect = JFDLAFInspectionManager.Instance.GetInspectNode int rows = _currRecipe.RowCount; int cols = _currRecipe.ColCount; string[] fovNames = _currRecipe.FovNames(); for (int currRow = 0; currRow < rows; currRow++) { for (int currCol = 0; currCol < cols; currCol++) { for (int currFov = 0; currFov < fovNames.Length; currFov++) { CheckCmd(CycleMilliseconds); //检测是否有暂停/恢复/退出 消息 string fovName = fovNames[currFov]; string fovSubFolder = "Row_" + currRow + "-" + "Col_" + currCol + "-Fov_" + fovName; string fovFolder = _currPiecePicFolder + "\\" + fovSubFolder;//存储图片的文件夹 if (!Directory.Exists(fovFolder)) { ExitWork(WorkExitCode.Error, "Fov图片文件夹:\"" + fovFolder + "\"不存在"); } InspectNode fovInspNode = JFDLAFInspectionManager.Instance.GetInspectNode(RecipeID, fovName); if (null == fovInspNode) { ExitWork(WorkExitCode.Error, "算子管理器中不存在 RecipeID = " + RecipeID + " Fov = " + fovName + " 的检测算子"); } string[] filesInFovFolder = Directory.GetFiles(fovFolder);//Fov文件夹中现有的文件 if (null == filesInFovFolder || filesInFovFolder.Length == 0) { ExitWork(WorkExitCode.Error, "Fov图片文件夹:\"" + fovFolder + "\"中没有文件"); } string[] taskNames = _currRecipe.TaskNames(fovName); List <HObject> taskImgs = new List <HObject>(); foreach (string taskName in taskNames) { HObject hoImg; HOperatorSet.GenEmptyObj(out hoImg); string taskImgFile = null; foreach (string s in filesInFovFolder) { string exn = Path.GetExtension(s); if (string.Compare(exn, ".bmp", true) != 0 && string.Compare(exn, ".tiff", true) != 0 && string.Compare(exn, ".tif", true) != 0 && string.Compare(exn, ".jpg", true) != 0 && string.Compare(exn, ".jpeg", true) != 0 && string.Compare(exn, ".png", true) != 0) { continue; //先过滤掉非图像文件 } string fnn = Path.GetFileNameWithoutExtension(s); //不带后缀的文件名 if (fnn.LastIndexOf(taskName) >= 0 && fnn.Length == (fnn.LastIndexOf(taskName) + taskName.Length)) { taskImgFile = s; break; } } if (null == taskImgFile) { ExitWork(WorkExitCode.Error, "Task = " + taskName + " 图片文件不存在"); } HOperatorSet.ReadImage(out hoImg, taskImgFile); taskImgs.Add(hoImg); } DlafFovDetectResult fdr = new DlafFovDetectResult(); fdr.FovName = fovName; fdr.ICRow = currRow; fdr.ICCol = currCol; fdr.TaskNames = taskNames; string errorInfo; //检测输入参数 HObject dieRegions; int[] dieRows, dieCols; int currDieRowCount, currDieColCount; if (!_visionFixer.GetDetectRegionInFov(currRow, currCol, out dieRegions, out dieRows, out dieCols, out currDieRowCount, out currDieColCount, out errorInfo)) { ExitWork(WorkExitCode.Error, "GetDetectRegionInFov failed,ErrorInfo:" + errorInfo); } fdr.DetectDiesRows = dieRows; fdr.DetectDiesCols = dieCols; fdr.CurrRowCount = currDieRowCount; fdr.CurrColCount = currDieColCount; //fdr.DieInspectResults = new List<InspectResultItem>[currDieRowCount* currDieColCount]; //for (int i = 0; i < currDieRowCount * currDieColCount; i++) // fdr.DieInspectResults[i] = new List<InspectResultItem>(); //检测输出参数 string detectErrorInfo; //算子执行信息 List <int[]> diesErrorCodes; //= new List<int[]>(); List <string[]> diesErrorTaskNames; List <HObject[]> diesFailedRegions; List <string[]> diesErrorDetails; //错误的详细描述信息 Dictionary <string, HObject> detectItems; //算子中输出的检测项(BondContours/WireRegions 等等) Dictionary <string, string> detectItemTaskNames; //bool isDetectOK = fovInspNode.InspectImage(taskImgs.ToArray(), taskNames, dieRegions, // out detectErrorInfo, out diesErrorCodes, out diesErrorTaskNames, out diesFailedRegions,out diesErrorDetails, // out detectItems,out detectItemTaskNames); //用于测试新数据结构 List <InspectResultItem[]> inspectResults = null; bool isDetectOK = fovInspNode.InspectImage(taskImgs.ToArray(), dieRegions, out detectErrorInfo, out inspectResults); fdr.DieInspectResults = inspectResults; //所有检测项 int dieCountInfov = dieRegions.CountObj(); //裁剪后的图象(按照Die的检测区域) HObject[] dieImgs = new HObject[dieCountInfov]; HTuple _row1, _col1, _row2, _col2; HTuple TWidth, THeight; for (int i = 0; i < dieCountInfov; i++) { HOperatorSet.SmallestRectangle1(dieRegions.SelectObj(i + 1), out _row1, out _col1, out _row2, out _col2); if (_row1 < 0) { _row1 = 0; } if (_col1 < 0) { _col1 = 0; } HOperatorSet.GetImageSize(taskImgs[0], out TWidth, out THeight); if (_row2 > THeight) { _row2 = THeight; } if (_col2 > TWidth) { _row2 = TWidth; } HObject hoImages = null; //一颗Die的多通道图 HOperatorSet.GenEmptyObj(out hoImages); for (int j = 0; j < taskImgs.Count; j++) { HObject ho; HOperatorSet.CropRectangle1(taskImgs[j], out ho, _row1, _col1, _row2, _col2); HOperatorSet.ConcatObj(hoImages, ho, out hoImages); } dieImgs[i] = hoImages; } fdr.DetectDiesImages = dieImgs; fdr.IsDetectSuccess = isDetectOK; fdr.DetectErrorInfo = detectErrorInfo; //if (null != diesErrorCodes) // fdr.DiesErrorCodes = diesErrorCodes.ToArray(); //else // fdr.DiesErrorCodes = null; //if (null != diesErrorTaskNames) // fdr.DiesErrorTaskNames = diesErrorTaskNames.ToArray(); //else // fdr.DiesErrorTaskNames = null; //if (null != diesFailedRegions) // fdr.DiesErrorRegions = diesFailedRegions.ToArray(); //else // fdr.DiesErrorRegions = null; //if (diesErrorDetails != null) // fdr.DiesErrorDetails = diesErrorDetails.ToArray(); //else // fdr.DiesErrorDetails = null; //fdr.DetectIterms = detectItems; //fdr.DetectItemTaskNames = detectItemTaskNames; //if (fdr.DetectIterms != null && fdr.DetectIterms.ContainsKey("WireRegions")) //{ // fdr.WireRegion = fdr.DetectIterms["WireRegions"]; // fdr.WireRegionTaskName = fdr.DetectItemTaskNames["WireRegions"]; // fdr.DetectIterms.Remove("WireRegions"); // fdr.DetectItemTaskNames.Remove("WireRegions"); //} NotifyCustomizeMsg(SCM_FovDetectResult, new object[] { taskImgs, //FOV原图 fdr //测试结果 }); } } } NotifyCustomizeMsg(SCM_PieceEnd, null); ExitWork(WorkExitCode.Normal, ""); }
/// <summary> /// 尝试将现有队列中的Fov结果合并为Die结果,并输出 /// (已经被计算合并过的FovResult将不再参与计算) /// </summary> /// <returns></returns> public InspectionData[] DisChargeDieResults() { if (null == _fovResults) { return(null); } List <InspectionData> ret = new List <InspectionData>(); bool isSmallDie = _recipe.DieRowInFov * _recipe.DieColInFov > 0; //一个Fov中是否含有多个Die if (isSmallDie) //小Die { for (int i = 0; i < _fovResults.Length; i++) { DlafFovDetectResult fovResult = _fovResults[i]; if (null == fovResult) //fov检测结果还没有输入 { continue; } if (_fovCounteds[i]) //fov检测结果已经被统计过 { continue; } for (int j = 0; j < fovResult.DetectDiesRows.Length; j++) { int dieRow = _recipe.DieRowInFov * fovResult.ICRow + fovResult.DetectDiesRows[j]; //料片中的die行列值 int dieCol = _recipe.DieColInFov * fovResult.ICCol + fovResult.DetectDiesCols[j]; InspectionData inspData = new InspectionData(); inspData.RecipeID = _recipeID; inspData.LotID = _lotID; inspData.FrameID = _pieceID; inspData.FovNames = _recipe.FovNames(); inspData.TaskNamesInFovs = new string[inspData.FovNames.Length][]; for (int h = 0; h < inspData.FovNames.Length; h++) { inspData.TaskNamesInFovs[h] = _recipe.TaskNames(inspData.FovNames[h]); } inspData.Code2D = null; inspData.ColumnIndex = dieCol; inspData.RowIndex = dieRow; if (null == fovResult.DetectDiesImages) //可能无图,(作为工站/界面交互数据) { inspData.Image = null; } else { inspData.Image = fovResult.DetectDiesImages[j].Clone(); } if (!fovResult.IsDetectSuccess) //图象检测失败 { inspData.InspectionResult = InspectionResults.NG; } else //图象检测成功 { //金线区域 inspData.Wire = null; if (null != fovResult.WireRegion) { HObject wireRegion = fovResult.WireRegion; //fovResult.DetectIterms["WireRegions"]; string wrieTaskName = fovResult.WireRegionTaskName; //fovResult.DetectItemTaskNames["WireRegions"]; int taskIdx = 0; for (int h = 0; h < inspData.TaskNamesInFovs[0].Length; h++) { if (inspData.TaskNamesInFovs[0][h] == wrieTaskName) { taskIdx = h; break; } } HObject emptyRegion; HOperatorSet.GenEmptyRegion(out emptyRegion); HObject hoConcatReg; if (taskIdx == 0) { hoConcatReg = wireRegion.Clone(); for (int h = 1; h < inspData.TaskNamesInFovs[0].Length; h++) { HOperatorSet.ConcatObj(hoConcatReg, emptyRegion, out hoConcatReg); } } else { HOperatorSet.GenEmptyRegion(out hoConcatReg); for (int h = 1; h < inspData.TaskNamesInFovs[0].Length; h++) { if (taskIdx == h) { HOperatorSet.ConcatObj(hoConcatReg, wireRegion.Clone(), out hoConcatReg); } else { HOperatorSet.ConcatObj(hoConcatReg, emptyRegion, out hoConcatReg); } } } inspData.Wire = hoConcatReg; } inspData.Region = null; //保存所有出错的Region , 一维长度和序号 if (fovResult.DiesErrorRegions != null && fovResult.DiesErrorRegions[j] != null && fovResult.DiesErrorRegions[j].Length > 0) { HObject ho = fovResult.DiesErrorRegions[j][0].Clone(); for (int h = 1; h < fovResult.DiesErrorRegions[j].Length; h++) { HOperatorSet.ConcatObj(ho, fovResult.DiesErrorRegions[j][h], out ho); } inspData.Region = ho; } int[] errorCodes = fovResult.DiesErrorCodes[j]; if (errorCodes.Length == 1 && errorCodes[0] == 0) //检测合格 { inspData.InspectionResult = InspectionResults.OK; inspData.List_DefectData = null; } else { inspData.InspectionResult = InspectionResults.NG; inspData.List_DefectData = new List <DefectData>(); for (int h = 0; h < fovResult.DiesErrorCodes.Length; h++) { DefectData dd = new DefectData(); dd.DefectTypeIndex = errorCodes[h]; dd.ErrorDetail = fovResult.DiesErrorDetails[j][h]; dd.ImageIndex = _ImgIndex(fovResult.FovName, fovResult.DiesErrorTaskNames[j][h]); inspData.List_DefectData.Add(dd); } } inspData.SuccessRegion = null; //所有检测成功区域 inspData.SuccessRegionTypes = null; inspData.SuccessRegionImageIndex = null; if (null != fovResult.DetectIterms && fovResult.DetectIterms.Count > 0) //存在除了金线之外的其他检测项 { List <HObject> itemRegs = new List <HObject>(); List <string> itemTyps = new List <string>(); List <int> itemImgIdx = new List <int>(); foreach (string itemName in fovResult.DetectIterms.Keys) { itemRegs.Add(fovResult.DetectIterms[itemName]); itemTyps.Add(itemName); string tskName = fovResult.DetectItemTaskNames[itemName]; for (int k = 0; k < fovResult.TaskNames[0].Length; k++) { if (tskName == fovResult.TaskNames[k]) { itemImgIdx.Add(k); break; } } } if (itemRegs.Count() == 1) { inspData.SuccessRegion = itemRegs[0]; } else { HObject hoReg = itemRegs[0].Clone(); for (int h = 1; h < itemRegs.Count(); h++) { HOperatorSet.ConcatObj(hoReg, itemRegs[h], out hoReg); } inspData.SuccessRegion = hoReg; } inspData.SuccessRegionTypes = itemTyps.ToArray(); inspData.SuccessRegionImageIndex = itemImgIdx.ToArray(); } if (null == inspData.List_DefectData) { inspData.List_DefectData = new List <DefectData>(); } ret.Add(inspData); } _fovCounteds[i] = true; } } } else //大Die,一颗Die包含多个Fov { int fovCountInDie = _recipe.FovCount; for (int i = 0; i < _fovResults.Length; i += fovCountInDie) { bool isFovsCan2Die = true; //多个Fov是否能集成为一个Die for (int j = 0; j < fovCountInDie; j++) { if (null == _fovResults[i + j] || _fovCounteds[i]) { isFovsCan2Die = false; break; } } if (!isFovsCan2Die) { continue; } InspectionData inspData = new InspectionData(); inspData.RecipeID = _recipeID; inspData.LotID = _lotID; inspData.FrameID = _pieceID; inspData.FovNames = _recipe.FovNames(); inspData.TaskNamesInFovs = new string[inspData.FovNames.Length][]; for (int h = 0; h < inspData.FovNames.Length; h++) { inspData.TaskNamesInFovs[h] = _recipe.TaskNames(inspData.FovNames[h]); } inspData.Code2D = null; inspData.ColumnIndex = _fovResults[i].ICCol; inspData.RowIndex = _fovResults[i].ICRow; HObject hoImg = null; ////将Die所属的所有多通道的图平铺成一维数组 HObject hoWire = null; HObject hoErrorRegions = null; bool isDieOK = true; //整颗die的检测结果是否OK List <DefectData> lstDefectData = new List <DefectData>(); HObject hoSuccessRegion = null; List <string> lstSuccessRegionTypes = new List <string>(); List <int> lstSuccessImgIndex = new List <int>(); for (int j = i; j < i + fovCountInDie; j++) //将多个Fov合为一个Die { DlafFovDetectResult fovRet = _fovResults[j]; HObject hoTaskImgs = fovRet.DetectDiesImages[0]; //每个Fov中只有一个Die(的一部分) if (null == hoImg) //第一个 { hoImg = hoTaskImgs.Clone(); } else { for (int k = 0; k < hoTaskImgs.CountObj(); k++) { HOperatorSet.ConcatObj(hoImg, hoTaskImgs.CopyObj(k + 1, 1), out hoImg); } } HObject hoRegion = fovRet.WireRegion;//将所有Fov中的WireRegion平铺成一维数组 if (null == hoRegion) { HOperatorSet.GenEmptyRegion(out hoRegion); } if (null == hoWire) { hoWire = hoRegion.Clone(); for (int k = 1; k < fovRet.TaskNames.Length; k++) { HOperatorSet.ConcatObj(hoWire, hoRegion.Clone(), out hoWire); } } else { for (int k = 0; k < fovRet.TaskNames.Length; k++) { HOperatorSet.ConcatObj(hoWire, hoRegion.Clone(), out hoWire); } } if (!fovRet.IsDetectSuccess)//视觉检测失败 { } else { ///错误区域 if (fovRet.DiesErrorCodes[0].Length != 1 || fovRet.DiesErrorCodes[0][0] == 0) { isDieOK = false; DefectData df = new DefectData(); df.DefectTypeIndex = fovRet.DiesErrorCodes[0][0]; df.ErrorDetail = fovRet.DiesErrorDetails[0][0]; df.ImageIndex = _ImgIndex(fovRet.FovName, fovRet.DiesErrorTaskNames[0][0]); lstDefectData.Add(df); if (null == hoErrorRegions) { hoErrorRegions = fovRet.DiesErrorRegions[0][0].Clone(); } else { HOperatorSet.ConcatObj(hoErrorRegions, fovRet.DiesErrorRegions[0][0], out hoErrorRegions); } for (int k = 1; k < fovRet.DiesErrorCodes[0].Length; k++) { df = new DefectData(); df.DefectTypeIndex = fovRet.DiesErrorCodes[0][k]; df.ErrorDetail = fovRet.DiesErrorDetails[0][k]; df.ImageIndex = _ImgIndex(fovRet.FovName, fovRet.DiesErrorTaskNames[0][k]); lstDefectData.Add(df); HOperatorSet.ConcatObj(hoErrorRegions, fovRet.DiesErrorRegions[0][k], out hoErrorRegions); } } /*public HObject*/ if (fovRet.DetectIterms != null && fovRet.DetectIterms.Count > 0) { foreach (KeyValuePair <string, HObject> kv in fovRet.DetectIterms) { if (null == hoSuccessRegion) { hoSuccessRegion = kv.Value.Clone(); } else { HOperatorSet.ConcatObj(hoSuccessRegion, kv.Value, out hoSuccessRegion); } lstSuccessRegionTypes.Add(kv.Key); lstSuccessImgIndex.Add(_ImgIndex(fovRet.FovName, kv.Key)); } } } _fovCounteds[j] = true; } inspData.Image = hoImg; inspData.Wire = hoWire; inspData.Region = hoErrorRegions; if (isDieOK) { inspData.InspectionResult = InspectionResults.OK; inspData.List_DefectData = null; } else { inspData.InspectionResult = InspectionResults.NG; inspData.List_DefectData = lstDefectData; } if (null != hoSuccessRegion) { inspData.SuccessRegion = hoSuccessRegion; //所有检测成功区域 inspData.SuccessRegionTypes = lstSuccessRegionTypes.ToArray(); inspData.SuccessRegionImageIndex = lstSuccessImgIndex.ToArray(); } if (null == inspData.List_DefectData) { inspData.List_DefectData = new List <DefectData>(); } ret.Add(inspData); } } if (ret.Count() == 0) { return(null); } return(ret.ToArray()); }