保留OpenCV中两个矩阵中具有最小绝对值的有符号值

时间:2015-12-19 06:52:47

标签: c++ opencv matrix

在OpenCV中,我有两个相同大小的矩阵One和Two。我想在两个矩阵中找到具有最小绝对值的带符号值,并将其保留在矩阵One中。为此,我使用以下代码:

for (int i = 0; i < One.rows; ++i)
{
    p=One.ptr<float>(i);
    p_two = Two.ptr<float>(i);
    for (int j = 0; j < One.cols; ++j)
    {
        if(fabsf(p_two[j])<fabsf(p[j])) 
             p[j] = p_two[j];
    }
}

这段代码似乎是我程序中的瓶颈。有谁知道如何提高性能?非常感谢!

1 个答案:

答案 0 :(得分:1)

您的代码不是您的程序的瓶颈。它确实非常快。您需要分析代码以查看实际瓶颈的位置。

如果您的矩阵是连续的(通常在实践中),您可以稍微优化它,例如:

int rows = one.rows;
int cols = one.cols;
if (one.isContinuous() && two.isContinuous())
{
    cols = rows * cols;
    rows = 1;
}

for (int r = 0; r < rows; ++r)
{
    float* pone = one.ptr<float>(r);
    float* ptwo = two.ptr<float>(r);
    for (int c = 0; c < cols; ++c)
    {
        if (fabs(ptwo[c]) < fabs(pone[c]))
        {
            pone[c] = ptwo[c];
        }
    }
}

这里还有一个小评价,也反对@ s1h在评论中提出的好的替代方法:

two.copyTo(one, abs(two) < abs(one));

时间(以毫秒为单位)

Size:           Yuanhao         s1h             Miki
[3 x 3]         0.000366543     0.117294        0.000366543
[10 x 10]       0.00109963      0.0157614       0.00109963
[100 x 100]     0.0964009       0.139653        0.112529
[1280 x 720]    8.70577         11.0267         8.65372
[1000 x 1000]   9.66538         13.5068         9.02026
[1920 x 1080]   16.5681         26.9706         15.7412
[4096 x 3112]   104.423         135.629         102.595
[5000 x 5000]   196.124         277.457         187.203

你看到你的方法非常快。我的速度要快一点。 @ s1h速度较慢,但​​更简洁易读。

<强>代码 您可以使用以下方法评估PC上的结果:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

int main()
{
    vector<Size> sizes{ Size(3, 3), Size(10, 10), Size(100, 100), Size(1280, 720), Size(1000, 1000), Size(1920, 1080), Size(4096, 3112), Size(5000, 5000) };

    cout << "Size: \t\tYuanhao \ts1h \t\tMiki" << endl;

    for (int is = 0; is < sizes.size(); ++is)
    {
        Size sz = sizes[is];

        cout << sz << "\t";

        Mat1f img1(sz);
        randu(img1, Scalar(-100), Scalar(100));

        Mat1f img2(sz);
        randu(img2, Scalar(-100), Scalar(100));

        {
            Mat1f one = img1.clone();
            Mat1f two = img2.clone();

            double tic = double(getTickCount());

            for (int r = 0; r < one.rows; ++r)
            {
                float* pone = one.ptr<float>(r);
                float* ptwo = two.ptr<float>(r);
                for (int c = 0; c < one.cols; ++c)
                {
                    if (fabs(ptwo[c]) < fabs(pone[c]))
                    {
                        pone[c] = ptwo[c];
                    }
                }
            }

            double toc = (double(getTickCount()) - tic) * 1000. / getTickFrequency();
            cout << toc << " \t";
        }


        {
            Mat1f one = img1.clone();
            Mat1f two = img2.clone();

            double tic = double(getTickCount());

            two.copyTo(one, abs(two) < abs(one));

            double toc = (double(getTickCount()) - tic) * 1000. / getTickFrequency();
            cout << toc << " \t";
        }


        {
            Mat1f one = img1.clone();
            Mat1f two = img2.clone();

            double tic = double(getTickCount());

            int rows = one.rows;
            int cols = one.cols;
            if (one.isContinuous() && two.isContinuous())
            {
                cols = rows * cols;
                rows = 1;
            }

            for (int r = 0; r < rows; ++r)
            {
                float* pone = one.ptr<float>(r);
                float* ptwo = two.ptr<float>(r);
                for (int c = 0; c < cols; ++c)
                {
                    if (fabs(ptwo[c]) < fabs(pone[c]))
                    {
                        pone[c] = ptwo[c];
                    }
                }
            }

            double toc = (double(getTickCount()) - tic) * 1000. / getTickFrequency();
            cout << toc << " \t";
        }

        cout << endl;
    }

    getchar();
    return 0;
}