Использование 2D штрих-кодов для выравнивания изображений в .NET/C#
Категория: Штрих-коды; Обработка форм документов; .NET
15 мая 2020
public static void Test() { AlignImages( new string[] { "BarcodeTemplateMatching_template1.png" }, new string[] { "BarcodeTemplateMatching_1_rotate90.png", "BarcodeTemplateMatching_1_scale-rotate150.png", "BarcodeTemplateMatching_1_scale-rotate180.png"}); } public static void AlignImages(string[] templates, string[] images) { // создать распознаватель ключевой зоны на базе штрих-кода BarcodeKeyZoneRecognizerCommand barcodeRecognizer = new BarcodeKeyZoneRecognizerCommand(); // установить настройки распознавателя штрих-кодов barcodeRecognizer.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.Aztec; barcodeRecognizer.Settings.ScanDirection = Vintasoft.Barcode.ScanDirection.Horizontal | Vintasoft.Barcode.ScanDirection.Vertical; barcodeRecognizer.Settings.AutomaticRecognition = true; // указать, что изображение содержит 3 штрих-кода barcodeRecognizer.Settings.ExpectedBarcodes = 3; // создать генератор отпечатков, который использует ключевые зоны на базе штрих-кодов Vintasoft.Imaging.FormsProcessing.TemplateMatching.ImageImprintGeneratorCommand barcodeImprintGenerator = new Vintasoft.Imaging.FormsProcessing.TemplateMatching.ImageImprintGeneratorCommand(barcodeRecognizer); // создать команду для сравнения шаблонов Vintasoft.Imaging.FormsProcessing.TemplateMatching.TemplateMatchingCommand templateMatchingCommand = new Vintasoft.Imaging.FormsProcessing.TemplateMatching.TemplateMatchingCommand(); // указать, что команда для сравнения шаблонов должна использовать генератор отпечатков, который использует ключевые зоны на базе штрих-кодов templateMatchingCommand.ImageImprintGenerator = barcodeImprintGenerator; // для каждого файла с изображением шаблона foreach (string template in templates) { // добавить файла с изображением шаблона в список шаблонов команды для сравнения шаблонов templateMatchingCommand.TemplateImages.Add(template); } // для каждого входного файла изображения foreach (string imageFilename in images) { // создать входное изображение using (Vintasoft.Imaging.VintasoftImage image = new Vintasoft.Imaging.VintasoftImage(imageFilename)) { // найти шаблон для изображения templateMatchingCommand.ExecuteInPlace(image); // получить результат сравнения изображения с шаблоном Vintasoft.Imaging.FormsProcessing.TemplateMatching.ImageImprintCompareResult compareResult = templateMatchingCommand.Result.ImageCompareResult; // напечатать имя входного файла System.Console.WriteLine(imageFilename); // напечатать результат сравнения изображения и шаблона System.Console.WriteLine(string.Format(" IsReliable ={0}", compareResult.IsReliable)); // если для изображения найден шаблон if (compareResult.IsReliable) { // напечатать информацию о уровне доверия к результату сравнения изображения и шаблона System.Console.WriteLine(string.Format(" Confidence ={0}%", compareResult.Confidence * 100)); // напечатать информацию о матрице, которая определяет трансформацию изображения по отношению к шаблону System.Console.WriteLine(string.Format(" TransformMatrix ={0}", compareResult.TransformMatrix)); // создать команду для выравнивания изображения по шаблону Vintasoft.Imaging.FormsProcessing.TemplateMatching.TemplateAligningCommand templateAligningCommand = new Vintasoft.Imaging.FormsProcessing.TemplateMatching.TemplateAligningCommand(); // указать, что команда для выравнивания изображения должна использовать матрицу, которая определяет трансформацию изображения по отношению к шаблону templateAligningCommand.CompareResult = compareResult; // выполнить выравнивание изображения templateAligningCommand.ExecuteInPlace(image); // сохранить выровненное изображение в файл image.Save(string.Format("{0}_result.png", System.IO.Path.GetFileNameWithoutExtension(imageFilename))); } System.Console.WriteLine(); } } }
/// <summary> /// Представляет ключевую зону на базе штрих-кода. /// </summary> public class BarcodeKeyZone : Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone { #region Constructors /// <summary> /// Initializes a new instance of the <see cref="BarcodeKeyZone"/> class. /// </summary> /// <param name="barcodeInfo">The barcode information.</param> public BarcodeKeyZone(Vintasoft.Barcode.IBarcodeInfo barcodeInfo) : base() { _barcodeInfo = barcodeInfo; if (barcodeInfo is Vintasoft.Barcode.BarcodeInfo.AztecInfo) { // get the barcode center from barcode info _location = ((Vintasoft.Barcode.BarcodeInfo.AztecInfo)barcodeInfo).BulleyeCenter; } else { // calculate the barcode center _location = System.Drawing.PointF.Empty; System.Drawing.Point[] points = barcodeInfo.Region.GetPoints(); for (int i = 0; i < points.Length; i++) { _location.X += points[i].X; _location.Y += points[i].Y; } _location.X /= points.Length; _location.Y /= points.Length; } } /// <summary> /// Initializes a new instance of the <see cref="BarcodeKeyZone"/> class. /// </summary> /// <param name="barcodeInfo">The barcode information.</param> /// <param name="location">The location.</param> private BarcodeKeyZone(Vintasoft.Barcode.IBarcodeInfo barcodeInfo, System.Drawing.PointF location) : base() { _barcodeInfo = barcodeInfo; _location = location; } #endregion #region Properties System.Drawing.PointF _location; /// <summary> /// Gets the location of the key zone on the image. /// </summary> public override System.Drawing.PointF Location { get { return _location; } } Vintasoft.Barcode.IBarcodeInfo _barcodeInfo; /// <summary> /// Gets the barcode information. /// </summary> public Vintasoft.Barcode.IBarcodeInfo BarcodeInfo { get { return _barcodeInfo; } } #endregion #region Methods /// <summary> /// Applies a transformation to the key zone. /// </summary> /// <param name="m">The <see cref="Vintasoft.Imaging.AffineMatrix" /> /// that specifies the transformation to apply.</param> public override void Transform(Vintasoft.Imaging.AffineMatrix m) { if (m == null) return; _location = Vintasoft.Imaging.PointFAffineTransform.TransformPoint(m, _location); } /// <summary> /// Returns the similarity of specified <see cref="Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone" /> and the current key zone. /// </summary> /// <param name="zone">The <see cref="Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone" /> to compare with.</param> /// <returns> /// The similarity of specified keyzone and the current key zone in range from 0 to 1.<br /> /// 0 means that zones are absolutely NOT similar; /// 1 means that zones are perfectly similar. /// </returns> public override double CalculateSimilarity(Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone zone) { BarcodeKeyZone barcodeZone = zone as BarcodeKeyZone; if (barcodeZone == null) return 0; if (barcodeZone.BarcodeInfo.Value == BarcodeInfo.Value && barcodeZone.BarcodeInfo.BarcodeType == BarcodeInfo.BarcodeType) return 1; return 0; } /// <summary> /// Creates a new object that is a copy of the current instance. /// </summary> /// <returns>A new object that is a copy of this instance.</returns> public override object Clone() { return new BarcodeKeyZone(BarcodeInfo, Location); } #endregion }
/// <summary> /// Представляет команду для поиска ключевых зон с штрих-кодами на изображении. /// </summary> public class BarcodeKeyZoneRecognizerCommand : Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZoneRecognizerCommand { #region Constructors /// <summary> /// Initializes a new instance of the <see cref="BarcodeKeyZoneRecognizerCommand"/> class. /// </summary> public BarcodeKeyZoneRecognizerCommand() : base() { } #endregion #region Properties static System.Collections.ObjectModel.ReadOnlyCollection<Vintasoft.Imaging.PixelFormat> _supportedNativePixelFormats; /// <summary> /// Gets a list of supported pixel formats for this processing command. /// </summary> public override System.Collections.ObjectModel.ReadOnlyCollection<Vintasoft.Imaging.PixelFormat> SupportedNativePixelFormats { get { if (_supportedNativePixelFormats == null) { System.Collections.Generic.List<Vintasoft.Imaging.PixelFormat> supportedPixelFormats = new System.Collections.Generic.List<Vintasoft.Imaging.PixelFormat>(); supportedPixelFormats.Add(Vintasoft.Imaging.PixelFormat.BlackWhite); supportedPixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgr24); supportedPixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgr32); supportedPixelFormats.Add(Vintasoft.Imaging.PixelFormat.Indexed1); supportedPixelFormats.Add(Vintasoft.Imaging.PixelFormat.Indexed8); supportedPixelFormats.Add(Vintasoft.Imaging.PixelFormat.Gray8); _supportedNativePixelFormats = supportedPixelFormats.AsReadOnly(); } return _supportedNativePixelFormats; } } Vintasoft.Barcode.ReaderSettings _settings = new Vintasoft.Barcode.ReaderSettings(); /// <summary> /// Gets or sets the barcode reader settings. /// </summary> /// <value> /// The reader settings. /// </value> public Vintasoft.Barcode.ReaderSettings Settings { get { return _settings; } set { if (value == null) throw new System.ArgumentNullException(); _settings = value; } } #endregion #region Methods /// <summary> /// Creates a new <see cref="BarcodeKeyZoneRecognizerCommand"/> that is a copy of the current /// instance. /// </summary> /// <returns>A new <see cref="BarcodeKeyZoneRecognizerCommand"/> that is a copy of this /// instance.</returns> public override object Clone() { BarcodeKeyZoneRecognizerCommand recognizer = new BarcodeKeyZoneRecognizerCommand(); recognizer.IsNested = IsNested; recognizer.RegionOfInterest = RegionOfInterest; recognizer.Settings = Settings.Clone(); return recognizer; } /// <summary> /// Recognizes key zones in the specified rectangle of the specified image. /// </summary> /// <param name="image">The image where key zones must be searched.</param> /// <param name="rect">The region of interest on image.</param> /// <returns>An array of recognized key zones.</returns> protected override Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone[] Recognize(Vintasoft.Imaging.VintasoftImage image, System.Drawing.Rectangle rect) { Vintasoft.Barcode.BarcodeReader reader = new Vintasoft.Barcode.BarcodeReader(); reader.Settings = Settings.Clone(); reader.Settings.ScanRectangle = rect; using (System.Drawing.Bitmap bitmap = image.GetAsBitmap()) { Vintasoft.Barcode.IBarcodeInfo[] infos = reader.ReadBarcodes(bitmap); Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone[] result = new Vintasoft.Imaging.FormsProcessing.TemplateMatching.KeyZone[infos.Length]; for (int i = 0; i < infos.Length; i++) result[i] = new BarcodeKeyZone(infos[i]); return result; } } #endregion }