据说,看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。
前言:
作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
✨个人主页:点我直达,在这里肯定能找到你想要的~
专栏介绍:OpenCV从入门到放弃 ,一个学习OpenCV的专栏~
专栏文章直链:
【OpenCV学习】初识OpenCV
在上一章节,说了读取图片,接下来可以保存图片
from cv2 import cv2
# 默认是按照彩色图片来读取的。
cat = cv2.imread('./cat.jpeg')
cv2.imwrite('./123.png', cat)
imwrite
就是保存图片(写入图片)的意思。
首先我们先要了解视频的本质。
我们常常听到说,电影是24帧的, 游戏30帧玩起来有点卡,流畅的话至少要60帧…
其实这些都是视频,帧率的意思就是,每秒钟播放几张图片。
通常帧率越高,看起来越流畅,但高到了一定程度,人眼就分辨不出来了。
所以视频其实本质上就是由一幅一幅的图片组成的。
import cv2
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('window', 640, 480)
# 如果打开失败,不会报错。
# cap = cv2.VideoCapture(1)
cap = cv2.VideoCapture(0)
这样我们就获取到了一个摄像头对象 cap
。
接下来我们通过循环 cap.isOpened()
判断摄像头有没有被关闭,达到不断刷新窗口的效果:
import cv2
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('window', 640, 480)
# 如果打开失败,不会报错。
# cap = cv2.VideoCapture(1)
cap = cv2.VideoCapture(0)
# 循环读取谁想投的每一帧。
# while True:
while cap.isOpened():
# 读一帧数据,返回标记和这一帧数据,True表示读到了数据,False表示没读到数据。
ret, frame = cap.read()
# 可以根据ret做个判断。
if not ret:
# 没读到数据,直接退出。
break
# 显示数据
cv2.imshow('video', frame)
key = cv2.waitKey(10)
if key & 0XFF == ord('q'):
break
# 别忘了释放资源
cap.release()
cv2.destroyAllWindows()
这样一个过程就是循环读取摄像头的每一帧,读取速度将依据 cv2.waitKey
设置的等待超时时长决定。
当然这边的时间设置还是有点夸张的,10毫秒获取一张图片,相当于是100帧这种速度,我们不需要这么快:
import cv2
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('window', 640, 480)
# 如果打开失败,不会报错。
# cap = cv2.VideoCapture(1)
# 打开视频,输入视频的地址
cap = cv2.VideoCapture('./1.mp4')
# 循环读取谁想投的每一帧。
# while True:
while cap.isOpened():
# 读一帧数据,返回标记和这一帧数据,True表示读到了数据,False表示没读到数据。
ret, frame = cap.read()
# 可以根据ret做个判断。
if not ret:
# 没读到数据,直接退出。
break
# 显示数据
cv2.imshow('video', frame)
# 假如一个视频是30帧,那么每张图之间要间隔多少毫秒。
# 只能是整数
key = cv2.waitKey(1000 // 30)
if key & 0XFF == ord('q'):
break
# 别忘了释放资源
cap.release()
cv2.destroyAllWindows()
现在换上 1000 // 30
就表明我们现在的帧率差不多是30帧了。
在上面打开摄像头的基础上,可以将视频录制下来~
from cv2 import cv2
cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
cv2.resizeWindow('frame', 640, 480)
cap = cv2.VideoCapture(0)
# *mp4就是解包操作,等同于 'm', 'p', '4', 'v'
# fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# avi格式的视频
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# 创建videowriter
# vw = cv2.VideoWriter('output.mp4', fourcc, 30, (640, 480))
vw = cv2.VideoWriter('output.avi', fourcc, 30, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 写每一帧数据
vw.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1000 // 30) == ord('q'):
break
# 别忘了release
cap.release()
vw.release()
cv2.destroyAllWindows()
关于 *“字符串” 这个解包操作,就是将字符串分成多个字符,由一个参数变成多个参数的过程,这里举几个小栗子,sep='|'
的意思是将多个接收参数当中用 |
分隔开来:
很明显解包的作用就显现出来了。
这是博主使用摄像头录制的视频(转换成了GIF文件,露脸是不可能的~):
作为图像处理套件,怎么能少了对窗口的控制呢?
他既能等待键盘输入,又能检测鼠标状态:
from cv2 import cv2
import numpy as np
# 函数名可以随便取,但是参数必须是5个
# event表示鼠标事件,x,y是鼠标的坐标
# flags鼠标的组合按键.
def mouse_callback(event, x, y, flags, userdata):
print(event, x, y, flags, userdata)
if event == 2:
cv2.destroyAllWindows()
# 创建窗口
cv2.namedWindow('mouse', cv2.WINDOW_NORMAL)
# 宽度和高度
cv2.resizeWindow('mouse', 640, 360)
# 设置鼠标回调函数
cv2.setMouseCallback('mouse', mouse_callback, '123')
# 生成全黑的图片
img = np.zeros((360, 640, 3), np.uint8)
while True:
cv2.imshow('mouse', img)
key = cv2.waitKey(1)
if key == ord('q'):
break
cv2.destroyAllWindows()
这里通过 numpy
生成全黑背景,然后鼠标的每一次移动,都会传递五个参数到 mouse_callback
这个回调函数上。
其中 x,y
是鼠标的窗口坐标,userdata
为用户数据,方便回调函数知道这是哪里产生的回调。
然后 event
是鼠标事件,flags
是鼠标的组合按键,总结如下:
也不是都要记住,在有提示的编辑器中,比如 PyCharm 中就能通过如下方法获取:
这个组件的意思就是滑动条,这里演示一段 “调色板” 的代码:
from cv2 import cv2
import numpy as np
# 创建窗口
cv2.namedWindow('trackbar', cv2.WINDOW_NORMAL)
cv2.resizeWindow('trackbar', 640, 480)
# 定义回调函数
def callback(value):
# print(value)
pass
# 创建3个trackbar
cv2.createTrackbar('R', 'trackbar', 0, 255, callback)
cv2.createTrackbar('G', 'trackbar', 0, 255, callback)
cv2.createTrackbar('B', 'trackbar', 0, 255, callback)
# 创建背景图片
img = np.zeros((480, 640, 3), np.uint8)
while True:
# 获取当前trackbar的值
r = cv2.getTrackbarPos('R', 'trackbar')
g = cv2.getTrackbarPos('G', 'trackbar')
b = cv2.getTrackbarPos('B', 'trackbar')
# 用获取到的三个值修改背景图片颜色
img[:] = [b, g, r]
cv2.imshow('trackbar', img)
key = cv2.waitKey(1)
if key == ord('q'):
break
cv2.destroyAllWindows()
运行后效果如下:
当然我还没学到像 tkinter
模块那样能自由调整组件位置,我也不知道他能不能调节位置,但我知道他能调色。
原理就是循环,每次循环都会获得 R、G、B
颜色的值,然后对三维数组的所有最内层数组赋值为 [b, g, r]
要注意这里的顺序不是 R、G、B
,不然你调红就会变蓝,你调蓝就会变红(不要问我为什么这么有经验…)。