C++结合OpenCV:图像的像素处理基础

像素是图像构成的基本单位,像素处理是图像处理的基本操作,可以通过位置索引的形式对图像内的元素进行访问、处理。

二值图像: 是一种特殊的灰度图像,在OPENCV中,将黑定义为0,255定义为白。 在OPENCV中,二值图像/灰度图像以二维数组形式进行存放彩色图像以三维数组形式进行存放(X*Y*3, 通道存放顺序为BGR,X,Y为图像x,y轴向上的像素点个数)。

为了方便理解,我们首先来生成一个8×8大小的数组,用来模拟一个黑色图像,并对其进行简单处理。

【例1】使用OpenCV库来创建一个8x8的黑色图像,所有元素的值都是0,然后修改其中一个像素点的值,并显示修改后的图像。根据题目要求及分析,编写代码如下:

#include <iostream>  

#include <opencv2/opencv.hpp>  

int main() {  

    cv::Mat img = cv::Mat::zeros(8, 8, CV_8UC1);  

    std::cout << "img=\n" << img << std::endl;  

    cv::imshow("one", img);  

    std::cout << "读取像素点img[0,3]=" << img.at<uchar>(0, 3) << std::endl;  

    img.at<uchar>(0, 3) = 255;  

    std::cout << "修改后img=\n" << img << std::endl;  

    std::cout << "读取修改后像素点img[0,3]=" << img.at<uchar>(0, 3) << std::endl;  

    cv::imshow("two", img);  

    cv::waitKey();  

    cv::destroyAllWindows();  

    return 0;  

}

代码分析如下。

● 使用OpenCV库生成了一个8×8大小的二维数组,其中所有的值都是0,数值类型是np.uint8。根据该数组的属性,可以将其看成一个黑色的图像。

● 语句img[0,3]访问的是img第0行第3列的像素点,需要注意的是,行序号、列序号都是从0开始的。

● 语句img[0,3]=255将img中第0行第3列的像素点的像素值设置为“255”。

运行上述程序,会出现名为one和two的两个非常小的窗口,其中:

● 名为one的窗口是一个纯黑色的图像。

● 名为two的窗口在顶部靠近中间位置有一个白点(对应修改后的值255),其他地方也都是纯黑的图像。同时,在控制台会输出如下内容:

img= [
[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0]]

读取像素点img[0,3]= 0

修改后img= [

[ 0 0 0 255 0 0 0 0]

[ 0 0 0 0 0 0 0 0]

[ 0 0 0 0 0 0 0 0]

[ 0 0 0 0 0 0 0 0]

[ 0 0 0 0 0 0 0 0]

[ 0 0 0 0 0 0 0 0]

[ 0 0 0 0 0 0 0 0]

[ 0 0 0 0 0 0 0 0]]

读取修改后像素点img[0,3]= 255

通过本例中两个窗口显示的图像可知,二维数组与图像之间存在对应关系。

【例2】读取一个灰度图像,并对其像素进行访问、修改。根据题目要求,编写代码如下:

#include <opencv2/opencv.hpp>  

int main() {  

    cv::Mat img = cv::imread("lena.bmp", cv::IMREAD_GRAYSCALE);  

    if (img.empty()) {  

        std::cout << "无法读取图像" << std::endl;  

        return -1;  

    }  

    cv::imshow("before", img);  

    cv::waitKey(0);  

    for (int i = 100; i < 120; i++) {  

        for (int j = 100; j < 120; j++) {  

            img.at<uchar>(i, j) = 255;  

        }  

    }  

    cv::imshow("after", img);  

    cv::waitKey(0);  

    cv::destroyAllWindows();  

    return 0;  

}

在本例中,使用了一个嵌套循环语句,将图像img中“第100行到119行”与“第100列到119列”交叉区域内的像素值设置为255。从图像img上来看,该交叉区域被设置为白色。运行程序,结果如图1所示,其中:

图1 像素修改示例

● 左图是读取的原始图像。

● 右图是经过修改后的图像。

2.彩色图像RGB模式的彩色图像在读入OpenCV内进行处理时,会按照行方向依次读取该RGB图像的B通道、G通道、R通道的像素点,并将像素点以行为单位存储在ndarray的列中。例如,有一幅大小为R行×C列的原始RGB图像,其在OpenCV内以BGR模式的三维数组形式存储,如图2所示。

图2 RGB图像以三维数组形式存储的情况说明

可以使用表达式访问数组内的值。例如,可以使用image[0][0][0]访问图像image的B通道内的第0行第0列上的像素点,式中:

● 第1个索引表示第0行。

● 第2个索引表示第0列。

● 第3个索引表示第0个颜色通道。

根据上述分析可知,假设有一个红色(其R通道值为255, G通道值为0, B通道值为0)图像,不同的访问方式得到的值如下:

● img[0][0]:访问图像img第0行第0列像素点的BGR值。图像是BGR格式的,得到的数值为[0,0,255]。

