OpenCV遍历图像像素

news/2024/7/21 5:11:41 标签: opencv, 计算机视觉, 像素遍历, 图像处理, Mat

引言:

为了构建计算机视觉应用程序,需要学会访问图像内容,有时也要修改或创建图像,如何操作图像的像素,就需要遍历一幅图像并处理每一个像素。现在我们就来介绍OpenCV三种图像像素的遍历方法。

一、 用cv::Mat类的at方法扫描图像

 利用cv::Mat的at(int x,int y)方法可以访问元素,其中x是行号,y是列号。在编译时必须明确方法返回值的类型,因为cv::Mat可以接受任何类型的元素,所以程序员需要指定返回值的预期类型。正因为如此,at方法被实现成一个模板方法。在调用at方法时,你必须指定图像元素的类型,例如:

// 单通道图像
image.at<uchar>(i,j)= 255;
// 三通道图像
image.at<cv::Vec3b>(i, j) = cv::Vec3b(255, 255, 255);

用cv::Mat类的at方法扫描图像代码如下:

void visit_mat_by_at(cv::Mat &img)
{
    for (int i = 0; i < img.rows; i++)
    {
        for (int j = 0; j < img.cols; j++)
        {
            // 单通道图像
            if (img.channels() == 1)
            {
                img.at<uchar>(i, j) += 50;
            }
            // 三通道图像
            else
            {
                img.at<cv::Vec3b>(i, j)[0] += 50;
                img.at<cv::Vec3b>(i, j)[1] += 50;
                img.at<cv::Vec3b>(i, j)[2] += 50;
            }
        }
    }
}

二、 用指针扫描图像

一般来说,用指针扫描图像比较高效。在大多数图像处理任务中,执行计算时你都需要对图像的所有像素进行扫描。需要访问的像素数量非常庞大,因此你必须采用高效的方式来执行这个任务。

用指针扫描图像代码如下:

void visit_mat_by_pointer(cv::Mat &img)
{
    for (int i = 0; i < img.rows; i++)
    {
        uchar *data = img.ptr<uchar>(i);
        for (int j = 0; j < img.cols * img.channels(); j++)
        {
            data[j] += 50;
        }
    }
}

三、 用迭代器扫描图像

在面向对象编程时,我们通常用迭代器对数据集合进行循环遍历。迭代器是一种类,专门用于遍历集合的每个元素,并能隐藏遍历过程的具体细节。标准模板库(Standard Template Library,STL)对每个集合类都定义了对应的迭代器类,OpenCV也提供了cv::Mat的迭代器类,并且与C++ STL中的标准迭代器兼容。

用迭代器扫描图像代码如下:

void visit_mat_by_iterator(cv::Mat &img)
{
    // 单通道图像
    if (img.channels() == 1)
    {
        cv::Mat_<uchar>::iterator begin = img.begin<uchar>();
        cv::Mat_<uchar>::iterator end = img.end<uchar>();
 
        for (auto it = begin; it != end; it++)
        {
            *it += 50;
        }
    }
    // 三通道图像
    else
    {
        cv::Mat_<cv::Vec3b>::iterator begin = img.begin<cv::Vec3b>();
        cv::Mat_<cv::Vec3b>::iterator end = img.end<cv::Vec3b>();
 
        for (auto it = begin; it != end; it++)
        {
            (*it)[0] += 50;
            (*it)[1] += 50;
            (*it)[2] += 50;
        }
    }
}

测试代码:

#include <iostream>
#include <opencv2/opencv.hpp>
 
int main()
{
    // 单通道图像
    cv::Mat img1(3, 4, CV_8UC1, 100);
    std::cout << "单通道图像像素修改前:" << std::endl;
    std::cout << img1 << std::endl;
 
    visit_mat_by_at(img1);
    //visit_mat_by_pointer(img1);
    //visit_mat_by_iterator(img1);
    std::cout << "单通道图像像素修改后:" << std::endl;
    std::cout << img1 << std::endl;
 
    // 三通道图像
    cv::Mat img2(3, 4, CV_8UC3, cv::Scalar(100, 150, 200));
    std::cout << "三通道图像像素修改前:" << std::endl;
    std::cout << img2 << std::endl;
 
    visit_mat_by_at(img2);
    //visit_mat_by_pointer(img2);
    //visit_mat_by_iterator(img2);
    std::cout << "三通道图像像素修改后:" << std::endl;
    std::cout << img2 << std::endl;
 
    cv::waitKey();
 
    return 0;
}

运行结果:

单通道图像像素修改前:
[100, 100, 100, 100;
 100, 100, 100, 100;
 100, 100, 100, 100]
单通道图像像素修改后:
[150, 150, 150, 150;
 150, 150, 150, 150;
 150, 150, 150, 150]
三通道图像像素修改前:
[100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200;
 100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200;
 100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200]
三通道图像像素修改后:
[150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250;
 150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250;
 150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250]

说明我们完成遍历图像,并成功修改了图像的像素。


http://www.niftyadmin.cn/n/5179861.html

相关文章

Lua的Resty-Request库写的一个简单爬虫

文章目录 准备工作编写爬虫运行爬虫代码分析拓展功能总结 &#x1f389;欢迎来到AIGC人工智能专栏~Lua的Resty-Request库写的一个简单爬虫 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;该系列文章专栏&#xff1a;AIGC人工智…

leetcode刷题日记:121. Best Time to Buy and Sell Stock( 买卖股票的最佳时机)

题目给了我们一组数prices&#xff0c;其中prices[i]表示第i天的股票价格&#xff0c;需要我们求出买卖股票所能获得的最大收益。 我们的第一想法就是从算出每一种买卖股票的情况然后求出里面的最大值&#xff0c;这样我们就能得到最大收益是多少&#xff0c;但是这种情况过于复…

提前编译:AOT

JIT与AOT的区别 IT和AOT这个名词是指两种不同的编译方式&#xff0c;这两种编译方式的主要区别在于是否在“运行时”进行编译 (1)JIT&#xff0c;Just-in-time,动态(即时)编译&#xff0c;边运行边编译 在程序运行时&#xff0c;根据算法计算出热点代码&#xff0c;然后进行JI…

Linux下MSSQL (SQL Server)数据库无法启动故障处理

有同事反馈一套CentOS7下的mssql server2017无法启动需要我帮忙看看&#xff0c;启动报错情况如下 检查日志并没有更新日志信息 乍一看mssql-server服务有问题&#xff0c;检查mssql也确实没有进程 既然服务有问题&#xff0c;那么我们用一种方式直接手工后台启动mssql引擎来…

2023/11/14JAVA学习

主子线程每次执行顺序可能都不一样

深度学习之基于YoloV5的目标检测和双目测距系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 双目测距系统利用两个相机的图像来计算目标到相机的距离。通过对左右相机图像进行立体匹配&#xff0c;可以获得目标…

c语言数据结构---三叉树

#include<stdio.h> #include<stdlib.h> #include<stack> using namespace std; typedef struct node{struct node*lchild;struct node*rchild;struct node*parent;char data; }Node,*Bit;Bit creat(){//先序创建 char b; int t; scanf("%c",&…

如何利用IP代理进行海外推广?

在当今数字化的时代&#xff0c;网络营销已经成为企业策略的重要组成部分。而对于进去海外市场的跨境玩家来说&#xff0c;海外的推广推广是重中之重。然而&#xff0c;在开展推广的过程中&#xff0c;我们常常会遇到各种挑战&#xff0c;如地域限制、访问速度慢等。 为了解决…