2

编辑:在 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);
            }
        }
    }
4

1 回答 1

1

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

于 2012-05-30T23:57:13.563 回答