OpenCV基础操作(2)OpevCV算术运算

news2024/11/17 21:49:31

OpenCV基础操作(2)OpevCV算术运算

在这里插入图片描述

import cv2 as cv
import numpy as np

一、图像的基础操作

1、获取并修改像素值

'''
你可以根据像素的行和列的坐标获取他的像素值。
对 BGR 图像而言,返回值为 B,G,R 的值。对灰度图像而言,会返回他的灰度值
'''

img = cv.imread('img.jpg')
px = img[100,100]
print(px)
blue = img[100,100,0]
print(blue)
[255 255 255]
255
# 以类似的方式修改像素值
img[100,100]=[0,0,0]
print(img[100,100])
[0 0 0]
'''
上面提到的方法被用来选取矩阵的一个区域,比如说前 5 行的后 3列。
对于获取每一个像素值,也许使用 Numpy 的 array.item() 和 array.itemset() 会更好。但是返回值是标量。
如果你想获得所有 B,G,R 的值,你需要使用 array.item() 分割他们。
'''
(494, 650, 3)
'''
获取像素值及修改的更好方法(推荐)
'''

img = cv.imread('img.jpg')
# 使用Image对象的item()取值
print(img.item(10,10,0))
# 使用Image对象的itemset()设置值
img.itemset((10,10,2),100)
print(img.item(10,10,2))
255
100

2、获取图像属性

img = cv.imread('img.jpg')
# img.shape 可以获取图像的形状。他的返回值是一个包含行数,列数,通道数的元组
# 如果图像是灰度图,返回值仅有行数和列数。所以通过检查这个返回值就可以知道加载的是灰度图还是彩色图
print(img.shape)
(494, 650, 3)
# img.size 可以返回图像的像素数目
print(img.size)
963300
# img.dtype 返回的是图像的数据类型
# 在debug时 img.dtype 非常重要。因为在 OpenCV Python 代码中经常出现数据类型的不一致
print(img.dtype)
uint8

3、图像ROI

'''
有时你需要对一幅图像的特定区域进行操作。例如我们要检测一副图像中眼睛的位置,我们首先应该在图像中找到脸,
再在脸的区域中找眼睛,而不是直接在一幅图像中搜索。这样会提高程序的准确性和性能。


ROI 也是使用 Numpy 索引来获得的。
'''
img = cv.imread('img.jpg')
img[0:100,0:100] = img[300:400,250:350]


cv.imshow('small_img',img)
cv.waitKey(0)
cv.destroyAllWindows()

4、拆分及合并图像通道

'''
有时我们需要对 BGR 三个通道分别进行操作。
这时你就需要把 BGR 拆分成单个通道。
有时你需要把独立通道的图片合并成一个 BGR 图像。

cv2.split() 是一个比较耗时的操作。只有真正需要时才用它,能用Numpy 索引就尽量用。
'''

img = cv.imread('img.jpg')
b,g,r = cv.split(img)
img = cv.merge([b,g,r])

# 或者
b= img[:,:,0]
# 假如你想使所有像素的红色通道值都为 0,你不必先拆分再赋值。你可以直接使用 Numpy 索引,这会更快

img[:,:,2] = 0

5、为图像扩边(填充)

'''
如果你想在图像周围创建一个边,就像相框一样,你可以使用 cv2.copyMakeBorder()函数。


这经常在卷积运算或 0 填充时被用到。这个函数包括如下参数:
• src 输入图像
• top, bottom, left, right 对应边界的像素数目。
• borderType 要添加那种类型的边界,类型如下
    – cv2.BORDER_REPLICATE 重复最后一个元素。例如: aaaaaa|abcdefgh|hhhhhhh
    – cv2.BORDER_REFLECT 边界元素的镜像。比如: fedcba|abcdefgh|hgfedcb
    – cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT 跟上面一样,但稍作改动。例如: gfedcb|abcdefgh|gfedcba
    – cv2.BORDER_WRAP 不知道怎么说了, 就像这样: cdefgh|abcdefgh|abcdefg
    – cv2.BORDER_CONSTANT 添加有颜色的常数值边界,还需要下一个参数(value)。
• value 边界颜色,如果边界的类型是 cv2.BORDER_CONSTANT
'''
from matplotlib import pyplot as plt
BLUE=[255,0,0]
img1 = cv.imread('open_cv.png')



