实战OpenCV之像素操作

基础入门

        在OpenCV中,像素是最基本的操作单位。图像可以视为一个三维数组,其中第三维表示颜色通道。图像数据在内存中以连续或几乎连续的方式存储,对于多通道图像(比如:BGR图像),每个像素的各通道值紧密排列。OpenCV主要使用BGR色彩空间,与常用的RGB顺序不同。因此,在进行像素操作时,需要特别注意色彩通道的顺序。OpenCV中最常见的图像格式是CV_8UC3,表示一个8位无符号整型的三通道图像。

        像素操作通常会涉及到颜色,在OpenCV中,Scalar类型常用来表示颜色。一个Scalar对象可以存储四个元素,分别对应于图像中的四个通道,通常为BGRA色彩空间。当处理彩色图像时,这四个值代表蓝色(B)、绿色(G)、红色(R)和可选的透明度(A,alpha通道)。如果处理的是灰度图像,则通常只使用第一个通道即可。

        如果我们想定义一个红色的颜色,可以参考下面的示例代码。

// BGR格式,故(0, 0, 255)代表红色
cv::Scalar redColor(0, 0, 255);

        对于带有透明度的颜色,可以像下面的示例代码这样,定义一个半透明的红色。

// 最后一个值是alpha通道,范围从0(完全透明)到255(完全不透明)
cv::Scalar semiTransparentColor(0, 0, 255, 128);

实战解析

        在OpenCV中,主要有两种方式来访问和修改像素值:指针访问和at函数访问。

        指针访问是指直接通过计算像素地址来进行操作,这种方式在性能上可能更优,但实现较为复杂,容易出错。在下面的示例代码中,我们创建了一个300 x 400像素的蓝色图像,并通过指针访问方式将图像最中间一行的像素修改为红色。

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main()
{// 创建一个300 x 400的蓝色图像Mat img(300, 400, CV_8UC3, Scalar(255, 0, 0));// 访问并修改最中间一行的像素,将其变为红色int nMidRow = img.rows / 2;uchar* pRow = img.ptr<uchar>(nMidRow);for (int nCol = 0; nCol < img.cols; nCol++){// B分量pRow[nCol * 3] = 0;// G分量pRow[nCol * 3 + 1] = 0;// R分量pRow[nCol * 3 + 2] = 255;}// 显示图像imshow("Image", img);waitKey(0);return 0;
}

        at函数访问提供了一种更安全、更易读的方式来访问和修改像素值,虽然牺牲了一点性能,但代码更加清晰。在下面的示例代码中,我们同样创建了一个300 x 400像素的蓝色图像,并通过at函数访问方式将图像最中间一行的像素修改为红色。

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main()
{// 创建一个300 x 400的蓝色图像Mat img(300, 400, CV_8UC3, Scalar(255, 0, 0));// 访问并修改最中间一行的像素,将其变为红色int nMidRow = img.rows / 2;for (int nCol = 0; nCol < img.cols; nCol++){// 通过at函数访问每个像素并修改其颜色分量img.at<Vec3b>(nMidRow, nCol)[0] = 0;img.at<Vec3b>(nMidRow, nCol)[1] = 0;img.at<Vec3b>(nMidRow, nCol)[2] = 255;}// 显示图像imshow("Image", img);waitKey(0);return 0;
}

        执行上面的示例代码,运行效果可参考下图。

均值计算

        在OpenCV中,计算图像的像素均值,主要利用cv::mean()函数。像素均值被计算出来后,可以作为图像亮度调整的基础。

Mat img;
Scalar avgPixel = cv::mean(img);
cout << avgPixel[0] << ", " << avgPixel[1] << ", " << avgPixel[2] << endl;

