OpenCV 3中图像操作像素的两种方法

2024-08-22 10:18

本文主要是介绍OpenCV 3中图像操作像素的两种方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目前只会两种操作像素点的方法,不过感觉只要能操作就行了。

环境:Ununtu14.04  Clion OpenCV3.2

1.指针

使用Mat类中获取指针的函数,获得图像中某行的指针,进而找到列的地址,即可操作对应地址的像素点,如下代码所示

uchar *row_ptr = image1.ptr < uchar > (y);
uchar *data_ptr = &row_ptr[x * image1.channels()];

row_ptr获取了第y行图像的起始地址,接着data_ptr获取第x列的地址,如果是单通道图像,使用*data_ptr = ...;即可对该点像素进行赋值。

2.直接使用at()方法。

若图像为单通道图像,直接使用image.at<uchar>(y, x) = ...;即可对第y行,x列的对应点进行操作。

3.实践

#include <iostream>
#include <chrono>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>using namespace std;int main() {cv::Mat image;// IMREAD_UNCHANGED            = -1// IMREAD_GRAYSCALE            = 0image = cv::imread("../test.jpg", -1);// 判断图像文件是否正确读取if (image.data == nullptr)    //数据不存在,可能是文件不存在{cout << "文件不存在." << endl;return 0;}// 文件顺利读取, 首先输出一些基本信息cout << "图像宽为" << image.cols << ",高为" << image.rows << ",通道数为"<< image.channels() << endl;// 用cv::imshow显示图像cv::imshow("test", image);// 暂停程序,等待一个按键输入cv::waitKey(0);// 遍历图像, 注意以下遍历方式亦可使用于随机像素访问// 使用 std::chrono 来给算法计时chrono::steady_clock::time_point t1 = chrono::steady_clock::now();for (size_t y = 0; y < image.rows; y++) {for (size_t x = 0; x < image.cols; x++) {uchar *row_ptr = image.ptr < uchar > (y);uchar *data_ptr = &row_ptr[x * image.channels()];for (int c = 0; c != image.channels(); c++) {uchar data = data_ptr[c];}}}chrono::steady_clock::time_point t2 = chrono::steady_clock::now();chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);cout << "遍历图像用时:" << time_used.count() << " 秒。" << endl;// 使用clone函数来拷贝数据cv::Mat image1 = image.clone();cv::Mat image2 = image.clone();for (size_t y = image1.rows / 2 - 5; y <= image1.rows / 2 + 5; y++) {for (size_t x = 0; x < image1.cols; x++) {uchar *row_ptr = image1.ptr < uchar > (y);uchar *data_ptr = &row_ptr[x * image1.channels()];if (image1.channels() == 1)*data_ptr = 240;if (image1.channels() == 3) {data_ptr[0] = 0;data_ptr[1] = 160;data_ptr[2] = 0;}}}for (size_t y = image2.rows / 2 - 5; y <= image2.rows / 2 + 5; y++) {for (size_t x = 0; x < image2.cols; x++) {if (image2.channels() == 1)image2.at<uchar>(y, x) = 180;if (image2.channels() == 3) {cv::Vec3b pixel;pixel[0] = 0;pixel[1] = 160;pixel[2] = 0;image2.at<cv::Vec3b>(y, x) = pixel;}}}cv::imshow("image1", image1);cv::imshow("image2", image2);cv::waitKey(0);// 关于 cv::Mat 的拷贝// 直接赋值并不会拷贝数据cv::Mat image_another = image;// 修改 image_another 会导致 image 发生变化// 将左上角50*50的块置零image_another(cv::Rect(0, 0, 50, 50)).setTo(0);cv::imshow("image_another", image);cv::waitKey(0);// 使用clone函数来拷贝数据cv::Mat image_clone = image.clone();image_clone(cv::Rect(0, 0, 50, 50)).setTo(255);cv::imshow("image_clone", image_clone);cv::waitKey(0);return 0;
}

最终效果为


这篇关于OpenCV 3中图像操作像素的两种方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095991

相关文章

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据