C#,使用输入参数填充图像的有效方法

问题描述 投票:0回答:2

我有一张尺寸为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());
 }

有没有更有效的方法?

c# emgucv
2个回答
2
投票

有没有更有效的方法?

其实不然。您需要至少处理每个 X/Y 像素一次,因此您无法获得任何算法改进。

可能会得到一些微观优化。例如,当从 X 和 Y 图像中读取值时,代码会将整数转换为双精度型,然后再转换回来,这可能会降低一些性能。使用不安全的代码和指针也可能会稍微快一些。但我不确定在不放弃 emgu 图像的情况下是否可以解决这两个问题。但我希望这只是相当小的改进。

我主要担心的是代码不是确定性的。如果存在任何重复的 x 和 y 坐标,则不会得到一致的结果。在不同时间运行具有相同输入的代码可能会导致不同的输出。我无法判断是否会发生这种情况,或者这是否会成为问题。

另一个潜在问题是您正在写入 24 位每像素图像。这意味着像素将不是 4 字节对齐的。我认为写入仍然应该是原子的,因此是线程安全的。但我相当确定这至少会损害性能,因为 CPU 喜欢以较大的块跟踪内存,而跨块边界的操作往往会受到影响。因此,我至少会尝试在 rgb 图像中使用 bgra(即每像素 32 位,对齐得更好)作为输出格式,看看它是否有任何区别。

    


1
投票

避免在 Parallel.For 内使用异步:通常不需要在 Parallel.For 循环内使用异步,除非您在循环内执行一些异步 I/O 操作。删除不必要的异步应该可以提高性能。

避免不必要的数组访问:每次执行 X[i, j].Intensity 或类似操作时,您都在执行数组访问,这会产生开销。相反,请考虑将值缓存在局部变量中。

更正循环大小:大小 - 0,这只是大小。

© www.soinside.com 2019 - 2024. All rights reserved.