我一直在寻找一种可靠的方法来对.NET中的图像进行去斜,但没有什么好的结果。
目前我正在使用AForge。这很麻烦,因为我正在使用WPF,所以我正在处理的图像是BitmapImage对象,而不是Bitmap对象,这意味着我需要从一个BitmapImage对象开始,将其保存到内存流中,然后从内存流中创建一个新的Bitmap对象,经过去斜过程,将去斜后的图像保存到新的内存流中,然后再从该内存流创建一个新的BitmapImage对象。不仅如此,还有去斜效果并不理想。
我正在尝试读取扫描到扫描仪中的一张纸上的OMR数据,因此我需要依赖于每次特定OMR框在相同的坐标位置,因此去斜需要是可靠的。
目前我正在使用AForge,我找不到其他免费/开源的.NET图像去斜库,我找到的所有内容要么非常昂贵,要么在C/C++中实现。
我的问题是是否存在其他免费/开源库可用于.NET中的图像去斜?如果是,它们叫什么,如果不是,我该如何解决这个问题?
编辑:例如,假设我有以下页面:
当我打印出来后,再将其扫描回扫描仪,它看起来像这样:
我需要对这个图像进行去斜,以使我的框每次都处于相同的位置。在现实世界中,有很多框,它们比较小,而且靠得很近,因此准确性很重要。
我目前的方法非常低效,很麻烦:
目前我正在使用AForge。这很麻烦,因为我正在使用WPF,所以我正在处理的图像是BitmapImage对象,而不是Bitmap对象,这意味着我需要从一个BitmapImage对象开始,将其保存到内存流中,然后从内存流中创建一个新的Bitmap对象,经过去斜过程,将去斜后的图像保存到新的内存流中,然后再从该内存流创建一个新的BitmapImage对象。不仅如此,还有去斜效果并不理想。
我正在尝试读取扫描到扫描仪中的一张纸上的OMR数据,因此我需要依赖于每次特定OMR框在相同的坐标位置,因此去斜需要是可靠的。
目前我正在使用AForge,我找不到其他免费/开源的.NET图像去斜库,我找到的所有内容要么非常昂贵,要么在C/C++中实现。
我的问题是是否存在其他免费/开源库可用于.NET中的图像去斜?如果是,它们叫什么,如果不是,我该如何解决这个问题?
编辑:例如,假设我有以下页面:
当我打印出来后,再将其扫描回扫描仪,它看起来像这样:
我需要对这个图像进行去斜,以使我的框每次都处于相同的位置。在现实世界中,有很多框,它们比较小,而且靠得很近,因此准确性很重要。
我目前的方法非常低效,很麻烦:
using AForge.Imaging;
using AForge.Imaging.Filters;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Media.Imaging;
public static BitmapImage DeskewBitmap(BitmapImage skewedBitmap)
{
//Using a memory stream to minimise disk IO
var memoryStream = BitmapImageToMemoryStream(skewedBitmap);
var bitmap = MemoryStreamToBitmap(memoryStream);
var skewAngle = CalculateSkewAngle(bitmap);
//Aforge needs a Bppp indexed image for the deskewing process
var bitmapConvertedToBbppIndexed = ConvertBitmapToBbppIndexed(bitmap);
var rotatedImage = DeskewBitmap(skewAngle, bitmapConvertedToBbppIndexed);
//I need to convert the image back to a non indexed format to put it back into a BitmapImage object
var imageConvertedToNonIndexed = ConvertImageToNonIndexed(rotatedImage);
var imageAsMemoryStream = BitmapToMemoryStream(imageConvertedToNonIndexed);
var memoryStreamAsBitmapImage = MemoryStreamToBitmapImage(imageAsMemoryStream);
return memoryStreamAsBitmapImage;
}
private static Bitmap ConvertImageToNonIndexed(Bitmap rotatedImage)
{
var imageConvertedToNonIndexed = rotatedImage.Clone(
new Rectangle(0, 0, rotatedImage.Width, rotatedImage.Height), PixelFormat.Format32bppArgb);
return imageConvertedToNonIndexed;
}
private static Bitmap DeskewBitmap(double skewAngle, Bitmap bitmapConvertedToBbppIndexed)
{
var rotationFilter = new RotateBilinear(-skewAngle) { FillColor = Color.White };
var rotatedImage = rotationFilter.Apply(bitmapConvertedToBbppIndexed);
return rotatedImage;
}
private static double CalculateSkewAngle(Bitmap bitmapConvertedToBbppIndexed)
{
var documentSkewChecker = new DocumentSkewChecker();
double skewAngle = documentSkewChecker.GetSkewAngle(bitmapConvertedToBbppIndexed);
return skewAngle;
}
private static Bitmap ConvertBitmapToBbppIndexed(Bitmap bitmap)
{
var bitmapConvertedToBbppIndexed = bitmap.Clone(
new Rectangle(0, 0, bitmap.Width, bitmap.Height), PixelFormat.Format8bppIndexed);
return bitmapConvertedToBbppIndexed;
}
private static BitmapImage ResizeBitmap(BitmapImage originalBitmap, int desiredWidth, int desiredHeight)
{
var ms = BitmapImageToMemoryStream(originalBitmap);
ms.Position = 0;
var result = new BitmapImage();
result.BeginInit();
result.DecodePixelHeight = desiredHeight;
result.DecodePixelWidth = desiredWidth;
result.StreamSource = ms;
result.CacheOption = BitmapCacheOption.OnLoad;
result.EndInit();
result.Freeze();
return result;
}
private static MemoryStream BitmapImageToMemoryStream(BitmapImage image)
{
var ms = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(ms);
return ms;
}
private static BitmapImage MemoryStreamToBitmapImage(MemoryStream ms)
{
ms.Position = 0;
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
}
private static Bitmap MemoryStreamToBitmap(MemoryStream ms)
{
return new Bitmap(ms);
}
private static MemoryStream BitmapToMemoryStream(Bitmap image)
{
var memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Bmp);
return memoryStream;
}
回顾过去,还有几个问题:
- 我是否正确地使用AForge?
- AForge是用于执行此任务的最佳库吗?
- 如何改进我的当前方法以获得更准确的结果?