replicate =  cv.copyMakeBorder(img1,30,30,30,30,cv.BORDER_REPLICATE)
reflect =    cv.copyMakeBorder(img1,30,30,30,30,cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1,30,30,30,30,cv.BORDER_REFLECT_101)
wrap =       cv.copyMakeBorder(img1,30,30,30,30,cv.BORDER_WRAP)
constant=    cv.copyMakeBorder(img1,30,30,30,30,cv.BORDER_CONSTANT,value=BLUE)


plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL'),plt.xticks([]),plt.yticks([])
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE'),plt.xticks([]),plt.yticks([])
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT'),plt.xticks([]),plt.yticks([])
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101'),plt.xticks([]),plt.yticks([])
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP'),plt.xticks([]),plt.yticks([])
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT'),plt.xticks([]),plt.yticks([])

plt.show()


在这里插入图片描述

二、图像上算数运算

1、图像加法

'''
你可以使用函数 cv2.add() 将两幅图像进行加法运算,当然也可以直接使用 numpy,res=img1+img。
两幅图像的大小,类型必须一致,或者第2个图像可以使一个简单的标量值。


注意:OpenCV 中的加法与 Numpy 的加法是有所不同的。OpenCV 的加法是一种饱和操作,而 Numpy 的加法是一种模操作

这种差别在你对两幅图像进行加法时会更加明显。OpenCV 的结果会更好一点。所以我们尽量使用 OpenCV 中的函数。
'''
x = np.uint8([250])
y = np.uint8([10])
print(cv.add(x,y)) # 250+10 = 260 => 255
print(x + y)       # 250+10 = 260 % 256 = 4
[[255]]
[4]

2、图像混合

'''
这其实也是加法,但是不同的是两幅图像的权重不同,这就会给人一种混合或者透明的感觉。

现在我们把两幅图混合在一起。第一幅图的权重是 0.7,第二幅图的权重是 0.3。

函数 cv2.addWeighted() 可以按下面的公式对图片进行混合操作
dst = α · img1 + β · img2 + γ
这里 γ 的取值为 0
'''
img1 = cv.imread('img.jpg')[:494,:467]
img2 = cv.imread('open_cv.png')[:494,:467]

dst = cv.addWeighted(img1,0.7,img2,0.3,0)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

3、按位运算

'''
按位操作有:AND,OR,NOT,XOR 等。

我想把 OpenCV 的标志放到另一幅图像上。
如果我使用加法,颜色会改变,如果使用混合,会得到透明效果,但是我不想要透明。
如果是矩形我可以使用 ROI。但是他不是矩形。
'''

# 加载图像
img1 = cv.imread('player.png')
img2 = cv.imread('small_open_cv.png')
# I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols]


