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

keep the signed value that has minimal absolute value in two matrix in OpenCV

本文关键字:符号 绝对值 两个 OpenCV      更新时间:2023-10-16

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

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];
    }
}

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

您的代码不是程序的瓶颈。确实很快。你需要分析你的代码,看看实际的瓶颈在哪里


如果你的矩阵是连续的(这在实践中很常见),你可以对它进行一点优化,比如:

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速度较慢,但更简洁易读。

代码你可以用这个在你的电脑上计算结果:

#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: ttYuanhao ts1h ttMiki" << 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;
}