C ++:OpenCV:快速像素迭代 [英] C++: OpenCV: fast pixel iteration

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

问题描述

我想从串流网路摄影机图片取得BGR值。我得到一个内存访问冲突,因为我没有在嵌套的for循环中正确使用指针,但我不知道语法应该是什么。我找不到文档,具体到足够看似基本的任务,我想做的。

I'm trying to get BGR values from a streaming webcam image. I'm getting a memory access violation because I'm not using the pointer correctly in the nested for loop but I don't know what the syntax should be. I can't find documentation that is specific enough to the seemingly basic task I'm trying to do.

除了解决内存访问冲突之外,我还希望能够即时编辑每个像素,而无需做深层复制,但不知道什么

In addition to solving he memory access violation, I want to also be able to edit each pixel on the fly without having to do a deep copy but don't know what he syntax should be for that also.

这是我到目前为止的代码:

This is the code I have so far:

int main(int argc, char** argv)
{

    int c;
    Mat img;
    VideoCapture capture(0);
    namedWindow("mainWin", CV_WINDOW_AUTOSIZE);
    bool readOk = true;

    while (capture.isOpened()) {

        readOk = capture.read(img);

        // make sure we grabbed the frame successfully 
        if (!readOk) {
            std::cout << "No frame" << std::endl;
            break;
        }

        int nChannels = img.channels();
        int nRows = img.rows;
        int nCols = img.cols * nChannels;

        if (img.isContinuous())
        {
            nCols *= nRows;
            nRows = 1;
        }

        int i, j;
        uchar r, g, b;
        for (i = 0; i < nRows; ++i)
        {
            for (j = 0; j < nCols; ++j)
            {
                r = img.ptr<uchar>(i)[nChannels*j + 2];
                g = img.ptr<uchar>(i)[nChannels*j + 1];
                b = img.ptr<uchar>(i)[nChannels*j + 0];
            }
        }

        if (!img.empty()) imshow("mainWin", img);
        c = waitKey(10);
        if (c == 27)
            break;
    }
}


推荐答案

扫描循环不正确。您应该只获取一行指向每行一次。

Your scanning loop is not correct. You should be only getting a pointer to the row once per row. Since pixels are 3 byte quantities, it is easiest to treat them as a Vec3b.

你应该有像

    uchar r, g, b;
    for (int i = 0; i < img.rows; ++i)
    {
        cv::Vec3b* pixel = img.ptr<cv::Vec3b>(i); // point to first pixel in row
        for (int j = 0; j < img.cols; ++j)
        {
            r = pixel[j][2];
            g = pixel[j][1];
            b = pixel[j][0];
        }
    }

OR

    uchar r, g, b;
    for (int i = 0; i < img.rows; ++i)
    {
        uchar* pixel = img.ptr<uchar>(i);  // point to first color in row
        for (int j = 0; j < img.cols; ++j)
        {
            b = *pixel++;
            g = *pixel++;
            r = *pixel++;
        }
    }






注意

这是很常见的看到 Mat :: at()按顺序访问像素:

It is fairly common to see Mat::at() used to access pixels sequentially like:

    // DON'T DO THIS!
    uchar r, g, b;
    for (int i = 0; i < img.rows; ++i)
    {
        for (int j = 0; j < img.cols; ++j)
        {
            cv::Vec3b pixel = img.at<cv::Vec3b>(i, j); 
            r = pixel[2];
            g = pixel[1];
            b = pixel[0];
        }
    }

但是这种使用不当。
对于每个像素访问, at()需要通过乘以行号和行长度来计算索引 - 并且在整个图像上,计算可以导致处理
此外,在调试模式下在每个行都有一个等价的计算。 ()有一个断言,使它再慢得多。

However such uses are inappropriate. For every pixel access, at() needs to calculate an index by multiplying the row number and row length - and over a whole image that calculation can result in processing times considerably slower than with the code above (where ptr() does an equivalent calculation once per row. Furthermore, in debug mode at() has an assertion that makes it much slower again.

如果你确定行之间没有填充,在这种情况下,上面第二个循环中的像素指针将在每行结束之后指向下一行的开始处。

If you are sure there is no padding between rows, it is possible to go faster by eliminating the call to ptr(). In this case the pixel pointer in the second loop above will after the end of each line be pointing at the start of the next line. But that wont work if your Mat is for example some region of interest of some other Mat.

另一方面,如果你以随机的方式访问像素,而不是像上面的顺序扫描, at()是非常合适的。

On the other hand, if you were accessing pixels in a random fashion, rather than scanning sequentially like above, at() is then very appropriate.

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

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