# 转换为灰度图像
img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
'''
cv.threshold()
图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。
在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。
double threshold( InputArray src, OutputArray dst,double thresh, double maxval, int type );
		enum ThresholdTypes {T
			THRESH_BINARY     = 0,	   // 大于thresh 为 maxval,否则为 0
			THRESH_BINARY_INV = 1,	  // 大于thresh 为 0,否则为 maxval
			THRESH_TRUNC      = 2,	  // 大于thresh 为 thresh,否则为 0
			THRESH_TOZERO     = 3,	  // 大于thresh  不变,否则为 0
			THRESH_TOZERO_INV = 4,	  // 大于thresh 为 0,否则 不变
			THRESH_MASK       = 7,
			THRESH_OTSU       = 8,	 // 使用OTSU阈值
			THRESH_TRIANGLE   = 16	 // 使用三角形算法阈值
		}

src:原始数组 (单通道 , 8-bit of 32-bit 浮点数)。
dst:输出数组,必须与 src 的类型一致,或者为 8-bit。
threshold:阈值
max_value:使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值。
threshold_type:阈值类型
threshold_type = THRESH_BINARY      :如果 src(x,y) > thresh ,dst(x,y) = max_value; 否则,dst(x,y)=0;
threshold_type = THRESH_BINARY_INV  :如果 src(x,y) > thresh,dst(x,y) = 0; 否则,dst(x,y) = max_value.
threshold_type = THRESH_TRUNC       :如果 src(x,y) > thresh,dst(x,y) = max_value; 否则dst(x,y) = src(x,y).
threshold_type = THRESH_TOZERO      :如果src(x,y)  > thresh,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0。
threshold_type = THRESH_TOZERO_INV  :如果 src(x,y)> thresh,dst(x,y) = 0 ; 否则dst(x,y) = src(x,y).
'''
# 二值化操作,转换为黑白图像
ret, mask = cv.threshold(img2gray, thresh=175, maxval=255, type=cv.THRESH_BINARY)
print('ret',ret)
print('mask',mask[0,:])
# 位运算,取相反的颜色
mask_inv = cv.bitwise_not(mask)
cv.imshow('img2gray', img2gray)
cv.imshow('1mask', mask)         # logo为黑色,即0
cv.imshow('2mask_inv', mask_inv) # logo为白色,即255
cv.waitKey(0)
cv.destroyAllWindows()





'''
按位操作符:cv.bitwise_and(srt1, srt2, mask),该函数相当于数学运算的“与”
原理如下:1&1=1、1&0=0、0&1=0、0&0=0。
srt1、srt2分别为相加的两个窗口,mask为指定要更改的输出数组的元素。
该函数运行时,只会将mask部分的像素进行“与”运算,最后保留指定色彩。
'''
# 注意这里必须有 mask=mask 或者 mask=mask_inv, 其中的 mask= 不能忽略
# 获取到背景图
img1_bg = cv.bitwise_and(roi,roi,mask = mask)        # 将logo区域设置为黑色
# 取到前景图
img2_fg = cv.bitwise_and(img2,img2,mask = mask_inv)  # 将logo以外的区域设置为黑色,log区域为原来颜色

cv.imshow('roi', roi)
cv.imshow('bg', img1_bg)
cv.imshow('fg', img2_fg)
cv.waitKey(0)
cv.destroyAllWindows()


# 将背景图和前景图颜色合并,此时img1_bg(logo区域为0) + img2_fg(logo区域不为0) = img2_fg(logo区域)
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols] = dst
cv.imshow('res', img1)
cv.waitKey(0)
cv.destroyAllWindows()
ret 175.0
mask [255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255]

图片效果分别如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、程序性能检测及优化

在图像处理中你每秒钟都要做大量的运算,所以你的程序不仅要能给出正确的结果,同时还必须要快。

除了 OpenCV,Python 也提供了一个叫 time 的的模块,你可以用它来测量程序的运行时间。
另外一个叫做 profile 的模块会帮你得到一份关于你的程序的详细报告,其中包含了代码中每个函数运行需要的时间,
以及每个函数被调用的次数。

1、使用OpenCV检测程序的效率

'''
cv2.getTickCount 函数返回从参考点到这个函数被执行的时钟数。
所以当你在一个函数执行前后都调用它的话,你就会得到这个函数的执行时间(时钟数)。


cv2.getTickFrequency 返回时钟频率,或者说每秒钟的时钟数。
'''
img1 = cv.imread('open_cv.png')
e1 = cv.getTickCount()
for i in range(5,49,2):
    # 用窗口大小不同(5,7,9)的核函数来做中值滤波
    img1 = cv.medianBlur(img1,i)
e2 = cv.getTickCount()
t = (e2 - e1) / cv.getTickFrequency()
print(t,' seconds')
0.5352825  seconds
import time

# 另一种方式

img1 = cv.imread('open_cv.png')
e1 = time.time()
for i in range(5,49,2):
    # 用窗口大小不同(5,7,9)的核函数来做中值滤波
    img1 = cv.medianBlur(img1,i)
