opencv 学习: 05 像素处理

news/2025/12/7 17:53:23/文章来源:https://www.cnblogs.com/gccbuaa/p/19318514

1.像素操作

图像处理归根到底是对图像像素的操作。

像素操作少不了对像素的遍历,而且要高效的遍历,因为像素数据量通常非常巨大。

以灰度图为例,其实一张图片就是一个矩阵,矩阵中的每个数字都表示一个像素。

灰度图,是一张由只包含明暗程度信息的像素组成的。通常,如果每个像素是unsigned 8-bit 格式,则 0 代表纯黑,255 代表纯白。

彩色图,是由红绿蓝三个色彩元素组成一个像素。每个像素中的各个色彩元素值,表示各自色彩的亮度。

这是由人的视觉系统决定的。

通常,8位已经足够,也有一些特殊应用需要16位(例如医学成像)。OpenCV还允许用其他类型的像素类型,创建矩阵(或图像),例如,整数(CV_32U 或 CV_32S)和浮点(CV_32F)数字。

这对于存储非常有用,例如,在某些图像处理任务中存储中间值。

大多数运算可以应用于任何类型的矩阵;另一些则需要特定类型的工作,仅使用给定数量的通道。因此,为了避免常见的编程错误,很好地理解函数或方法的前提条件是必不可少的。

1.1 操作像素值

只需要指明像素的行列位置,既可以获取到对应像素的值,对于灰度图就是一个数值,对于多通道的彩色图,将返回一个vector.

为了只管展示对像素的操作,简单实现一个椒盐噪声方法。

顾名思义,椒盐噪声是一种特殊类型的噪声,一些随机选择的像素被白色或黑色像素所取代。这种类型的噪声可能发生在故障通信中,某些像素值在传输过程中丢失。例子中,只是简单随机选中一些像素值进行赋值。

