技术背景

在机器视觉等领域,最基本的图像处理处理操作,可以通过opencv这个库来实现。opencv提供了python的接口,所需安装的库为opencv-python,但是在库的导入的时候一般用的是import cv2,因此很多也把opencv-python简称为cv2

cv2的安装

如果是使用anaconda所搭建的python的编程环境,一般会事先安装好cv2这个仓库。在上面的超链接中可以找到适合自己本地环境的anaconda环境进行安装,这是一个非常常用的python包集成管理工具,其中预安装了很多python库,使得我们不需要去手动安装各种的第三方库,我们知道自己取手动安装的过程中,很容易就会遇到一些报错,解决起来也非常的麻烦。



如果系统中没有这个库,可以通过pip来进行安装和管理:

[dechin@dechin-manjaro cv2]$ python3 -m pip install opencv-python
Requirement already satisfied: opencv-python in /home/dechin/anaconda3/lib/python3.8/site-packages (4.5.1.48)
Requirement already satisfied: numpy>=1.17.3 in /home/dechin/anaconda3/lib/python3.8/site-packages (from opencv-python) (1.20.1)

需要注意的是,这里虽然安装的时候是使用opencv-python这个名字,但是在python代码中调用的时候是用的cv2这个名字:

[dechin@dechin-manjaro cv2]$ ipython
Python 3.8.5 (default, Sep 4 2020, 07:30:14)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: import cv2 In [2]: quit()

cv2基本图像操作

首先假定我们已经获取了这么一个图片,接下来我们要对这个图片进行各式各样的处理(图片来自于参考链接1):

重构大小

我们可以对输入的图片进行大小调整,由于大小被改变,因此会涉及到一些插值算法。cv2内置的有线性插值和最近邻插值等,我们可以直接使用:

# cv2_reshape.py

import cv2
import numpy as np width = 400
height = 200
img = cv2.imread('test.png') # 读取图像
print ('The shape of initial graph is: {}'.format(img.shape)) # 打印原图大小
img = cv2.resize(img, (width, height), interpolation=cv2.INTER_NEAREST) # 最近邻插值缩放
print ('The changed shape of graph is: {}'.format(img.shape)) # 打印更改后图片大小
cv2.imwrite('new_logo.png', img) # 保存图片

在这个案例中,我们首先读取了一个516×254的图片,由于是RGB格式的,因此会有三层图像。然后通过cv2将该图像重构成一个400×200的图像。上述代码的执行结果如下:

[dechin@dechin-manjaro cv2]$ python3 cv2_reshape.py
The shape of initial graph is: (254, 516, 3)
The changed shape of graph is: (200, 400, 3)

同时会在当前的目录下生成一个新的图像,这个图像就是经过我们缩放重构之后的图像:

图像翻转

图像的翻转也是一种常用的基本操作,cv2里面提供了三种模式的翻转:编码为1的横向翻转,编码为0的纵向翻转,以及编码为-1的同时翻转,这里我们演示其中的一种纵向翻转:

# cv2_rotate.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of initial graph is: {}'.format(img.shape))
img = cv2.flip(img, 0)
print ('The changed shape of graph is: {}'.format(img.shape))
cv2.imwrite('rotate_logo.png', img)

执行完成后,因为是翻转操作,所以并不会影响图像大小:

[dechin@dechin-manjaro cv2]$ python3 cv2_rotate.py
The shape of initial graph is: (254, 516, 3)
The changed shape of graph is: (254, 516, 3)

同样的,会在当前目录下生成一个翻转之后的图像:

灰度图

在很多图像特征提取的场景中,其实并不需要RGB配色。比如我们判断一个图片中的动物是猫还是狗,这跟猫和狗身上的颜色并没有太大的关系,因此我们需要一个灰度图就够了:

# cv2_color.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of initial graph is: {}'.format(img.shape))
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
print ('The changed shape of graph is: {}'.format(img.shape))
cv2.imwrite('gray_logo.png', img)

因为提取的灰度图并没有显含RGB的配色,因此得到的图片没有3层,只有1层:

[dechin@dechin-manjaro cv2]$ python3 cv2_color.py
The shape of initial graph is: (254, 516, 3)
The changed shape of graph is: (254, 516)

同时在本地目录下会生成一个新的灰度图:

卷积与滑窗

卷积操作在卷积神经网络中有重要的应用,其本质是通过滑窗的方式,对原本的图像进行小范围内的指定操作,而这个小范围内的指定操作,则是由卷积核来定义的。我们先来看一下三个卷积核的使用案例,这些卷积核的作用是进行边缘检测。并且这三个卷积核都是3×3的大小,也就是说,原图像经过卷积核操作之后,在横向和纵向两个维度的大小都会减去2。

# convolution.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of input img is: {}'.format(img.shape)) conv_img = np.zeros((int(img.shape[0])-2,
int(img.shape[1])-2,
int(img.shape[2])))
for i in range(int(img.shape[0])-2):
for j in range(int(img.shape[1])-2):
conv_img[i][j] = img[i][j] - img[i+2][j] - img[i][j+2] + img[i+2][j+2] print ('The shape of output img is: {}'.format(conv_img.shape))
cv2.imwrite('conv.png', conv_img)

这个案例所对应的卷积核为:

\[\left[
\begin{matrix}
1&0&-1\\
0&0&0\\
-1&0&1
\end{matrix}
\right]
\]

执行结果如下:

[dechin@dechin-manjaro cv2]$ python3 convolution.py
The shape of input img is: (254, 516, 3)
The shape of output img is: (252, 514, 3)

我们可以看到图像的最终大小是符合我们所预期的,再看看生成的图像:



我们可以明显的发觉,原本图像中一些不太重要的信息就被忽略了,仅保留了一些边缘的信息。那么在一些图像特征识别的场景下,就可以先用卷积层转换成这种边缘图像,再结合池化层和潜藏层构成一个卷积神经网络,对图像进行分辨和识别。由于卷积核并不是唯一固定的,因此我们可以对比以下另外两种卷积核:

# convolution1.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of input img is: {}'.format(img.shape)) conv_img = np.zeros((int(img.shape[0])-2,
int(img.shape[1])-2,
int(img.shape[2])))
for i in range(int(img.shape[0])-2):
for j in range(int(img.shape[1])-2):
conv_img[i][j] = img[i][j+1] + img[i+1][j] + img[i+2][j+1] + img[i+1][j+2] - 4*img[i+1][j+1] print ('The shape of output img is: {}'.format(conv_img.shape))
cv2.imwrite('conv1.png', conv_img)

这个案例所对应的卷积核为:

\[\left[
\begin{matrix}
0&1&0\\
1&-4&1\\
0&1&0
\end{matrix}
\right]
\]

执行结果如下:

[dechin@dechin-manjaro cv2]$ python3 convolution1.py
The shape of input img is: (254, 516, 3)
The shape of output img is: (252, 514, 3)

得到的新图像与第一种卷积核有显著的差异:

再看看另外一种卷积和:

# convolution2.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of input img is: {}'.format(img.shape)) conv_img = np.zeros((int(img.shape[0])-2,
int(img.shape[1])-2,
int(img.shape[2])))
for i in range(int(img.shape[0])-2):
for j in range(int(img.shape[1])-2):
conv_img[i][j] = -img[i][j] - img[i][j+1] - img[i][j+2] -\
img[i+1][j] + 8*img[i+1][j+1] - img[i+1][j+2] -\
img[i+2][j] - img[i+2][j+1] - img[i+2][j+2] print ('The shape of output img is: {}'.format(conv_img.shape))
cv2.imwrite('conv2.png', conv_img)

这个案例所对应的卷积核为:

\[\left[
\begin{matrix}
-1&-1&-1\\
-1&8&-1\\
-1&-1&-1
\end{matrix}
\right]
\]

执行结果如下所示:

[dechin@dechin-manjaro cv2]$ python3 convolution2.py
The shape of input img is: (254, 516, 3)
The shape of output img is: (252, 514, 3)

最终生成的图像与前两种卷积和都截然不同:

最后还要介绍一种可以锐化图像的卷积核,与前面介绍的边缘检测的卷积核不同的是,锐化的卷积核保留了大部分的图像特征,只是更加显著的突出了图像的的边缘:

# convolution3.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of input img is: {}'.format(img.shape)) conv_img = np.zeros((int(img.shape[0])-2,
int(img.shape[1])-2,
int(img.shape[2])))
for i in range(int(img.shape[0])-2):
for j in range(int(img.shape[1])-2):
conv_img[i][j] = - img[i][j+1] - img[i+1][j] - img[i+2][j+1] - img[i+1][j+2] + 5*img[i+1][j+1] print ('The shape of output img is: {}'.format(conv_img.shape))
cv2.imwrite('conv3.png', conv_img)

这个案例所对应的卷积核为:

\[\left[
\begin{matrix}
0&-1&0\\
-1&5&-1\\
0&-1&0
\end{matrix}
\right]
\]

执行结果如下:

[dechin@dechin-manjaro cv2]$ python3 convolution3.py
The shape of input img is: (254, 516, 3)
The shape of output img is: (252, 514, 3)

可以看到跟其他其中卷积核相比,锐化的卷积核是最接近于原始图像的:

在上述的几个输出图像中,我们可以大致评估,第一种卷积边缘检测的方法有效的去除了很多无用的背景信息,可以在这种类型下的图像中进行使用,我们可以针对不同的场景选择不同的操作。

平均池化

在上面所介绍的卷积核中,我们使用的滑窗步长都是1,但是在实际场景中,增大滑窗的步长不仅可以达到很好的效果,还可以很大程度上介绍需要处理的图像的大小。这里介绍的池化,可以认为是一种特殊的卷积运算。常用的池化方法有最大池化和平均池化,顾名思义,最大池化就是取卷积/池化区域中的最大值,而平均池化则是取平均值。这里我们展示一个平均池化的示例:

# avg_pooling.py

import cv2
import numpy as np img = cv2.imread('test.png')
print ('The shape of input img is: {}'.format(img.shape)) pooling_img = np.zeros((int(int(img.shape[0])/2),
int(int(img.shape[1])/2),
int(img.shape[2])))
for i in range(int(int(img.shape[0])/2)):
for j in range(int(int(img.shape[1])/2)):
pooling_img[i][j] = (img[2*i][2*j] + img[2*i][2*j+1] + img[2*i+1][2*j] + img[2*i+1][2*j+1])/4 print ('The shape of output img is: {}'.format(pooling_img.shape))
cv2.imwrite('pooling.png', pooling_img)

该平均池化如果用卷积核来表示的化,大概是如下的形式:

\[\left[
\begin{matrix}
0.25&0.25\\
0.25&0.25
\end{matrix}
\right]
\]

上述代码的输出结果如下:

[dechin@dechin-manjaro cv2]$ python3 avg_pooling.py
The shape of input img is: (254, 516, 3)
The shape of output img is: (127, 258, 3)

我们发现由于这里的滑窗步长设置为了2,滑窗大小变为了2×2,因此得到的结果图像缩小了一半。最终得到的池化的图像如下:



在这个池化的图片中我们其实并没有得到太多的信息,更多的作用还是等效的去压缩一个图像的信息,尤其是最大池化,可以很好的保留原图像中的显著特征。

总结概要

本文介绍了使用opencv-python对输入图像进行处理的基本操作,包括图像读取、图像变换等。有了这些基础的操作支撑后,我们可以执行跟高层次的图像处理,比如常用于深度学习的卷积和池化操作,这里我们也作了简单介绍,并给出了使用示例。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/cv2.html

作者ID:DechinPhy

更多原著文章请参考:https://www.cnblogs.com/dechinphy/

参考链接

  1. http://qutip.org/docs/latest/index.html