e2 = time.time()
t = (e2 - e1)
print(t,' seconds')
0.5371222496032715  seconds

2、默认优化

'''
OpenCV 中的很多函数都被优化过。也包含一些没有被优化的代码。
如果我们的系统支持优化的话,要尽量利用。在编译时优化是被默认开启的。


因此 OpenCV 运行的就是优化后的代码,如果你把优化关闭的话就只能执行低效的代码了。
你可以使用函数 cv2.useOptimized()来查看优化是否被开启了,使用函数 cv2.setUseOptimized() 来开启优化。
'''
# check if optimization is enabled
print(cv.useOptimized())

%timeit res = cv.medianBlur(img,49)
True
27.6 ms ± 1.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 关闭
cv.setUseOptimized(False)
print(cv.useOptimized())

%timeit res = cv.medianBlur(img,49)
False
28.8 ms ± 1.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

3、在 IPython 中检测程序效率

'''
有时你需要比较两个相似操作的效率,这时你可以使用 IPython 为你提供的魔法命令%time。
他会让代码运行好几次从而得到一个准确的(运行)时间。它也可以被用来测试单行代码的。
'''
z = np.uint8([5])
%timeit y=z*z
%timeit y=np.square(z)
382 ns ± 8.59 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
370 ns ± 9.3 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
img = cv.imread('img.jpg',0)

# 一般情况下 OpenCV 的函数要比 Numpy 函数快。所以对于相同的操作最好使用 OpenCV 的函数。
%timeit z = cv.countNonZero(img)
%timeit z = np.count_nonzero(img)
12.4 µs ± 322 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
14.4 µs ± 180 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

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

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

相关文章

微信小程序node+vue+uniapp课程在线答疑学习答题考试系统

系统主要分为管理员和学生、教师三部分,管理员服务端:首页、个人中心、学生管理、教师管理、课程资源管理、课程类型管理、学习记录管理、系统管理,教师服务端:首页、个人中心、课程资源管理、学习记录管理、试题管理、试卷管理、…

JAVA期末考内容知识点的梳理

作者的话 前言:这些都是很基本的,还有很多没有写出来,重点在于考试复习,包括后四章的内容 前面内容请参考JAVA阶段考内容知识点的梳理 一、集合、流 课堂总结1集合 集合概念: 保存和盛装数据的容器,将许多…

maven的常用命令clean/package/install/deploy

如标题,下面放图: 這就是一个pom对应的maven操作命令, 那这些命令中,最常用的打包项目的命令是什么? 两种最常用打包方法: 1.先 clean,然后 package2.先 clean,然后install 下面…

实验四 车辆定位导航

有想自己动手的同学可在末尾看教程 【实验目的】 1、了解全球定位导航系统的定位原理和电子地图技术,掌握电子地图API使用方法。 2、了解导航数据报文数据格式,解析导航数据并在电子地图上进行导航应用。 【实验性质】 验证性实验。 【实验要求】 1、相…

【动态规划专栏】--基础-- 动态规划经典题型

目录 动态规划 动态规划思维(基础) 状态表示(最重要) 状态转移方程(最难) 初始化(细节) 填表顺序(细节) 返回值(结果) 1、第 …

C++实现日期类Date(超详细)

个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】💌 本专栏旨在记录C的学习路线,望对大家有所帮助🙇‍ 希望我们一起努力、成长&…

C++笔试笔记2

C笔试笔记2 百富计算机的笔试 const限定符:首先作用于左边,如果左边没东西,就作用于右边。 const int: 左边没有内容,所以const作用于右边,就是“整型常量”。等同于int const; int * const&am…

NSS LitCTF部分wp

web 1、PHP是世界上最好的语言!! 直接cat flag flagNSSCTF{11eaebe0-3764-410d-be83-b23532a24235} 2、这是什么?SQL !注一下 ! 直接查询,发现注入点是id 使用sqlmap列出所以数据库 ​sqlmap -u "h…

亚马逊,shopee,lazada卖家如何组建自己的测评团队

