图像像素读写image.at、image.ptr、指针

news2025/1/24 17:40:44

image.at

在OpenCV中,使用Mat对象表示图像数据,在使用at方法时,需要确保使用正确的数据类型(如uchar或Vec3b),这取决于图像的通道数和数据深度。

单通道图像

对于单通道图像(如灰度图像),每个像素值由一个字节表示,范围是0到255。可以使用uchar类型来访问和修改像素值:

// 访问位于(y, x)的像素值
uchar pixelValue = image.at<uchar>(y, x);

// 修改位于(y, x)的像素值
image.at<uchar>(y, x) = newValue;

多通道图像

对于多通道图像(如RGB彩色图像),每个像素由多个值组成(在RGB图像中是3个值,分别对应红、绿、蓝通道)。要访问这种图像的像素,可以使用Vec3b类型,这是一个包含3个uchar值的向量,对应于一个像素的所有通道:

// 访问位于(y, x)的像素的所有通道
Vec3b pixelValue = image.at<Vec3b>(y, x);

// 访问特定通道(例如蓝色通道)
uchar blueValue = pixelValue[0];

// 修改位于(y, x)的像素的红色通道值
image.at<Vec3b>(y, x)[2] = newValue; // 对于RGB图像,索引2通常对应红色通道

应用示例1-没有用到指针

quick_opencv.h

#include<opencv2\opencv.hpp>
using namespace cv;
class QuickDemo{
    public:
		void pixel_visit_demo_nopointer(Mat &image);//图像像素读写
};

QuickDemo.cpp

#include<quick_opencv.h>

//图像像素读写
void QuickDemo::pixel_visit_demo_nopointer(Mat &image) {
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	for (int row = 0; row < h; row++) {
		for (int col = 0; col < w; col++) {
			if (dims == 1) {
				int pv = image.at<uchar>(row, col);
				image.at<uchar>(row, col) = 255 - pv;
			}
			if (dims == 3) {
				Vec3b bgr = image.at<Vec3b>(row, col);
				image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
				image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
				image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
			}
		}
	}
	imshow("像素读写演示结果", image);
}

主函数main.cpp

#include<opencv2/opencv.hpp>
#include<quick_opencv.h>
#include<iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	
	//读取并显示图像,如果imread返回的Mat对象(src)是空的,打印错误消息并退出程序。
	Mat src = imread("C:/Users/Desktop/opencv-0/win.png");//B G R 蓝绿红
	if (src.empty())
	{
		printf("could not find the image...\n");
		return -1;
	}
	namedWindow("输入窗口", WINDOW_FREERATIO);//创建一个可以自由调整比例的窗口
	imshow("输入窗口", src);

	//创建QuickDemo类的实例qd
	QuickDemo qd;
	//像素读写
	qd.pixel_visit_demo_nopointer(src);
	
	//等待用户输入并清理资源
	waitKey(0);
	destroyAllWindows();
	return 0;
}

在这里插入图片描述在这里插入图片描述
可以利用image.ptr结合指针对上述代码进行优化,优化结果会简洁代码并且提高运行速度。

image.ptr

在OpenCV中,cv::Mat类的ptr方法用于获取指向图像数据某一行的指针。通过这个指针,可以直接访问和修改图像数据。这种方法比使用at方法访问单个像素值更快,特别是在需要遍历图像所有像素或进行大量像素级操作时。但是,使用指针访问数据需要更加小心,以避免越界访问和其他内存错误。

uchar* ptr = image.ptr<uchar>(y);

y是图像中行的索引(行号)。
<uchar>指定了数据的类型。对于单通道的灰度图像,可以使用uchar(无符号字符)。对于多通道图像,可能需要使用不同的类型,例如Vec3b对于一个3通道的BGR图像。

获取了指针后,可以通过指针运算来访问或修改像素值。例如,修改第y行第x列像素的值:

ptr[x] = newValue; // 对于灰度图像
Vec3b* ptr = image.ptr<Vec3b>(y);// 对于多通道图像
ptr[x] = Vec3b(blue, green, red); // 设置像素值

或者直接访问和修改特定通道的值:

ptr[x][0] = newBlue;  // 修改蓝色通道的值
ptr[x][1] = newGreen; // 修改绿色通道的值
ptr[x][2] = newRed;   // 修改红色通道的值

应用示例2-用到指针

quick_opencv.h

#include<opencv2\opencv.hpp>
using namespace cv;
class QuickDemo{
    public:
		void pixel_visit_demo_usepointer(Mat &image);//图像像素读写
};

