Методы обработки изображений - прямое манипулирование целевым изображением или виртуализация?
Мне нужно повторно спроецировать серию изображений Ариэля, которые были привязаны в географической системе координат, в проекцию UTM. Я читал, что использование getPixel и setPixel может быть медленным - следует установить серию 2-мерных массивов для промежуточного доступа, а затем сбросить значения в целевое изображение, когда я закончу.
Обычно это обработка изображений выполняется профессионалами?
4 ответа
Большая часть обработки изображений - это обнаружение признаков, сегментация сцены, поиск неисправностей, классификация и отслеживание....
Вы можете взглянуть на книгу:
- Обработка изображений на С (применима и для других языков)
- Обработка изображений - принципы и применение
Который описывает множество быстрых и эффективных способов многих преобразований изображений. Эти две книги помогли мне, когда я обрабатывал изображения:)
Если я понимаю ваш вопрос... Если вы повторно выравниваете или собираете много изображений, и у вас нет ориентации, а также положения, вы можете использовать эти алгоритмы для повторного выравнивания краев и общих характеристик. Если вы выполняете сшивание по положению, тогда эти алгоритмы помогут повторно сэмплировать / изменить размеры ваших изображений для более эффективной сборки. Есть также несколько библиотек с открытым исходным кодом для такого рода вещей. (На ум приходит OpenCV)
редактировать: если бы я повторно проецировал большие изображения в новые проекции, основанные на преобразовании положения (и это было динамическое, а не статическое), я бы посмотрел на создание приложения по требованию, которое будет рефакторировать изображения с требуемым разрешением и желаемой позицией. Затем приложение может получить самое близкое разрешение изображений относительного соседства и предоставить результат с желаемым разрешением.
Надеюсь, без дополнительной информации это поможет!
edit 2: Комментарий от ответа ниже: Зависит от изображений. Если они имеют фиксированный размер, то массив может быть хорошим. Если они различаются, то может быть лучше внедрить систему, которая обеспечивает get / setpixel, используя относительную выборку / усреднение для сопоставления изображений с разным разрешением?
Я не знаю все входы и выходы изображений, с которыми вы работаете, и того, что вы делаете, но часто полезно абстрагироваться от "пикселя", а не от доступа к значениям в массиве. Таким образом, вы можете реализовать алгоритмы преобразования, выборки, поворота, исправления на бэкэнде. Как GetVPixel() или SetVPixel(). Это может быть более полезно при работе с несколькими, разными изображениями в формате res/format. подобно
SetVPixel(img1, coord1, GetVPixel(img2, coord2))
Очевидно, в ООП /C# манере. img1 и img2 могут отличаться по размеру, размеру, географическому расположению, выравниванию или чему-либо еще, если ваш бэкэнд понимает и то, и другое.
Если вы не возражаете против использования небезопасного кода, вы можете поместить BitmapData в растровое изображение в объект, который позволяет эффективно получать и устанавливать пиксели. Приведенный ниже код в основном взят из фильтра размытия по Гауссу, с несколькими моими модификациями. Это не самый гибкий код, если ваши форматы растровых изображений отличаются, но я надеюсь, что он иллюстрирует, как вы можете более эффективно управлять растровыми изображениями.
public unsafe class RawBitmap : IDisposable
{
private BitmapData _bitmapData;
private byte* _begin;
public RawBitmap(Bitmap originBitmap)
{
OriginBitmap = originBitmap;
_bitmapData = OriginBitmap.LockBits(new Rectangle(0, 0, OriginBitmap.Width, OriginBitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
_begin = (byte*)(void*)_bitmapData.Scan0;
}
#region IDisposable Members
public void Dispose()
{
OriginBitmap.UnlockBits(_bitmapData);
}
#endregion
public unsafe byte* Begin
{
get { return _begin; }
}
public unsafe byte* this[int x, int y]
{
get
{
return _begin + y * (_bitmapData.Stride) + x * 3;
}
}
public unsafe byte* this[int x, int y, int offset]
{
get
{
return _begin + y * (_bitmapData.Stride) + x * 3 + offset;
}
}
public unsafe void SetColor(int x, int y, Color color)
{
byte* p = this[x, y];
p[0] = color.B;
p[1] = color.G;
p[2] = color.R;
}
public unsafe Color GetColor(int x, int y)
{
byte* p = this[x, y];
return new Color
(
p[2],
p[1],
p[0]
);
}
public int Stride
{
get { return _bitmapData.Stride; }
}
public int Width
{
get { return _bitmapData.Width; }
}
public int Height
{
get { return _bitmapData.Height; }
}
public int GetOffset()
{
return _bitmapData.Stride - _bitmapData.Width * 3;
}
public Bitmap OriginBitmap { get; private set; }
}
Библиотека FreeImage довольно быстрая и предлагает вырезать и вставить, которые могут быть полезны. Дистрибутив поставляется с оболочкой C#.
AFAIK издержки GetPixel/SetPixel - это вызов к нему, при обращении к массиву нет вызова, следовательно, меньше накладных расходов.
Вы должны начать с GetPixel/SetPixel, вы всегда можете переопределить эти вызовы позже, чтобы использовать прямой доступ к данным.