● img[0][0][0]:访问图像img第0行第0列第0个通道的像素值。图像是BGR格式的,所以第0个通道是B通道,会得到B通道内第0行第0列的位置所对应的值0。

● img[0][0][1]:访问图像img第0行第0列第1个通道的像素值。图像是BGR格式的,所以第1个通道是G通道,会得到G通道内第0行第0列的位置所对应的值0。

● img[0][0][2]:访问图像img第0行第0列第2个通道的像素值。图像是BGR格式的,所以第2个通道是R通道,会得到R通道内第0行第0列的位置所对应的值255。

彩色图像的像素级处理

【例3】生成一个三维数组,用来观察三个通道值的变化情况。根据题目要求,编写代码如下:

#include <opencv2/opencv.hpp>  

int main() {  

    // 创建一个300x300大小的蓝色通道图像  

    cv::Mat blue(300, 300, CV_8UC3, cv::Scalar(0, 0, 255));  

    cv::imshow("blue", blue);  

    // 创建一个300x300大小的绿色通道图像  

    cv::Mat green(300, 300, CV_8UC3, cv::Scalar(255, 0, 0));  

    cv::imshow("green", green);  

    // 创建一个300x300大小的红色通道图像  

    cv::Mat red(300, 300, CV_8UC3, cv::Scalar(0, 255, 0));  

    cv::imshow("red", red);  

    // 等待用户按键,然后关闭所有窗口  

    cv::waitKey(0);  

    cv::destroyAllWindows();  

    return 0;  

}

在本例中,分别生成了blue、green、red三个数组,其初始值都是0。接下来,分别改变各通道值。

● 针对数组blue,将其第0个通道的值设置为255。从图像角度来看,图像blue的B通道值为255,其余两个通道值为0,因此图像blue为蓝色图像。

● 针对数组green,将其第1个通道的值设置为255。从图像角度来看,图像green的G通道值为255,其余两个通道值为0,因此图像green为绿色图像。● 针对数组red,将其第2个通道的值设置为255。从图像角度来看,图像red的R通道值为255,其余两个通道值为0,因此图像red为红色图像。运行上述程序,会显示颜色为蓝色、绿色、红色的三幅图像,分别对应数组blue、数组green、数组red。因为黑白印刷无法显示彩色图像,所以请读者运行程序后观察结果。

除了显示图像,还会显示每个数组的输出值,部分输出结果如图3所示。

图3 【例3】程序的部分输出结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c++例题2点和直线关系

#include<iostream> #include<string> using namespace std; //圆的类 class yuan{ public:int x2 10;int y2 10;int r 5; }; //点的类 class dian{ public :void setx(int x){x1 x;}int getx(){return x1;}void sety(int y){y1 y;}int gety(){return y1;} pr…

Sqoop性能优化:高效数据传输的技巧

当使用Apache Sqoop进行数据传输时&#xff0c;性能优化至关重要。高效的数据传输可以减少任务运行时间&#xff0c;减轻集群负载&#xff0c;提高整体工作效率。在本文中&#xff0c;将深入探讨Sqoop性能优化的关键技巧&#xff0c;并提供丰富的示例代码&#xff0c;以帮助大家…

(学习日记)2024.01.09

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

Github 2024-01-13 C#开源项目日报 Top8

根据Github Trendings的统计&#xff0c;今日(2024-01-13统计)共有8个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量C项目8 Redis - 内存数据库和数据结构服务器 创建周期&#xff1a;5411 天开发语言&#xff1a;C协议类型&am…

功效产品如何做好营销?媒介盒子解答

功能性产品目前的营销痛点就在于宣传夸张导致用户信任度降低&#xff0c;尤其是健康类产品&#xff0c;作为消费者&#xff0c;对此类产品大多持观望态度&#xff0c;但媒介盒子作为提供品牌宣传服务的团队&#xff0c;想和大家聊聊&#xff1a;功能性产品除了在功能上进行宣传…

Vue+ElementUI+Axios实现携带参数的文件上传(数据校验+进度条)

VueElementUIAxios实现携带参数的文件上传&#xff08;数据校验进度条&#xff09; 可以实现对上传文件的类型&#xff0c;大小进行数据校验&#xff0c;以及对上传文件所要携带的数据也进行的校验&#xff0c;也有文件上传进度的进度条。 一、Vue 结构部分 弹窗显示&#xff0…

Linux集锦大全【持续更新】

文章目录 Linux集锦大全【持续更新】Linux最常用的几个归档和压缩命令解压方法之一 tar语法压缩文件查看压缩文件的内容解压文件 解压方法之一 zip语法参数参考实例仅保存文件名 解压命令之一 unzip基本命令指定目录解压不解压某些文件 解压命令之一 gzip Linux最危险的几个命令…

crackmapexec工具详解

