示例#1
0
        /// <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);
            }
        }
示例#2
0
        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
        }
示例#3
0
        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
        }
示例#4
0
        /// <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
        }
示例#6
0
        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
        }
示例#7
0
        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
        }
示例#8
0
 /// <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());
     }
 }
示例#9
0
        /// <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);
        }
示例#10
0
        /// <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.");
            }
        }
示例#12
0
        /// <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
        }
示例#15
0
        /// <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);
            }
        }
示例#16
0
 /// <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
 }
示例#18
0
        /// <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);
            }
        }
示例#19
0
        /// <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: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
        }
示例#21
0
        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
        }
示例#23
0
        /// <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);
            }
        }
示例#24
0
        /// <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
        }
示例#25
0
        /// <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;
            }
        }
示例#26
0
        /// <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);
        }
示例#27
0
        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);
            }
        }
示例#28
0
        /// <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);
            }
        }
示例#29
0
        /// <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);
        }