opencv中访问Mat的三种方法

转载自官方教程 https://docs.opencv.org/master/db/da5/tutorial_how_to_scan_images.html

官方给出的代码: https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp

分为三种不同的访问方式:

1. 通过Mat的ptr指针的[]操作符号,按照数组的方式遍历--->效率最高

2. 通过迭代器 cv::MatIterator_进行访问--->效率次之,但是是安全的

3. 不通过ptr指针,直接通过Mat进行访问--->效率最低, 不适合遍历操作,常用于随机位置的访问, "The final method isn't recommended for scanning. It was made to acquire or modify somehow random elements in the image."


#include <opencv2/core.hpp>
#include <opencv2/core/utility.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <iostream>
#include <sstream>

cv::Mat& ScanImageAndReduceC(cv::Mat& I, const uchar* const table);
cv::Mat& ScanImageAndReduceIterator(cv::Mat& I, const uchar* const table);
cv::Mat& ScanImageAndReduceRandomAccess(cv::Mat& I, const uchar* const table);


int main(int argc, char** argv)
{
    std::string imageName( "../data/lei.jpeg" ); // by default

    //cv::imread(imageName, cv::IMREAD_COLOR);
    cv::Mat I = cv::imread(imageName, cv::IMREAD_GRAYSCALE);
    cv::Mat J;

    int dividewith = 8;
    uchar table[256];

    for(int i=0; i<256; ++i)
    {
        table[i] = (uchar)(dividewith * (table[i]/dividewith));
    }

    const int times = 100;

    double t;

    t = (double)cv::getTickCount();

    for(int i=0; i<times; ++i)
    {
        cv::Mat clone_i = I.clone();
        J = ScanImageAndReduceC(clone_i, table);
    }

    t = 1000*((double)cv::getTickCount() - t)/cv::getTickFrequency();
    t /= times;

    std::cout << "Time of reducing with the c operator [] (averaged for "
              << times << " runs):" << t << " milliseconds." << std::endl;


    /***************************************/

    t = (double)cv::getTickCount();
    for(int i=0; i<times; ++i)
    {
        cv::Mat clone_i = I.clone();
        J = ScanImageAndReduceIterator(clone_i, table);
    }

    t = 1000*((double)cv::getTickCount() - t)/cv::getTickFrequency();
    t /= times;

    std::cout << "Time of reducing with the iterator (averaged for "
              << times << " runs): " << t << " millseconds." << std::endl;

    /***********************************************/
    t = (double)cv::getTickCount();
    for(int i=0; i<times; ++i)
    {
        cv::Mat clone_i = I.clone();
        ScanImageAndReduceRandomAccess(clone_i, table);
    }

    t = 1000*((double)cv::getTickCount() - t)/cv::getTickFrequency();
    t /= times;

    std::cout << "Time of reducing with the random access (averagd for "
              << times << " runs): " << t << " millseconds" << std::endl;

    cv::Mat lookUpTable(1,256, CV_8U);
    uchar *p = lookUpTable.ptr();
    for(int i=0; i<256; ++i)
    {
        p[i] = table[i];
    }

    t = (double)cv::getTickCount();
    for(int i=0; i<times; ++i)
    {
        //调用LUT函数并通过查找表来进行"color space reduction"
        cv::LUT(I, lookUpTable, J);
    }

    t = 1000 * ((double)cv::getTickCount() - t)/cv::getTickFrequency();
    t /= times;
    std::cout << "Time of reducing with the LUT function (averaged for "
              << times << " runs): " << t << " millseconds" << std::endl;

    return 0;
}


cv::Mat& ScanImageAndReduceC(cv::Mat& I, const uchar* const table)
{
    CV_Assert(I.depth() == CV_8U);

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

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


    int i, j;
    uchar* p;
    for(i=0; i<nRows; ++i)
    {
        p = I.ptr<uchar>(i);
        for(j=0; j<nCols; ++j)
        {
            p[j] = table[p[j]];
        }
    }
    return I;
}



cv::Mat& ScanImageAndReduceIterator(cv::Mat& I, const uchar* const table)
{
    CV_Assert(I.depth() == CV_8U);

    const int channels = I.channels();
    switch(channels)
    {
    case 1:
        {
            cv::MatIterator_<uchar> it, end;
            for(it=I.begin<uchar>(), end=I.end<uchar>(); it!=end; ++it)
            {
                *it = table[*it];
            }
            break;
        }

    case 3:
        {
            cv::MatIterator_<cv::Vec3b> it, end;
            for(it=I.begin<cv::Vec3b>(), end=I.end<cv::Vec3b>(); it != end; ++it)
            {
                (*it)[0] = table[(*it)[0]];
                (*it)[1] = table[(*it)[1]];
                (*it)[2] = table[(*it)[2]];
            }

        }

    }

    return I;
}


cv::Mat& ScanImageAndReduceRandomAccess(cv::Mat& I, const uchar* const table)
{
    CV_Assert(I.depth() == CV_8U);

    const int channels = I.channels();

    switch(channels)
    {
    case 1:
        {
            for(int i=0; i<I.rows; ++i)
            {
                for(int j=0; j<I.cols; ++j)
                {
                    I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
                }
            }

            break;
        }

    case 3:
    {
        cv::Mat_<cv::Vec3b> _I = I;

        for(int i=0; i<I.rows; ++i)
        {
            for(int j=0; j<I.cols; ++j)
            {
                _I(i,j)[0] = table[_I(i,j)[0]];
                _I(i,j)[1] = table[_I(i,j)[1]];
                _I(i,j)[2] = table[_I(i,j)[2]];
            }
        }

        I = _I;
        break;

        }


    }

    return I;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCVMat是一个重要的数据型,它是用来存储图像的。Mat可以看作是一个多维数组,它包含了图像的像素数据以及图像的元数据(如图像的大小,通道数,数据型等)。 Mat的常用构造函数有以下几种: 1. Mat(): 创建一个空的Mat对象。 2. Mat(int rows, int cols, int type): 创建一个指定大小和型的Mat对象。 3. Mat(Size size, int type): 创建一个指定大小和型的Mat对象。 4. Mat(int rows, int cols, int type, Scalar s): 创建一个指定大小和型,并用指定颜色初始化的Mat对象。 5. Mat(Size size, int type, Scalar s): 创建一个指定大小和型,并用指定颜色初始化的Mat对象。 6. Mat(const Mat& m): 创建一个与给定Mat对象大小和型相同的Mat对象,并复制给定对象的数据Mat的一些常用方法: 1. Mat::at(): 用于访问Mat对象的像素值。 2. Mat::clone(): 创建一个与原Mat对象大小和型相同的新对象,并将原对象数据复制到新对象。 3. Mat::convertTo(): 将Mat对象的像素值转换成指定的数据型。 4. Mat::copyTo(): 复制一个Mat对象到另一个Mat对象。 5. Mat::reshape(): 改变Mat对象的大小和通道数。 6. Mat::rows(): 返回Mat对象的行数。 7. Mat::cols(): 返回Mat对象的列数。 8. Mat::size(): 返回Mat对象的大小。 9. Mat::type(): 返回Mat对象的数据型。 以下是一个简单的Mat的例子: ``` #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("lena.jpg", IMREAD_COLOR); if (image.empty()) { return -1; } Mat gray_image; cvtColor(image, gray_image, COLOR_BGR2GRAY); imshow("原图", image); imshow("灰度图", gray_image); waitKey(); return 0; } ``` 这段代码读取了一张彩色图像,将其转换为灰度图像,并显示在窗口

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值