public VideoObjectsRecognition(Image <Bgr, Byte> observedSrcImg) { viewer = new ImageViewer(); viewer.StartPosition = System.Windows.Forms.FormStartPosition.Manual; viewer.Location = new Point(860, 200); SetUpSignBoardSURFFeatureData(); observedImg = observedSrcImg.Copy(); obervedSurfData = null; //要有深度過濾才行使用此code //Image<Bgr, Byte> dst = SkinFilter(observedImg); //objectImg = GetObjectBoundingBoxImg(dst); //取得專案執行檔所在的目錄=>WPF:AppDomain.CurrentDomain.BaseDirectory //使用DirectoryInfo移動至上層 dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); string projectPath = dir.Parent.Parent.Parent.FullName; LoadHistogramDataFiles(projectPath); LoadSurfDataFiles(projectPath); surfDatas = new Dictionary <string, SURFFeatureData>(); histDatas = new Dictionary <string, DenseHistogram>(); voice = new SpVoice(); voice.Voice = voice.GetVoices(string.Empty, string.Empty).Item(0);//Item(0)中文女聲 }
////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// 讀取特徵類別檔案 /// </summary> /// <param name="fileName">'檔案路徑'名稱</param> /// <returns></returns> public static SURFFeatureData ReadSURFFeature(string fileName) { SURFFeatureData templateSURF = FeatureDataFilesOperation.ReadSURFFeatureDataFromBinaryXml(fileName); Console.WriteLine("\n@@@ Read SURF Data........"); return(templateSURF); }
public SURFFeatureData ReadSURFFeature(string fileName) { matchingModelSurfData = ReadSURFFeatureDataFromBinaryXml(fileName); Console.WriteLine("Read Descriptor Data........\n"); // ConsoleOutputMethod.ShowDescriptorDataOnConsole(descriptor); return(matchingModelSurfData); }
/// <summary> /// 比配特徵,對所有檔案匹配並找出最好的匹配檔 /// </summary> /// <param name="surfFiles">載入所有可能作為匹配的特徵資料</param> /// <param name="observedImg">要比對觀察的影像</param> /// <param name="viewer">顯示出匹配結果的物件</param> /// <returns>回傳匹配到的相關資訊類別,String是檔案名稱,如果未匹配到,則Key與Values皆會回傳null,因此要先做檢查</returns> public static SURFMatchedData MatchSURFFeatureForVideoObjs(SURFFeatureData templateSURFData, SURFFeatureData obervedSurfData, ImageViewer viewer) { SURFMatchedData matchedData; //縮放到一樣大小 (系統修改成可讀圖片時才能加入) //observedImg = observedImg.Resize(3, INTER.CV_INTER_LINEAR); //Console.WriteLine("### One-by-One Mathed Start.....\n============================"); if (obervedSurfData.GetDescriptors() != null) { matchedData = SURFMatch.MatchSURFFeatureByFLANNForObjs(templateSURFData, obervedSurfData); if (matchedData != null) { if (viewer != null) { SURFMatch.ShowSURFMatchForm(matchedData, obervedSurfData, viewer); } return(matchedData); } else { return(null); } } else { return(null); } }
private void SaveSURFFeatureFile(SURFFeatureData surf) { string saveSURFDataPath = dir.Parent.Parent.Parent.FullName + @"\SignBoardSURFFeatureData"; if (File.Exists(saveSURFDataPath)) { MessageBox.Show("路徑錯誤"); } // Displays a SaveFileDialog so the user can save the Image // assigned to Button2. SaveFileDialog dlg = new SaveFileDialog(); dlg.Filter = "XML Files (*.xml)|*.xml"; dlg.Title = "Save Descriptor to File"; dlg.RestoreDirectory = true; dlg.InitialDirectory = saveSURFDataPath; // If the file name is not an empty string open it for saving. if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK == true && dlg.FileName != "" && learningSys != null) { bool isOk = learningSys.SaveSURFFeatureData(dlg.FileName, surf); if (isOk) { MessageBox.Show("Save SURF Feature Data Ok"); } else { MessageBox.Show("Save SURF Feature Data Faild"); } } }
/// <summary> /// 設置要作為辨識的輸入影像 /// </summary> /// <param name="observedSrcImg">要比對觀察的影響</param> public void SetupInputImage(Image <Bgr, Byte> observedSrcImg) { observedImg = observedSrcImg.Copy(); obervedSurfData = null; //要有深度過濾才行使用此code //Image<Bgr, Byte> dst = SkinFilter(observedImg); // objectImg = GetObjectBoundingBoxImg(dst); }
/// <summary> /// 畫上特徵點到圖上 /// </summary> /// <param name="surf">SURF特徵類別</param> /// <returns>回傳畫好特徵點的影像</returns> public static Image <Bgr, byte> DrawSURFFeature(SURFFeatureData surf) { VectorOfKeyPoint keyPoints = surf.GetKeyPoints(); //繪製特徵 Image <Bgr, byte> result = Features2DToolbox.DrawKeypoints(surf.GetImg(), surf.GetKeyPoints(), new Bgr(255, 255, 255), Features2DToolbox.KeypointDrawType.DEFAULT); return(result); }
private void extractFeatureButton_Click(object sender, EventArgs e) { trainingExtractSurfData = SURFMatch.CalSURFFeature(extractFeatureImage, new MCvSURFParams(500, false)); //繪製特徵 Image <Bgr, byte> result = Features2DToolbox.DrawKeypoints(trainingExtractSurfData.GetImg(), trainingExtractSurfData.GetKeyPoints(), new Bgr(255, 255, 255), Features2DToolbox.KeypointDrawType.DEFAULT); //顯示 ImageViewer viewer = new ImageViewer(result, "Extracted Feature"); viewer.Show(); }
private void extractFeatureButton_Click(object sender, EventArgs e) { if (learningSys != null) { surfData = learningSys.CalSURFFeature(); Image <Bgr, byte> drawKeyPointImg = SystemToolBox.DrawSURFFeature(surfData); new ImageViewer(SystemToolBox.DrawSURFFeatureToWPF(surfData, surfData.GetImg())).Show(); extractFeatureImgBox.Image = drawKeyPointImg.Resize(320, 240, INTER.CV_INTER_LINEAR); } }
private void getMappingFeatureButton_Click(object sender, RoutedEventArgs e) { if (templateHistFilePathName != null) { string templateHistFileName = System.IO.Path.GetFileName(templateHistFilePathName); //取得路徑的檔案名稱 templateSURFPathFileName = SystemToolBox.GetMappingDescriptorDataFile(templateHistFileName, dir); if (templateSURFPathFileName != null) { templateSurfFeature = MatchRecognition.ReadSURFFeature(templateSURFPathFileName); Image <Bgr, byte> showFeatureImg = SystemToolBox.DrawSURFFeature(templateSurfFeature); new ImageViewer(showFeatureImg, "取得樣板特徵圖像").Show(); } } }
/// <summary> /// 繪製特徵點到圖像上 /// </summary> /// <param name="surf">特徵資料</param> /// <param name="drawImg">要繪製的圖像</param> /// <returns>回傳已繪製特徵點的圖像</returns> public static Image <Bgr, Byte> DrawSURFFeature(SURFFeatureData surf, Image <Bgr, Byte> drawImg) { VectorOfKeyPoint keyPoints = surf.GetKeyPoints(); Bitmap imgForDraw = drawImg.ToBitmap(); //使用Graphics繪製 using (Graphics g = Graphics.FromImage(imgForDraw)) { for (int i = 0; i < keyPoints.Size; i++) { g.DrawEllipse(new Pen(new SolidBrush(Color.White), 2), (int)keyPoints[i].Point.X, (int)keyPoints[i].Point.Y, 15, 15); } g.Dispose(); } return(new Image <Bgr, Byte>(imgForDraw).Resize(320, 240, INTER.CV_INTER_LINEAR)); }
private void extractFeatureButton_Click(object sender, EventArgs e) { if (wantExtractFeatureImage != null) { if (learningSys != null) { learningSys.SetLearningImage(wantExtractFeatureImage); } else { learningSys = new FeatureLearning(wantExtractFeatureImage); } surfData = learningSys.CalSURFFeature(); //Draw Feature Image <Bgr, byte> drawKeyPointImg = SystemToolBox.DrawSURFFeature(surfData); new ImageViewer(drawKeyPointImg, "擷取特徵點結果").Show(); } }
/// <summary> /// 寫成二位元檔案 /// </summary> /// <param name="surf">SURF特徵類別</param> /// <param name="TextFileName">檔案的路徑名稱</param> public static void WriteSURFFeatureDataToBinaryXml(SURFFeatureData surf, string TextFileName) { Stream stream; System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter; //寫檔 try { // serialize histogram stream = File.Open(TextFileName, FileMode.Create); bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); bformatter.Serialize(stream, surf); stream.Close(); } catch (IOException ex) { throw new InvalidOperationException(ex.Message); } }
////////////////////////////////////////////////////////////////////////////////////////////// #endregion #region 商家看板辨識 ////////////////////////////////////////////////////////////////////////////////////////////// public static SURFMatchedData MatchSURFFeature(SURFFeatureData template, Image <Bgr, Byte> observedImg, bool isShowResult) { //縮放到一樣大小 (系統修改成可讀圖片時才能加入) //observedImg = observedImg.Resize(3, INTER.CV_INTER_LINEAR); SURFFeatureData observed = SURFMatch.CalSURFFeature(observedImg); if (observed.GetDescriptors() != null) { SURFMatchedData matchedData = SURFMatch.MatchSURFFeatureByFLANNForObjs(template, observed); if (matchedData != null && isShowResult) { SURFMatch.ShowSURFMatchForm(matchedData, observed, new ImageViewer()); } return(matchedData); } else { return(null); } }
/// <summary> /// 儲存特徵點 /// </summary> /// <param name="fileName">檔案路徑名稱</param> /// <param name="surf">特徵資料</param> /// <returns>回傳是否儲存成功</returns> public bool SaveSURFFeatureData(string fileName, SURFFeatureData surf) { if (surf.GetDescriptors() != null) { string format = Path.GetExtension(fileName); if (format == ".xml") { FeatureDataFilesOperation.WriteSURFFeatureDataToBinaryXml(surf, fileName); //Console Output觀看數值 Console.WriteLine("Save SURF Feature Data........\n"); Console.WriteLine("\n"); return(true); } else { Console.WriteLine("Only support xml file........\n"); } Console.WriteLine("\n"); return(false); } return(false); }
private void MatchImage(object obj) { Image <Bgr, byte> senceImg = (Image <Bgr, byte>)obj; SURFFeatureData modelSurfData = ReadSURFFeature(dir.Parent.Parent.FullName + "\\SurfFeatureData\\000-0.xml"); if (modelSurfData != null) { long matchTime; int pairCount; SURFFeatureData senceSurfData = SURFMatch.CalSURFFeature(senceImage); Image <Bgr, byte> result = SURFMatch.MatchSURFFeatureByBF(modelSurfData, senceSurfData, out matchTime, out pairCount); Console.WriteLine("match time = " + matchTime.ToString() + "ms ,PairCount = " + pairCount.ToString()); if (result != null) { DelegateViewer del_MatchViewer = new DelegateViewer(UpdateSURFMatchViewer); this.Invoke(del_MatchViewer, result); // matchViewer.Image = result; //matchViewer.Show(); //跨執行緒UI存取,使用委派處理... } } }
////////////////////////////////////////////////////////////////////////////////////////////// #endregion #region 匹配特徵點 #region 物品辨識 ////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// 比配特徵,對所有檔案匹配並找出最好的匹配檔 /// </summary> /// <param name="surfFiles">載入所有可能作為匹配的特徵資料</param> /// <param name="observedImg">要比對觀察的影像</param> /// <param name="isShowResult">是否要顯示出匹配結果</param> /// <returns>回傳匹配到的相關資訊類別,String是檔案名稱,如果未匹配到,則Key與Values皆會回傳null,因此要先做檢查</returns> public static KeyValuePair <string, SURFMatchedData> MatchSURFFeatureForGoods(List <string> surfFiles, Image <Bgr, Byte> observedImg, bool isShowResult) { Dictionary <string, SURFMatchedData> matchList = new Dictionary <string, SURFMatchedData>(); SURFFeatureData templateSURFData; SURFMatchedData matchedData; //縮放到一樣大小 (系統修改成可讀圖片時才能加入) //observedImg = observedImg.Resize(3, INTER.CV_INTER_LINEAR); //1.依序比對 SURFFeatureData observed = SURFMatch.CalSURFFeature(observedImg); Console.WriteLine("### One-by-One Mathed Start.....\n============================"); foreach (string fileName in surfFiles) { templateSURFData = MatchRecognition.ReadSURFFeature(fileName); Console.WriteLine("SurfData: fileName =>" + Path.GetFileName(fileName)); matchedData = SURFMatch.MatchSURFFeatureByBruteForceForGoods(templateSURFData, observed); //如果Homography !=null 表示有匹配到(條件容忍與允許) if (matchedData.GetHomography() != null) { matchList.Add(Path.GetFileName(fileName), matchedData); } Console.WriteLine("match num:" + matchedData.GetMatchedCount().ToString() + "\n-----------------"); } //2.再找出count最大的 int bestMatched = -1; string bestTemplateId = null; //樣板檔案名稱(Id) if (matchList.Count != 0) { foreach (KeyValuePair <string, SURFMatchedData> matchedSURFData in matchList) { if (bestMatched == -1 && bestTemplateId == null) { bestMatched = matchedSURFData.Value.GetMatchedCount(); bestTemplateId = matchedSURFData.Key; } else { //開始找出最多匹配點的檔案名稱與匹配資訊 if (bestMatched < matchedSURFData.Value.GetMatchedCount()) { bestMatched = matchedSURFData.Value.GetMatchedCount(); bestTemplateId = matchedSURFData.Key; } } } Console.WriteLine("\n**** Matched fileName=" + bestTemplateId + ", match num:" + bestMatched.ToString() + " ****"); if (isShowResult) { SURFMatch.ShowSURFMatchForm(matchList[bestTemplateId], observed, new ImageViewer()); } Console.WriteLine("============================\n### Matched Finish.......\n"); //回傳匹配到的類別 return(new KeyValuePair <string, SURFMatchedData>(bestTemplateId, matchList[bestTemplateId])); } else { Console.WriteLine("\n**** No Matched fileName !"); Console.WriteLine("============================\n### Matched Finish.......\n"); return(new KeyValuePair <string, SURFMatchedData>(null, null)); } }
//////////////////////////////////////////////////////////////////////////// #endregion /// <summary> /// 執行辨識 /// </summary> /// <param name="isDrawResultToShowOnDialog">是否要顯示出辨識的結果</param> /// <returns>回傳看板資訊, 格式=>"看板名稱" ;請記得做字串切割,若無比對到或有任何問題則會回傳null</returns> public void RunRecognition(bool isDrawResultToShowOnDialog) { SURFMatchedData mathedObjectsData = null; string matchedFileName = null; Image <Bgr, byte> observedContourRectImg = null; if (surfFiles.Count != 0 && histFiles.Count != 0) { Stopwatch watch = Stopwatch.StartNew(); ////偵測物體 foreach (string histFilePath in histFiles) { //1.取出直方圖資料 DenseHistogram hist; string histFilename = System.IO.Path.GetFileName(histFilePath); if (!histDatas.ContainsKey(histFilename)) { hist = DetectObjects.ReadHistogram(histFilePath, false); histDatas.Add(histFilename, hist); } else { hist = histDatas[histFilename]; } //2.取出SURF資料 string templateHistFileName = System.IO.Path.GetFileName(histFilePath); //取得路徑的檔案名稱 string templateSURFPathFileName = SystemToolBox.GetMappingDescriptorDataFile(templateHistFileName, dir); SURFFeatureData templateSurf; string surfFilename = System.IO.Path.GetFileName(templateSURFPathFileName); if (!surfDatas.ContainsKey(surfFilename)) { templateSurf = MatchRecognition.ReadSURFFeature(templateSURFPathFileName); surfDatas.Add(surfFilename, templateSurf); } else { templateSurf = surfDatas[surfFilename]; } //3.做偵測 using (Image <Gray, byte> backProjectImg = DetectObjects.DoBackProject(hist, observedImg)) using (Image <Gray, byte> binaryImg = DetectObjects.DoBinaryThreshold(backProjectImg, 200)) { Image <Gray, byte> morphologyImg = DetectObjects.DoErode(binaryImg, 2); morphologyImg = DetectObjects.DoDilate(morphologyImg, 1); List <Contour <System.Drawing.Point> > topContours = DetectObjects.GetOrderMaxContours(morphologyImg); //new ImageViewer(DetectObjects.DrawContoursTopThreeBoundingBoxOnImg(topContours, observedImg.Copy())).Show(); int i = 0; double histMatchRate = 1; int matchIndex = -1; foreach (Contour <System.Drawing.Point> c in topContours) { if (i == 3) { break; } //判斷待偵測的輪廓面積是否過小,如果太小就省略 if (c.Area >= (templateSurf.GetImg().Width *templateSurf.GetImg().Height) * 0.4) { DenseHistogram observedRectHist; observedContourRectImg = DetectObjects.GetBoundingBoxImage(c, observedImg.Copy()); double compareRate = DetectObjects.CompareHistogram(hist, observedContourRectImg, out observedRectHist); if (compareRate < histMatchRate) { histMatchRate = compareRate; matchIndex = i; } observedRectHist.Dispose(); } i++; } if (histMatchRate < 0.5) { //影像正規化(如果觀察影像過大的話) // if (observedContourRectImg != null && observedContourRectImg.Height * observedContourRectImg.Width > templateSurf.GetImg().Width * templateSurf.GetImg().Height) //observedContourRectImg = observedContourRectImg.Resize(templateSurf.GetImg().Width, templateSurf.GetImg().Height, INTER.CV_INTER_LINEAR); //取出特徵 if (obervedSurfData == null && observedContourRectImg != null) { obervedSurfData = SURFMatch.CalSURFFeature(observedContourRectImg); observedContourRectImg.Dispose(); } //匹配特徵並取回匹配到的特徵 SURFMatchedData mathedCandidateData = MatchRecognition.MatchSURFFeatureForVideoObjs(templateSurf, obervedSurfData, null); //招出最好的特徵 if (mathedCandidateData != null && mathedCandidateData.GetHomography() != null) { if (mathedObjectsData == null) { mathedObjectsData = mathedCandidateData; matchedFileName = templateSURFPathFileName; } else if (mathedCandidateData.GetMatchedCount() > mathedObjectsData.GetMatchedCount() && mathedCandidateData.GetHomography() != null) { mathedObjectsData = mathedCandidateData; matchedFileName = templateSURFPathFileName; } } } morphologyImg.Dispose(); topContours.Clear(); if (mathedObjectsData != null && obervedSurfData != null) { SURFMatch.ShowSURFMatchForm(mathedObjectsData, obervedSurfData, viewer); } } } watch.Stop(); Console.WriteLine("File = " + System.IO.Path.GetFileName(matchedFileName) + " Video Analytics time = " + watch.ElapsedMilliseconds); //if (matchedFileName != null) //{ // string[] split = System.IO.Path.GetFileName(matchedFileName).Split('b'); // //voice.Speak("前方有" + split[0], SpeechVoiceSpeakFlags.SVSFlagsAsync); //} } }