python-opencv基础入门
参考资料:
普通摄像头的数据输出格式YUV与mjpeg之间联系、DCT离散余弦变换去噪跟压缩
OpenCV的VideoCapture类的get、set参数列表
学习目标:
- 掌握cv获取图片数据
- 掌握cv获取视频流数据
- 掌握cv对图像数据进行处理(如画框)
记录时间:
- 2023.9.14
- 2023.9.15
学习内容:
图片
import cv2
image_path = "C:/***/***/Desktop/image.jpg" #图片路径,不含中文
img = cv2.imread(image_path)
cv2.imshow('窗口名称',img) #显示图片,[图片窗口名字,图片]
# 等待一个按键按下,再执行之后的代码
cv2.waitKey(0) # 无限期显示窗口,同时开始处理High_GUI的各种事件
b,g,r = cv2.split(img)
cv2.imshow("Blue_1",b)
cv2.imshow("Green_1",g)
cv2.imshow("Red_1",r)
cv2.waitKey(0) # 无限期显示窗口
cv2.destroyAllWindows() # 关闭所有窗口
isOk = cv2.imwrite(r"./blue_img.jpg", b) # 保存图片
if isOk:
print("save success")
说明:
- imread函数
Mat cv::imread(const String & filename,int flags = IMREAD_COLOR)
该函数通过内容确定图像的类型,而不是通过文件扩展名。在彩色图像的情况下,解码的图像将具有以B G R顺序存储的通道。当使用IMREAD_GRAYSCALE时,如果可用,将使用编解码器内部的灰度转换。结果可能与cvtColor()的输出不同。在Microsoft Windows操作系统和MacOSX上,默认使用OpenCV图像中提供的编解码器(libjpeg、libpng、libtiff和libjasper)。因此,OpenCV可以始终读取JPEG、PNG和TIFF。 - imwrite函数
bool cv::imwrite ( const String & filename,InputArray img,const std::vector< int > & params = std::vector< int >() )
Python:
cv.imwrite( filename, img[, params] ) -> retval
imwrite将图像保存到指定的文件中图像格式是根据文件扩展名选择的。通常,只有8位单通道或3通道(具有’BGR’通道顺序)的图像可以使用此函数保存,但有以下例外:
- 16位无符号(CV_16U)图像可以保存为PNG、JPEG 2000和TIFF格式
- 32位浮点数(CV_32F)图像可以保存为PFM、TIFF、OpenEXR和Radiance HDR格式;3通道(CV_32FC3)TIFF图像将使用LogLuv高动态范围编码(每像素4字节)保存
- 具有alpha通道的PNG图像可以使用此函数保存,请创建8位(或16位)4通道BGRA图像,其中alpha通道在最后完全透明的像素应将alpha设置为0,完全不透明的像素应将alpha设置为255(8位的情况)/65535(16位的情况)
多个图像(Mat的向量)可以保存为TIFF格式。如果图像格式不受支持,则图像将转换为8位无符号(CV_8U)并以这种方式保存
如果格式、深度或通道顺序不同,请在保存之前使用Mat::convertTo和cv::cvtColor进行转换或者,使用通用的FileStorage I/O函数将图像保存为XML或YAML格式。
-
imshow函数
void cv::imshow ( const String & winname,InputArray mat )
imshow在winname窗口中显示图像。如果窗口是用cv::WINDOW_AUTOSIZE标志创建的,那么图像将以其原始大小显示,但仍然受屏幕分辨率的限制。否则,图像将被缩放以适应窗口。
如果你的窗口在imshow函数之前没有被创建,那么默认会创建一个带有cv::WINDOW_AUTOSIZE标志的窗口。如果你需要显示比屏幕分辨率更大的图像,你需要在imshow之前调用namedWindow(“”, WINDOW_NORMAL) -
split函数
void cv::split(InputArray m,OutputArrayOfArrays mv )
Python:
cv.split( m[, mv] ) -> mv 返回多个矩阵组成的vector -
waitKey函数
waitKey函数等待按键事件的发生,无限期等待(当delay≤0时)或者在delay毫秒内等待(当delay大于0时)。由于操作系统在切换线程之间有一个最小的时间间隔,所以该函数不会严格按照delay毫秒来等待,实际上它将至少等待delay毫秒,这取决于当时计算机上正在运行的其他程序。函数返回按下的键的代码,或者当在指定的时间内没有按键按下时返回-1。要检查是否有键按下而不等待,请使用pollKey。
函数waitKey和pollKey是HighGUI中唯一可以获取和处理GUI事件的方法,因此除非在处理事件的环境中使用HighGUI,否则需要定期调用其中之一进行正常的事件处理。只有当至少创建一个HighGUI窗口并且该窗口处于活动状态时,该函数才能工作。如果有多个HighGUI窗口,则其中任何一个都可以处于活动状态。 -
namedWindow函数
void cv::namedWindow(const String & winname, int flags = WINDOW_AUTOSIZE)
创建一个窗口。
函数namedWindow创建了一个窗口,该窗口可以作为图像和滚动条的占位符。创建的窗口以其名称作为标识。
如果具有相同名称的窗口已经存在,则该函数不会执行任何操作。
您可以使用cv::destroyWindow或cv::destroyAllWindows关闭窗口,并释放任何相关的内存使用。对于简单的程序,您不必调用这些函数,因为应用程序的所有资源和窗口都会在退出时由操作系统自动关闭。
注意:
WINDOW_NORMAL或WINDOW_AUTOSIZE:WINDOW_NORMAL使您能够调整窗口的大小,而WINDOW_AUTOSIZE自动调整窗口大小以适应显示图像(请参见imshow),并且您无法手动更改窗口大小。
WINDOW_FREERATIO或WINDOW_KEEPRATIO:WINDOW_FREERATIO不按比例调整图像,而WINDOW_KEEPRATIO保持图像比例。
WINDOW_GUI_NORMAL或WINDOW_GUI_EXPANDED:WINDOW_GUI_NORMAL是旧版无状态栏和工具栏的窗口绘制方式,而WINDOW_GUI_EXPANDED是新的增强型GUI。默认情况下,flags == WINDOW_AUTOSIZE | WINDOW_KEEPRATIO | WINDOW_GUI_EXPANDED
视频
读取视频文件
import cv2
vc = cv2.VideoCapture('test.mp4') # 视频路径
isVCOpened = vc.isOpened()
ret = False
if vc.isOpened():
# 检查是否打开正确,正确则读取第一帧
ret, frame = vc.read()
while ret:
ret, frame = vc.read()
if ret is False:
break
else:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('result', gray)
if cv2.waitKey(100) & 0xFF == ord('q'):
break
vc.release()
cv2.destroyAllWindows()
说明:
-
VideoCapture类构造函数
cv::VideoCapture::VideoCapture ( const String & filename, int apiPreference = CAP_ANY )
打开视频文件,使用API设置默认为任意捕获设备
参数
文件名 可以是以下格式:
视频文件名称(例如 video.avi)
或图像序列(例如 img_%02d.jpg,这将读取类似 img_00.jpg、img_01.jpg、img_02.jpg 等的样本)
或视频流URL(例如 protocol://host:port/script_name?script_params|auth)
或在使用GStreamer作为后端的情况下使用gst-launch工具格式的GStreamer管道字符串。请注意,每个视频流或IP摄像机馈送都有自己的URL方案。请查阅源流的文档,了解正确的URL。
apiPreference 优先使用特定的捕获API后端可以用于强制使用特定读取器实现(如果有多个可用实现)例如 cv::CAP_FFMPEG 或 cv::CAP_IMAGES 或 cv::CAP_DSHOW。
使用cv::CAP_ANY 有时后出现警告,这时一般使用cv::CAP_DSHOW就行(DirectShow) -
read函数
virtual bool cv::VideoCapture::read (OutputArray image )
Python:
cv.VideoCapture.read([, image]) -> retval, image
获取、解码并返回下一个视频帧。
返回image视频帧。如果没有抓取帧,则图像将为空且retval返回false。
该函数将VideoCapture::grab()和VideoCapture::retrieve()组合在一起调用。这是读取视频文件或从解码捕获数据的最方便的方法。
使用电脑默认摄像机
import cv2
# 创建一个窗口 名字叫做Window
cv2.namedWindow('Window', flags=cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO | cv2.WINDOW_GUI_EXPANDED)
# 打开默认摄像头
# CAP_DSHOW是以YUV格式传入的,帧率往往很低。不传入参数,默认以MJPG格式传入,图像质量稍差,但是帧率会更高
# cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 注:使用CAP_DSHOW虽然可以解决警告问题,但很可能会降低摄像机帧率(降为原来的一半)
cap = cv2.VideoCapture(0)
# 使用远程摄像头
# # 摄像头的IP地址,http://用户名:密码@IP地址:端口/
# ip_camera_url = 'http://admin:admin@192.168.1.101:8081/'
# cap = cv2.VideoCapture(ip_camera_url)
print('摄像头是否开启: {}'.format(cap.isOpened()))
# 显示缓存数
print(cap.get(cv2.CAP_PROP_BUFFERSIZE))
# 设置缓存区的大小
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# 调节摄像头分辨率 和窗口尺寸有点关系,但又不是完全相同
# 注意cap.set如果失败,并不会显示任何信息。cap.set必须根据自己摄像机的实际情况来,有的摄像机
# 就是只有720p、360p等等,这时设置其他的width、height是不管用的。摄像机帧率也是如此,
# 普通的摄像机就是恒定30fps的,不能设为其他帧率的。
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
print(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
print(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 设置FPS (帧率或帧/秒)
print('setfps', cap.set(cv2.CAP_PROP_FPS, 25))
print(cap.get(cv2.CAP_PROP_FPS))
flag = cap.isOpened()
while (flag):
# 逐帧捕获
ret, frame = cap.read() # 第一个参数返回一个布尔值(True/False),代表有没有读取到图片;第二个参数表示截取到一帧的图片
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('Window', gray)
# 按q建退出
if cv2.waitKey(1) & 0xFF == ord('q'): # waitKey最小1ms,也就是说理论上FPS最大为1000
# 目前设置的25FPS显然足够,即使waitKey(40)也几乎不会卡
break
# 当一切结束后,释放VideoCapture对象
cap.release()
cv2.destroyAllWindows()
说明:
- cv::VideoCapture::VideoCapture ( int index, int apiPreference = CAP_ANY )
index:这是要打开的视频捕获设备的ID。如果想要用默认的后端打开默认的摄像头,只需要传入0即可。(为了向后兼容,当apiPreference是CAP_ANY时,使用camera_id + domain_offset (CAP_*)是有效的。)
apiPreference:这是您想要使用的首选视频捕获API后端。这个参数可以用于强制使用特定的读取器实现,如果存在多种可用的实现的话。例如,cv::CAP_DSHOW 或 cv::CAP_MSMF 或 cv::CAP_V4L。
画框
使用cv2.rectangle画方框和cv2.circle画圆
cv2.rectangle(图像矩阵, (左上角x, 左上角y), (右下角x, 右下角y), 颜色, 线宽度) ==> 返回画了框的图像矩阵
例如drawed_img = cv2.rectangle(image, (x_center-half_w, y_center-half_h), (x_center+half_w, y_center+half_h), (255, 0, 0), 2)
说明:
- rectangle函数
void cv::rectangle ( InputOutputArray img,
Point pt1,
Point pt2,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
)
函数可以在图像上画出一个矩形框或者填充的矩形
参数说明:- img:输入/输出图像。矩形将在该图像上绘制。
- pt1:矩形的一个顶点。
- pt2:与pt1相对的矩形顶点。
- color:矩形的颜色或亮度(在灰度图像中)。color顺序也是B G R
- thickness:构成矩形的线的厚度。负值,如“FILLED”,表示绘制填充的矩形。
- lineType:线的类型。详见下图。
- shift:点坐标中的小数位数。
学习小结:
提示:这里总结学习知识