/// <summary> /// Select the image /// </summary> private void mnuNewFromImage_Click(object sender, EventArgs e) { try { if (this.m_isDirty && MessageBox.Show("Discard unsaved changes?", "Confirm New", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No) { this.mnuSave_Click(sender, e); } // Open the image var dlgOpen = new OpenFileDialog() { Title = "New From Image", Filter = "All Images (*.jpg;*.jpeg;*.bmp;*.png)|*.jpg;*.jpeg;*.bmp;*.png|JPEG Images (*.jpg;*.jpeg)|*.jpg;*.jpeg|Bitmaps (*.bmp)|*.bmp|PNG Images (*.png)|*.png" }; // Open if (dlgOpen.ShowDialog() == System.Windows.Forms.DialogResult.OK) { //skHost1.Canvas.Clear(); this.lsvImages.Clear(); this.m_currentTemplate = OmrTemplate.FromFile(dlgOpen.FileName); this.UpdateTemplateDiagram(); this.testToolStripMenuItem.Enabled = true; this.SelectRootImageProperties(); } } catch (Exception ex) { MessageBox.Show("Can not create template: " + ex.Message); } }
public static void Run() { // ExStart:SetElementLevelThreshold // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); // Load the image to be analyzed OmrImage image = OmrImage.Load(dataDir + "answers.jpg"); // Get the first page of the template OmrPage page = template.Pages[0]; // Create an element by passing the name, location and size GridElement element = new GridElement("grid1", new PointF(10, 20), new SizeF(60, 30)); // Add element to the page page.Elements.Add(element); // Create configuration for the element element.Configuration = new OmrConfig(); // Set the TrimWhitePixels to false element.Configuration.TrimWhitePixels = false; // Create an instance of OmrEngine and pass object of OmrTemplate as parameter OmrEngine engine = new OmrEngine(template); // Extract the data OmrProcessingResult result = engine.ExtractData(new OmrImage[] { image }); // ExEnd:SetElementLevelThreshold }
public static void Run() { // ExStart:LoadTemplateFromUrl string templateUrl = "https://Github.com/asposeocr/Aspose_OCR_NET/raw/master/Examples/Data/OCR/questions.amr"; string imageUrl = "https://Github.com/asposeocr/Aspose_OCR_NET/raw/master/Examples/Data/OCR/answers.jpg"; // Initialize an instance of OmrTemplate by loading the OMR template from URL OmrTemplate template = OmrTemplate.LoadFromUrl(templateUrl); // image loading from url OmrImage image = OmrImage.LoadFromUrl(imageUrl); // continue working with template and image as usual OmrEngine engine = new OmrEngine(template); OmrProcessingResult result = engine.ExtractData(new OmrImage[] { image }); // Get all page data into an instance of Hashtable Hashtable[] pages = result.PageData; // Loop over all the pages foreach (Hashtable page in pages) { // Display key and value foreach (string key in page.Keys) { Console.WriteLine("[KEY] " + key + " => " + "[VALUE] " + page[key]); } } // ExEnd:LoadTemplateFromUrl }
/// <summary> /// Converts template view model to template model /// </summary> /// <param name="templateViewModel">TemplateViewModel to convert</param> /// <param name="saveImage">Flag to save image data</param> /// <returns>Resulting template</returns> public static OmrTemplate ConvertViewModelToModel(TemplateViewModel templateViewModel, bool saveImage) { OmrTemplate template = new OmrTemplate(); template.TemplateId = templateViewModel.TemplateId; template.FinalizationComplete = templateViewModel.FinalizationComplete; OmrPage page = template.AddPage(); page.Height = templateViewModel.PageHeight; page.Width = templateViewModel.PageWidth; page.ImageName = templateViewModel.TemplateImageName; page.ImageFormat = templateViewModel.ImageFileFormat; if (saveImage) { page.ImageData = CheckAndCompressImage(templateViewModel.TemplateImage, templateViewModel.ImageFileFormat, templateViewModel.ImageSizeInBytes); } foreach (BaseQuestionViewModel element in templateViewModel.PageQuestions) { if (element is ChoiceBoxViewModel) { AddChoiceBoxElement(page, (ChoiceBoxViewModel)element); } else if (element is GridViewModel) { AddGridElement(page, (GridViewModel)element); } } return(template); }
public static void Run() { // ExStart:SettingMarkThreshold // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); // Load the image to be analyzed OmrImage image = OmrImage.Load(dataDir + "answers.jpg"); // Create an instance of OmrEngine and pass object of OmrTemplate as parameter OmrEngine engine = new OmrEngine(template); // Get the configurations of OmrEngine OmrConfig config = engine.Configuration; // Set fill threshold config.FillThreshold = 0.12; // Extract the data OmrProcessingResult result = engine.ExtractData(new OmrImage[] { image }); // ExEnd:SettingMarkThreshold }
public static void Run() { // ExStart:DetectImageResolutionAutomatically // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); // Load the image to be analyzed OmrImage image = OmrImage.Load(dataDir + "answers.jpg"); //Set the auto image resolution detection property image.AutoDetectResolution = true; // Instantiate the recognition engine for the template OmrEngine engine = new OmrEngine(template); // Extract data. This template has only one page. OmrProcessingResult result = engine.ExtractData(new OmrImage[] { image }); // Load actual result from Hashtable OmrResult = result.PageData[0]; // Get Collection of Keys ICollection key = OmrResult.Keys; foreach (string k in key) { Console.WriteLine(k + ": " + OmrResult[k]); } // ExEnd:DetectImageResolutionAutomatically }
public static void Run() { // ExStart:SkewImageCorrectionUsingAlgorithm // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); // Load the image to be analyzed OmrImage image = OmrImage.Load(dataDir + "answers.jpg"); // Area of the image to be processed Rectangle area = new Rectangle(0, 0, image.Width, image.Height); // Grayscale conversion GrayscaleAlgorithm gs = new GrayscaleAlgorithm(); gs.Process(image, area); // Binarization AverageThresholdAlgorithm threshold = new AverageThresholdAlgorithm(); threshold.Process(image, area); // Skew correction SkewCorrectionAlgorithm skewCorrection = new SkewCorrectionAlgorithm(); skewCorrection.Process(ref image, area); // save image image.AsBitmap().Save(dataDir + "result_out.jpg"); // ExEnd:SkewImageCorrectionUsingAlgorithm }
/// <summary> /// Transform /// </summary> public byte[] Transform(OmrTemplate template, OmrPageOutputCollection pages) { using (var ms = new MemoryStream()) { new XmlSerializer(typeof(OmrPageOutputCollection)).Serialize(ms, pages); ms.Flush(); return(ms.ToArray()); } }
/// <summary> /// Converts template data model to template view model /// </summary> /// <param name="template">OmrTemplate to convert</param> /// <returns>Resulting TemplateViewModel</returns> public static TemplateViewModel ConvertModelToViewModel(OmrTemplate template) { TemplateViewModel templateViewModel = new TemplateViewModel("Loaded template"); templateViewModel.TemplateId = template.TemplateId; templateViewModel.FinalizationComplete = template.FinalizationComplete; OmrPage page = template.Pages[0]; templateViewModel.TemplateImageName = page.ImageName; templateViewModel.ImageFileFormat = page.ImageFormat; List <BaseQuestionViewModel> elements = new List <BaseQuestionViewModel>(); foreach (OmrElement modelElement in page.Elements) { if (modelElement is ChoiceBoxElement) { var choiceBoxViewModel = CreateChoiceBoxViewModel((ChoiceBoxElement)modelElement); elements.Add(choiceBoxViewModel); } else if (modelElement is GridElement) { var gridViewModel = CreateGridViewModel((GridElement)modelElement); elements.Add(gridViewModel); } } templateViewModel.AddQuestions(elements); if (page.ImageData != null) { // loading from file double monitorWidth, monitorHeight; ResolutionUtility.GetMonitorResolution(out monitorWidth, out monitorHeight); var image = TemplateSerializer.DecompressImage(page.ImageData); templateViewModel.TemplateImage = image; templateViewModel.PageWidth = page.Width; templateViewModel.PageHeight = page.Height; TemplateViewModel.ZoomKoefficient = image.PixelWidth / page.Width < 1 ? image.PixelWidth / page.Width : 1; } else { // processing server response templateViewModel.PageWidth = page.Width; templateViewModel.PageHeight = page.Height; } return(templateViewModel); }
/// <summary> /// Converts template data model to template view model /// </summary> /// <param name="template">OmrTemplate to convert</param> /// <returns>Resulting TemplateViewModel</returns> public static TemplateViewModel ConvertModelToViewModel(OmrTemplate template) { TemplateViewModel templateViewModel = new TemplateViewModel(template.FinalizationComplete, template.TemplateId); templateViewModel.TemplateName = template.Name; templateViewModel.IsGeneratedTemplate = template.IsGenerated; OmrPage page = template.Pages[0]; templateViewModel.TemplateImageName = page.ImageName; templateViewModel.ImageFileFormat = page.ImageFormat; templateViewModel.PageWidth = page.Width; templateViewModel.PageHeight = page.Height; List <BaseQuestionViewModel> elements = new List <BaseQuestionViewModel>(); List <ReferencePointElement> refPoints = new List <ReferencePointElement>(); foreach (OmrElement modelElement in page.Elements) { if (modelElement is ChoiceBoxElement) { ChoiceBoxViewModel choiceBoxViewModel = CreateChoiceBoxViewModel((ChoiceBoxElement)modelElement, templateViewModel); elements.Add(choiceBoxViewModel); } else if (modelElement is GridElement) { GridViewModel gridViewModel = CreateGridViewModel((GridElement)modelElement, templateViewModel); elements.Add(gridViewModel); } else if (modelElement is BarcodeElement) { BarcodeViewModel barcodeViewModel = CreateBarcodeViewModel((BarcodeElement)modelElement, templateViewModel); elements.Add(barcodeViewModel); } else if (modelElement is ClipAreaElement) { ClipAreaViewModel clipViewModel = CreateClipAreaViewModel((ClipAreaElement)modelElement, templateViewModel); elements.Add(clipViewModel); } else if (modelElement is ReferencePointElement) { refPoints.Add((ReferencePointElement)modelElement); } } templateViewModel.AddQuestions(elements); templateViewModel.ReferencePointsModels = refPoints.ToArray(); templateViewModel.IsDirty = false; return(templateViewModel); }
public static void Run() { try { // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "sample_1.amr"); // Load the image to be analyzed OmrImage image = OmrImage.Load(dataDir + "sample1.jpg"); // do not forget to set the license for BarCode in case BarCode elements are used //Aspose.BarCode.License licenseBarCode = new Aspose.BarCode.License(); //licenseBarCode.SetLicense(dataDir + "Aspose.Total.lic"); //// do not forget to set the license for BarCode in case BarCode elements are used //var licenseOmr = new Aspose.OCR.License(); //licenseOmr.SetLicense(dataDir + "Aspose.Total.lic"); // Adding BarCode element requires creation of BarcodeElement object // While specifying the barcode display name, its position and size BarcodeElement barcodeElement = new BarcodeElement("Aztec BarCode", new PointF(0, 0), new SizeF(205, 205)); // Add the BarCode element to the page element collection template.Pages[0].Elements.Add(barcodeElement); // Create an instance of OmrEngine and load the template using file path OmrEngine engine = new OmrEngine(template); // Extract OMR data and store the results in an instance of OmrProcessingResults OmrProcessingResult result = engine.ExtractData(new[] { image }); // Get all page data into an instance of Hashtable Hashtable[] pages = result.PageData; // Loop over all the pages foreach (Hashtable page in pages) { // Display key and value foreach (string key in page.Keys) { Console.WriteLine("key: " + key + ": " + "value: " + page[key]); } } } catch (Exception ex) { Console.WriteLine(ex.Message); // Console.WriteLine(ex.Message + "\nThis example will only work if you apply a valid Aspose License. You can purchase full license or get 30 day temporary license from http:// Www.aspose.com/purchase/default.aspx."); } }
/// <summary> /// Converts template view model to template model /// </summary> /// <param name="templateViewModel">TemplateViewModel to convert</param> /// <returns>Resulting template</returns> public static OmrTemplate ConvertViewModelToModel(TemplateViewModel templateViewModel) { OmrTemplate template = new OmrTemplate(); template.TemplateId = templateViewModel.TemplateId; template.FinalizationComplete = templateViewModel.FinalizationComplete; template.Name = templateViewModel.TemplateName; template.IsGenerated = templateViewModel.IsGeneratedTemplate; OmrPage page = template.AddPage(); page.Height = templateViewModel.PageHeight; page.Width = templateViewModel.PageWidth; page.ImageName = templateViewModel.TemplateImageName; page.ImageFormat = templateViewModel.ImageFileFormat; if (templateViewModel.ReferencePointsModels != null && templateViewModel.ReferencePointsModels.Length > 0) { for (int i = 0; i < templateViewModel.ReferencePointsModels.Length; i++) { page.AddRefPointElement(templateViewModel.ReferencePointsModels[i]); } } foreach (BaseQuestionViewModel element in templateViewModel.PageQuestions) { if (element is ChoiceBoxViewModel) { AddChoiceBoxElement(page, (ChoiceBoxViewModel)element); } else if (element is GridViewModel) { AddGridElement(page, (GridViewModel)element); } else if (element is BarcodeViewModel) { AddBarcodeElement(page, (BarcodeViewModel)element); } else if (element is ClipAreaViewModel) { AddClipAreaElement(page, (ClipAreaViewModel)element); } } return(template); }
/// <summary> /// The background image shape ctor /// </summary> public BackgroundImageShape(OmrTemplate template) { this.m_template = template; if (System.IO.File.Exists(template.SourcePath)) { this.Image = Image.FromFile(template.SourcePath); } else if (System.IO.File.Exists(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(template.FileName), template.SourcePath))) { this.Image = Image.FromFile(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(template.FileName), template.SourcePath)); } else { this.Image = (Image) new Bitmap((int)template.BottomRight.X, (int)template.BottomRight.Y, System.Drawing.Imaging.PixelFormat.Format24bppRgb); } this.m_template.PropertyChanged += m_template_PropertyChanged; this.Tag = this.m_template; }
public static void Run() { // ExStart:DetectUsingElements // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file and Instantiate the recognition engine for the template OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); OmrEngine engine = new OmrEngine(template); // First, remove all default steps engine.ProcessingPipeline.Clear(); // Now add the grayscale convertor It may not be necessary to add it if the scans are already in grayscale and Adding the Otsu’s binarization algorithm engine.ProcessingPipeline.Add(new GrayscaleAlgorithm()); engine.ProcessingPipeline.Add(new OtsuBinarizationAlgorithm()); // ExEnd:DetectUsingElements }
/// <summary> /// Copy /// </summary> private void copyToolStripMenuItem_Click(object sender, EventArgs e) { if (this.pgMain.SelectedObjects.Count(o => o is OmrQuestionField) == 0) { return; } OmrTemplate template = new OmrTemplate(); template.Fields.AddRange(this.pgMain.SelectedObjects.Where(o => o is OmrQuestionField).Select(o => o as OmrQuestionField).ToArray()); using (StringWriter sw = new StringWriter()) { new XmlSerializer(typeof(OmrTemplate)).Serialize(sw, template); sw.Flush(); Clipboard.SetText(sw.ToString(), TextDataFormat.Text); } }
/// <summary> /// The background image shape ctor /// </summary> public BackgroundImageShape(OmrTemplate template) { m_template = template; if (File.Exists(template.SourcePath)) { Image = Image.FromFile(template.SourcePath); } else if (File.Exists(Path.Combine(Path.GetDirectoryName(template.FileName), template.SourcePath))) { Image = Image.FromFile(Path.Combine(Path.GetDirectoryName(template.FileName), template.SourcePath)); } else { Image = new Bitmap((int)template.BottomRight.X, (int)template.BottomRight.Y, PixelFormat.Format24bppRgb); } m_template.PropertyChanged += m_template_PropertyChanged; Tag = m_template; }
public static void Run() { // ExStart:DynamicallyCreateOMRTemplates // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OMR(); OmrTemplate template = new OmrTemplate(); OmrPage page = template.Pages[0]; page.Width = 215.9; page.Height = 279.4; PointF choiceBoxPosition = new PointF(20, 5); // 20 mm to the right, 5 mm from the top SizeF choiceBoxSize = new SizeF(12, 24); ChoiceBoxElement choiceBox = new ChoiceBoxElement("AnotherElement", choiceBoxPosition, choiceBoxSize); choiceBox.IsHorizontal = false; choiceBox.Cells.Add(new OmrCell("A")); // Three marks: (A) (B) (C) choiceBox.Cells.Add(new OmrCell("B")); choiceBox.Cells.Add(new OmrCell("C")); page.Elements.Add(choiceBox); template.Save(dataDir + "New_template_out.amr"); // ExEnd:DynamicallyCreateOMRTemplates }
/// <summary> /// New scan click /// </summary> private void newTsi_Click(object sender, EventArgs e) { try { if (m_isDirty && (MessageBox.Show("Discard unsaved changes?", "Confirm New", MessageBoxButtons.YesNo) == DialogResult.No)) { mnuSave_Click(sender, e); } lblStatus.Text = "Scanning..."; var imgData = m_scanEngine.ScanSingle((sender as ToolStripMenuItem).Tag as ScannerInfo); using (var ms = new MemoryStream(imgData)) { var img = Image.FromStream(ms); img.RotateFlip(RotateFlipType.Rotate270FlipNone); using (var sci = new ScannedImage(img)) { var tFile = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); sci.Analyze(); using (var correctedImage = sci.GetCorrectedImage()) { correctedImage.Save(tFile); } lsvImages.Clear(); m_currentTemplate = OmrTemplate.FromFile(tFile); } } UpdateTemplateDiagram(); testToolStripMenuItem.Enabled = true; lblStatus.Text = "Idle..."; SelectRootImageProperties(); } catch (Exception ex) { MessageBox.Show("Could not create template : " + ex.Message); } }
/// <summary> /// Serializes template into JSON string /// </summary> /// <param name="template">Template view model</param> /// <param name="isLocalSave">Indicates whether template is saved locally</param> /// <returns>JSON string</returns> public static string TemplateToJson(TemplateViewModel template, bool isLocalSave) { OmrTemplate templateModel = TemplateConverter.ConvertViewModelToModel(template, isLocalSave); string res; using (MemoryStream jsonStream = new MemoryStream()) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(OmrTemplate)); serializer.WriteObject(jsonStream, templateModel); byte[] json = jsonStream.ToArray(); res = Encoding.UTF8.GetString(json, 0, json.Length); StringBuilder sb = new StringBuilder(res); PostprocessJson(sb); res = FormatJson(sb.ToString()); } return(res); }
public static void Run() { // ExStart:ExtractText // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); // Load the image to be analyzed OmrImage image = OmrImage.Load(dataDir + "answers.jpg"); // Set resource for TextOcrElement TextOcrElement.Resource = dataDir + "Aspose.OCR.Spanish.Resources.zip"; // Create an instance of TextOcrElement and initialize it by specifying the location of text and its size in mm TextOcrElement textElement = new TextOcrElement("OCR Text", new PointF(23.6f, 15.5f), new SizeF(14.6f, 4.7f)); // Add the TextOcrElement to the page element collection template.Pages[0].Elements.Add(textElement); // Create an instance of OmrEngine and load the template using file path OmrEngine engine = new OmrEngine(template); // Extract OMR data and store the results in an instance of OmrProcessingResults OmrProcessingResult result = engine.ExtractData(new OmrImage[] { image }); // Get all page data into an instance of Hashtable Hashtable[] pages = result.PageData; // Loop over all the pages foreach (Hashtable page in pages) { // Display key and value foreach (string key in page.Keys) { Console.WriteLine("key: " + key + ": " + "value: " + page[key]); } } // ExEnd:ExtractText }
public static void Run() { // ExStart:DetectUsingElements // The path to the documents directory. string dataDir = RunExamples.GetDataDir_OCR(); // Load template file OmrTemplate template = OmrTemplate.Load(dataDir + "questions.amr"); // Iterate over the pages in template foreach (OmrPage page in template.Pages) { // Get elements of each page OmrElementsCollection collection = page.Elements; // Iterate over the element collection foreach (Object obj in collection) { // Display element name Console.WriteLine(obj.GetType().ToString()); } } // ExEnd:DetectUsingElements }
/// <summary> /// Do work /// </summary> private void ProcessImageWorker(object state) { ScannedImage scannedImage = null; Image original = null; try { lock (this.m_lockObject) using (var ms = new MemoryStream((byte[])state)) { var img = Image.FromStream(ms); img.RotateFlip(RotateFlipType.Rotate270FlipNone); scannedImage = new ScannedImage(img); } scannedImage.Analyze(); original = (Image) new AForge.Imaging.Filters.ResizeNearestNeighbor(scannedImage.Image.Width / 4, scannedImage.Image.Height / 4).Apply((Bitmap)scannedImage.Image); } catch { if (scannedImage != null) { scannedImage.Dispose(); } return; // Abort } try { // Add an Error entry if (!scannedImage.IsScannable) { ListViewItem lsv = new ListViewItem(); lsv.Tag = 2; lsv.SubItems.Add(new ListViewItem.ListViewSubItem(lsv, "Scanned image doesn't appear to be a scannable form.")); lock (this.m_lockObject) this.m_uiResults.Add(lsv, original); } else { Engine engine = new Engine(); var templateFile = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), scannedImage.TemplateName + ".mxml"); if (!File.Exists(templateFile)) { ListViewItem lsv = new ListViewItem(); lsv.Tag = 0; lsv.SubItems.Add(new ListViewItem.ListViewSubItem(lsv, "Template file " + templateFile + " is missing")); lock (this.m_lockObject) this.m_uiResults.Add(lsv, original); return; } // Apply template var template = OmrTemplate.Load(templateFile); var pageData = engine.ApplyTemplate( template, scannedImage); // Draw the page data ICanvas canvas = new DesignerCanvas(); canvas.Add(new OmrMarkEngine.Output.Design.OutputVisualizationStencil(pageData)); original.Dispose(); original = new Bitmap((int)template.BottomRight.X, (int)template.BottomLeft.Y, System.Drawing.Imaging.PixelFormat.Format24bppRgb); using (Graphics g = Graphics.FromImage(original)) { float width = template.TopRight.X - template.TopLeft.X, height = template.BottomLeft.Y - template.TopLeft.Y; g.DrawImage(scannedImage.Image, template.TopLeft.X, template.TopLeft.Y, width, height); canvas.DrawTo(g); } // Save original analyzed image try { String tPath = Path.GetTempFileName(); original.Save(tPath); pageData.AnalyzedImage = tPath; } catch { } var oldOriginal = original; original = (Image) new AForge.Imaging.Filters.ResizeNearestNeighbor(scannedImage.Image.Width / 2, scannedImage.Image.Height / 2).Apply((Bitmap)original); oldOriginal.Dispose(); lock (this.m_lockObject) { if (pageData.Outcome == OmrScanOutcome.Failure) { ListViewItem lsv = new ListViewItem(); lsv.Tag = 0; lsv.SubItems.Add(new ListViewItem.ListViewSubItem(lsv, pageData.ErrorMessage)); lock (this.m_lockObject) this.m_uiResults.Add(lsv, original); } else { var validation = pageData.Validate(template); ListViewItem lsv = new ListViewItem(); lsv.Tag = validation.IsValid ? 2 : 1; if (!validation.IsValid) { lsv.SubItems.Add(validation.Issues[0]); } lsv.Tag = pageData; lock (this.m_lockObject) this.m_executionQueue.Enqueue(new KeyValuePair <OmrTemplate, OmrPageOutput>(template, pageData)); lock (this.m_lockObject) this.m_uiResults.Add(lsv, original); } this.m_scannedPages.Pages.Add(pageData); } } } catch (Exception e) { ListViewItem lsv = new ListViewItem(); lsv.Tag = 0; lsv.SubItems.Add(e.Message); lock (this.m_lockObject) this.m_uiResults.Add(lsv, original); } }
/// <summary> /// Transform the output /// </summary> public byte[] Transform(OmrTemplate template, OmrPageOutputCollection pages) { // CSV output is formatted as follows: // BARCODE0 BARCODE1 BARCODEN BUBBLEQ1 BUBBLEQ2 BUBBLEQ3 // PAGE1 ROW1 // PAGE1 ROW2 // PAGE1 ROWN // PAGE2 ROW1 // PAGE2 ROW2 // PAGE2 ROWN // PAGEN using (var ms = new MemoryStream()) { using (var sw = new StreamWriter(ms)) { // Get the headings var barcodeGroup = template.FlatFields.OfType <OmrBarcodeField>().GroupBy(o => o.AnswerRowGroup).FirstOrDefault(); var nBarcodesPerRow = 0; if (barcodeGroup != null) { nBarcodesPerRow = barcodeGroup.Count(); } var questionsPerRow = template.FlatFields.OfType <OmrBubbleField>().Select(o => o.Question).Distinct().ToArray(); // Output header row sw.Write("PAGE,ROW"); for (var i = 0; i < nBarcodesPerRow; i++) { sw.Write(",BARCODE{0}", i); } foreach (var q in questionsPerRow) { sw.Write(",{0}", q); } sw.WriteLine(); foreach (var pg in pages.Pages) { foreach (var rw in pg.Details.OfType <OmrRowData>()) { sw.Write("{0},{1}", pg.Id, rw.Id); var barcodes = rw.Details.OfType <OmrBarcodeData>().ToArray(); // Barcode for (var i = 0; i < nBarcodesPerRow; i++) { if (barcodes.Length > i) { sw.Write(",\"{0}\"", barcodes[i].BarcodeData); } else { sw.Write(","); } } // Questions foreach (var q in questionsPerRow) { var answerBubble = rw.Details.OfType <OmrBubbleData>().Where(o => o.Key == q).ToArray(); var aggregate = rw.Details.OfType <OmrAggregateDataOutput>().Where(o => o.Id == q).ToArray(); var nonGroupedAnswer = pg.Details.OfType <OmrBubbleData>().Where(o => o.Key == q).ToArray(); if (aggregate.Length > 0) { sw.Write(",{0}", MakeString(aggregate)); } else if (answerBubble.Length > 0) { sw.Write(",{0}", MakeString(answerBubble)); } else if (nonGroupedAnswer.Length > 0) { sw.Write(",{0}", MakeString(nonGroupedAnswer)); } else { sw.Write(","); } } sw.WriteLine(); } } sw.Flush(); return(ms.ToArray()); } } // Get the header }
/// <summary> /// Process the template data /// </summary> public void Run(OmrTemplate template, OmrPageOutput processedOutput) { if (template.Script == null) { return; } // First we need to compile the script Assembly asmToRun = null; if (!s_compiledScripts.TryGetValue(template.Id, out asmToRun)) { using ( var strm = new StreamReader( typeof(TemplateScriptUtil).Assembly.GetManifestResourceStream( "OmrMarkEngine.Core.Template.Scripting.ScriptTemplate.txt"))) { var scriptTemplate = strm.ReadToEnd(); scriptTemplate = scriptTemplate.Replace("$$script$$", template.Script.Script); var asmOption = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = true, CompilerOptions = "/d:TRACE /d:DEBUG", IncludeDebugInformation = true }; // Add assemblies asmOption.ReferencedAssemblies.Add(typeof(INotifyPropertyChanged).Assembly.Location); asmOption.ReferencedAssemblies.Add(typeof(string).Assembly.Location); asmOption.ReferencedAssemblies.Add(typeof(Enumerable).Assembly.Location); asmOption.ReferencedAssemblies.Add(typeof(OmrTemplate).Assembly.Location); asmOption.ReferencedAssemblies.Add(typeof(DataContractAttribute).Assembly.Location); foreach (var asmRef in template.Script.Assemblies) { var asmLocation = asmRef; if (!Path.IsPathRooted(asmLocation)) { asmLocation = Path.Combine(Path.GetDirectoryName(template.FileName), asmLocation); } Assembly.LoadFile(asmLocation); asmOption.ReferencedAssemblies.Add(asmLocation); } // Compile var compileResult = CodeDomProvider.CreateProvider("CS") .CompileAssemblyFromSource(asmOption, scriptTemplate); if (compileResult.Errors.HasErrors) { foreach (var err in compileResult.Errors) { Trace.TraceError("{0}", err); } throw new InvalidOperationException("Error exeucting post processing script"); } asmToRun = compileResult.CompiledAssembly; s_compiledScripts.Add(template.Id, asmToRun); } } // Now we need to run the script var templateScript = asmToRun.GetType("OmrScannerApplication.Scripting.Script"); if (templateScript == null) { throw new InvalidOperationException("Cannot execute post processing script"); } var errField = templateScript.GetField("Err"); var runMethod = templateScript.GetMethod("Run", new[] { typeof(OmrPageOutput) }); if ((runMethod == null) || (errField == null)) { throw new InvalidOperationException("Cannot execute post processing script"); } // Invoke try { lock (s_syncLock) { errField.SetValue(null, null); runMethod.Invoke(null, new object[] { processedOutput }); if (!string.IsNullOrEmpty(errField.GetValue(null) as string)) { throw new ScriptingErrorException(errField.GetValue(null).ToString()); } } } catch { throw; } }
/// <summary> /// Validates the input against the template /// </summary> public virtual ValidationResult Validate(OmrTemplate template) { ValidationResult retVal = new ValidationResult(); retVal.IsValid = true; // Row ID String rowId = null; if (this is OmrRowData) { rowId = (this as OmrRowData).Id; } else if (this is OmrAggregateDataOutput) { rowId = (this as OmrAggregateDataOutput).RowId; } List <OmrQuestionField> requiredFields = new List <OmrQuestionField>(template.Fields.Where(o => o.IsQuestionRequired && o.AnswerRowGroup == rowId)); // Validate foreach (var itm in this.Details) { if (itm is OmrOutputDataCollection) { var sub = (itm as OmrOutputDataCollection).Validate(template); retVal.IsValid &= sub.IsValid; retVal.Issues.AddRange(sub.Issues); } else if (itm is OmrBarcodeData) { // First find the template data var templateData = template.Fields.Find(o => o.Id == itm.Id && o.AnswerRowGroup == rowId); if (templateData == null) { retVal.IsValid = false; retVal.Issues.Add(String.Format("Missing template data for {0}", itm.Id)); } requiredFields.Remove(templateData); } else if (itm is OmrBubbleData) { var bubbleData = itm as OmrBubbleData; var templateData = template.Fields.Find(o => o.Id == itm.Id && o.AnswerRowGroup == rowId) as OmrBubbleField; var otherOptions = template.Fields.FindAll(o => o is OmrBubbleField && (o as OmrBubbleField).Question == bubbleData.Key && o.AnswerRowGroup == rowId); // Mutli not permitted if (templateData.Behavior == BubbleBehaviorType.One && this.Details.OfType <OmrBubbleData>().Count(o => otherOptions.Exists(p => p.Id == o.Id)) != 1) { retVal.IsValid = false; retVal.Issues.Add(String.Format("Only one response for {0} can be registered", bubbleData.Key)); } // Remove all from required fields requiredFields.RemoveAll(o => o is OmrBubbleField && (o as OmrBubbleField).Question == templateData.Question); } } // How many remaining required fields remain, is it the number of total required fields in the row? // if so then the row is valid because nothing was filled out if (rowId != null) { var uniqueQuestionCountInTpl = template.Fields.Where(o => o.AnswerRowGroup == rowId && o.IsQuestionRequired).OfType <OmrBubbleField>().Select(o => o.Question).Distinct(); var uniqueQuestionCountInReq = requiredFields.OfType <OmrBubbleField>().Select(o => o.Question).Distinct(); if (uniqueQuestionCountInReq.Count() != 0 && uniqueQuestionCountInReq.Count() != uniqueQuestionCountInTpl.Count()) { retVal.IsValid = false; String flds = String.Empty; var distinctFields = requiredFields.Select(o => o is OmrBubbleField ? (o as OmrBubbleField).Question : o.Id).Distinct().ToList(); distinctFields.ForEach(o => flds = String.Format("{0} {1},", flds, o)); retVal.Issues.Add(String.Format("Missing required fields ({1}) for row {0}", rowId, flds)); } } else { retVal.IsValid &= requiredFields.Count == 0; } return(retVal); }
private static void Main(string[] args) { try { Console.WriteLine("Optical Mark Engine Console Utility"); Console.WriteLine("Version {0}, {1}", Assembly.GetEntryAssembly().GetName().Version, Assembly.GetEntryAssembly() .GetCustomAttributes(typeof(AssemblyCopyrightAttribute)) .Select(o => o as AssemblyCopyrightAttribute) .First() .Copyright); // Parse parameters var parser = new ParameterParser <ConsoleParameters>(); var parameters = parser.Parse(args); // Show help? var showHelp = string.IsNullOrEmpty(parameters.OutputFile) || string.IsNullOrEmpty(parameters.Template) || (parameters.SourceFiles == null) || parameters.Help; if (showHelp) { parser.WriteHelp(Console.Out); } else if (!File.Exists(parameters.Template)) { throw new ArgumentException(string.Format("{0} not found", parameters.Template)); } else if ((parameters.OutputFormat.ToLower() != "csv") && (parameters.OutputFormat.ToLower() != "xml")) { throw new ArgumentException("Output format must be XML or CSV!"); } // Load the files foreach (var ptrn in parameters.SourceFiles) { string directory = Path.GetDirectoryName(ptrn) ?? ".", pattern = Path.GetFileName(ptrn); // Get files var outputCollection = new OmrPageOutputCollection(); var engine = new Engine(); var tsu = new TemplateScriptUtil(); var template = OmrTemplate.Load(parameters.Template); // Process files foreach (var fileName in Directory.GetFiles(directory, pattern)) { Console.Write("Processing {0}...", Path.GetFileName(fileName)); using (var sci = new ScannedImage(fileName)) { sci.Analyze(); if (sci.TemplateName != template.Id) { Console.WriteLine("Wrong template!"); continue; } var output = engine.ApplyTemplate(template, sci); var validate = output.Validate(template); if (parameters.Validate && !validate.IsValid) { Console.WriteLine("Invalid"); foreach (var iss in validate.Issues) { Console.WriteLine("\t{0}", iss); } } else { try { if (parameters.Run) { tsu.Run(template, output); } outputCollection.Pages.Add(output); Console.WriteLine("Success"); } catch (Exception e) { Console.WriteLine("Error\r\n\t{0}", e.Message); } } } } // Save the output? switch (parameters.OutputFormat) { case "csv": { var outputBytes = new CsvOutputTransform().Transform(template, outputCollection); using (var fs = File.Create(parameters.OutputFile)) { fs.Write(outputBytes, 0, outputBytes.Length); } break; } default: { var outputBytes = new RawOutputTransform().Transform(template, outputCollection); using (var fs = File.Create(parameters.OutputFile)) { fs.Write(outputBytes, 0, outputBytes.Length); } } break; } } #if DEBUG Console.ReadKey(); #endif Environment.Exit(0); } catch (Exception e) { Trace.TraceError(e.ToString()); Console.WriteLine("Error: {0}", e.Message); Environment.Exit(-1); } }
/// <summary> /// Open /// </summary> private void mnuOpen_Click(object sender, EventArgs e) { try { if (this.m_currentTemplate != null) { switch (MessageBox.Show("Do you want to save your changes before opening another template?", "Confirm Open", MessageBoxButtons.YesNoCancel)) { case System.Windows.Forms.DialogResult.Cancel: return; case System.Windows.Forms.DialogResult.Yes: this.mnuSave_Click(sender, e); break; } } var openDialog = new OpenFileDialog() { Title = "Open Template", Filter = "Marker Engine XML (*.mxml)|*.mxml", AddExtension = true }; if (openDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { this.m_currentTemplate = OmrTemplate.Load(openDialog.FileName); lsvImages.Items.Clear(); this.mnuSave.Enabled = true; this.UpdateTemplateDiagram(); // Add field data foreach (var itm in this.m_currentTemplate.Fields) { PointF pos = itm.TopLeft; SizeF size = new SizeF(itm.TopRight.X - itm.TopLeft.X, itm.BottomLeft.Y - itm.TopLeft.Y); if (itm is OmrBarcodeField) { this.m_canvas.Add(new BarcodeFormFieldStencil(itm as OmrBarcodeField) { Position = pos, Size = size }, itm.Id); } else if (itm is OmrBubbleField) { this.m_canvas.Add(new BubbleFormFieldStencil(itm as OmrBubbleField) { Position = pos, Size = size }, itm.Id); } this.testToolStripMenuItem.Enabled = true; } } else { return; } } catch (Exception ex) { MessageBox.Show("Could not open template: " + ex.Message); } }
/// <summary> /// Apply template /// </summary> /// <param name="template"></param> /// <param name="image"></param> public OmrPageOutput ApplyTemplate(OmrTemplate template, ScannedImage image) { // Image ready for scan if (!image.IsReadyForScan) { if (!image.IsScannable) { image.Analyze(); } image.PrepareProcessing(); } // Page output OmrPageOutput retVal = new OmrPageOutput() { Id = image.TemplateName + DateTime.Now.ToString("yyyyMMddHHmmss"), TemplateId = image.TemplateName, Parameters = image.Parameters, StartTime = DateTime.Now, Template = template }; // Save directory for output images string saveDirectory = String.Empty; var parmStr = new StringBuilder(); if (this.SaveIntermediaryImages) { if (image.Parameters != null) { foreach (var pv in image.Parameters) { parmStr.AppendFormat("{0}.", pv); } } retVal.RefImages = new List <string>() { String.Format("{0}-{1}-init.bmp", retVal.Id, parmStr), String.Format("{0}-{1}-tx.bmp", retVal.Id, parmStr), String.Format("{0}-{1}-fields.bmp", retVal.Id, parmStr), String.Format("{0}-{1}-gs.bmp", retVal.Id, parmStr), String.Format("{0}-{1}-bw.bmp", retVal.Id, parmStr), String.Format("{0}-{1}-inv.bmp", retVal.Id, parmStr) }; saveDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "imgproc"); if (!Directory.Exists(saveDirectory)) { Directory.CreateDirectory(saveDirectory); } image.Image.Save(Path.Combine(saveDirectory, string.Format("{0}-{1}-init.bmp", DateTime.Now.ToString("yyyyMMddHHmmss"), parmStr))); } // First, we want to get the image from the scanned image and translate it to the original // position in the template Bitmap bmp = null; try { bmp = new Bitmap((int)template.BottomRight.X, (int)template.BottomRight.Y, System.Drawing.Imaging.PixelFormat.Format24bppRgb); // Scale float width = template.TopRight.X - template.TopLeft.X, height = template.BottomLeft.Y - template.TopLeft.Y; // Translate to original using (Graphics g = Graphics.FromImage(bmp)) { ResizeBicubic bc = new ResizeBicubic((int)width, (int)height); g.DrawImage(bc.Apply((Bitmap)image.Image), template.TopLeft.X, template.TopLeft.Y); } if (this.SaveIntermediaryImages) { bmp.Save(Path.Combine(saveDirectory, string.Format("{0}-{1}-tx.bmp", DateTime.Now.ToString("yyyyMMddHHmmss"), parmStr))); } // Now try to do hit from the template if (this.SaveIntermediaryImages) { using (var tbmp = bmp.Clone() as Bitmap) { using (Graphics g = Graphics.FromImage(tbmp)) { foreach (var field in template.Fields) { g.DrawRectangle(Pens.Black, field.TopLeft.X, field.TopLeft.Y, field.TopRight.X - field.TopLeft.X, field.BottomLeft.Y - field.TopLeft.Y); g.DrawString(field.Id, SystemFonts.CaptionFont, Brushes.Black, field.TopLeft); } } tbmp.Save(Path.Combine(saveDirectory, string.Format("{0}-{1}-fields.bmp", DateTime.Now.ToString("yyyyMMddHHmmss"), parmStr))); } } // Now convert to Grayscale GrayscaleY grayFilter = new GrayscaleY(); var gray = grayFilter.Apply(bmp); bmp.Dispose(); bmp = gray; if (this.SaveIntermediaryImages) { bmp.Save(Path.Combine(saveDirectory, string.Format("{0}-{1}-gs.bmp", DateTime.Now.ToString("yyyyMMddHHmmss"), parmStr))); } // Prepare answers Dictionary <OmrQuestionField, OmrOutputData> hitFields = new Dictionary <OmrQuestionField, OmrOutputData>(); BarcodeReader barScan = new BarcodeReader(); barScan.Options.UseCode39ExtendedMode = true; barScan.Options.UseCode39RelaxedExtendedMode = true; barScan.Options.TryHarder = true; barScan.TryInverted = true; barScan.Options.PureBarcode = false; barScan.AutoRotate = true; foreach (var itm in template.Fields.Where(o => o is OmrBarcodeField)) { PointF position = itm.TopLeft; SizeF size = new SizeF(itm.TopRight.X - itm.TopLeft.X, itm.BottomLeft.Y - itm.TopLeft.Y); using (var areaOfInterest = new Crop(new Rectangle((int)position.X, (int)position.Y, (int)size.Width, (int)size.Height)).Apply(bmp)) { // Scan the barcode var result = barScan.Decode(areaOfInterest); if (result != null) { hitFields.Add(itm, new OmrBarcodeData() { BarcodeData = result.Text, Format = result.BarcodeFormat, Id = itm.Id, TopLeft = new PointF(result.ResultPoints[0].X + position.X, result.ResultPoints[0].Y + position.Y), BottomRight = new PointF(result.ResultPoints[1].X + position.X, result.ResultPoints[0].Y + position.Y + 10) }); } } } // Now binarize Threshold binaryThreshold = new Threshold(template.ScanThreshold); binaryThreshold.ApplyInPlace(bmp); if (this.SaveIntermediaryImages) { bmp.Save(Path.Combine(saveDirectory, string.Format("{0}-{1}-bw.bmp", DateTime.Now.ToString("yyyyMMddHHmmss"), parmStr))); } // Set return parameters String tAnalyzeFile = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); bmp.Save(tAnalyzeFile, System.Drawing.Imaging.ImageFormat.Jpeg); retVal.AnalyzedImage = tAnalyzeFile; retVal.BottomRight = new PointF(bmp.Width, bmp.Height); // Now Invert Invert invertFiter = new Invert(); invertFiter.ApplyInPlace(bmp); if (this.SaveIntermediaryImages) { bmp.Save(Path.Combine(saveDirectory, string.Format("{0}-{1}-inv.bmp", DateTime.Now.ToString("yyyyMMddHHmmss"), parmStr))); } // Crop out areas of interest List <KeyValuePair <OmrQuestionField, Bitmap> > areasOfInterest = new List <KeyValuePair <OmrQuestionField, Bitmap> >(); foreach (var itm in template.Fields.Where(o => o is OmrBubbleField)) { PointF position = itm.TopLeft; SizeF size = new SizeF(itm.TopRight.X - itm.TopLeft.X, itm.BottomLeft.Y - itm.TopLeft.Y); areasOfInterest.Add(new KeyValuePair <OmrQuestionField, Bitmap>( itm, new Crop(new Rectangle((int)position.X, (int)position.Y, (int)size.Width, (int)size.Height)).Apply(bmp)) ); } // Queue analysis WaitThreadPool wtp = new WaitThreadPool(); Object syncLock = new object(); foreach (var itm in areasOfInterest) { wtp.QueueUserWorkItem(img => { var parm = (KeyValuePair <OmrQuestionField, Bitmap>)itm; try { var areaOfInterest = parm.Value; var field = parm.Key; BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; // Check for circles blobCounter.ProcessImage(areaOfInterest); Blob[] blobs = blobCounter.GetObjectsInformation(); var blob = blobs.FirstOrDefault(o => o.Area == blobs.Max(b => b.Area)); if (blob != null) { //var area = new AForge.Imaging.ImageStatistics(blob).PixelsCountWithoutBlack; if (blob.Area < 30) { return; } var bubbleField = field as OmrBubbleField; lock (syncLock) hitFields.Add(field, new OmrBubbleData() { Id = field.Id, Key = bubbleField.Question, Value = bubbleField.Value, TopLeft = new PointF(blob.Rectangle.X + field.TopLeft.X, blob.Rectangle.Y + field.TopLeft.Y), BottomRight = new PointF(blob.Rectangle.X + blob.Rectangle.Width + field.TopLeft.X, blob.Rectangle.Y + blob.Rectangle.Height + field.TopLeft.Y), BlobArea = blob.Area }); } } catch (Exception e) { Trace.TraceError(e.ToString()); } finally { parm.Value.Dispose(); } }, itm); } wtp.WaitOne(); // Organize the response foreach (var res in hitFields) { if (String.IsNullOrEmpty(res.Key.AnswerRowGroup)) { this.AddAnswerToOutputCollection(retVal, res); } else { // Rows of data OmrRowData rowGroup = retVal.Details.Find(o => o.Id == res.Key.AnswerRowGroup) as OmrRowData; if (rowGroup == null) { rowGroup = new OmrRowData() { Id = res.Key.AnswerRowGroup }; retVal.Details.Add(rowGroup); } this.AddAnswerToOutputCollection(rowGroup, res); } } // Remove temporary images //foreach (var f in retVal.RefImages) // File.Delete(Path.Combine(saveDirectory, f)); // Outcome is success retVal.Outcome = OmrScanOutcome.Success; } catch (Exception e) { retVal.Outcome = OmrScanOutcome.Failure; retVal.ErrorMessage = e.Message; Trace.TraceError(e.ToString()); } finally { retVal.StopTime = DateTime.Now; bmp.Dispose(); } return(retVal); }