返回顶部
首页 > 资讯 > 精选 >OpenCV通过Mat遍历图像的方法有哪些
  • 505
分享到

OpenCV通过Mat遍历图像的方法有哪些

2023-06-29 07:06:33 505人浏览 泡泡鱼
摘要

本文小编为大家详细介绍“OpenCV通过Mat遍历图像的方法有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“OpenCV通过Mat遍历图像的方法有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。我们在实际

本文小编为大家详细介绍“OpenCV通过Mat遍历图像的方法有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“OpenCV通过Mat遍历图像的方法有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

我们在实际应用中对图像进行的操作,往往并不是将图像作为一个整体进行操作,而是对图像中的所有点或特殊点进行运算,所以遍历图像就显得很重要,如何高效的遍历图像是一个很值得探讨的问题。

Color Reduce
还是使用经典的Reduce Color的例子,即对图像中的像素表达进行量化。如常见的RGB24图像有256×256×256中颜色,通过Reduce Color将每个通道的像素减少8倍至256/8=32种,则图像只有32×32×32种颜色。假设量化减少的倍数是N,则代码实现时就是简单的value/N*N,通常我们会再加上N/2以得到相邻的N的倍数的中间值,最后图像被量化为(256/N)×(256/N)×(256/N)种颜色。

并对图像降色彩后的彩色直方图进行统计。

方法一、直接对图像像素修改.at<typename>(i,j)

Mat类提供了一个at的方法用于取得图像上的点,它是一个模板函数,可以取到任何类型的图像上的点。

void colorReduce(Mat& image,int div){    for(int i=0;i<image.rows;i++)    {        for(int j=0;j<image.cols;j++)        {            image.at<Vec3b>(i,j)[0]=image.at<Vec3b>(i,j)[0]/div*div+div/2;            image.at<Vec3b>(i,j)[1]=image.at<Vec3b>(i,j)[1]/div*div+div/2;            image.at<Vec3b>(i,j)[2]=image.at<Vec3b>(i,j)[2]/div*div+div/2;        }    }}

OpenCV通过Mat遍历图像的方法有哪些

通过上面的例子我们可以看出,at方法取图像中的点的用法:

image.at<uchar>(i,j):取出灰度图像中i行j列的点。
image.at<Vec3b>(i,j)[k]:取出彩色图像中i行j列第k通道的颜色点,k=[0,1,2],分别代表B,G,R。

其中uchar,Vec3b都是图像像素值的类型,不要对Vec3b这种类型感觉害怕,其实在core里它是通过typedef Vec<T,N>来定义的,N代表元素的个数,T代表类型。

更简单一些的方法:OpenCV定义了一个Mat的模板子类为Mat_,它重载了operator()让我们可以更方便的取图像上的点。

Mat_<uchar> im=image;im(i,j)=im(i,j)/div*div+div/2;

二、用指针.ptr<uchar>(k)来遍历输入图像,数组[]生成输出图像

上面的例程中可以看到,我们实际喜欢把原图传进函数内,但是在函数内我们对原图像进行了修改,而将原图作为一个结果输出,很多时候我们需要保留原图,这样我们需要一个原图的副本。

