【问题标题】:How to do per-element comparison and do different operation according to result如何进行逐元素比较并根据结果进行不同的操作
【发布时间】:2013-08-28 12:39:11
【问题描述】:

我在 C++ 中使用 OpenCV,但我陷入了困境。我需要执行以下操作:

if(src(I) < aNumber)
     do operation1
else
     do operation2

对于 1000x750 图像,For 循环需要 100 多毫秒。我不想使用for 循环,因为它需要很多时间。我想使用一个(一些)OpenCV 函数和那个函数,我可以编辑矩阵中的一些值。比如我的数组是

[1 4 5;
 4 6 2;
 3 2 1]

我想要:

if(an element of mat < 4)
    pow(element,2)
else
    element--;

据此if-else

[1 3 4;
 3 5 4
 9 4 1]

将成为我的结果矩阵。

除了使用两个for 循环之外,有没有人知道任何处理这个问题的函数?

【问题讨论】:

  • 您是否正在尝试优化您的代码?什么“for循环”?,您应该发布更大的sn-p代码以显示src()和我是什么,并显示for循环......然后......问一个具体问题:)跨度>
  • 一般而言,对于向量化操作,您需要执行这两个操作,然后根据src(I) 的值合并结果(使用按位操作)。我不知道opencv,但可能有更明确的方法支持这一点。
  • 我已经编辑了这个问题。抱歉最初的问题是:)

标签: c++ opencv matrix


【解决方案1】:

您可能想查看compare。示例:

//Mat mask; compare(src, 10.0, mask, CMP_LT);
Mat mask = src < 10.0;

根据您希望执行的实际操作,您可以使用比较的结果,否则您可以查看gpu module。特别是Per-element Operations

就我个人而言,我觉得 OpenCV 应该有点像 MATLAB,避免循环,使用矩阵,并尽可能尝试使用内置函数(即使它们只是作为循环实现,它也可以节省你输入同样的事情一次又一次)。

编辑:以下是使用循环和使用内置矩阵运算符实现更新问题中任务的示例代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
//#include <opencv2/gpu/gpu.hpp>
using namespace cv;

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
    // Load Image
    Mat matImage = imread("Test.png");

    // Convert to Grayscale
    Mat matGray(matImage.rows, matImage.cols, CV_8UC1);
    cvtColor(matImage, matGray, CV_BGR2GRAY);

    double time, dThreshold = 50.0;
    //int TIMES = 1000;

    //namedWindow("Display", WINDOW_NORMAL);
    //char chKey;

    //imshow("Display", matGray);
    //chKey = '\0'; while (chKey != '') chKey = waitKey(0);

    //----------------------------- Loop Method -------------------------------

    time = (double) getTickCount();

    //for (int k = 0; k < TIMES; k++)
    //{
        Mat matLoop = matGray.clone();

        for (int i = 0; i < matLoop.rows; ++i)
        {
            for (int j = 0; j < matLoop.cols; ++j)
            {
                uchar& unValue = matLoop.at<uchar>(i, j);
                if (unValue < dThreshold)
                    unValue = pow(unValue, 2);
                else
                    unValue--;
            }
        }
    //}

    time = 1000*((double)getTickCount() - time)/getTickFrequency();
    //time /= TIMES;
    cout << "Loop Method Time: " << time << " milliseconds." << endl;

    //imshow("Display", matLoop);
    //chKey = '\0'; while (chKey != '') chKey = waitKey(0);

    //---------------------------- Matrix Method ------------------------------

    time = (double) getTickCount();

    //for (int i = 0; i < TIMES; i++)
    //{
        Mat matMask, matMatrix;

        matMask = matGray < dThreshold;
        bitwise_and(matGray, matMask, matMatrix);
        pow(matMatrix, 2.0, matMatrix);
        subtract(matGray, 1.0, matMatrix, ~matMask);
    //}

    time = 1000*((double)getTickCount() - time)/getTickFrequency();
    //time /= TIMES;
    cout << "Matrix Method Time: " << time << " milliseconds." << endl;

    //imshow("Display", matMatrix);
    //chKey = '\0'; while (chKey != '') chKey = waitKey(0);

    return 0;
}

除了将需要键入的代码行数从 12 行减少到 5 行之外,矩阵方法也更快。启用定时循环(使用TIMES = 1000;),我得到以下时间用于中等大小的图像:

Loop Method Time: 9.19669 milliseconds.
Matrix Method Time: 2.82657 milliseconds.

使用 gpu 模块我相信您可以进一步减少第二次,但不幸的是我目前没有合适的显卡连接到我当前的系统。

【讨论】:

  • 我已经检查了比较,但它使某些值等于 255。如果我能找到一种使用它的方法,那就太好了。另外,我可以直接使用 gpu 模块还是应该安装 CUDA 或其他一些库?
  • @smttsp 我已经用一个使用compare 创建掩码的示例更新了我的答案。
  • 非常感谢。这就是我需要的。还有两个问题:图像的大小是多少?你能指导我如何使用 gpu 模块吗?例如,如果我写gpu::add(...) 或者我应该做更多的事情,而不是add(...) 函数,我的代码会更快吗?注:我看过opencv gpu归纳
  • 图片尺寸为 960x540(大、中或小,取决于您对世界的看法)。使用 GPU 的代码有时会更快,看看这个 (stackoverflow.com/questions/12074281/…) 问题。这 (on-demand.gputechconf.com/gtc/2013/webinar/…) 也可能会有所帮助。
猜你喜欢
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 2016-11-14
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
相关资源
最近更新 更多