QuickDemo.cpp

#include<quick_opencv.h>

//图像像素读写
void QuickDemo::pixel_visit_demo_usepointer(Mat &image) {
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	for (int row = 0; row < h; row++) {
		uchar* current_row= image.ptr<uchar>(row);
		for (int col = 0; col < w; col++) {
			if (dims == 1) {
				int pv = *current_row;
				*current_row++ = 255 - *current_row;
			}
			if (dims == 3) {
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
			}
		}
	}
	imshow("像素读写演示结果", image);
}

主函数main.cpp

#include<opencv2/opencv.hpp>
#include<quick_opencv.h>
#include<iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	
	//读取并显示图像,如果imread返回的Mat对象(src)是空的,打印错误消息并退出程序。
	Mat src = imread("C:/Users/Desktop/opencv-0/win.png");//B G R 蓝绿红
	if (src.empty())
	{
		printf("could not find the image...\n");
		return -1;
	}
	namedWindow("输入窗口", WINDOW_FREERATIO);//创建一个可以自由调整比例的窗口
	imshow("输入窗口", src);

	//创建QuickDemo类的实例qd
	QuickDemo qd;
	//像素读写
	qd.pixel_visit_demo_usepointer(src);
	
	//等待用户输入并清理资源
	waitKey(0);
	destroyAllWindows();
	return 0;
}

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1454319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

正信晟锦:借钱后不还算诈骗吗

在探讨“借钱后不还”这一行为是否构成诈骗时&#xff0c;我们应首先明确诈骗的法律定义。根据《中华人民共和国刑法》&#xff0c;诈骗是指以非法占有为目的&#xff0c;采用虚构事实或隐瞒真相的手段&#xff0c;骗取他人财物的行为。关键在于是否存在欺诈行为和非法占有的主…

12.QT文件对话框 文件的弹窗选择-QFileDialog

目录 前言&#xff1a; 技能&#xff1a; 内容&#xff1a; 1. 界面 2.信号槽 3.其他函数 参考&#xff1a; 前言&#xff1a; 通过按钮实现文件弹窗选择以及关联的操作 效果图就和平时用电脑弹出的选文件对话框一样 技能&#xff1a; QString filename QFileDialog::ge…

消毒柜行业分析:市场渗透率不足20%

目前消毒柜仍然属于“小众”品类&#xff0c;疫情前期市场渗透率也不足20%。有业内人士表示&#xff0c;多年来消毒柜零售量规模基本在400万台左右徘徊&#xff0c;这个角度看&#xff0c;消毒柜是具有自身的产品消费人群的&#xff0c;其市场相对稳定&#xff0c;而且消毒柜的…

【Java EE初阶十六】网络原理(一)

在网络原理中主要学习TCP/IP四层模型中的重点网络协议 1. 应用层 1.1 应用程序与协议 应用层是和程序员接触最密切的&#xff1b; 应用程序&#xff1a;在应用层这里&#xff0c;很多时候都是程序员自定义应用层协议&#xff08;步骤&#xff1a;1、根据需求&#xff0c;明确…

前端工程化面试题 | 14.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

2974. 最小数字游戏【简单】

2974. 最小数字游戏 题目描述&#xff1a; 你有一个下标从 0 开始、长度为 偶数 的整数数组 nums &#xff0c;同时还有一个空数组 arr 。Alice 和 Bob 决定玩一个游戏&#xff0c;游戏中每一轮 Alice 和 Bob 都会各自执行一次操作。游戏规则如下&#xff1a; 每一轮&#xf…

001kafka源码项目gradle报错UnsupportedClassVersionError-kafka-报错-大数据学习

1 报错提示 java.lang.UnsupportedClassVersionError: org/eclipse/jgit/lib/AnyObjectId has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 如…

AI:131- 法律文件图像中的隐含信息挖掘与敲诈勒索检测

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

2024最全的性能测试种类介绍,这6个种类特别重要!

系统的性能是一个很大的概念&#xff0c;覆盖面非常广泛&#xff0c;包括执行效率、资源占用、系统稳定性、安全性、兼容性、可靠性、可扩展性等&#xff0c;性能测试就是描述测试对象与性能相关的特征并对其进行评价而实施的一类测试。 性能测试是一个统称&#xff0c;它其实包…

Nginx高级课程扩容(四)

