Opencv计算机视觉基础:(一)图像基本操作

首先展示以下实例原图像给大家萌一萌:

环境搭建

下面直接列举需要搭建的环境:

  1. Anaconda+python大环境(相信大家都早已安装好了,若没有请前往百度搜索自行安装)
  2. opencv以及扩展包的安装:
    • 直接在命令行输入以下两行分别安装即可:

      pip install opencv-python
      pip install opencv-contrib-python

    • 若在第一个opencv-python中指定了版本号,比如(pip install opencv-python==4.2.0),需要注意在第二行的安装中也需要输入相同的版本号,opencv-contrib-python相当于给opencv-python添加了额外的扩展,比如特征提取的算法等。
    • 若安装出错建议多安装几次(很可能是网络的问题),实在安装不了可以直接去官网下载,需要注意选择适当的python版本以及windows位数的安装包进行下载
    • 安装完之后进入python,导入相应的包并查看版本号,若无异常就可以进入正题啦~
      1
      2
         import cv2
      cv2.__version__

图像读取

我们看到的每一张彩色图片事实上都是由RGB三个颜色通道堆叠而成,每个通道实际上是一个矩阵,里面的每个元素大小从0-256不等,对于灰度图则只有一个通道。

我们很容易通过以下代码验证:

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

img = cv2.imread("Pic/animal.jpg")
print(img)

img2 = cv2.imread("Pic/animal.jpg", cv2.IMREAD_GRAYSCALE)
print(img2)

当我们想要查看图像,可以通过下面三行代码实现:

1
2
3
cv2.imshow("image1", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

上面第一行imshow是用于展示图像;第二行waitKey是控制图片显示时间,若设置为0则当鼠标单击图像会消失,若设置为一个>0的数,该数会转化成毫秒显示图像,比如可以试试20000;第三行是控制窗口关闭的,要注意区分cv2.destroyAllWindows()和cv2.destroyWindow()的区别。为了便于调用,可以将这三行代码写成一个函数:

1
2
3
4
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()

可以通过img.shape显示图像形状:

正如前例所述,图像转换的命令为:

  • cv2.IMREAD_COLOR:彩色图像

  • cv2.IMREAD_GRAYSCACLE:灰度图像

视频读取

读取视频的代码如下:

1
vc = cv2.VideoCapture("Video/turtle.mp4")

可以通过下面代码读取视频每一帧:

1
2
3
4
if vc.isOpened():
open, frame = vc.read()
else:
open = False

可以通过下面完整代码调节视频速度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vc = cv2.VideoCapture("Video/turtle.mp4")

while open:
ret, frame = vc.read()
if frame is None:
break
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow("result1", gray)
if cv2.waitKey(100) & 0xFF == 27:
break

vc.release()
cv2.destroyAllWindows()

其主要思想是将视频转化为帧,然后定时一张张播放图片,可以修改waitKey控制播放进度。

图片基本操作

截取图片及像素转换

1
2
3
img = cv2.imread("Pic/animal.jpg")
cat = img[0:200,0:200]
cv_show("cat", cat)

上述直接通过索引截取对应的部分矩阵(图像),可以通过以下代码实现分割RGB通道:

1
b, g, r = cv2.split(img)

这其中需要注意的是,通道的顺序并不是RGB,而是BGR!

我们切分完之后,若希望看各个通道的图像,可以通过下面三块代码实现:

其中红图的结果如下:

若想要重新将bgr通道组合在一起,可以通过merge函数实现:

1
2
img = cv2.merge((b, g, r))
img.shape

边界填充

我们做卷积时,常常会给图像做一个边界的填充,具体实现方式及效果如下:

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)

replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_CONSTANT, value=0)

import matplotlib.pyplot as plt
plt.subplot(231), plt.imshow(img, "gray"), plt.title("ORIGINAL")
plt.subplot(232), plt.imshow(replicate, "gray"), plt.title("REPLICATE")
plt.subplot(233), plt.imshow(reflect, "gray"), plt.title("REFLECT")
plt.subplot(234), plt.imshow(reflect101, "gray"), plt.title("REFLECT_101")
plt.subplot(235), plt.imshow(wrap, "gray"), plt.title("WRAP")
plt.subplot(236), plt.imshow(constant, "gray"), plt.title("CONSTANT")
plt.savefig("border2.png")

下面解释一下这几个填充原理:

  • 第一个是BORDER_REPLICATE,顾名思义就是直接复制边界像素;
  • 第二个BORDER_REFLECT是反射法,也就是对感兴趣的图像中的像素子两边进行复制,比如fedcba|abcdefgh|hgfedcb;
  • 第三个BORDER_REFLECT_101也是反射法,但是以最边缘像素为轴对称反射;
  • 第四个BORDER_WRAP是外包装法:cdefgh|abcdefgh|abcdefg
  • 第五个为常量法,使用常数值填充(在图中很明显为黑色边框)

数值计算

我们可以直接把图片所有像素点做同一运算:比如下图所示的给所有像素加10:

若两图像维度一致也可以直接相加:

1
2
3
img_1 = img_ + img
cv2.imwrite("add.png", img_1)
cv_show("Add", img_1)

得到的图像也挺有趣的:

我们可以感觉到有些像素点变化有些大,这是由于当两个图像的像素点直接相加时,由于像素最高为256,若越界就会自动对256取余,因此图像有些部分比较怪异。

图像融合

我们可以将两张同大小的图片按比例融合到一张图片中,当我们发现这两张图片大小不一致,我们需要将图片resize成大小一致的图片方能进行融合,操作如下:

结果如下:

具体操作为:

1
res = cv2.addWeighted(img1, 0.4, img3, 0.6, 0)

其中0.4与0.6分别为这两张图片的权重,最后的0为偏置项,可以设置为其他值调节亮度。

另外,resize操作还可以不指定数值,而只是写出图像倍数关系,比如 :

具体操作如下:

1
2
res1 = cv2.resize(res, (0, 0), fx=3,fy=1)
plt.imshow(res1)
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2020-2021 chenk
  • 由 帅气的CK本尊 强力驱动
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信