Я пытаюсь создать программу, которая, используя указатели, обнаруживает линии в изображении и удаляет эти строки. В настоящее время часть обнаруживающих линий работает очень хорошо, и по большей части также работает удаление части линий. Однако после примерно 150-200 изображений программа будет генерировать случайные AccessViolationExceptions в местах, которые не имеют ничего общего с небезопасными битами кода.Random AccessViolationException от работы с растровыми изображениями
Это бит, что делает удаление строки:
static unsafe Bitmap RemoveLines(Bitmap input, int[] horizontalLines, int[] verticalLines)
{
Bitmap output;
if (input.PixelFormat == PixelFormat.Format24bppRgb)
{
output = (Bitmap) input.Clone();
}
else
{
output = ConvertTo24bpp((Bitmap)input.Clone());
}
BitmapData bitmapData = output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.ReadWrite, output.PixelFormat);
int w = output.Width;
int h = output.Height;
int bpp = 3;
int s = bitmapData.Stride;
byte* p = (byte*) bitmapData.Scan0;
for (int r = 0; r < h; r++)
{
for (int c = 0; c < h; c++)
{
if (horizontalLines.Contains(r) || verticalLines.Contains(c))
{
int i = (r * s) + c * bpp;
p[i + 0] = 255;
p[i + 1] = 255;
p[i + 2] = 255;
}
}
}
output.UnlockBits(bitmapData);
return output;
}
После этого кода, я сохранить полученный Bitmap, а также встраивание его в другой Bitmap для целей сравнения:
// ... Detect lines and such
Bitmap export = new Bitmap(bitmap.Width * 3, bitmap.Height, PixelFormat.Format24bppRgb);
Graphics fg = Graphics.FromImage(export);
fg.DrawImage(bitmap, 0, 0); // Draw the original input bitmap
fg.DrawImage(edited, bitmap.Width, 0); // Draw the input after processing (Line Detection)
try
{
Bitmap lineRemoved = RemoveLines(bitmap, horizontalLines.ToArray(), verticalLines.ToArray()); // Remove lines based on earlier detection
lineRemoved.Save(cellDirectory + "\\Lines\\cell_lr_" + i.ToString("D2") + j.ToString("D2") + ".gif", ImageFormat.Gif); // Save image after removal
fg.DrawImage(lineRemoved, bitmap.Width * 2, 0); // Add image to composite for comparison; This line is what throws the error most of the time
lineRemoved.Dispose();
export.Save(cellDirectory + "\\Lines\\cell" + i.ToString("D2") + j.ToString("D2") + ".gif", ImageFormat.Gif);
}
catch (Exception ex)
{ }
Вызов DrawImage - это то, что вызывает ошибки, и это всегда исключение AccessViolationException, за которым следует исключение InvalidOperationException. Глядя на lineRemoved во время ошибки, видно, что большинство ее членов «выбрали исключение типа InvalidOperationException» вместо реальных значений, хотя одна строка до того, как один битмарт был сохранен просто отлично. Растровое изображение ввода остается неизменным во всем коде и всегда клонируется или рисуется в другое растровое изображение, когда мне нужно его каким-либо образом изменить.
Я пробовал комментировать строки после сохранения строкиРедактировал, но затем эта же ошибка появляется позже в коде. Более того, try/catch фактически не захватывает Exception - он всегда говорит о необработанном. Это должно быть чем-то связано с указателями, но в остальном я полностью потерял то, что вызывает это.
для (int c = 0; c
@KrisVandermotten Это своего рода замедление смущения. Возникла проблема, когда удаление линии не охватывало весь образ, но я поставил эту проблему в более низкий приоритет, чтобы выяснить ее. Конечно, решение было бы одинаковым для обоих вопросов ... – Abion47
«замедленное смущение» :-) «Конечно, решение было бы одинаковым для обоих вопросов». Подтверждаете ли вы, что нарушения доступа ушли? –