OpenCV - 加速3x3补丁的SSD计算

时间:2014-06-18 13:17:26

标签: c++ opencv image-processing

作为更大应用程序的一部分,我需要计算以下代码:

ax2 += (int)(25 + 0.5);
ay2 += (int)(25 + 0.5);

bx2 += (int)(25 + 0.5);
by2 += (int)(25 + 0.5);

cx2 += (int)(25 + 0.5);
cy2 += (int)(25 + 0.5);

    for (int ix = -1; ix <= 1; ix++){
        for (int iy = -1; iy <= 1; iy++){
            suma += (grayImage.at<uchar>(ay2 + iy, ax2 + ix) - grayImage.at<uchar>(by2 + iy, bx2 + ix))* grayImage.at<uchar>(ay2 + iy, ax2 + ix) - grayImage.at<uchar>(by2 + iy, bx2 + ix));
}
}

它基本上计算两个3X3补丁的平方差的总和。

它运行得非常慢。有没有办法加快速度?

编辑:

我改为以下版本:

for (int ix = -1; ix <= 1; ix++){
        for (int iy = -1; iy <= 1; iy++){
            double difa = grayImage.at<uchar>(ay2 + iy, ax2 + ix) - grayImage.at<uchar>(by2 + iy, bx2 + ix);
            suma += (difa)*(difa);
        }
}

它运行得更快,但有没有办法进一步改进它?

谢谢,

吉尔。

编辑:在评论和答案之后,我没有使用以下代码:

//int iy = -1;
     Mi_a = grayImage.ptr<uchar>(ay2 - 1);
     Mi_b = grayImage.ptr<uchar>(by2 - 1);
     Mi_c = grayImage.ptr<uchar>(cy2 - 1);

    difa = Mi_a[ax2 - 1] - Mi_b[bx2 - 1];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 - 1] - Mi_b[bx2 - 1];
    sumc += (difc)*(difc);
    difa = Mi_a[ax2 + 0] - Mi_b[bx2 + 0];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 + 0] - Mi_b[bx2 + 0];
    sumc += (difc)*(difc);
    difa = Mi_a[ax2 + 1] - Mi_b[bx2 + 1];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 + 1] - Mi_b[bx2 + 1];
    sumc += (difc)*(difc);



    //int iy=0;
    Mi_a = grayImage.ptr<uchar>(ay2 + 0);
    Mi_b = grayImage.ptr<uchar>(by2 + 0);
    Mi_c = grayImage.ptr<uchar>(cy2 + 0);

    difa = Mi_a[ax2 - 1] - Mi_b[bx2 - 1];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 - 1] - Mi_b[bx2 - 1];
    sumc += (difc)*(difc);
    difa = Mi_a[ax2 + 0] - Mi_b[bx2 + 0];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 + 0] - Mi_b[bx2 + 0];
    sumc += (difc)*(difc);
    difa = Mi_a[ax2 + 1] - Mi_b[bx2 + 1];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 + 1] - Mi_b[bx2 + 1];
    sumc += (difc)*(difc);


    //int iy=1
    Mi_a = grayImage.ptr<uchar>(ay2 + 1);
    Mi_b = grayImage.ptr<uchar>(by2 + 1);
    Mi_c = grayImage.ptr<uchar>(cy2 + 1);

    difa = Mi_a[ax2 - 1] - Mi_b[bx2 - 1];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 - 1] - Mi_b[bx2 - 1];
    sumc += (difc)*(difc);
    difa = Mi_a[ax2 + 0] - Mi_b[bx2 + 0];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 + 0] - Mi_b[bx2 + 0];
    sumc += (difc)*(difc);
    difa = Mi_a[ax2 + 1] - Mi_b[bx2 + 1];
    suma += (difa)*(difa);
    difc = Mi_c[cx2 + 1] - Mi_b[bx2 + 1];
    sumc += (difc)*(difc);

或者它的循环版本具有相同的运行时间:

for (int iy = -1; iy <= 1; iy++)
    {
        const uchar * Mi_a = grayImage.ptr<uchar>(ay2 + iy);
        const uchar * Mi_b = grayImage.ptr<uchar>(by2 + iy);
        const uchar * Mi_c = grayImage.ptr<uchar>(cy2 + iy);
        for (int ix = -1; ix <= 1; ix++)
        {
            double difa = Mi_a[ax2 + ix] - Mi_b[bx2 + ix];
            suma += (difa)*(difa);

            double difc = Mi_c[cx2 + ix] - Mi_b[bx2 + ix];
            sumc += (difc)*(difc);
        }
    }

有没有办法进一步加快速度?

由于

吉尔

1 个答案:

答案 0 :(得分:4)

来自OpenCv Mat documentation

  

如果需要处理整个2D数组,最有效的方法是首先获取指向行的指针,然后只使用普通的C运算符[]

所以:

for (int iy = -1; iy <= 1; iy++)
{
    const uchar * Mi_a = grayImage.ptr<uchar>(ay2 + iy);
    const uchar * Mi_b = grayImage.ptr<uchar>(by2 + iy);

    for (int ix = -1; ix <= 1; ix++)
    {
        double difa = Mi_a[ax2 + ix] - Mi_b[bx2 + ix]
        suma += (difa)*(difa);
    }    
}