下载地址&#xff1a;https://github.com/Porchetta-Industries/CrackMapExec wiki&#xff1a;https://www.crackmapexec.wiki/ 1.安装&#xff08;MAC&#xff09; 1.1.python3.9 pipx 安装&#xff08;运行软件有警告&#xff0c;推荐 python3.11 pipx 安装&#xff09; …

准备好迎接新兴的汽车雷达卫星架构了吗?(TI文档)

引言 随着全球新车评估计划的安全等级和法规对主动安全功能的要求越来越严格&#xff0c;安全是当今车辆的一个不容置疑的特征。全球汽车制造商正在满足这些安全要求&#xff0c;并通过不断增强车辆内的高级驾驶辅助系统(ADAS)功能&#xff0c;包括自动紧急制动(AEB)、自适应巡…

鸿蒙HarmonyOS兼容JS的类Web开发

鸿蒙HarmonyOS兼容JS的类Web开发 文章目录 鸿蒙HarmonyOS兼容JS的类Web开发文件组织目录结构文件访问规则媒体文件格式 js标签配置pageswindow示例 app.js应用生命周期应用对象6 HML语法参考页面结构数据绑定普通事件绑定冒泡事件绑定5捕获事件绑定5列表渲染条件渲染逻辑控制块…

2024上半年教资笔试报名详细教程1月12日开始报名啦

重点提醒&#xff1a; 1、注册开放时间&#xff1a;2024年1月10日开始。 &#xff08;参加过笔试的考生&#xff0c;需要重新注册&#xff0c; 不影响已获得的笔试成绩。名额少的考点建议提前注册抢名额&#xff09; 2、网上报名时间&#xff1a;2024年1月12日至15日。 千万不…

机器人制作开源方案 | 基于混合现实的可移动机械臂平台

作者&#xff1a;董泽宇 李肖兵 叶彤 李秉宸 吴雅霏 单位&#xff1a;广西大学 电气工程学院 指导老师&#xff1a;李勇 雷圆媛 为应对特殊条件下不便于实地进行移动式操作的问题&#xff0c;本作品设计了一套基于混合现实的可移动机械臂操作控制系统。该系统分为人机交互、机…

【期末不挂科-C++考前速过系列P3】大二C++第3次过程考核(20道选择题&12道判断题&2道代码题)【解析,注释】

前言 大家好吖&#xff0c;欢迎来到 YY 滴C考前速过系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《…

Linux中断 -- 中断应答、嵌套、

接上文&#xff0c;本文继续介绍Linux软件部分逻辑。 参考内核版本&#xff1a;kernel-4.19 目录 1.中断信号在各级中断控制器中的应答 2.supports_deactivate_key意义 3.中断嵌套 1.中断信号在各级中断控制器中的应答 本章主要从内核软件层面来看各中断控制器对中断信号处…

self-attention机制详解

目前&#xff0c;对于我们的network&#xff0c;给定的input大都是一个向量&#xff1a; 但是对于更复杂的情况&#xff0c;我们的input是a set of vec: 举例&#xff1a; nlp中的句子&#xff0c;对于每个word都是一个word embedding&#xff1a; 图学习中每个节点有一个e…

SpringBoot3.X源码分析(启动流程)

SpringBootApplication(scanBasePackages {"com.javaedge.base"} ) public class BaseApplication {public BaseApplication() {}public static void main(String[] args) {SpringApplication.run(BaseApplication.class, args);} } 1 启动入口 静态辅助类&#x…

【从0上手cornerstone3D】如何渲染一个基础的Dicom文件(含演示)

一、Cornerstone3D 是什么&#xff1f; Cornerstone3D官网&#xff1a;https://www.cornerstonejs.org/ 在线查看显示效果&#xff08;加载需时间&#xff0c;可先点击运行&#xff09;&#xff0c;欢迎fork 二、代码示例 了解了Cornerstone是什么&#xff0c;有什么作用后&…

SpringBoot3自动配置原理

​​​​​​自动配置 遵循约定大约配置的原则&#xff0c;在boot程序启动后&#xff0c;起步依赖中的一些bean对象会自动注入到ioc容器 看一下我们前面写的代码有没有达到自动配置的效果呢&#xff1f; 没有自动&#xff0c;我们写了配置类&#xff0c;写了Import注解&#…

解释程序基本原理

解释程序基本原理 1、解释程序的基本结构2、高级语言编译与解释方式的比较 语言处理程序是一类系统软件的总称&#xff0c;其主要作用是将高级语言或汇编语言编写的程序翻译成某种机器语言程序&#xff0c;使程序可在计算机上运行。语言处理程序主要分为汇编程序、编译程序和解…

匠心科技BLDC开发板原理图讲解

匠心科技BLDC开发板资料 链接&#xff1a;https://pan.baidu.com/s/1s5YjzRSDLKQvl86lBVAqKA?pwda6cx 提取码&#xff1a;a6cx 解压密码&#xff1a;JXKJ_RALDNWB站视频讲解&#xff08;&#xff09; 链接: 匠心科技直流无刷电机开发板原理图讲解 BLDC的开发板主要分为四个模…