Szukałem wysokiego i niskiego poziomu, aby uzyskać niezawodny sposób na zdjęcie obrazu w .Net, i nie mam dużo szczęścia.Korzystanie z .Net do korekcji obrazu
Z chwilą użycia Aforge. To jest ból, ponieważ pracuję z WPF, więc obrazy, z którymi pracuję są obiektami BitmapImage, w przeciwieństwie do obiektów Bitmap, co oznacza, że muszę zacząć od obiektu BitmapImage, zapisać go w strumieniu pamięci, utworzyć nowy obiekt Bitmap ze strumienia pamięci, przejdź przez proces usuwania, zapisz zniekształcony obraz do nowego strumienia pamięci, a następnie utwórz nowy obiekt BitmapImage ze wspomnianego strumienia pamięci. Nie tylko to, ale nie jest to świetne rozwiązanie.
Próbuję odczytać dane OMR z kawałka papieru zeskanowanego do skanera, a zatem muszę polegać na konkretnym polu OMR, które za każdym razem jest za każdym razem tak samo skorelowane, więc poprawa musi być niezawodna.
Używam Aforge z minuty na minutę, nie mogę znaleźć żadnych innych darmowych bibliotek/open source do tworzenia obrazów w .Net, wszystko co znalazłem jest albo odpowiednio drogie albo w C/C++.
Moje pytanie brzmi: czy istnieją inne biblioteki wolnego/otwartego źródła, które pomagają w tworzeniu obrazów w .Net? Jeśli tak, jak się nazywają, jeśli nie, w jaki sposób powinienem podejść do tego problemu?
Edit: Na przykład, powiedzmy, że mam poniższej strony:
Uwaga: To jest tylko dla celów poglądowych, ale rzeczywisty obraz rzeczywiście ma czarny prostokąt na każdym rogu stronę, może to pomoże.
Podczas drukowania na to uwagę i skanować je z powrotem do mojego skanera, wygląda to tak:
muszę prostowanie ten obraz tak, że moja skrzynka jest w tym samym miejscu za każdym razem. W prawdziwym świecie istnieje wiele pudeł, są mniejsze i blisko siebie, więc dokładność jest ważna.
Moja obecna metoda ta jest nieskuteczna masywny ból-in-the-ass:
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;
}
Z perspektywy czasu, jeszcze kilka pytań:
- używam AForge prawidłowo?
- Czy należy wybrać najlepszą bibliotekę do wykorzystania w tym zadaniu?
- W jaki sposób można poprawić moje obecne podejście, aby uzyskać dokładniejsze wyniki?
Jest to problem używania narzędzi do przetwarzania obrazu jako czarnej skrzynki. Istnieje wiele sposobów na rozluźnienie i ważne jest, aby wiedzieć, że stosowane podejście jest szczególnie użyteczne, gdy "nie jest wspaniałe". W przeciwnym razie, skąd wiadomo, czy inna prostokątna czarna skrzynka ma szansę uzyskać lepsze wyniki niż obecna czarna skrzynka? Letponica ma również metodę black-boxow, ale na http://tpgit.github.com/Leptonica/skew_8c.html możesz przeczytać, co robi. Istnieje również wiele innych sposobów, aby to osiągnąć. – mmgp
@mmgp Zgadzam się i chciałbym mieć czas na poznanie tajników algorytmu transformacji algorytmu i C++, ale niestety mam termin, więc black boxing jest teraz moją jedyną opcją! Dziękuję za link, sprawdzę to. – JMK
John, Czy mógłbyś umieścić link do obrazów, które masz problemy, lub dołączyć je do pytania? Ułatwi to ludziom odpowiedź. – DermFrench