Использование 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
}