并行化元素矩阵 (2dArray) 计算

时间:2020-12-21 22:35:13

标签: c# arrays matrix optimization parallel-processing

这是我的第一个问题,我对 C# 比较陌生。 (原谅我英语不好)

我正在使用 .NET Framework 和 Visual Studio 中的 WindowsForms 应用程序在 C# 中编写模板匹配算法。遗憾的是,C#8.0 中的新索引和范围函数,尤其是范围运算符 (..),没有在 .NET Framework 中实现。我知道有一个解决方法,正如您在此 thread 中看到的那样,但 Microsoft 不支持它。所以我正在寻找另一种方法来并行化我的元素 2dArray(矩阵)计算,以使我的程序更快。

在我的程序中,我正在计算 2dArray(我的图像)和 2dArray(我的模板)内一个区域(具有我的模板的大小)的微分平方 (ds)。这些值被写入一个新的 2dAary (DS),它保存了图像相应位置的所有微分平方。我可以搜索DS的索引,其中差分平方最小,等于图像内模板的匹配位置(模板和图像之间的最高对应)。

在 python 中,使用索引范围运算符 (:) 计算 DS 非常快,如下所示:

H,W = I.shape                                # read out Height H & Width W from Image I
h,w = T.shape                                # read out Height h & Width w from Template T

for i in range(H-h+1):
        for j in range(W-w+1):
            DS[i,j] = np.sum((I[i:i+h,j:j+w] - T)**2)

但在 C# 中,我必须按元素计算 DS,因此它看起来像这样并且永远需要:

int Tw = template.Width;
int Th = template.Height;
int Iw = image.Width;
int Ih = image.Height;

int d = 0;
int[,] ds = new int[Tw, Th];
int[,] DS = new int[Iw - Tw + 1, Ih - Th + 1];
         
for (int y = 0; y < Ih - Th + 1; y++)
        {
            for (int x = 0; x < Iw - Tw + 1; x++)
            {
                for (int yT = 0; yT < Th; yT++)
                {
                    for (int xT = 0; xT < Tw; xT++)
                    {
                        d = I[x + xT, y + yT] - T[xT, yT];
                        ds[xt, yt] = d * d;
                    }
                }

                int sum = ds.Cast<int>().Sum();
                DS[x, y] = sum;
            }
        }

我知道我可以使用线程,但这对我来说有点复杂。 或者,也许我可以将 CUDA 与我的 Nvidia GPU 结合使用以加快速度。

但我问你和我自己是否有另一种方法来并行化(优化)我的元素级 2dArray 计算?

我期待任何帮助。 非常感谢提前!

编辑:

这里我有一个 .NET Framework 控制台应用程序代码的工作示例。正如您所看到的,我进行了很多元素方面的 2d 和 3d 数组计算,我想并行处理这些计算(或以任何其他方式更快地执行它们):

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TemplateMatcher_Console
{
    class Program
    {
        public static int[,,] bitmapToMatrix(Bitmap bmp)
        {
            int[,,] I = new int[bmp.Width, bmp.Height, 3];

            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    Color pix = bmp.GetPixel(x, y);

                    I[x, y, 0] = Convert.ToInt32(pix.R);
                    I[x, y, 1] = Convert.ToInt32(pix.G);
                    I[x, y, 2] = Convert.ToInt32(pix.B);
                }
            }

            return I;
        }

        public static int[] indexOfMiniumValue(int[,] matrix)
        {
            int value = 0;
            int minValue = 999999999;
            int minFirstIndex = 0;
            int minSecondIndex = 0;

            int[] ij = new int[2];

            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    value = matrix[i, j];

                    if (value < minValue)
                    {
                        minValue = value;

                        minFirstIndex = i;
                        minSecondIndex = j;
                    }
                }
            }

            ij[0] = minFirstIndex;
            ij[1] = minSecondIndex;

            return ij;
        }

        public static void Print2DArray<T>(T[,] matrix)
        {
            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    Console.Write(matrix[i, j] + "\t");
                }
                Console.WriteLine();
            }
        }

        static void Main(string[] args)
        {
            // Deklaration & Eingabe

            Console.WriteLine("Type the filepath for your image and then press Enter");
            string im = Console.ReadLine();

            Console.WriteLine("\nType the filepath for your template and then press Enter");
            string temp = Console.ReadLine();

            Bitmap template = new Bitmap(@temp);
            Bitmap image = new Bitmap(@im);

            int Tw = template.Width;
            int Th = template.Height;
            int Iw = image.Width;
            int Ih = image.Height;

            int[,] ds = new int[Tw, Th];
            int[,] DS = new int[Iw - Tw + 1, Ih - Th + 1];
            int[,,] DS_rgb = new int[Iw - Tw + 1, Ih - Th + 1, 3];

            int[] xy = new int[2];


            // Verarbeitung
            // int[,,] I = Array.ConvertAll(image_I, new Converter<byte, int>(Convert.ToInt32));
            int[,,] I = bitmapToMatrix(image);
            int[,,] T = bitmapToMatrix(template);


            for (int rgb = 0; rgb < 3; rgb++)
            {
                for (int y = 0; y < Ih - Th + 1; y++)
                {
                    for (int x = 0; x < Iw - Tw + 1; x++)
                    {
                        //DS_rgb[x, y, rgb] = (I[x .. x + template.Width, y .. y + template.Height, rgb] - T[0 .. template.Width, 0 .. template.Height, rgb]);
                        for (int yT = 0; yT < Th; yT++)
                        {
                            for (int xT = 0; xT < Tw; xT++)
                            {
                                ds[xT, yT] = (I[x + xT, y + yT, rgb] - T[xT, yT, rgb]) * (I[x + xT, y + yT, rgb] - T[xT, yT, rgb]);
                            }
                        }

                        int sum = ds.Cast<int>().Sum();
                        DS_rgb[x, y, rgb] = sum;
                    }
                }
            }


            //DS[.., ..] = DS_rgb[.., .., 0] + DS_rgb[.., .., 1] + DS_rgb[.., .., 2];
            for (int y = 0; y < Ih - Th + 1; y++)
            {
                for (int x = 0; x < Iw - Tw + 1; x++)
                {
                    DS[x, y] = DS_rgb[x, y, 0] + DS_rgb[x, y, 1] + DS_rgb[x, y, 2];
                }
            }

            //xy = DS.FindIndex(z => z == Math.Min(DS));
            xy = indexOfMiniumValue(DS);

            // Ausgabe

            // Ausgeben der Matrix DS
            /*
            Console.WriteLine("\nMatrix with all differtial squares:");
            Print2DArray(DS);
            */

            Console.WriteLine($"\nPosition of your template in your image (upper left corner): ({xy[0]}, {xy[1]})");
            Console.Write("\nPress any key to close the TemplateMatcher console app...");
            Console.ReadKey();
        }
    }
}

0 个答案:

没有答案