像素级逻辑操作

        像素级逻辑操作通常涉及按位与、或、异或等操作,主要用于图像处理中的掩码应用、图像合成等场景。OpenCV提供了一系列函数来执行像素级的逻辑操作,下面逐一进行介绍。

        1、逻辑与。cv::bitwise_and()函数用于对两个图像的对应像素执行逻辑与操作。如果两个像素都为非零,结果像素就是非零;否则,结果像素为零。这对于应用掩码、选取图像的交集区域非常有用。

        2、逻辑或。cv::bitwise_or()函数用于对两个图像的对应像素执行逻辑或操作。只要两个像素中有一个为非零,结果像素就是非零。这可以用来合并图像的区域,或增加特征检测的鲁棒性。

        3、逻辑异或。cv::bitwise_xor()函数用于对两个图像的对应像素执行逻辑异或操作。当两个对应像素不同时,结果像素为非零;否则,结果像素为零。这可以用于突出显示两个图像之间的差异。

        4、逻辑非。cv::bitwise_not()函数用于对图像中的每个像素执行逻辑非操作,即将1变为0,0变为1。这常用于图像的反转,或颜色空间转换前的预处理。

        注意:在使用以上这些函数时,需要确保输入图像的数据类型兼容,并且大小相同。此外,还可以传入一个可选的掩码参数,仅对掩码中非零的像素执行操作,这对于局部处理非常有用。

        接下来,我们通过下面的实战代码来理解cv::bitwise_and()函数。

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main()
{Mat srcImage = imread("OpenCV.png");if(srcImage.empty()){cout << "Image not found" << endl;return -1;}// 创建一个矩形的掩码图像,初始化为全黑Mat mask = Mat::zeros(srcImage.size(), CV_8UC1);// 画一个白色矩形作为掩码rectangle(mask, Point(150, 0), Point(450, 250), Scalar(255, 255, 255), -1);// 使用bitwise_and函数应用掩码Mat destImage;bitwise_and(srcImage, srcImage, destImage, mask);// 显示原图、掩码和结果imshow("Original Image", srcImage);imshow("Mask", mask);imshow("Result Image", destImage);waitKey(0);destroyAllWindows();return 0;
}

        在上面的示例代码中,我们首先读取了一张图片到srcImage中。接着,我们创建了一个与原图同样大小的单通道灰度图像mask,并用一个白色矩形填充了其中一部分。这个白色矩形就是我们的“感兴趣区域”,其余部分为黑色,代表透明或不需要的部分。

        通过bitwise_and函数,我们将原图srcImage与自身进行了按位与操作,并且指定了掩码mask。这意味着只有掩码中为白色(值为255)的部分,在结果图像中保留了原图的像素值。而掩码中为黑色(值为0)的部分,在结果图像中对应的像素值将被设为0(黑色),从而达到了只显示我们感兴趣区域的效果。

        最后,我们使用imshow显示了原图、掩码、应用掩码后的结果图像,可参考如下。

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

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

相关文章

EmguCV学习笔记 VB.Net 11.5 目标检测

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

初识时序数据库InfluxDB

最近项目开发中,需要记录时间序列的日志信息,InfluxDB 刚好契合。于是准备研究一下,发现已经有整理很好的文档,以下两篇觉得很好,入门开发可以参考一下。 因为项目是用C#开发的,因此,简单介绍一下C#开发中,InfluxDB的API使用。 1.简介 InfluxDB是一个由InfluxData开发…

《食品安全导刊》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《食品安全导刊》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《食品安全导刊》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a; 中国商业联合会 主办单…

ONLYOFFICE8.0部署集成(vue+java)并配置存储为minio

文章目录 前言一、使用docker安装onlyoffice8安装使用DockerDesktop方式命令行方式使用 HTTPS 运行展示 二、项目集成前端集成-vue3html方式后端集成-java 三、onlyoffice基础原理四、配置存储为minio1.onlyoffice配置文件挂载问题2.配置存储为minio3.验证切换minio存储是否生效…

生成式AI介绍

生成式AI介绍 生成式AI&#xff08;Generative AI&#xff09;是人工智能领域的一种技术&#xff0c;能够通过学习现有数据来生成新的内容。不同于传统的人工智能模型只进行分类、回归等分析任务&#xff0c;生成式AI具备创作能力&#xff0c;能够生成文本、图像、音频甚至视频…

基于spring拦截器实现博客项目的强制登录功能(四)

6. 强制登录 当⽤⼾访问 博客列表和博客详情⻚ 时, 如果⽤⼾当前尚未登陆, 就⾃动跳转到登陆⻚⾯. 我们可以采⽤拦截器来完成, token通常由前端放在header中, 我们从header中获取token, 并校验 token是否合法 6.1 添加拦截器 package com.example.spring_blog_24_9_8.config;…

性能测试-jmeter的控制器(十六)

一、if控制器 需求&#xff1a;使用“用户自定义变量”定义name变量&#xff0c;值可以是“baidu”或“itcast”,使用变量值&#xff0c;控制是否访问对应网站。 1、步骤&#xff1a; 在测试计划中添加用户定义的变量name,取值可为baidu或itcast添加两个http请求&#xff1a…

misc音频隐写

一、MP3隐写 &#xff08;1&#xff09;题解&#xff1a;下载附件之后是一个mp3的音频文件&#xff1b;并且题目提示keysyclovergeek;所以直接使用MP3stego对音频文件进行解密&#xff1b;mp3stego工具是音频数据分析与隐写工具 &#xff08;2)mp3stego工具的使用&#xff1a;…

