像素的访问和算术运算

【欢迎关注编码小哥,学习更多实用的编程方法和技巧】

一、常用的访问像素的方法

1、使用at()方法

// 灰度图
cv::Mat grayImage;
for (int y = 0; y < grayImage.rows; y++) {for (int x = 0; x < grayImage.cols; x++) {uchar pixel = grayImage.at<uchar>(y, x);// 处理像素grayImage.at<uchar>(y, x) = pixel + 10;}
}// 彩色图
cv::Mat colorImage;
for (int y = 0; y < colorImage.rows; y++) {for (int x = 0; x < colorImage.cols; x++) {cv::Vec3b pixel = colorImage.at<cv::Vec3b>(y, x);// 处理像素pixel[0] = pixel[0] + 10; // B通道pixel[1] = pixel[1] + 10; // G通道pixel[2] = pixel[2] + 10; // R通道colorImage.at<cv::Vec3b>(y, x) = pixel;}
}

2、使用指针遍历

// 灰度图
cv::Mat grayImage;
for (int y = 0; y < grayImage.rows; y++) {uchar* row = grayImage.ptr<uchar>(y);for (int x = 0; x < grayImage.cols; x++) {row[x] = row[x] + 10;}
}// 彩色图
cv::Mat colorImage;
for (int y = 0; y < colorImage.rows; y++) {cv::Vec3b* row = colorImage.ptr<cv::Vec3b>(y);for (int x = 0; x < colorImage.cols; x++) {row[x][0] = row[x][0] + 10; // B通道row[x][1] = row[x][1] + 10; // G通道row[x][2] = row[x][2] + 10; // R通道}
}

3、迭代器遍历

// 灰度图
cv::Mat grayImage;
cv::MatIterator_<uchar> it, end;
for (it = grayImage.begin<uchar>(), end = grayImage.end<uchar>(); it != end; ++it) {*it = *it + 10;
}// 彩色图
cv::Mat colorImage;
cv::MatIterator_<cv::Vec3b> it, end;
for (it = colorImage.begin<cv::Vec3b>(), end = colorImage.end<cv::Vec3b>(); it != end; ++it) {(*it)[0] = (*it)[0] + 10; // B通道(*it)[1] = (*it)[1] + 10; // G通道(*it)[2] = (*it)[2] + 10; // R通道
}

4、forEach()方法(C++11)

// 灰度图
cv::Mat grayImage;
grayImage.forEach<uchar>([](uchar &pixel, const int * position) {pixel = pixel + 10;
});// 彩色图
cv::Mat colorImage;
colorImage.forEach<cv::Vec3b>([](cv::Vec3b &pixel, const int * position) {pixel[0] = pixel[0] + 10; // B通道pixel[1] = pixel[1] + 10; // G通道pixel[2] = pixel[2] + 10; // R通道
});

二、基于image.data直接访问像素数据方法 

1、数据访问基础

// 获取图像基本信息
int width = image.cols;
int height = image.rows;
int channels = image.channels();
uchar* pixelPtr = image.data;

2、灰度图像访问

cv::Mat grayImage;
for (int y = 0; y < grayImage.rows; y++) {for (int x = 0; x < grayImage.cols; x++) {// 直接通过data指针访问uchar* pixel = grayImage.data + y * grayImage.step + x;*pixel = *pixel + 10; // 像素处理}
}

 3、彩色图像访问

cv::Mat colorImage;
for (int y = 0; y < colorImage.rows; y++) {for (int x = 0; x < colorImage.cols; x++) {// 计算像素位置int index = y * colorImage.step + x * colorImage.channels();// BGR通道uchar blue = colorImage.data[index];uchar green = colorImage.data[index + 1];uchar red = colorImage.data[index + 2];// 修改像素colorImage.data[index] = blue + 10;colorImage.data[index + 1] = green + 10;colorImage.data[index + 2] = red + 10;}
}

 4、通用像素访问模板

template<typename T>
void processImage(cv::Mat& image) {int channels = image.channels();for (int y = 0; y < image.rows; y++) {for (int x = 0; x < image.cols; x++) {// 计算像素起始位置int index = y * image.step + x * channels;// 根据通道数处理if (channels == 1) {T& pixel = reinterpret_cast<T&>(image.data[index]);pixel = pixel + 10;} else if (channels == 3) {T* pixel = reinterpret_cast<T*>(&image.data[index]);pixel[0] = pixel[0] + 10; // Bpixel[1] = pixel[1] + 10; // Gpixel[2] = pixel[2] + 10; // R}}}
}// 使用示例
cv::Mat grayImage(height, width, CV_8UC1);
cv::Mat colorImage(height, width, CV_8UC3);processImage<uchar>(grayImage);
processImage<uchar>(colorImage);

5、高级数据访问 

class ImageProcessor {
private:cv::Mat image;uchar* data;int width, height, channels, step;public:ImageProcessor(cv::Mat& img) : image(img) {data = image.data;width = image.cols;height = image.rows;channels = image.channels();step = image.step;}// 安全的像素访问uchar& pixel(int x, int y, int channel = 0) {return data[y * step + x * channels + channel];}// 像素处理void process() {for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {// 处理每个通道for (int c = 0; c < channels; c++) {uchar& p = pixel(x, y, c);p = cv::saturate_cast<uchar>(p * 1.2);}}}}
};// 使用
cv::Mat image = cv::imread("image.jpg");
ImageProcessor processor(image);
processor.process();

三、像素算术运算 

1、基本像素算术运算

// 像素加法
cv::Mat result = image1 + image2;// 像素减法
cv::Mat result = image1 - image2;// 像素乘法
cv::Mat result = image1.mul(image2);// 像素除法
cv::Mat result = image1 / image2;

2、标量运算

// 对整个图像进行标量运算
cv::Mat brightened = image + 50;  // 增加亮度
cv::Mat darkened = image - 50;    // 降低亮度
cv::Mat increased_contrast = image * 1.5;  // 增加对比度
cv::Mat decreased_contrast = image * 0.5;  // 降低对比度

3、像素逐元素运算

// 自定义像素运算函数
cv::Mat pixelWiseOperation(const cv::Mat& src) {cv::Mat dst = src.clone();// 遍历每个像素for (int y = 0; y < dst.rows; y++) {for (int x = 0; x < dst.cols; x++) {// 灰度图if (dst.channels() == 1) {uchar& pixel = dst.at<uchar>(y, x);pixel = cv::saturate_cast<uchar>(std::pow(pixel, 1.2));}// 彩色图else if (dst.channels() == 3) {cv::Vec3b& pixel = dst.at<cv::Vec3b>(y, x);pixel[0] = cv::saturate_cast<uchar>(std::pow(pixel[0], 1.2));pixel[1] = cv::saturate_cast<uchar>(std::pow(pixel[1], 1.2));pixel[2] = cv::saturate_cast<uchar>(std::pow(pixel[2], 1.2));}}}return dst;
}

4、通道分离与运算

// 分离通道并对特定通道进行运算
cv::Mat performChannelOperation(const cv::Mat& src) {std::vector<cv::Mat> channels;cv::split(src, channels);// 对蓝色通道进行操作channels[0] = channels[0] * 1.5;cv::Mat result;cv::merge(channels, result);return result;
}

5、安全像素运算模板

template<typename T>
cv::Mat safePixelOperation(const cv::Mat& src, double factor) {cv::Mat dst = src.clone();for (int y = 0; y < dst.rows; y++) {for (int x = 0; x < dst.cols; x++) {if (dst.channels() == 1) {T& pixel = dst.at<T>(y, x);pixel = cv::saturate_cast<T>(pixel * factor);}else if (dst.channels() == 3) {T* pixel = dst.at<T>(y, x);pixel[0] = cv::saturate_cast<T>(pixel[0] * factor);pixel[1] = cv::saturate_cast<T>(pixel[1] * factor);pixel[2] = cv::saturate_cast<T>(pixel[2] * factor);}}}return dst;
}// 使用示例
cv::Mat result8U = safePixelOperation<uchar>(image, 1.5);
cv::Mat result16U = safePixelOperation<ushort>(image16, 1.5);

6、复杂像素运算

// 多图像混合
cv::Mat blendImages(const cv::Mat& img1, const cv::Mat& img2, double alpha = 0.5) {cv::Mat blended;cv::addWeighted(img1, alpha, img2, 1 - alpha, 0, blended);return blended;
}// 图像映射变换
cv::Mat gammaCorrection(const cv::Mat& src, double gamma = 1.0) {cv::Mat dst;src.convertTo(dst, CV_32F, 1.0/255);cv::pow(dst, gamma, dst);dst = dst * 255;dst.convertTo(dst, CV_8U);return dst;
}

7、位运算 

// 位运算
cv::Mat bitwiseOperations(const cv::Mat& src) {cv::Mat mask = src > 128;  // 创建二值化掩膜cv::Mat result1, result2;cv::bitwise_and(src, mask, result1);     // 与运算cv::bitwise_or(src, mask, result2);      // 或运算return result1;
}

8、高级像素映射

// 自定义像素映射
cv::Mat customPixelMapping(const cv::Mat& src) {cv::Mat lookupTable(1, 256, CV_8U);uchar* lut = lookupTable.ptr();// 创建查找表for (int i = 0; i < 256; i++) {lut[i] = cv::saturate_cast<uchar>(std::sin(i * CV_PI / 255.0) * 255.0);}cv::Mat result;cv::LUT(src, lookupTable, result);return result;
}

注意事项

  1. 使用cv::saturate_cast防止溢出
  2. 注意数据类型转换
  3. 考虑图像通道数
  4. 处理边界情况
  5. 性能优化

性能建议

  1. 使用cv::Mat操作替代逐像素遍历
  2. 利用OpenCV的矩阵运算
  3. 对于大图像,考虑并行处理
  4. 使用cv::cuda进行GPU加速

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

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

相关文章

【深度学习】卷积网络代码实战ResNet

ResNet (Residual Network) 是由微软研究院的何凯明等人在2015年提出的一种深度卷积神经网络结构。ResNet的设计目标是解决深层网络训练中的梯度消失和梯度爆炸问题&#xff0c;进一步提高网络的表现。下面是一个ResNet模型实现&#xff0c;使用PyTorch框架来展示如何实现基本的…

雷电「模拟器」v9 最新清爽去广

前言 雷电模拟器9是基于安卓9内核开发的全新版本模拟器 安装环境 [名称]&#xff1a;雷电「模拟器」 [大小]&#xff1a;579MB [版本]&#xff1a;9.1.34 [语言]&#xff1a;简体中文 [安装环境]&#xff1a;Windows 通过网盘分享的文件&#xff1a;雷电模拟器 链接:…

大模型 API 接入初探

文章目录 大模型 API 接入初探一、使用大模型 API 的前置步骤&#xff08;一&#xff09;注册账户与获取凭证&#xff08;二&#xff09;理解 API 文档 二、三个常用 API&#xff08;一&#xff09;列出模型&#xff08;二&#xff09;FIM 补全&#xff08;三&#xff09;对话补…

实时在线翻译谷歌插件

Real - time Translation插件的安装 1、下载插件并解压 2、打开谷歌浏览器&#xff0c;在地址栏输入 “chrome://extensions/” 进入扩展程序页面. 3、开启页面右上角的 “开发者模式”. 4、点击 “加载已解压的扩展程序” 按钮&#xff0c;选择之前解压的文件夹&#xff0c;点…

[数据集][图像分类]常见鱼类分类数据集2w张8类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;7554&#xff08;剩余1w多为测试集&#xff09; 分类类别数&#xff1a;…

uniapp开发小程序内嵌h5页面,video视频两边有细小黑色边框

1.问题如图 2.原因分析 是否为设置上述属性呢&#xff1f; 设置了&#xff0c;但是仍然有黑边。经过选中页面元素分析后&#xff0c;判断video元素本身就有这种特点&#xff0c;就是视频资源无法完全铺满元素容器。 3.解决方案

【SpringMVC】SpringMVC 快速入门

通常&#xff0c;Web 应用的工作流程如下&#xff1a; 用户通过浏览器访问前端页面&#xff1b; 前端页面通过异步请求向后端服务器发送数据&#xff1b; 后端采用“表现层-业务层-数据层”三层架构进行开发&#xff1a; 表现层接收页面请求将请求参数传递给业务层业务层访问…

OpenGL变换矩阵和输入控制

在前面的文章当中我们已经成功播放了动画&#xff0c;让我们的角色动了起来&#xff0c;这一切变得比较有意思了起来。不过我们发现&#xff0c;角色虽然说是动了起来&#xff0c;不过只是在不停地原地踏步而已&#xff0c;而且我们也没有办法通过键盘来控制这个角色来进行移动…

【Spring MVC 核心机制】核心组件和工作流程解析

在 Web 应用开发中&#xff0c;处理用户请求的逻辑常常会涉及到路径匹配、请求分发、视图渲染等多个环节。Spring MVC 作为一款强大的 Web 框架&#xff0c;将这些复杂的操作高度抽象化&#xff0c;通过组件协作简化了开发者的工作。 无论是处理表单请求、生成动态页面&#x…

Verilog 过程赋值

关键词&#xff1a;阻塞赋值&#xff0c;非阻塞赋值&#xff0c;并行 过程性赋值是在 initial 或 always 语句块里的赋值&#xff0c;赋值对象是寄存器、整数、实数等类型。 这些变量在被赋值后&#xff0c;其值将保持不变&#xff0c;直到重新被赋予新值。 连续性赋值总是处…

[并发与并行] python如何构建并发管道处理多阶段任务?

文章目录 1. 背景&目标2. show me the code3.知识点4. 总结 1. 背景&目标 背景&#xff1a;一个任务可分为多个阶段(各个阶段非CPU密集型任务&#xff0c;而是属于IO密集型任务)&#xff0c;希望每个阶段能够交给各自的线程去执行。 目标&#xff1a;构建支持多并发的…

07 基于OpenAMP的核间通信方案

引言 ZYNQ7020有两个CPU核心&#xff0c;这两个核心可以采用SMP或AMP方式进行调度&#xff0c;当采用AMP方式进行调度时核0和核1可以运行不同的操作系统&#xff0c;如核0运行Linux系统&#xff0c;提供有些复杂的用户交互工作&#xff0c;核1运行实时操作系统&#xff0c;对设…

7.若依参数设置、通知公告、日志管理

参数设置 对系统中的参数进行动态维护。 关闭验证码校验功能 打开页面注册功能 需要修改前端页面代码 通知公告 促进组织内部信息传递 若依只提供了一个半成品&#xff0c;只实现了管理员可以添加通知公告。 日志管理 追踪用户行为和系统运行状况。 登录日志 和操作日志…

基于Docker+模拟器的Appium自动化测试(二)

模拟器的设置 打开“夜神模拟器”的系统设置&#xff0c;切换到“手机与网络”页&#xff0c;选中网络设置下的“开启网络连接”和“开启网络桥接模式”复选框&#xff0c;而后选择“静态IP”单选框&#xff0c;在IP地址中输入“192.168.0.105”&#xff0c;网关等内容不再赘述…

大数据技术-Hadoop(三)Mapreduce的介绍与使用

目录 一、概念和定义 二、WordCount案例 1、WordCountMapper 2、WordCountReducer 3、WordCountDriver 三、序列化 1、为什么序列化 2、为什么不用Java的序列化 3、Hadoop序列化特点&#xff1a; 4、自定义bean对象实现序列化接口&#xff08;Writable&#xff09; 4…

【数据仓库】SparkSQL数仓实践

文章目录 集成hive metastoreSQL测试spark-sql 语法SQL执行流程两种数仓架构的选择hive on spark数仓配置经验 spark-sql没有元数据管理功能&#xff0c;只有sql 到RDD的解释翻译功能&#xff0c;所以需要和hive的metastore服务集成在一起使用。 集成hive metastore 在spark安…

基本算法——回归

本节将通过分析能源效率数据集&#xff08;Tsanas和Xifara&#xff0c;2012&#xff09;学习基本的回归算法。我们将基 于建筑的结构特点&#xff08;比如表面、墙体与屋顶面积、高度、紧凑度&#xff09;研究它们的加热与冷却负载要 求。研究者使用一个模拟器设计了12种不…

V-Express - 一款针对人像视频生成的开源软件

V-Express是腾讯AI Lab开发的一款针对人像视频生成的开源软件。它旨在通过条件性丢弃&#xff08;Conditional Dropout&#xff09;技术&#xff0c;实现渐进式训练&#xff0c;以改善使用单一图像生成人像视频时的控制信号平衡问题。 在生成过程中&#xff0c;不同的控制信号&…

Java与SQL Server数据库连接的实践与要点

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Java和SQL Server数据库交互是企业级应用开发中的重要环节。本文详细探讨了使用Java通过JDBC连接到SQL Server数据库的过程&#xff0c;包括加载驱动、建立连接、执行SQL语句、处理异常、资源管理、事务处理和连…

学习记录—正则表达式-基本语法

正则表达式简介-《菜鸟教程》 正则表达式是一种用于匹配和操作文本的强大工具&#xff0c;它是由一系列字符和特殊字符组成的模式&#xff0c;用于描述要匹配的文本模式。 正则表达式可以在文本中查找、替换、提取和验证特定的模式。 本期内容将介绍普通字符&#xff0c;特殊…