像素的访问和算术运算

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

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

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框架来展示如何实现基本的…

js的讲解

Proxy 是 ES6&#xff08;ECMAScript 2015&#xff09;中引入的一个新的内置对象&#xff0c;用于定义某些操作的自定义行为&#xff08;如属性查找、赋值、枚举、函数调用等&#xff09;。Proxy 可以被看作是一个拦截器&#xff0c;它拦截并自定义对象上的基本操作。通过创建一…

雷电「模拟器」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;对话补…

ACPI PM Timer

ACPI PM Timer 概述&#xff1a; ACPI PM Timer是一个非常简单的计时器&#xff0c;它以 3.579545 MHz 运行&#xff0c;在计数器溢出时生成系统控制中断&#xff08;SCI&#xff09;。它精度较低&#xff0c;建议使用其他定时器&#xff0c;如HPET或APIC定时器。 检测ACPI P…

力扣--LCR 188.买卖芯片的最佳时机

题目 数组 prices 记录了某芯片近期的交易价格&#xff0c;其中 prices[i] 表示的 i 天该芯片的价格。你只能选择 某一天 买入芯片&#xff0c;并选择在 未来的某一个不同的日子 卖出该芯片。请设计一个算法计算并返回你从这笔交易中能获取的最大利润。 如果你不能获取任何利…

工业相机基本参数

分辨率&#xff08;Resolution&#xff09; 定义&#xff1a;分辨率指的是相机图像的像素数&#xff0c;通常以 宽度 x 高度 的形式表示&#xff0c;如 1920x1080 或 2592x1944。作用&#xff1a;分辨率越高&#xff0c;相机可以捕捉到更多的细节。高分辨率相机适用于需要精确…

实时在线翻译谷歌插件

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

torch.sparse_csc_tensor

torch.sparse_csc_tensor 以CSC格式构建一个稀疏张量。CSC格式的稀疏张量乘法运算通常比 COO 格式的稀疏张量更快。 CSC格式&#xff08;Compressed Sparse Column Format&#xff09;是一种存储稀疏矩阵的常用格式&#xff0c;它通过三个数组来表示稀疏矩阵&#xff1a; 非零…

C++ 设计模式:原型模式(Prototype Pattern)

链接&#xff1a;C 设计模式 链接&#xff1a;C 设计模式 - 工厂方法 链接&#xff1a;C 设计模式 - 抽象工厂 链接&#xff1a;C 设计模式 - 建造者模式 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许一个对象通过复制现有对象来…

C语言中的贪心算法

贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取当前最优解的算法&#xff0c;希望通过局部最优解的选择&#xff0c;最终得到全局最优解。它常用于解决最优化问题&#xff0c;如最小生成树、最短路径等。本文将从理论到实践&#xff0c;逐步引导…

区块链:概念与应用场景

一、区块链的定义 区块链是一种分布式账本技术&#xff0c;它以去中心化的方式存储数据&#xff0c;通过密码学保证数据的安全性和不可篡改性。 &#xff08;一&#xff09;分布式账本 账本结构&#xff1a;区块链可以看作是一个由多个节点共同维护的账本。这个账本是由一系列…

[数据集][图像分类]常见鱼类分类数据集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.解决方案

pod生命周期和pod的优雅终止

pod优雅终止 概念&#xff1a;当一个pod需要被终止时&#xff0c;系统会给予一定的时间窗口让pod内的应用程序完成正在处理的任务并安全地关闭&#xff0c;而不是立即强制终止。这样可以避免因突然终止而导致的数据丢失或服务中断 1. 发送终止信号&#xff1a; 当一个 pod 被…

Android 13 Launcher3 移除桌面抽屉入口

com.android.launcher3.taskbar.TaskbarView.updateHotseatItems // 移除任务栏抽屉入口 // if (mAllAppsButton != null) { // int index = Utilities.isRtl(getResources()) ? 0 : getChildCount(); // addView(mAllAppsButton, index)…

深度学习任务中的 `ulimit` 设置优化指南

深度学习任务中的 ulimit 设置优化指南 1. 什么是 ulimit&#xff1f;2. 深度学习任务中的关键 ulimit 设置2.1 max locked memory&#xff08;-l&#xff09;2.2 open files&#xff08;-n&#xff09;2.3 core file size&#xff08;-c&#xff09;2.4 stack size&#xff08…

【SpringMVC】SpringMVC 快速入门

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

OpenGL变换矩阵和输入控制

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

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

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