CSS实现前端布局更巧妙的方案!在 flex 布局中通过使用 margin 实现水平垂直居中以及其他常见的前端布局

在前端开发中&#xff0c;实现水平垂直居中一直是个热门话题。随着 CSS Flexbox 布局的普及&#xff0c;开发者们开始更多地使用 justify-content 和 align-items 这两个属性来解决这个问题。 然而&#xff0c;还有一种更加简洁、灵活的方式——使用 margin: auto; 来实现居中以…

大数据之Flink(二)

4、部署模式 flink部署模式&#xff1a; 会话模式&#xff08;Session Mode&#xff09;单作业模式&#xff08;Per-Job Mode&#xff09;应用模式&#xff08;Application Mode&#xff09; 区别在于集群的生命周期以及资源的分配方式&#xff1b;以及应用的main方法到底在…

Vue3使用vue-qrcode-reader实现扫码绑定设备功能

需求描述 移动端进入网站后&#xff0c;登录网站进入设备管理界面。点击添加设备&#xff0c;可以选择直接添加或者扫一扫。点击扫一扫进行扫描二维码获取设备序列号自动填充到添加设备界面的序列号输入框中。然后点击完成进行设备绑定。 安装vue-qrcode-reader 这里使用的版…

2024.9.11 作业

绘制组件制作时钟 代码&#xff1a; /*******************************************/ 文件名&#xff1a;widget.h /*******************************************/ #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include &l…

MAX3483ESA+T具有±15kV ESD保护的+3.3V、低功耗收发器,适用于RS-485和RS-422通信

MAX3483ESAT具有15kV ESD保护的3.3V、低功耗收发器&#xff0c;适用于RS-485和RS-422通信。每个器件包含一个驱动器和一个接收器。MAX3483ESAT具有限摆率驱动器&#xff0c;可充分降低EMI并减少因电缆端接不当引起的反射&#xff0c;从而实现数据速率高达250kbps的无误差数据传…

【中间件】-容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么&#xff1f; K8s的架构原理 控制平面(Control plane) kube-apiserver etcd kube-scheduler kube-controller-manager cloud-controller-manager 小结 节点组件(Node) container runtime Pod kubelet ku…

AnyChart 数据可视化框架

AnyChart 数据可视化框架 AnyChart 是一个灵活的 JavaScript&#xff08;HTML5、SVG、VML&#xff09;图表框架&#xff0c;适合任何需要数据可视化的解决方案。 目录 下载并安装开始插件将 AnyChart 与 TypeScript 结合使用将 AnyChart 与 ECMAScript 6 结合使用技术集成贡献…

Anolis OS 7.9(龙蜥操作系统)上Oracle12C Release 2 (12.2)打补丁

本文的oracle使用的是单实例环境 一、打补丁前环境准备 1、确保make, ar, ld,和 nm四个可执行命令在$PATH中 export PATH$PATH:/bin2、查看已装的Oracle的OPatch版本 #切换到oracle用户 su - oracle#进入到数据库的安装目录下的opatch目录 cd /ora01/app/oracle/product/12…

JS_函数声明

JS中的方法,多称为函数,函数的声明语法和JAVA中有较大区别 函数说明 函数没有权限控制符不用声明函数的返回值类型,需要返回在函数体中直接return即可,也无需void关键字参数列表中,无需数据类型调用函数时,实参和形参的个数可以不一致声明函数时需要用function关键字函数没有…

github actions CICD简单使用案例

参考&#xff1a; https://developer.aliyun.com/article/1540773 https://github.com/ViggoZ/producthunt-daily-hot/blob/main/.github/workflows/generate_markdown.yml 1、创建github项目 目录&#xff1a; .github/workflows/fetch-news.yml actions执行yaml&#xff08;…

C语言 | Leetcode C语言题解之第397题整数替换

题目&#xff1a; 题解&#xff1a; //第一种动态规划:超时 // class Solution { // public: // int integerReplacement(int n) { // vector<int>dp(n1,0); // dp[1]0; // for(int i2;i<n;i){ // if(i%20){ // …

Vue接入高德地图并实现基本的路线规划功能

目录 一、申请密钥 二、安装依赖 三、代码实现 四、运行截图 五、官方文档 一、申请密钥 登录高德开放平台&#xff0c;点击我的应用&#xff0c;先添加新应用&#xff0c;然后再添加Key。 如图所示填写对应的信息&#xff0c;系统就会自动生成。 二、安装依赖 npm i am…