c++ - 将矩阵应用于图像,寻求性能改进

标签 c++ c performance image-processing matrix-multiplication

编辑:在 Windows 平台上工作。

问题:问题少了,建议多了。我目前不太精通低级程序,但我正在尝试优化下面的代码以提高我的整体代码的性能。此应用程序依赖于极高速的图像处理。

当前性能:在我的计算机上,当前计算 512x512 图像的时间约为 4-6 毫秒。如果可能的话,我想把它减半。

局限性:由于此项目规模庞大,因此很难对应用程序进行根本性更改,因此移植到 DirectX 或其他 GPU 方法等操作不太可行。该项目目前正在运行,我只是想弄清楚如何让它运行得更快。

关于我对此的使用的具体信息:进入此方法的图像总是完全正方形并且增量为 128。(最有可能是 512 x 512)他们总是会出来相同的大小。除此之外,没有别的了。矩阵是在别处计算的,所以这只是将矩阵应用于我的图像。原镜像和新镜像都在使用,所以复制镜像是必要的。

这是我当前的实现:

void ReprojectRectangle( double *mpProjMatrix, unsigned char *pDstScan0, unsigned char *pSrcScan0, 
        int NewBitmapDataStride, int SrcBitmapDataStride, int YOffset, double InversedAspect, int RectX, int RectY, int RectW, int RectH)
        {
            int      i, j;
            double   Xnorm, Ynorm;
            double  Ynorm_X_ProjMatrix4, Ynorm_X_ProjMatrix5, Ynorm_X_ProjMatrix7;;         
            double   SrcX, SrcY, T;
            int      SrcXnt, SrcYnt;
            int      SrcXec, SrcYec, SrcYnvDec;
            unsigned char   *pNewPtr, *pSrcPtr1, *pSrcPtr2, *pSrcPtr3, *pSrcPtr4;
            int      RectX2, RectY2;

            /* Compensate (or re-center) the Y-coordinate regarding the aspect ratio */
            RectY -= YOffset;   

            /* Compute the second point of the rectangle for the loops */
            RectX2 = RectX + RectW;
            RectY2 = RectY + RectH;

            /* Clamp values (be careful with aspect ratio */
            if (RectY < 0) RectY = 0;
            if (RectY2 < 0) RectY2 = 0;
            if ((double)RectY > (InversedAspect * 512.0)) RectY = (int)(InversedAspect * 512.0);
            if ((double)RectY2 > (InversedAspect * 512.0)) RectY2 = (int)(InversedAspect * 512.0);

            /* Iterate through each pixel of the scaled re-Proj */
            for (i=RectY; i<RectY2; i++)
            {      
            /* Normalize Y-coordinate and take the ratio into account */
            Ynorm = InversedAspect - (double)i / 512.0;

            /* Pre-compute some matrix coefficients */
            Ynorm_X_ProjMatrix4 = Ynorm * mpProjMatrix[4] + mpProjMatrix[12];
            Ynorm_X_ProjMatrix5 = Ynorm * mpProjMatrix[5] + mpProjMatrix[13];
            Ynorm_X_ProjMatrix7 = Ynorm * mpProjMatrix[7] + mpProjMatrix[15];

            for (j=RectX; j<RectX2; j++)
            {
                 /* Get a pointer to the pixel on (i,j) */
                 pNewPtr = pDstScan0 + ((i+YOffset) * NewBitmapDataStride) + j;

                 /* Normalize X-coordinates */
                 Xnorm = (double)j / 512.0;                  

                 /* Compute the corresponding coordinates in the source image, before Proj and normalize source coordinates*/
                 T =    (Xnorm * mpProjMatrix[3] + Ynorm_X_ProjMatrix7);
                 SrcY = (Xnorm * mpProjMatrix[0] + Ynorm_X_ProjMatrix4)/T;
                 SrcX = (Xnorm * mpProjMatrix[1] + Ynorm_X_ProjMatrix5)/T;

                // Compute the integer and decimal values of the coordinates in the sources image                     
                SrcXnt = (int) SrcX;
                SrcYnt = (int) SrcY;
                SrcXec = 64 - (int) ((SrcX - (double) SrcXnt) * 64);
                SrcYec = 64 - (int) ((SrcY - (double) SrcYnt) * 64);

                // Get the values of the four pixels up down right left
                pSrcPtr1 = pSrcScan0 + (SrcXnt * SrcBitmapDataStride) + SrcYnt;
                pSrcPtr2 = pSrcPtr1 + 1;
                pSrcPtr3 = pSrcScan0 + ((SrcXnt+1) * SrcBitmapDataStride) + SrcYnt;
                pSrcPtr4 = pSrcPtr3 + 1;

                SrcYnvDec = (64-SrcYec);

                (*pNewPtr) = (unsigned char)(((SrcYec * (*pSrcPtr1) + SrcYnvDec * (*pSrcPtr2)) * SrcXec + 
                                         (SrcYec * (*pSrcPtr3) + SrcYnvDec * (*pSrcPtr4)) * (64 - SrcXec)) >> 12);
            }
        }
    }

最佳答案

有两件事可以提供帮助:多处理和 SIMD。使用多处理,您可以将输出图像分解为多个图 block ,并让每个处理器处理下一个可用的图 block 。您可以使用 SIMD指令(如 SSE、AVX、AltiVec 等)同时计算多项内容,例如同时对多个坐标执行相同的矩阵数学运算。您甚至可以将两者结合起来——使用多个运行 SIMD 指令的处理器来完成尽可能多的工作。你没有提到你在哪个平台上工作。

关于c++ - 将矩阵应用于图像,寻求性能改进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10825730/

相关文章:

c++ - 什么应该是一个随机变量总是生成 5

c - 如何用2个线程同时读取/写入文件?

c# - 小于 0-255 时按位二进制溢出,例如0-32?

c++ - 为什么要声明一个 double 组来存储一个整数(C++)

c++ - SFML SoundBuffer 到音乐缓冲区

c++ - C++ 程序中的 C 头文件

C 输出模糊度

java - Apache Ignite BinaryObject 膨胀

scala - 为什么在 Scala 中压缩比 zip 快?

C++ REST SDK 如何检查http地址是否无效