我有一张尺寸为8192 * 8192的大图像
img
,我有3个尺寸为4096 * 4096的矩阵:
矩阵
X
包含 x 像素坐标
矩阵
Y
包含 y 像素坐标
矩阵
RGB
包含RGB值
对于矩阵中的每个值,我想用 rgb 值填充像素 x,y 处的
img
。
示例: 如果 X[0,0] = 500,Y[0,0] = 200 且 RGB[0,0] = (255,0,0),则大图像[500,200] = (255,0,0)
到目前为止我有这个
public void Test()
{
Image<Bgr, byte> img = new(8196, 8192);
//Parameter
int size = 4096;
Image<Gray, int> X = new(size, size);
Image<Gray, int> Y = new(size, size);
Image<Bgr, byte> rgb = new(size, size);
//Timer
Stopwatch cs = new Stopwatch();
cs.Start();
Parallel.For(0, size, i =>
{
for (int j = 0; j < size; j++)
{
int xTarget = (int)X[i, j].Intensity;
int yTarget = (int)Y[i, j].Intensity;
Bgr bgrTarget = rgb[i, j];
img[xTarget, yTarget] = bgrTarget;
}
});
cs.Stop();
MessageBox.Show(cs.ElapsedMilliseconds.ToString());
}
有没有更有效的方法?
有没有更有效的方法?
其实不然。您需要至少处理每个 X/Y 像素一次,因此您无法获得任何算法改进。
可能会得到一些微观优化。例如,当从 X 和 Y 图像中读取值时,代码会将整数转换为双精度型,然后再转换回来,这可能会降低一些性能。使用不安全的代码和指针也可能会稍微快一些。但我不确定在不放弃 emgu 图像的情况下是否可以解决这两个问题。但我希望这只是相当小的改进。
我主要担心的是代码不是确定性的。如果存在任何重复的 x 和 y 坐标,则不会得到一致的结果。在不同时间运行具有相同输入的代码可能会导致不同的输出。我无法判断是否会发生这种情况,或者这是否会成为问题。
另一个潜在问题是您正在写入 24 位每像素图像。这意味着像素将不是 4 字节对齐的。我认为写入仍然应该是原子的,因此是线程安全的。但我相当确定这至少会损害性能,因为 CPU 喜欢以较大的块跟踪内存,而跨块边界的操作往往会受到影响。因此,我至少会尝试在 rgb
图像中使用 bgra(即每像素 32 位,对齐得更好)作为输出格式,看看它是否有任何区别。
避免在 Parallel.For 内使用异步:通常不需要在 Parallel.For 循环内使用异步,除非您在循环内执行一些异步 I/O 操作。删除不必要的异步应该可以提高性能。
避免不必要的数组访问:每次执行 X[i, j].Intensity 或类似操作时,您都在执行数组访问,这会产生开销。相反,请考虑将值缓存在局部变量中。
更正循环大小:大小 - 0,这只是大小。