void colorReduce(const Mat& image,Mat& outImage,int div){    // 创建与原图像等尺寸的图像    outImage.create(image.size(),image.type());    int nr=image.rows;    // 将3通道转换为1通道    int nl=image.cols*image.channels();    for(int k=0;k<nr;k++)    {        // 每一行图像的指针        const uchar* inData=image.ptr<uchar>(k);        uchar* outData=outImage.ptr<uchar>(k);        for(int i=0;i<nl;i++)        {            outData[i]=inData[i]/div*div+div/2;        }    }}

OpenCV通过Mat遍历图像的方法有哪些

从上面的例子中可以看出,取出图像中第i行数据的指针:image.ptr<uchar>(i)。

值得说明的是:程序中将3通道的数据转换为1通道,在建立在每一行数据元素之间在内存里是连续存储的,每个像素三通道像素按顺序存储。也就是一幅图像数据最开始的三个值,是最左上角的那像素的三个通道的值。

但是这种用法不能用在行与行之间,因为图像在OpenCV里的存储机制问题,行与行之间可能有空白单元。这些空白单元对图像来说是没有意思的,只是为了在某些架构上能够更有效率,比如intel MMX可以更有效的处理那种个数是4或8倍数的行。但是我们可以申明一个连续的空间来存储图像,这个话题引入下面最为高效的遍历图像的机制。

三、用指针.ptr<uchar>(k)来遍历输入图像,指针方式生成输出图像

与上述方法二遍历图像的方法相同,而生成输出图像的方式从数组换成了指针的方式。因此只需改动一句话。

void colorReduce(const Mat& image,Mat& outImage,int div){    // 创建与原图像等尺寸的图像    outImage.create(image.size(),image.type());    int nr=image.rows;    // 将3通道转换为1通道    int nl=image.cols*image.channels();    for(int k=0;k<nr;k++)    {        // 每一行图像的指针        const uchar* inData=image.ptr<uchar>(k);        uchar* outData=outImage.ptr<uchar>(k);        for(int i=0;i<nl;i++)        {            *outData++ = *inData++ / div*div + div / 2;        }    }}

OpenCV通过Mat遍历图像的方法有哪些

四、用指针.ptr<uchar>(k)来遍历输入图像,指针方式结合位运算生成输出图像

与上述方法遍历图像的方法相同,而生成输出图像的方式从加减乘除基本四则运算的方式换成了位运算的方式。

这里特别需要注意的是,位运算的优先级是低于乘除加减的,所以一定要在位运算加括号。

void colorReduce(const Mat& image, Mat& outImage, int div){    // 创建与原图像等尺寸的图像    outImage.create(image.size(), image.type());    int nr = image.rows;    // 将3通道转换为1通道    int nl = image.cols*image.channels();    //对数换底公式log a(b) = log b/log a    int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));    // mask used to round the pixel value  e.g. for div=16, mask= 0xF0    uchar mask = 0xFF << n;    for (int k = 0; k<nr; k++)    {        // 每一行图像的指针        const uchar* inData = image.ptr<uchar>(k);        uchar* outData = outImage.ptr<uchar>(k);        for (int i = 0; i<nl; i++)        {            //进行位运算时要注意加括号,位运算优先级低于+-*/            *outData++ = (*inData++ & mask)  + div / 2;        }    }}

OpenCV通过Mat遍历图像的方法有哪些

五、用指针.ptr<uchar>(k)来遍历输入图像,指针方式结合取模运算生成输出图像

与上述方法遍历图像的方法相同,而生成输出图像的方式从位运算的方式换成了取模运算的方式。

void colorReduce(const Mat& image, Mat& outImage, int div){    // 创建与原图像等尺寸的图像    outImage.create(image.size(), image.type());    int nr = image.rows;    // 将3通道转换为1通道    int nl = image.cols*image.channels();    int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));    // mask used to round the pixel value  e.g. for div=16, mask= 0xF0    uchar mask = 0xFF << n;    for (int k = 0; k<nr; k++)    {        // 每一行图像的指针        const uchar* inData = image.ptr<uchar>(k);        uchar* outData = outImage.ptr<uchar>(k);        for (int i = 0; i<nl; i++)        {            int Data = *inData++;            *outData++ = Data - Data%div + div / 2;        }    }}

OpenCV通过Mat遍历图像的方法有哪些

六、连续图像isContinuous()函数方法。

上面已经提到过了,一般来说图像行与行之间往往存储是不连续的,但是有些图像可以是连续的,Mat提供了一个检测图像是否连续的函数isContinuous()。当图像连通时,我们就可以把图像完全展开,看成是一行。

void colorReduce(const Mat& image,Mat& outImage,int div){    int nr=image.rows;    int nc=image.cols;    outImage.create(image.size(),image.type());    if(image.isContinuous()&&outImage.isContinuous())    {        nr=1;        nc=nc*image.rows*image.channels();    }    for(int i=0;i<nr;i++)    {        const uchar* inData=image.ptr<uchar>(i);        uchar* outData=outImage.ptr<uchar>(i);        for(int j=0;j<nc;j++)        {            *outData++=*inData++/div*div+div/2;        }    }}

OpenCV通过Mat遍历图像的方法有哪些

用指针除了用上面的方法外,还可以用指针来索引固定位置的像素:

image.step返回图像一行像素元素的个数(包括空白元素),image.elemSize()返回一个图像像素的大小。

image.at<uchar>(i,j)=image.data+i*image.step+j*image.elemSize();

七、迭代器Mat_iterator方法。

下面的方法可以让我们来为图像中的像素声明一个迭代器:

MatIterator_<Vec3b> it; Mat_<Vec3b>::iterator it;

如果迭代器指向一个const图像,则可以用下面的声明:

MatConstIterator<Vec3b> it;或者Mat_<Vec3b>::const_iterator it;

下面我们用迭代器来简化上面的colorReduce程序:

void colorReduce(const Mat& image,Mat& outImage,int div){    outImage.create(image.size(),image.type());    MatConstIterator_<Vec3b> it_in=image.begin<Vec3b>();    MatConstIterator_<Vec3b> itend_in=image.end<Vec3b>();    MatIterator_<Vec3b> it_out=outImage.begin<Vec3b>();    MatIterator_<Vec3b> itend_out=outImage.end<Vec3b>();    while(it_in!=itend_in)    {        (*it_out)[0]=(*it_in)[0]/div*div+div/2;        (*it_out)[1]=(*it_in)[1]/div*div+div/2;        (*it_out)[2]=(*it_in)[2]/div*div+div/2;        it_in++;        it_out++;    }}

OpenCV通过Mat遍历图像的方法有哪些

如果你想从第二行开始,则可以从

image.begin<Vec3b>()+image.rows

读到这里,这篇“OpenCV通过Mat遍历图像的方法有哪些”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: OpenCV通过Mat遍历图像的方法有哪些

本文链接: https://lsjlt.com/news/323482.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • OpenCV通过Mat遍历图像的方法有哪些
    本文小编为大家详细介绍“OpenCV通过Mat遍历图像的方法有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“OpenCV通过Mat遍历图像的方法有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。我们在实际...
    99+
    2023-06-29
  • OpenCV 通过Mat遍历图像的方法汇总
    目录方法一、直接对图像像素修改.at<typename>(i,j)二、用指针.ptr<uchar>(k)来遍历输入图像,数组[]生成输出图像三、用指针.ptr...
    99+
    2024-04-02
  • ResultSet的遍历方法有哪些
    这篇文章主要介绍“ResultSet的遍历方法有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“ResultSet的遍历方法有哪些”文章能帮助大家解决问题。ResultSet的遍历方法Result...
    99+
    2023-07-05
  • react有哪些遍历方法
    这篇文章主要讲解了“react有哪些遍历方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“react有哪些遍历方法”吧! rea...
    99+
    2024-04-02
  • jquery有哪些遍历方法
    本教程操作环境:windows7系统、jquery3.6版本、Dell G3电脑。jQuery 遍历方法总结jQuery 遍历函数包括了用于筛选、查找和串联元素的方法。方法描述add()把元素添加到匹配元素的集合中addBack()把之前的...
    99+
    2023-05-14
    jquery javascript
  • python中遍历的方法有哪些
    python中实现遍历的方法:1.使用iter()函数遍历;2.使用enumerate()函数遍历;3.使用range()和len()函数遍历;python中实现遍历的方法有以下几种使用iter()函数遍历cities = ["G...
    99+
    2024-04-02
  • Dictionary遍历的使用方法有哪些
    本篇内容主要讲解“Dictionary遍历的使用方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Dictionary遍历的使用方法有哪些”吧! ...
    99+
    2024-04-02
  • es6遍历对象的方法有哪些
    这篇文章主要介绍了es6遍历对象的方法有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇es6遍历对象的方法有哪些文章都会有所收获,下面我们一起来看看吧。 ...
    99+
    2024-04-02
  • java有哪些遍历集合的方法
    java中遍历集合的方法有:1.使用循环方式遍历;2.使用加强for循环遍历;3.使用Lambda表达式遍历;4.使用迭代方式遍历;java中遍历集合的方法有以下几种使用循环方式遍历for (int i = 0; i < listNames...
    99+
    2024-04-02
  • java遍历集合的方法有哪些
    Java中遍历集合的方法有以下几种:1. 使用foreach循环:通过foreach循环可以遍历Collection集合和数组。``...
    99+
    2023-09-27
    java
  • Map实现遍历的方法有哪些
    Map实现遍历的方法有哪些?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Map获取键值Map以按键/数值对的形式存储数据,和数组非常相似,在数组中存在的索引,它们本身也是对...
    99+
    2023-05-31
    map 遍历
  • jquery遍历元素的方法有哪些
    jQuery提供了许多方法来遍历元素。以下是一些常用的方法:1. `.each()`:用于遍历一个jQuery对象中的每个元素。``...
    99+
    2023-08-15
    jquery
  • es6遍历数组的方法有哪些
    ES6中遍历数组的方法有以下几种: for...of循环:通过for...of循环可以依次遍历数组中的每个元素。例如: cons...
    99+
    2023-10-26
    es6
  • es6遍历数组有哪些方法
    这篇文章主要为大家展示了“es6遍历数组有哪些方法”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“es6遍历数组有哪些方法”这篇文章吧。 ...
    99+
    2024-04-02
  • Python的遍历字典的方法有哪些
    这期内容当中小编将会给大家带来有关Python的遍历字典的方法有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向对象的脚...
    99+
    2023-06-14
  • JS中遍历对象的方法有哪些
    本篇内容主要讲解“JS中遍历对象的方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS中遍历对象的方法有哪些”吧! 1 简介对象是在编程中最常...
    99+
    2024-04-02
  • JavaScript中有哪些遍历数组的方法
    这篇文章给大家介绍JavaScript中有哪些遍历数组的方法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。javascript是一种什么语言javascript是一种动态类型、弱类型的语言,基于对象和事件驱动并具有相对...
    99+
    2023-06-14
  • JavaScript中有哪些遍历对象的方法
    这篇文章将为大家详细讲解有关JavaScript中有哪些遍历对象的方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JavaScript可以做什么1.可以使网页具有交互性,例如响应用户点击,...
    99+
    2023-06-14
  • java遍历map集合的方法有哪些
    Java遍历Map集合的方法有以下几种:1. 使用entrySet()方法遍历:通过Map的entrySet()方法获取Map集合的...
    99+
    2023-09-13
    java
  • python遍历文件夹的方法有哪些
    在Python中,可以使用os模块、glob模块和os.walk()函数来遍历文件夹。1. 使用os模块:```pythonimpo...
    99+
    2023-08-08
    python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作