python3使用cv2对图像进行基本操作的更多相关文章

  1. opencv入门系列教学(五)图像的基本操作(像素值、属性、ROI和边框)

    0.序言 每个图像是由一个个点组成的,而这些点可以表示为像素值的形式. 这篇博客里我们将学会: 访问像素值并修改它们 . 访问图像属性 . 设置感兴趣区域(ROI) . 分割和合并图像. 对于图像的基 ...

  2. Matlab基础:关于图像的基本操作

    -- %% 学习目标:学习关于图像的基本操作 %% 通过抖动来增强图像的的色彩对比度 clear all; close all; I = imread('cameraman.tif');%读取灰度图像 ...

  3. MATLAB中图像的基本操作

    MATLAB中图像的基本操作 1.读取.显示图片 MATLAB中提供了immread()与imshow()函数读取和显示图片.其中读取函数imread()原型: imread: A = imread( ...

  4. 机器学习进阶-图像金字塔与轮廓检测-轮廓检测 1.cv2.cvtColor(图像颜色转换) 2.cv2.findContours(找出图像的轮廓) 3.cv2.drawContours(画出图像轮廓) 4.cv2.contourArea(轮廓面积) 5.cv2.arcLength(轮廓周长) 6.cv2.aprroxPloyDP(获得轮廓近似) 7.cv2.boudingrect(外接圆)..

    1. cv2.cvtcolor(img, cv2.COLOR_BGR2GRAY) # 将彩色图转换为灰度图 参数说明: img表示输入的图片, cv2.COLOR_BGR2GRAY表示颜色的变换形式 ...

  5. cv2对图像进行旋转和放缩变换

    旋转: def get_image_rotation(image): #通用写法,即使传入的是三通道图片依然不会出错 height, width = image.shape[:2] center = ...

  6. OpenCV学习笔记(3)——图像的基本操作

    获取图像的像素值并修改 获取图像的属性(信息) 图像的ROI() 图像通道的拆分及合并 1.获取并修改像素值 先读入图像装入一个图像实体,然后该实体相当于一个多维list,可以直接用数组操作提取像素信 ...

  7. opencv图像的基本操作3

    1.获取像素并修改 读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值 import cv2 import numpy img = cv2. ...

  8. Opencv笔记(二):图像的基本操作——续写

    1.图像的透视变换 对于视角变换,我们需要一个 3x3 变换矩阵.在变换前后直线还是直线.要构建这个变换矩阵,你需要在输入图像上找 4 个点,以及他们在输出图像上对应的位置.这四个点中的任意三个都不能 ...

  9. Opencv笔记(一):图像的基本操作

    1.图像的读.显示和保存操作 import cv2 img = cv2.imread('filename',0); cv2.imshow('name',img); k=cv2.waitKey(0); ...

随机推荐

  1. React Fragment All In One

    React Fragment All In One React还提供了一个无需包装即可呈现多个元素的组件. https://reactjs.org/docs/react-api.html#fragme ...

  2. PWA & Service Workers 版本更新 bug

    PWA & Service Workers 版本更新 bug PWA & Service Worker https://developer.mozilla.org/zh-CN/docs ...

  3. Web Vitals

    Web Vitals https://www.youtube.com/watch?v=2k1QbgLAFdI&feature=youtu.be $ npm i -S web-vitals ht ...

  4. Inspect Network Activity In Chrome DevTools

    Inspect Network Activity In Chrome DevTools https://developers.google.com/web/tools/chrome-devtools/ ...

  5. Techme INC:红光和近红外光疗法有效加速肌肉恢复,美国橄榄球队已采用

    Techme INC创始人兼董事长MADELEINE VAUGHAN表示:在运动结束后,肌肉纤维因为细微损伤造成酸痛情形,即是延迟性肌肉酸痛-DOMS.这类酸痛发生时,需要适度的恢复,避免造成肌肉拉伤 ...

  6. NGK主网上线后内存价格上涨30倍,NGK RAM是否值得买入?

    美国加州时间10月14日上午10时,NGK主网正式上线.因为市场预期向好,NGK上线以后迎来了大涨,NGK的代币价格上涨了10倍,内存价格上涨了30倍.目前,NGK上线已经有五天的时间,盘面上已经出现 ...

  7. 聊一下PBN程序图例中的XTT

       PBN航路点的定位容差用XTT与ATT来表示,ATT=0.8*XTT.保护区半宽用1.5*XTT+BV计算得到,BV值在不同的航段取值不同. 对于A至E类航空器,距ARP 30nm以外BV值为2 ...

  8. Mybites逆向工程的搭建

    这个链接写的很全:https://www.cnblogs.com/whgk/p/7140638.html 这段时间太忙,等周末写上自己尝试的步骤.暂时仅作记录.

  9. 别再恐惧 IP 协议(万字长文 | 多图预警)

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...

  10. macOS下Chrome和Safari导入证实抓包HTTPS

    目录 下载证书 mac OS导入证书 Chrome设置代理 Safari设置代理 下面的操作基于Mac OS Catalina(v10.15.3),抓包拦截工具基于Burp Suite v2.1.05 ...