测评补单,这个话题在如今不管国内还是国外的电商行业已经是众所周知,它能够快速帮助自己的产品添加评论,获取排名,打造爆款,可以让用户更加真实、清晰、快捷的了解产品,以及产品的使用,快速上手…

低代码,或将颠覆开发行业?

前言 传统的软件开发过程往往需要耗费大量的时间和精力,因为开发人员需编写复杂的代码以完成各种功能。 低代码行业的发展,正好解决了这个问题,让复杂的代码编写一去不复返了。 文章目录 前言引入强大的平台总结 引入 低代码平台 是一种通过可…

【团购-HeaderView Objective-C语言】

一、那么,我们看上面这个东西,这就是我们保存在HeaderView里面的一个东西吧, HeaderView里面的一个东西, 1.因为这个东西,看起来,是不是也是一个这个样子,也是一个固定的样子啊, 所以我们这个UITableView的HeaderView,也可以使用一个xib来描述,也可以使用xib来描述,…

D. The Wu(数据范围)

Problem - D - Codeforces Childan正在编造一个传奇故事并试图出售他的伪造品——一条带有强烈“Wu”感的项链给Kasoura家族。但是,Kasoura先生正在质疑Childan故事的真实性。因此,他将询问有关Childan所谓的“个人珍藏”项链的一些问题。 这个“个人珍…

k8s系列(三)——补充内容

k8s架构补充 高可用集群副本数最好是 > 3 奇数个 master节点 scheduler 调度器,负责介绍任务,选择合适的节点进行分配任务 决定将任务分配至哪个node节点中,与api server进行交互 api server 所有服务访问的统一入口 压力巨大&…

计算机组成原理-计算机系统概述

目录 一,基本组成 二、各部件工作原理 2.1存储器 2.2运算器 2.3控制器 2.4输入设备 2.5输出设备 一条指令的工作原理 三、计算机系统的层次结构 三种基本语言 四、计算机性能指标 一,基本组成 “存储程序”的概念,指将指令以二进制代码的…

English Learning - L3 作业打卡 Lesson2 Day14 2023.5.18 周四

English Learning - L3 作业打卡 Lesson2 Day14 2023.5.18 周四 引言🍉句1: A brown out is an expression for a reduction in electric power.成分划分弱读连读爆破语调 🍉句2: Brown outs happen when there is too much demand for electricity.成分…

字节薪酬体系曝光,实在是太强了,真的不服不行...

曾经的互联网是PC的时代,随着智能手机的普及,移动互联网开始飞速崛起。而字节跳动抓住了这波机遇,2015年,字节跳动全面加码短视频,从那以后,抖音成为了字节跳动用户、收入和估值的最大增长引擎。 自从字节…

波奇学Linux:时间指令,查找指令,压缩指令,热键

日志:时间,日志等级,日志具体信息,其他信息用来记录程序信息 时间指令 data指令显示时间 修改时间显示格式 时间戳: date %s 时间戳:统一的时间格式,因为有时差原因,时间相对于各…

Python系列之文件操作和函数

感谢点赞和关注 ,每天进步一点点!加油! 目录 一、文件操作 1.1 Shell里的文件操作 1.2 Python文件操作的步骤 1.3 Python打开和关闭文件 1.3.1 open 函数 1.4 文件定位 1.5 Python文件访问模式 1.5.1 只读模式 1.5.2 只写模式 1.5.…

大厂笔试真题解析

文章目录 2023/5/6 华为第一题:喷墨水2023/5/16 华为第二题:表达式计算 2023/5/6 华为第一题:喷墨水 模拟题,代码未提交,样例过 输入处理:双字节十六进制转二进制 十六进制转十进制再转二进制,…

Baklib盘点:企业做知识管理时遇到的困惑类型有哪些?

作为一家专注于企业知识管理的公司,Baklib深入了解了企业在进行知识管理时可能遇到的各种困惑。在此,我们盘点了企业做知识管理时遇到的困惑类型,并就如何解决这些困惑提出了建议。 企业做知识管理时遇到的困惑类型 知识流失 许多企业面临…