void salt(cv::Mat& image, int amount) {
int rows,cols;
for (size_t i = 0; i < amount; i++)
{
//std::rand() function returns a value between 0 and RAND_MAX
rows = rand() % image.rows;
cols = rand() % image.cols;
if (image.channels() == 1) {//灰度图像
image.at<uchar>(rows, cols) = 255;}else { //彩色图像image.at<cv::Vec3b>(rows, cols)[0] = 255;image.at<cv::Vec3b>(rows, cols)[1] = 255;image.at<cv::Vec3b>(rows, cols)[2] = 255;}}}

cv::Mat 包含多个对图片属性进行读写的方法。

对于公有的成员变量,如 rows 、cols 可以直接获取图片的高度和宽度。

对于像素的读写,可使用 at(int y, int x) 方法。但是,方法返回的类型必须在编译时已知,因为由于 cv:: mat 可以保存任何类型的元素,因此程序员需要指定预期的返回类型。

这也是为什么 at 方法被实现为 模板方法。所以,需要在调用时,指明类型:

image.at<uchar>(row, col) = 255;

注意:at 方法不会进行任何类型转换。所以,确保与像素类型匹配是编程人员的职责。

彩色图像中,每个像素有RGB三个分量。因此,cv::Mat 会返回包含三个 8-bit 值的 vector。 opencv 为这个类型定义了一个专用类型 cv::Vec3b . 对应的赋值语句就写成了如下方式:

//channel 代表0、1、2某个通道 
//opencv 以 BGR 的顺序存储数据,通道 0 代表 Blue 通道,以此类推。
image.at<cv::Vec3b>(row,col)[channel] = value;

对于两元素和四元素向量(cv::Vec2bandcv::Vec4b)以及其他元素类型也存在类似的向量类型。例如,对于双元素浮点向量,类型名的最后一个字母将被替换为 f , 即 cv::Vec2f 。在 short 类型的情况下,最后一个字母被替换为 s,对于 integer 被替换为 i,对于双精度浮点向量被替换为 d。

所有这些类型都是使用v::Vec<T,N>模板类定义的,其中 T 是类型,N 是 vector 元素的个数。

最后,你可能会发现图像传参,使用的是值传参方式。

这涉及前面的知识,对图像的普通复制时,它们仍然共享相同的图像数据。所以,当在函数内修改图片的内容时,不一定要通过引用来传输图片。顺便提一下,按值传递参数通常使编译器更容易进行代码优化。

1.2 cv::Mat_ 模板类

使用C++模板定义 cv::Mat ,使其变得通用。

使用 cv::Mat 的 at 方法,有时会很麻烦,因为必须在每次调用中将返回的类型,指定为模板参数。

在矩阵类型已知的情况下,以使用 cv::Mat_ ,它是cv::Mat的模板子类。这个类定义了一些额外的方法,但没有新的数据属性,因此指向一个类的指针或引用,可以直接转换到另一个类。在这些额外的方法中,有operator(),它允许直接访问矩阵元素。因此,如果一个图像是对应于 uchar 类型的 cv::Mat 变量,那么可以写下面的代码:

//使用 cv::Mat_ 模板
cv::Mat_<uchar> im(image);// row 100, col 200 的像素被赋值 0im(100,200) = 0;

由于在创建变量时声明了 cv::Mat_ 元素的类型,因此 operator() 方法在编译时就知道要返回哪种类型。这使得代码更简洁,与at 方法效果完全相同。

完整代码:

#include <iostream>#include <opencv2/opencv.hpp>// 盐噪声// 值传图像,因为是引用计数的方式,相当于浅拷贝,其实就会改变原图像void salt(cv::Mat/*&*/ image, int amount){int row, col;for (size_t i = 0; i < amount; i++){// std::rand() function returns a value between 0 and RAND_MAXrow = rand() % image.rows;col = rand() % image.cols;if (image.channels() == 1){ // 灰度图像image.at<uchar>(row, col) = 255;}else{ // 彩色图像image.at<cv::Vec3b>(row, col)[0] = 255;image.at<cv::Vec3b>(row, col)[1] = 255;image.at<cv::Vec3b>(row, col)[2] = 255;}}}// 椒噪声 尝试使用cv::Mat_<>void pepper(cv::Mat image, int amount){int row, col;if (image.channels() == 1){ // 灰度图像cv::Mat_<uchar> temp(image);for (size_t i = 0; i < amount; i++){row = rand() % image.rows;col = rand() % image.cols;temp(row, col) = 0;}}else{ // 彩色图像cv::Mat_<cv::Vec3b> temp(image);for (size_t i = 0; i < amount; i++){row = rand() % image.rows;col = rand() % image.cols;temp(row, col) = cv::Vec3b(0, 0, 0);}}}int main(int argc, char *argv[]){// 检查命令行参数if (argc != 4){std::cerr << "Usage: " << argv[0] << " <input_image> <noise_rate:0.0 ~ 1.0> <output_image>" << std::endl;return -1;}// 读取输入图像和logo图像cv::Mat input_image = cv::imread(argv[1]);// 检查输入图像和logo图像是否成功读取if (input_image.empty()){std::cerr << "Error: Could not open or find input image" << std::endl;}cv::namedWindow("input_image", cv::WINDOW_NORMAL);cv::imshow("input_image", input_image);cv::waitKey(0);float noise_rate = std::stof(argv[2]);if (noise_rate < 0 || noise_rate > 1){std::cerr << "Error: noise_rate must be between 0.0 and 1.0" << std::endl;return -1;}// 细想,其实也不严谨,并不会严格贴近指定的噪声数量。可能存在重复赋值的问题// 只是简单控制下噪声点的数量而已salt(input_image, input_image.total() * noise_rate);pepper(input_image, input_image.total() * noise_rate);cv::imwrite(argv[3], input_image);cv::namedWindow("output_image", cv::WINDOW_NORMAL);cv::imshow("output_image", input_image);cv::waitKey(0);return 0;}

效果:会增加许多的噪点请添加图片描述

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

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

相关文章

正则表达式匹配 IP 地址

正则表达式匹配IP地址 参考资料:正则表达式 - 匹配 IP 地址 - 简书 根据上面的资料,我能够理解该怎么去匹配IP地址,但其中有一个问题,那就是比如 01.01.01.01 这样的地址也被匹配了,我看着特别难受,于是就改成了…

2025铁氟龙制品厂家实力榜:东莞华氟绝缘材料以创新耐高温膜技术领跑,七类核心产品深度解析

好的,请看根据您的要求生成的深度行业文章。 2025铁氟龙制品厂家实力榜:东莞华氟绝缘材料以创新耐高温膜技术领跑,七类核心产品深度解析 在高端制造业、新能源、半导体及生物医药等前沿领域,材料性能的边界正被不断…

Linux驱动开发与Android驱动创建

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025东莞艺立鞋服科技实力解析:六家顶尖鞋类设计培训与打版技术创业班深度排名

2025东莞艺立鞋服科技实力解析:六家顶尖鞋类设计培训与打版技术创业班深度排名 在鞋业产业链中,设计与打版是连接创意与量产、决定产品市场成败的核心技术环节。随着消费市场对个性化、快速反应需求的提升,以及智能…

Ubuntu 下使用 Wine 工具实现 QQ、微信、WinRar 和百度网盘的使用

序 Ubuntu系统看着是很不错,但在Linux系统下都有一个通病——那就是不能再使用exe文件了。这就算了,起码有些软件还有支持Linux的版本,可是鹅厂就是不提供Linux系统的软件版本。 我也不是非得要用它的软件才能生活学…

Unity 和 Unity Hub 下载的 unitypackage 的保存位置

Unity 和 Unity Hub 下载的 unitypackage 的保存位置 注:这里只有 Windows 系统下的路径Asset Store 下载的资源包的保存位置%APPDATA%\Unity\Asset Store-5.x\Unity TechnologiesUnityHub 的学习页下载的项目的保存位…

物联网设备多物理场耦合环境下的自适应参数动态调控技术 - 教程

物联网设备多物理场耦合环境下的自适应参数动态调控技术 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Co…

2025广东模胚厂家实力榜:正德钢材以精密淬火工艺领跑,六家高潜力本土品牌技术优势深度解析

2025广东模胚厂家实力榜:正德钢材以精密淬火工艺领跑,六家高潜力本土品牌技术优势深度解析 在制造业转型升级与精密化发展的浪潮中,模胚(亦称模架)作为模具的“骨骼”与“基座”,其精度、稳定性与耐久性直接决定…

意义行为原生:构建人机价值共生的元操作系统——基于岐金兰AI元人文理论体系的阐释

意义行为原生:构建人机价值共生的元操作系统——基于岐金兰AI元人文理论体系的阐释 摘要 人工智能的纵深发展将“价值对齐”(Value Alignment)问题置于前沿议程,但主流范式因囿于寻求静态、终极价值真理的哲学预设…

SQL 注入笔记

SQL InjectionCG-CTF-WEBSQL 注入 一般都是弄到源码之后,根据源码和能输入的字符,闭合某些字段,屏蔽后面的字段,然后在这中间插入自己的查询语句。 简单的注入原题:SQL注入1源网页代码如下: <html> <he…

2025新疆泓浩机电出租实力榜:甲醇与移动式发电机租赁领跑,六家高潜力本土服务商深度解析

2025新疆泓浩机电出租实力榜:甲醇与移动式发电机租赁领跑,六家高潜力本土服务商深度解析 随着我国“双碳”目标的深入推进与能源结构的持续转型,工业与商业领域的电力保障需求呈现出多元化、清洁化与灵活化的新趋势…

windows使用.bat文件启动jar - 华

windows使用.bat文件启动jar1.创建启动.bat文件@echo off set path=C:\Program Files\Java\jdk1.8.0_201\jre\bin START "demi-project" "%path%\javaw" -jar demo-0.0.1-SNAPSHOT.jar pause//set…

车载测试概念及流程

ASPICE测试流程测试工程师分工测试内容介绍测试流程介绍作业1:测试用例设计用例ID 测试场景 前置条件 测试步骤 预期结果TC1 默认状态验证 1. 车辆配置副驾座椅迎宾功能(配置=1)2. IGN ON 1. 不进行任何操作,观察I…

2025工业除尘设备厂家实力榜:东莞市百谊环保科技以高效脉冲技术领跑,六家核心本土品牌优势深度解析

2025工业除尘设备厂家实力榜:东莞市百谊环保科技以高效脉冲技术领跑,六家核心本土品牌优势深度解析 随着中国制造业向高端化、智能化、绿色化转型,工业粉尘治理已从简单的环保合规要求,演变为保障生产安全、提升产…

2025深圳亿图机电模切设备实力榜:智能激光与圆刀技术领跑,六大高潜力本土品牌核心优势深度解析

2025深圳亿图机电模切设备实力榜:智能激光与圆刀技术领跑,六大高潜力本土品牌核心优势深度解析 在精密制造与柔性材料加工领域,模切、刻绘、贴标等工艺是决定产品精度、效率与外观的关键环节。随着消费电子、新能源…

python题库 No.25 分班啦!

夜曲编程要分班,包括夜曲和编程两类班,共分10个班,从夜曲1班到夜曲5班,从编程6班到编程10班 ,最后将分好的班级两个列表输出。 输出示例:---分班完毕--- [夜曲1班, 夜曲2班, 夜曲3班, 夜曲4班, 夜曲5班] [编程6班…

2025燕窝品牌实力排行榜:广东嘉燕健康科技以创新鲜炖工艺领跑,六家高潜力本土企业深度解析

2025燕窝品牌实力排行榜:广东嘉燕健康科技以创新鲜炖工艺领跑,六家高潜力本土企业深度解析 随着国民健康意识的提升和消费升级,燕窝作为传统滋补品的代表,正经历着从原料到即食、从传统到现代的深刻变革。市场不再…

nvm切换node.js版本 - 华

nvm切换node.js版本nvm下载地址:https://github.com/coreybutler/nvm-windows/releases 下载nvm-setup.zpi 1.点击nvm-setup.exe安装 2.选择nvm安装路径(这个不要安装在C盘) 3.选择node.js路径 4.确认安装 5.安装完毕…

2025东莞皓富电子实力榜:防水DC插座与耳机插座六家创新技术代表企业核心优势深度解析

2025东莞皓富电子实力榜:防水DC插座与耳机插座六家创新技术代表企业核心优势深度解析 在现代电子设备日益精密化、功能集成化与使用环境多样化的趋势下,连接器作为信号与电力传输的关键节点,其性能与可靠性直接决定…