В настоящее время я участвую в проекте, где у меня очень большие объемы изображений. Эти тома должны обрабатываться очень быстро (сложение, вычитание, пороговое значение и т. Д.). Кроме того, большая часть тома настолько велика, что она не помещается в память системы.
По этой причине я создал абстрактный класс тома (VoxelVolume), который содержит данные тома и изображения и перегружает операторы, чтобы можно было выполнять обычные математические операции над томами. Тем самым открылись еще два вопроса, которые я добавлю в stackoverflow в два дополнительных потока.
Вот мой первый вопрос. Мой том реализован таким образом, что он может содержать только данные массива с плавающей запятой, но большинство содержащихся данных получены из источника изображения UInt16. Только операции с томом могут создавать образы массивов с плавающей точкой.
Когда я начал реализовывать такой том, класс выглядел следующим образом:
public abstract class VoxelVolume<T>
{
...
}
но потом я понял, что перегрузка операторов или возвращаемых значений будет более сложной. Примером может быть:
public abstract class VoxelVolume<T>
{
...
public static VoxelVolume<T> Import<T>(param string[] files)
{
}
}
также добавление двух операторов перегрузки будет более сложным:
...
public static VoxelVolume<T> operator+(VoxelVolume<T> A, VoxelVolume<T> B)
{
...
}
Давайте предположим, что я могу преодолеть проблемы, описанные выше, тем не менее, у меня есть различные типы массивов, которые содержат данные изображения. Так как я установил свой тип в томах для плавания, это не проблема, и я могу сделать небезопасную операцию при добавлении содержимого двух массивов томов изображений. Я прочитал несколько веток здесь и осмотрел сеть, но не нашел по-настоящему хорошего объяснения того, что делать, когда я хочу быстро добавить два массива разных типов. К сожалению, каждая математическая операция над обобщениями невозможна, поскольку C # не может рассчитать размер базового типа данных. Конечно, можно обойти эту проблему, используя C ++ / CLR, но в настоящее время все, что я сделал до сих пор, работает в 32-битном и 64-битном режимах без необходимости что-либо делать. Переключение на C ++ / CLR показалось мне (приятно поправить меня, если я ошибаюсь), что я привязан к определенной платформе (32-битной) и мне нужно скомпилировать две сборки, когда я позволяю приложению работать на другой платформе (64-битной). Это правда?
Итак, коротко спросили: как можно быстро добавить два массива двух разных типов. Правда ли, что разработчики C # не думали об этом. Переключение на другой язык (C # -> C ++) не представляется возможным.
Я понимаю, что просто выполняя эту операцию
float []A = new float[]{1,2,3};
byte []B = new byte[]{1,2,3};
float []C = A+B;
невозможно и не нужно, хотя было бы неплохо, если бы это работало. Мое решение, которое я пробовал, заключалось в следующем:
public static class ArrayExt
{
public static unsafe TResult[] Add<T1, T2, TResult>(T1 []A, T2 []B)
{
// Assume the length of both arrays is equal
TResult[] result = new TResult[A.Length];
GCHandle h1 = GCHandle.Alloc (A, Pinned);
GCHandle h2 = GCHandle.Alloc (B, Pinned);
GCHandle hR = GCHandle.Alloc (C, Pinned);
void *ptrA = h1.ToPointer();
void *ptrB = h2.ToPointer();
void *ptrR = hR.ToPointer();
for (int i=0; i<A.Length; i++)
{
*((TResult *)ptrR) = (TResult *)((T1)*ptrA + (T2)*ptrB));
}
h1.Free();
h2.Free();
hR.Free();
return result;
}
}
Пожалуйста, извините, если приведенный выше код не совсем корректен, я написал его без использования редактора C #. Возможно ли такое решение, показанное выше? Пожалуйста, не стесняйтесь спрашивать, сделал ли я ошибку или описал некоторые вещи не полностью.
Спасибо за вашу помощь
Martin