2022年 11月 4日

Python 之CV2详解

 

气死人不偿命,本来觉得看一下代码了解一下CV2挺好,但是发现此路不通。然后还是乖乖把代码复现一遍!!!

一、读入图像

使用函数cv2.imread(filepath,flags)读入一副图片

    • filepath:要读入图片的完整路径
    • flags:读入图片的标志 
      • cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道
      • cv2.IMREAD_GRAYSCALE:读入灰度图片
      • cv2.IMREAD_UNCHANGED:读入完整图片,包括alpha通道

二、显示图像

使用函数cv2.imshow(wname,img)显示图像,第一个参数是显示图像的窗口的名字,第二个参数是要显示的图像(imread读入的图像),窗口大小自动调整为图片大小。

  1. import cv2
  2. img = cv2.imread('123.png',cv2.IMREAD_GRAYSCALE)
  3. #print(img)
  4. cv2.imshow('image',img)
  5. cv2.waitKey(0)
  6. cv2.destroyAllWindows()
  • cv2.waitKey顾名思义等待键盘输入,单位为毫秒,即等待指定的毫秒数看是否有键盘输入,若在等待时间内按下任意键则返回按键的ASCII码,程序继续运行。若没有按下任何键,超时后返回-1。参数为0表示无限等待。不调用waitKey的话,窗口会一闪而逝,看不到显示的图片。
  • cv2.destroyAllWindow()销毁所有窗口
  • cv2.destroyWindow(wname)销毁指定窗口

三、保存图像

使用函数cv2.imwrite(file,img,num)保存一个图像。第一个参数是要保存的文件名,第二个参数是要保存的图像。可选的第三个参数,它针对特定的格式:对于JPEG,其表示的是图像的质量,用0 – 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别。默认为3.

注意:

  • cv2.IMWRITE_JPEG_QUALITY类型为 long ,必须转换成 int
  • cv2.IMWRITE_PNG_COMPRESSION, 从0到9 压缩级别越高图像越小。

四、图片操作

1、使用函数cv2.flip(img,flipcode)翻转图像,flipcode控制翻转效果,复制图像。

  • flipcode = 0:沿x轴翻转
  • flipcode > 0:沿y轴翻转
  • flipcode < 0:x,y轴同时翻转
  1. imgflip = cv2.flip(img,1)
  2. cv2.imshow('My honey',imgflip)
  3. cv2.waitKey(0)
  4. imgcopy = img.copy()
  5. cv2.imshow('My honey',imgcopy)
  6. cv2.waitKey(0)

2、颜色空间转换

  1. img3 = cv2.cvtColor(img,cv2.COLOR_GRAY2RGB)
  2. cv2.imshow('My honey',imgcopy)
  3. cv2.waitKey(0)
  4. ## cv2.COLOR_X2Y,其中X,Y = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS

 示例1:入一副图像,按’s’键保存后退出,其它任意键则直接退出不保存

  1. import cv2
  2. img = cv2.imread('1.jpg',cv2.IMREAD_UNCHANGED)
  3. cv2.imshow('image',img)
  4. k = cv2.waitKey(0)
  5. if k == ord('s'): # wait for 's' key to save and exit
  6. cv2.imwrite('1.png',img)
  7. cv2.destroyAllWindows()
  8. else:
  9. cv2.destroyAllWindows()

示例2:读入一幅图像,给图片加文本

  1. img =cv2.imread('123.png')
  2. font = cv2.FONT_HERSHEY_DUPLEX #设置字体
  3. #图片对象、文本、像素、字体、字体大小、颜色、字体粗细
  4. imgzi = cv2.putText(img,"Baby",(100,100),font,2.5,(0,0,255),2,)
  5. cv2.imshow('bb',imgzi)
  6. cv2.waitKey(0)

 

                                                               

                                                                             

五、图像的表示

前面章节已经提到过了单通道的灰度图像在计算机中的表示,就是一个8位无符号整形的矩阵。在OpenCV的C++代码中,表示图像有个专门的结构叫做cv::Mat,不过在Python-OpenCV中,因为已经有了numpy这种强大的基础工具,所以这个矩阵就用numpy的array表示。如果是多通道情况,最常见的就是红绿蓝(RGB)三通道,则第一个维度是高度,第二个维度是高度,第三个维度是通道,比如图6-1a是一幅3×3图像在计算机中表示的例子:

 

                                                                                  

  1. import numpy as np
  2. import cv2
  3. import matplotlib.pyplot as plt
  4. # 图6-1中的矩阵
  5. img = np.array([
  6. [[255, 0, 0], [0, 255, 0], [0, 0, 255]],
  7. [[255, 255, 0], [255, 0, 255], [0, 255, 255]],
  8. [[255, 255, 255], [128, 128, 128], [0, 0, 0]],
  9. ], dtype=np.uint8)
  10. # 用matplotlib存储
  11. plt.imsave('img_pyplot.jpg', img)
  12. # 用OpenCV存储
  13. cv2.imwrite('img_cv2.jpg', img)

