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

时间:2012-05-30 23:40:08

标签: 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);
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

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