python学opencv|读取图像(四十七)使用cv2.bitwise_not()函数实现图像按位取反运算

【0】基础定义

按位与运算:两个等长度二进制数上下对齐,全1取1,其余取0。按位或运算:两个等长度二进制数上下对齐,有1取1,其余取0。

按位取反运算:一个二进制数,0变1,1变0。

【1】引言

前序已经学习了cv2.bitwise_and()函数进行图像按位与计算和按位或运算,相关文章链接为:

python学opencv|读取图像(四十三)使用cv2.bitwise_and()函数实现图像按位与运算-CSDN博客

python学opencv|读取图像(四十四)原理探究:bitwise_and()函数实现图像按位与运算-CSDN博客

python学opencv|读取图像(四十五)增加掩模:使用cv2.bitwise_and()函数实现图像按位与运算-CSDN博客

python学opencv|读取图像(四十六)使用cv2.bitwise_or()函数实现图像按位或运算-CSDN博客

在此基础上,我们尝试对单个图像操作“按位取反”,此处使用的函数为cv2.bitwise_not()。

【2】官网教程

【2.1】cv2.bitwise_not()函数

点击下方链接,直达函数cv2.bitwise_not()的官网教程:

OpenCV: Operations on arrays

官网对函数的说明页面为:

图1  cv2.bitwise_not()的官网教程

在cv2.bitwise_not()的官网教程可以看到,函数的参数说明为:

void cv::bitwise_not     (     InputArray     src,      #输入图像
        OutputArray     dst,                                      #输出图像
        InputArray     mask = noArray() )                 #掩模

在函数cv2.bitwise_not()中,也可以调用掩模效果,而且掩模为8位单通道二维矩阵。

【2.2】np.bitwise_not()函数

点击下方链接,可以=直达numpy官网对bitwise_not()函数的官网页面:numpy.bitwise_invert — NumPy v2.2 Manual

代码先后使用cv2.bitwise_not()函数和np.bitwise_not()函数来展示图像按位取反操作的基本原理。

【3】代码测试

参考前述学习进程中调用的代码,按照输入图像-按位取反-输出图像的顺序规划代码。

首先引入相关模块和图像:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块# 读取图片-直接转化灰度图
src = cv.imread('srcx.png') #读取图像
dst=src #输出图像
gray_src=cv.cvtColor(src,cv.COLOR_BGR2GRAY) #转化为灰度图
dstg=gray_src #输出图像
print('初始图像像素大小为',src.shape)
print('初始图像灰度图像素大小为',gray_src.shape)

然后定义一个掩模矩阵,掩模矩阵直接使用引入图像的尺寸来约束大小:

#定义掩模矩阵
mask = np.zeros((gray_src.shape), np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
mask[280:350, :] = 155  # 水平区域
mask[:,150:350] = 200  # 竖直区域

然后进行按位取反运算:

#按位取反运算
img=cv.bitwise_not(src) #按位取反运算
img2=cv.bitwise_not(src,mask=mask) #按位取反运算

然后进行BGR值的二进制取反运算验证:

#显示BGR值
print("dst像素数为[300,180]位置处的BGR=", dst[300,180])  # 获取像素数为[100,100]位置处的BGR
print("mask像素数为[300,180]位置处的BGR=", mask[300,180])  # 获取像素数为[100,100]位置处的BGR
print("img像素数为[300,180]位置处的BGR=", img[300,180])  # 获取像素数为[100,100]位置处的BGR
print("img2像素数为[300,180]位置处的BGR=", img2[300,180])  # 获取像素数为[100,100]位置处的BGRa=np.zeros((1,3),np.uint8) #定义矩阵
a=dst[300,180] #将像素点BGR直接赋值给矩阵
b=np.zeros((1,3),np.uint8) #定义矩阵
b=img[300,180] #将像素点BGR直接赋值给矩阵
c=np.zeros((1,3),np.uint8) #定义矩阵
d=np.zeros((1,3),np.uint8) #定义矩阵
e=np.zeros((1,3),np.uint8) #定义矩阵
e=img2[300,180] #将像素点BGR直接赋值给矩阵#二进制按位取反计算
for i in range(3): #计数print('a','[0,',i,']=',a[i],'的二进制转化值= ', bin(a[i])) #输出二进制转化值c[0,i]=np.bitwise_not(a[i]) #赋值按位与计算值print('c','[0,',i,']=',c[0,i],'的二进制转化值=', bin(c[0,i])) #输出二进制转化值print('c',[0,i],'是a','[0,',i,']转到二进制后按位取反从,再二进制转回十进制=',c[0,i]) #输出按位与计算值print('b','[0,',i,']=',b[i],'的二进制转化值=', bin(b[i])) #输出二进制转化值d[0,i]=np.bitwise_not(b[i]) #赋值按位与计算值print('d', '[0,', i, ']=', d[0, i], '的二进制转化值=', bin(d[0, i]))  # 输出二进制转化值print('d', [0, i], '是b', '[0,', i, ']转到二进制后按位取反从,再二进制转回十进制=', d[0, i])  # 输出按位与计算值print('e','[0,',i,']=',[i],'的二进制转化值=', bin(e[i])) #输出二进制转化值
#输出矩阵结果
print('a=',a) #输出矩阵
print('b=',b) #输出矩阵
print('c=',c) #输出矩阵
print('d=',d) #输出矩阵
print('e=',e) #输出矩阵

再把图像显示和输出即可:

#合并图像
himg=np.hstack((src,img))
himg2=np.hstack((src,img2))
himg3=np.hstack((img,img2))
# 显示和保存定义的图像
cv.imshow('dst', dst)  # 显示图像
cv.imshow('or-img', img)  # 显示图像
cv.imwrite('or-img.png', img)  # 保存图像
cv.imshow('or-img2', img2)  # 显示图像
cv.imwrite('or-img2.png', img2)  # 保存图像cv.imshow('or-mask', mask)  # 显示图像
cv.imwrite('or-mask.png', mask)  # 保存图像
cv.imshow('or-himg', himg)  # 显示图像
cv.imwrite('or-himg.png', himg)  # 保存图像
cv.imshow('or-himg2', himg2)  # 显示图像
cv.imwrite('or-himg2.png', himg2)  # 保存图像
cv.imshow('or-himg3', himg3)  # 显示图像
cv.imwrite('or-himg3.png', himg3)  # 保存图像
cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

代码运行使用的图像有:

图2  初始图像srcx.png

图3  掩模矩阵对应图像or-mask.png

 图4  图像不带掩模按位取反效果or-img.png

 图5  初始图像对比不带掩模按位取反图像

由图2、图4和图5可见,初始图像进行按位取反以后,颜色发生了显著变化。

如果添加掩模效果,会有:

 图6  图像带掩模按位取反效果or-img2.png

 图7  初始图像对比带掩模按位取反图像 

由图6和图7可见,初始图像叠加掩模效果进行按位取反以后,颜色发生了显著变化,但只保留了掩模所在区域的图像。

在此基础上,读取特定像素点的BGR值进行二进制取反操作:

图8 BGR值取反验证

图8中,代码调用np.bitwise_not()函数对BGR值执行了取反-再取反的验证过程,实践表明:

使用cv2.bitwise_not()函数执行图像按位取反计算时,各个像素点的BGR值都是按照十进制转二进制、二进制按位取反计算,然后再转回十进制的顺序进行。

图9  cv2.bitwise_not()函数实现图像带掩模矩阵按位取反计算

【4】细节说明

由于掩模矩阵是单通道二维矩阵,所以掩模本身只会在黑白色之间变化。

【5】总结

掌握了python+opencv实现使用cv2.bitwise_not()函数实现图像带掩模矩阵按位取反计算的技巧。

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

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

相关文章

初二回娘家

昨天下午在相亲相爱一家人群里聊天,今天来娘家拜年。 聊天结束后,开始准备今天的菜肴,梳理了一下,凉菜,热菜,碗菜。 上次做菜,粉丝感觉泡的不透,有的硬,这次使用开水浸泡…

“星门计划对AI未来的意义——以及谁将掌控它”

“星门计划对AI未来的意义——以及谁将掌控它” 图片由DALL-E 3生成 就在几天前,唐纳德特朗普宣布了“星门计划”,OpenAI随即跟进,分享了更多细节。他们明确表示,计划在未来四年内投资5000亿美元,在美国为OpenAI构建一…

内外网文件摆渡企业常见应用场景和对应方案

在如今的企业环境中,内外网文件摆渡的需求越来越常见,也变得越来越重要。随着信息化的不断推进,企业内部和外部之间的数据交换越来越频繁,如何安全、高效地进行文件传输成了一个关键问题。今天,咱就来聊聊内外网文件摆…

2025一区新风口:小波变换+KAN!速占!

今天给大家分享一个能让审稿人眼前一亮,好发一区的idea:小波变换KAN! 一方面:KAN刚中稿ICLR25,正是风口上,与小波变换的结合还处于起步阶段,正是红利期,创新空间广阔。 另一方面&a…

idea修改模块名导致程序编译出错

本文简单描述分别用Idea菜单、pom.xml文件管理项目模块module 踩过的坑: 通过idea菜单创建模块,并用idea菜单修改模块名,结构程序编译报错,出错的代码莫名奇妙。双击maven弹窗clean时,还是报错。因为模块是新建的&am…

线程池以及在QT中的接口使用

文章目录 前言线程池架构组成**一、任务队列(Task Queue)****二、工作线程组(Worker Threads)****三、管理者线程(Manager Thread)** 系统协作流程图解 一、QRunnable二、QThreadPool三、线程池的应用场景W…

P1044 [NOIP2003 普及组] 栈 C语言

P1044 [NOIP2003 普及组] 栈 - 洛谷 | 计算机科学教育新生态 题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。 栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 pus…

随机矩阵投影长度保持引理及其证明

原论文中的引理 2 \textbf{2} 2 引理 2 \textbf{2} 2的内容​​ 👉前提 1 1 1:设一个随机矩阵 S ( s i j ) ∈ R t d S\text{}(s_{ij})\text{∈}\mathbb{R}^{t\text{}d} S(sij​)∈Rtd,每个元素 s i j s_{ij} sij​独立同分布于 N ( 0 , …

CF 761A.Dasha and Stairs(Java实现)

题目分析 大概意思是输入偶数值奇数值,判断是否能够凑成一连串数字 思路分析 能够连成一串数字的条件考虑:1.偶数与奇数差为1;2.偶数与奇数相等,且不为0 代码 import java.util.*;public class Main {public static void…

FastExcel使用详解

文章目录 FastExcel使用详解一、引言二、环境准备与依赖引入1、Maven 依赖引入2、实体类定义 三、核心操作:读写 Excel1、读取 Excel1.1 自定义监听器1.2 读取文件 2、写入 Excel2.1 简单写入2.2 模板写入 四、Spring Boot 集成示例1、文件上传(导入&…

zabbix7 配置字体 解决中文乱码问题(随手记)

目录 问题网传的方法(无效)正确的修改方式步骤 问题 zabbix 最新数据 中,图标的中文显示不出。 网传的方法(无效) 网传有一个方法:上传字体文件到/usr/share/zabbix/assets/fonts;修改/usr/…

我的求职面经:(1)C++里指针和数组的区别

经典问题&#xff1a; char s1[]"hello"; char *s2"hello"; 1、s1的值是放在栈上的&#xff0c;值是可以修改的&#xff0c;而hello是一个字符串常量放在静态存储区是不能修改的。 2、内存大小不一样 #include<stdio.h>int main(){char s1[]&quo…

01. 计算机系统

计算机系统简单概述 计算机系统是一个综合性的系统&#xff0c;旨在按人的要求接收和存储信息&#xff0c;自动进行数据处理和计算&#xff0c;并输出结果信息。以下是关于计算机系统的详细介绍&#xff1a; 一、定义与组成 计算机系统是由硬件和软件组成的&#xff0c;用于执…

Git进阶之旅:.gitignore 文件

介绍&#xff1a; 在项目中&#xff0c;我们可能一起提交多个文件 git add -A&#xff1a;提交所有变化git add -u&#xff1a;提交被修改(modified) 和被删除文件(deleted) 文件&#xff0c;不包括新文件(new) git add .&#xff1a;提交新文件(new) 和被修改文件(modif…

指针(C语言)从0到1掌握指针,为后续学习c++打下基础

目录 一&#xff0c;指针 二&#xff0c;内存地址和指针 1&#xff0c;什么是内存地址 2&#xff0c;指针在不同系统下所占内存 三&#xff0c;指针的声明和初始化以及类型 1,指针的声明 2,指针 的初始化 1&#xff0c; 初始化方式优点及适用场景 4,指针的声明初始化类型…

Leetcode 45. 跳跃游戏 II

这题是一个动态规划问题&#xff0c;首先我先说一下自己的动态规划解题步骤&#xff1a; 1&#xff0c;首先需要明确动态规划数组的含义&#xff1a;这个是根据题目来定的&#xff0c;这一个题目的数组含义&#xff1a;dp【i】指的是从0跳到i所需要的最小的步骤。 2&#xff…

【Block总结】PConv,部分卷积|即插即用

论文信息 标题: Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks 论文链接: https://arxiv.org/pdf/2303.03667 GitHub链接: https://github.com/JierunChen/FasterNet 创新点 该论文的核心创新在于提出了一种新的运算符——部分卷积&#xff08;PCo…

Maven的单元测试

1. 单元测试的基本概念 单元测试&#xff08;Unit Testing&#xff09; 是一种软件测试方法&#xff0c;专注于测试程序中的最小可测试单元——通常是单个类或方法。通过单元测试&#xff0c;可以确保每个模块按预期工作&#xff0c;从而提高代码的质量和可靠性。 2.安装和配…

【漫话机器学习系列】069.哈达马乘积(Hadamard Product)

哈达马乘积&#xff08;Hadamard Product&#xff09; 哈达马乘积&#xff08;Hadamard Product&#xff09;是两个矩阵之间的一种元素级操作&#xff0c;也称为逐元素乘积&#xff08;Element-wise Product&#xff09;。它以矩阵的对应元素相乘为规则&#xff0c;生成一个新…

【设计测试用例自动化测试性能测试 实战篇】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a; c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 设计测试用例…