不管是RGB还是BGR,都是高度×宽度×通道数,H×W×C的表达方式,而在深度学习中,因为要对不同通道应用卷积,所以用的是另一种方式:C×H×W,就是把每个通道都单独表达成一个二维矩阵,如图6-1c所示。

六、视频功能

视频中最常用的就是从视频设备采集图片或者视频,或者读取视频文件并从中采样。所以比较重要的也是两个模块,一个是VideoCapture,用于获取相机设备并捕获图像和视频,或是从文件中捕获。还有一个VideoWriter,用于生成视频。还是来看例子理解这两个功能的用法,首先是一个制作延时摄影视频的小例子:

  1. import cv2
  2. import time
  3. interval = 60 # 捕获图像的间隔,单位:秒
  4. num_frames = 500 # 捕获图像的总帧数
  5. out_fps = 24 # 输出文件的帧率
  6. # VideoCapture(0)表示打开默认的相机
  7. cap = cv2.VideoCapture(0)
  8. # 获取捕获的分辨率
  9. size =(int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
  10. int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
  11. # 设置要保存视频的编码,分辨率和帧率
  12. video = cv2.VideoWriter(
  13. "time_lapse.avi",
  14. cv2.VideoWriter_fourcc('M','P','4','2'),
  15. out_fps,
  16. size
  17. )
  18. # 对于一些低画质的摄像头,前面的帧可能不稳定,略过
  19. for i in range(42):
  20. cap.read()
  21. # 开始捕获,通过read()函数获取捕获的帧
  22. try:
  23. for i in range(num_frames):
  24. _, frame = cap.read()
  25. video.write(frame)
  26. # 如果希望把每一帧也存成文件,比如制作GIF,则取消下面的注释
  27. # filename = '{:0>6d}.png'.format(i)
  28. # cv2.imwrite(filename, frame)
  29. print('Frame {} is captured.'.format(i))
  30. time.sleep(interval)
  31. except KeyboardInterrupt:
  32. # 提前停止捕获
  33. print('Stopped! {}/{} frames captured!'.format(i, num_frames))
  34. # 释放资源并写入视频文件
  35. video.release()
  36. cap.release()

示例:从视频中截取帧

下面代码实现的是遍历一个指定文件夹下的所有视频并按照指定的间隔进行截屏并保存:

  1. import cv2
  2. import os
  3. import sys
  4. # 第一个输入参数是包含视频片段的路径
  5. input_path = sys.argv[1] #或者删除自行输入
  6. # 第二个输入参数是设定每隔多少帧截取一帧
  7. frame_interval = int(sys.argv[2]) #或者删除自行输入
  8. # 列出文件夹下所有的视频文件
  9. filenames = os.listdir(input_path)
  10. # 获取文件夹名称
  11. video_prefix = input_path.split(os.sep)[-1]
  12. # 建立一个新的文件夹,名称为原文件夹名称后加上_frames
  13. frame_path = '{}_frames'.format(input_path)
  14. if not os.path.exists(frame_path):
  15. os.mkdir(frame_path)
  16. # 初始化一个VideoCapture对象
  17. cap = cv2.VideoCapture()
  18. # 遍历所有文件
  19. for filename in filenames:
  20. filepath = os.sep.join([input_path, filename])
  21. # VideoCapture::open函数可以从文件获取视频
  22. cap.open(filepath)
  23. # 获取视频帧数
  24. n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
  25. # 同样为了避免视频头几帧质量低下,黑屏或者无关等
  26. for i in range(42):
  27. cap.read()
  28. for i in range(n_frames):
  29. ret, frame = cap.read()
  30. # 每隔frame_interval帧进行一次截屏操作
  31. if i % frame_interval == 0:
  32. imagename = '{}_{}_{:0>6d}.jpg'.format(video_prefix, filename.split('.')[0], i)
  33. imagepath = os.sep.join([frame_path, imagename])
  34. print('exported {}!'.format(imagepath))
  35. cv2.imwrite(imagepath, frame)
  36. # 执行结束释放资源
  37. cap.release()