C ++ OpenCV:迭代Mat中的像素,这是另一个Mat的ROI [英] C++ OpenCV: Iterate through pixels in a Mat which is ROI of another Mat

查看:186
本文介绍了C ++ OpenCV:迭代Mat中的像素,这是另一个Mat的ROI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常大的Mat,它实际上是另一个Mat的ROI(由otherMat获得(cv :: Rect(x,y,w,h)))。我想通过Mat的所有像素,做一些像素计算并使用指针将结果写入另一个Mat。

I have a very large Mat which is actually a ROI of another Mat (obtained by otherMat(cv::Rect(x,y,w,h))). I want to go through all the pixels of the Mat, do some pixelwise computation and write the result to another Mat by using a pointer.

遍历所有像素,包括到目前为止ROI之外的工作正常,但我想知道在ROI之外跳过像素的最快方法是什么。我希望尽可能少地缓存未命中,并且我也不希望有一个低效的分支预测。什么是最好的方法呢?

Going through all pixels, including the ones outside the ROI is working fine so far, but I am wondering what the fastest way of skipping the pixels outside the ROI is. I want to have as few cache misses as possible and also I don't want to have an inefficient branch prediction. What would be the best way to go about this?

编辑:我对获得一个感兴趣的特定区域的子矩阵不感兴趣。我感兴趣的是以最有效的方式通过指针迭代像素,而无需访问子矩阵区域之外的数据。

I am not interested in getting a submatrix for a specifitc region of interest. I am interested in iterating through the pixel by pointer in an maximally efficient way without accessing data outside the submatrix' region.

推荐答案

使用子矩阵:

cv::Mat largeMat
cv::Rect roi(yourROI);
cv::Mat submatrix = largeMat(roi);

// now iterate over all the pixels of submatrix

你将拥有每行末尾的缓存未命中

you will have cache misses at the end of each row

这是实际的代码示例,它显示了子像素之外的像素被跳过(您将获得额外的缓存未命中每一行的结尾,但应该是全部。)

Here's the actual code example which shows, that the pixels outside of the submat are skipped (you'll get an additional cache miss at the end of each row but that should be all).

int main(int argc, char* argv[])
{
    cv::Mat input = cv::imread("C:/StackOverflow/Input/Lenna.png");

    cv::Rect roi(128, 128, 256, 256);
    cv::Mat submat = input(roi);

    cv::MatIterator_<cv::Vec3b> it; // = src_it.begin<cv::Vec3b>();
    for (it = submat.begin<cv::Vec3b>(); it != submat.end<cv::Vec3b>(); ++it)
    {
        (*it)[0] = 0;
        (*it)[1] = 0;
    }

    cv::imshow("input", input);
    cv::imwrite("C:/StackOverflow/Output/submatIter.png", input);
    cv::waitKey(0);
    return 0;
}

给出这个结果:

如果你想要它快一点,可以使用行指针: http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/ how_to_scan_images.html

If you want it a little faster you can use row-Pointers: http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html

请注意,在链接中他们比较了调试模式的运行时速度,这就是随机访问速度太慢的原因。在发布模式下,它应该比迭代器verson快(或者更快)。
但是这里是行-Ptr版本(它可以计算每个像素访问时的行偏移量),它提供了相同的结果,应该是最快的方法(如果openCV的LUT函数不能用于你的任务) :

Please mind, that in the link they compared debug mode runtime speed, that's why the random access is so slow. In release mode it should be as fast (or maybe faster) than the iterator verson. But here's the row-Ptr version (which spares to compute the row-offset on each pixel access) which gives the same result and should be the fastest way (if openCV's LUT function can't be used for your task):

int main(int argc, char* argv[])
{
    cv::Mat input = cv::imread("C:/StackOverflow/Input/Lenna.png");

    cv::Rect roi(128, 128, 256, 256);
    cv::Mat submat = input(roi);

    cv::Vec3b * currentRow;

    for (int j = 0; j < submat.rows; ++j)
    {
        currentRow = submat.ptr<cv::Vec3b>(j);
        for (int i = 0; i < submat.cols; ++i)
        {
            currentRow[i][0] = 0;
            currentRow[i][1] = 0;
        }
    }

    cv::imshow("input", input);
    cv::imwrite("C:/StackOverflow/Output/submatIter.png", input);
    cv::waitKey(0);
    return 0;
}

这篇关于C ++ OpenCV:迭代Mat中的像素,这是另一个Mat的ROI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