我有一个代表3D图像的大型数据集(大约100,000,000像素)。我想反转沿着' z'图像的轴。我的数据存储在一个字节数组中,数据排序为x,y,z(即[] = {(x = 0,y,z = 0),(x = 1,y = 0,z = 0), (x = 2,y = 0,z = 0)......)
我可以使用以下代码轻松对它们进行排序,但我希望尽可能减少计算时间(目前报告大约7秒)。我正在考虑使用数组'排序'函数,但不知道如何处理索引。
这是我目前的代码:
private int GetIndex(Image _image, int _x, int _y, int _z)
{
return (_z * _image.Size.X * _image.Size.Y) + (_y * _image.Size.X) + _x;;
}
private void InvertZ(Image _image)
{
for (int z = 0; z < _image.Size.Z/2; z++)
{
for (int y = 0; y < _image.Size.Y; y++)
{
for (int x = 0; x < _image.Size.X; x++)
{
int srcIndex = GetIndex(_image, x, y, z);
int destIndex = GetIndex(_image, x, y, _image.Size.Z - z - 1);
byte src = _image.Buffer[srcIndex];
byte dest = _image.Buffer[destIndex];
_image.Buffer[srcIndex] = dest;
_image.Buffer[destIndex] = src;
}
}
}
}
答案 0 :(得分:1)
一种解决方案是复制每个帧。大幅减少迭代次数。
private void InvertZ(Image _image)
{
int frameSize = _image.Size.X * _image.Size.Y;
byte[] temp = new byte[frameSize];
for (int z = 0; z < _image.Size.Z / 2; z++)
{
int inverseZ = _image.Size.Z - z - 1;
Array.Copy(_image.Buffer, z * frameSize, temp, 0, frameSize);
Array.Copy(_image.Buffer, inverseZ * frameSize, _image.Buffer, z * frameSize, frameSize);
Array.Copy(temp, 0, _image.Buffer, inverseZ * frameSize, frameSize);
}
}
运行时间约&lt; 18毫秒与3175毫秒相比。
答案 1 :(得分:0)
即使它使用多个循环(每个轴一个循环),这可能比单循环解决方案更快。
有两种主要的速度增强功能(图像处理中非常常见的算法增强功能)。
图像被转换为数组以便快速进行腿部练习
索引在循环中部分预先计算,确保尽可能少地计算。 (不再使用Image中的内置物,这对于一个像素和另一个像素都很好但不适合整个地图)
我通常只在2d上完成这项工作,所以只添加了z轴。将它作为最后一个循环可能会更快。 (边缘示例在2d运行,如果y在x之前,那么由于内存/缓存的构建方式,你会以大约30-40%的速度运行Src这也发生在3d(这就是为什么我放置了z(前面的水平/页面))
以下是我将以解决方案为基础的代码。
private void InvertZ(Image _image)
{
byte[] array =imageToByteArray(_image);
int pageSize = _Image.Size.Y * _Image.Size.X;
for (int z = 0; z < _image.Size.Z/2; z++)
{
int level = z * pageSize;
int dstLevel = (_image.Size.Z - z - 1) * pageSize;
for (int x = 0; x < _image.Size.X; x++)
{
int Row = x*_Image.Size.Y;
int RowOnLevel = level + Row ;
int dstRowOnLevel = dstLevel + xRow;
for (int y = 0; y < _image.Size.Y; y++)
{
int srcIndex = RowOnLevel + y;
int destIndex = dstRowOnLevel + y;
byte tmpDest = array[destIndex];
array[destIndex] = array[srcIndex];
array[srcIndex] = tmpDest;
}
}
}
return byteArrayToImage(array);
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
答案 2 :(得分:0)
你可以使用数组布局就是这样的事实
Z Length
==== ======
[0] x * y
[1] x * y
[2] x * y
...
[z-1] x * y
这使我们可以大大减少索引计算。我们可以使用像这样的经典O(N)反向算法的变体
static void InvertZ(Image _image)
{
int len = _image.Size.X * _image.Size.Y;
for (int lo = 0, hi = (_image.Size.Z - 1) * len; lo < hi; lo += len, hi -= len)
for (int i = 0; i < len; i++)
Swap(ref _image.Buffer[lo + i], ref _image.Buffer[hi + i]);
}
static void Swap<T>(ref T a, ref T b) { var c = a; a = b; b = c; }