Brotli 安装 ● 官网 ● https://github.com/google/ngx_brotli ● https://codeload.github.com/google/brotli/tar.gz/refs/tags/v1.0.9 ● 下载 两个项目 ● 解压缩模块化编译 ./configure --with-compat --add-dynamic-module/root/ngx_brotli-1.0.0rc --prefix/usr/local…

[嵌入式系统-28]:开源的虚拟机监视器和仿真器:QEMU(Quick EMUlator)与VirtualBox、VMware Workstation的比较

目录 一、QEMU概述 1.1 QEMU架构 1.2 QEMU概述 1.3 什么时候需要QEMU 1.4 QEMU两种操作模式 1.5 QEMU模拟多种CPU架构 二、QEMU与其他虚拟机的比较 2.1 常见的虚拟化技术 2.1 Linux KVM 2.2 Windows VirtualBox 2.3 Windows VMware workstation 三、VirtualBox、VM…

【Java程序员面试专栏 Java领域】Java集合 核心面试指引

关于Java 集合部分的核心知识进行一网打尽,主要包括Java各类集合以及Java的HashMap底层原理,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 集合基本概念和比较 关于集合的基本分类和知识 Java集合有哪些种类 Java 集合, 也叫作容器…

leetcode hot100 打家劫舍

本题中&#xff0c;依旧可以发现&#xff0c;当前位置的金额受到前两个位置金额是否被偷的影响&#xff0c;所以这明显是动态规划的问题。 我们采用动态规划五部曲来进行做 首先我们确定dp数组的含义&#xff1a;考虑下标i&#xff08;包括i&#xff09;以内的房屋&#xff0…

3秒开服《幻兽帕鲁》!如何抓住游戏背后的云计算机遇?

导语 | 2024 年伊始&#xff0c;《幻兽帕鲁》的火热就为新一年的游戏市场带来了极高的热度&#xff0c;无论是超千万份的销量还是关于游戏“缝合”与“借鉴”的争议&#xff0c;都使得开年游戏市场的销售前景与话题度拉满。而在游戏市场之外&#xff0c;云服务市场尤其是其面向…

K8s服务发现组件之CoreDNS/NodeLocalDNS /kubeDNS

1 coredns 1.1 概述 1.1.1 什么是CoreDNS CoreDNS 是一个灵活可扩展的 DNS 服务器&#xff0c;可以作为 Kubernetes 集群 DNS&#xff0c;在Kubernetes1.12版本之后成为了默认的DNS服务。 与 Kubernetes 一样&#xff0c;CoreDNS 项目由 CNCF 托管。 coredns在K8S中的用途,…

大屏设计:公说公有理婆说婆有理!错,看这十个判定标准。

“公说公有理&#xff0c;婆说婆有理”这句话通常用来形容争论双方都认为自己是正确的&#xff0c;而且都有自己的理由和观点。在设计中&#xff0c;这种情况也是很常见的。 为什么会公说公有理婆说婆有理&#xff1f; 设计是一门艺术和技术相结合的学科&#xff0c;涉及到很多…

人机工程学和人机交互理论:智能座舱设计

hello家人们...本人熟悉PS、Xd、Ai、Sketch、Figma、墨刀、即时设计、mastergo、Pixso等行业设计软件以及前端开发等技能&#xff0c;拥有10年的UI经验&#xff0c;我们可以通过关注评论私信交流以帮助到您解决UI工作中的烦恼&#xff01;谢谢 人机工程学与人机交互理论&#x…

源聚达:抖音网店做多久可以做起来

在数字化浪潮中&#xff0c;抖音作为新兴的电商平台&#xff0c;吸引了无数创业者的目光。然而&#xff0c;“抖音网店做多久可以做起来”这一问题&#xff0c;却像一道复杂的数学题&#xff0c;需要细致的解析与推导。 成功的抖音网店并非一蹴而就。根据业内数据分析&#xff…

Find My资讯|苹果Vision Pro无法通过Find My进行远程定位和发声

苹果 Vision Pro 头显现在已经正式开售&#xff0c;不过根据该公司日前发布的支持文件&#xff0c;这款头显目前缺乏一系列关键查找功能&#xff0c;用户无法在 iCloud 网站或Find My应用中获悉头显的位置&#xff0c;也无法让这款头显远程播放声音。 不过支持文件同时提到 V…

Java 学习和实践笔记(12)

这个就比较有意思了&#xff01;所有的事情&#xff0c;拆分完之后&#xff0c;都有且只有这三种状态流程&#xff01; //TIP To <b>Run</b> code, press <shortcut actionId"Run"/> or // click the <icon src"AllIcons.Actions.Execute&…