第一节、初识OpenCV3-图像的读、写、显、格式转化等
目录
之前一直在看深度学习,用到了图像处理的知识,所以过来补充一下OpenCV基础。
就顺便从网上了买了一本《OpenCV 3计算机视觉》这本书,这本书比较薄,但是目前已经够我用了,在这里就记录一下我的学习笔记。
一 、OpenCV3安装
1.1 Open CV3安装
在前面我已经介绍过我的python运行环境,是运行在windos 7操作系统下,安装的Anaconda集成开发环境。具体安装步骤可以参考文章《第一节,windows下深度学习theano环境搭建》。
下面介绍一下如何在Anaconda命令窗口下安装opencv:
conda install -c https://conda.binstar.org/menpo opencv
打开Anaconda Prompt,输入python,进入python环境之后,import cv2。如果不报错,说明安装成功。
1.2 内容大纲
本节主要介绍以下7块内容:
- 读写图像文件;
- 图像与原始字节之间的转换;
- 使用numpy.array访问图像数据;
- 视频文件的读写(复制视频);
- 捕获摄像头的帧,并保存视频文件;
- 窗口显示图像;
- 在窗口显示摄像头帧;
为了做测试,我专门创建了一个OpenCV文件夹,在下面放一些测试代码,并创建了两个文件夹,video和image分别保存一些视频和图像文件。
二、基础API
2.1 读写图像文件
OpenCV的imread()和imwrite()函数能支持各种静态图像文件格式。不同系统支持的文件格式不一样,但是都支持bmp格式,通常还支持 png,jpeg,tiff格式文件 :
- bmp格式:每个像素每个通道为8位;
- png:每个像素每个通道为8位或者16位。
2.1.1 读入图像
读取图像函数原型:
cv2.imread(filename[,flags])
该函数返回我们读取的图像数据:
- 第一个参数,这幅图像应该在此程序的工作路径,或者给函数提供完整路径;
- 第二个参数是标志位,要告诉函数应该如何读取这幅图片,即指定加载图片的颜色类型,默认加载类型是cv2.IMREAD_COLOR:
- cv2.IMREAD_COLOR=1:读入一副彩色图像,将图像转化为三通道BGR彩色图像。图像的透明度会被忽略,这是默认参数;
- cv2.IMREAD_GRAYSCALE=0:将加载的图像转换为单通道灰度图;
- cv2.IMREAD_UNCHANGED = -1: 已经废除,不再使用;
- cv2.IMREAD_ANYDEPTH=2: 若载入图像深度为16位或32为就返回其对应深度,否则将图像转换为8位图像;
- cv2.IMREAD_ANYCOLOR=4: 保持图像原格式,可以读取任意可能的彩色格式;
- cv2.IMREAD_LOAD_GDAL=8: 使用文件格式驱动加载图像,在现阶段用处不多。
在使用flags时可能会同时使用多种flags,如果发生冲突,函数将自动采用较小数字值对应的加载方式。如:cv2.IMREAD_COLOR | cv2.IMREAD_ANYCOLOR,则imread()函数将自动载入cv2.IMREAD_COLOR所对应的3通道彩色图。如果要载入图像原本的彩色格式和深度,则可以使用: cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH。
也可以利用flags是int类型的变量输入其他值以达到加载特定图像格式的目的,但符合一下标准:
- flags > 0:返回一个三通道的彩色图像;
- flags = 0: 返回灰度图像 ;
- flags < 0: 返回包含Alpha通道的图像。
图像在默认情况下不是从Alpha通道进来的,如果需要载入Alpha通道的话就取负值。
2.1.2 保存图像
保存图像函数原型:
cv2.imwrite(filename,img[,params])
该函数用于保存图像:
- 第一个参数,这幅图像应该保存的工作路径,或者给函数提供完整路径;
- 第二个参数是输入图像;
- 第三个参数表示为特定保存格式的参数编码,在一般情况下不需要更改;
2.1.3 格式转换
格式转换函数原型:
cv2.cvtColor(src,code[,dst[,dstCn]])
输出为输入图像进行颜色空间变换的图像。我们生活中大多数看到的彩色图片都是BGR类型,但是在进行图像处理时,需要用到灰度图、二值图、HSV、HSI等颜色制式,opencv提供了cv2.cvtColor()函数来实现这些功能:
- 第一个参数输入图像即要进行颜色空间变换的原图像;
- 第二个参数转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片;
- 第三个参数为为输出图像即进行颜色空间变换后存储图像;
- 第四个参数是目标图像通道数,如果取0,则由src和code决定;
函数的作用是将一个图像从一个颜色空间转换到另一个颜色空间,但是从BGR向其它类型转换时,必须明确指出图像的颜色通道,在opencv中,其默认的颜色制式排列是BGR而非RGB。所以对于24位颜色图像来说,前8-bit是蓝色,中间8-bit是绿色,最后8-bit是红色。常见的B,G,R通道的取值范围为:
- . 0-255 :cv2.CV_8U类型图片;
- . 0-65535: cv2.CV_16U类型图片;
- . 0-1::cv2.CV_32F类型图片;
讲到这里有必要介绍一下图像的数据类型,一张图片就是一个简单的numpy数组,数组的数据类型有很多种,相互之间也可以转换,这些数据类型以及取值范围如下表所示:
Data type | Range |
---|---|
uint8 | 0 to 255 |
uint16 | 0 to 65535 |
uint32 | 0 to 232 |
float32 | -1 to 1 or 0 to 1 |
int8 | -128 to 127 |
int16 | -32768 to 32767 |
int32 | -231 to 231 - 1 |
对于线性变换来说,这些取值范围是无关紧要的。但是对于非线性转换,输入的BGR图像必须归一化到其对应的取值范围来或得最终正确的转换结果,例如从BGR>L*u*v转换。如果从一个8-bit类型图像不经过任何缩放(scaling)直接转换为32-bit浮点型图像,函数将会以0-255的取值范围来取代0-1的取值范围,所以在使用cvtColor函数之前需要对图像进行缩放如下:
img *= 1.0/255;
cvtColor(img,cv2.COLOR_BGR2Luv);
如果对8-bit图像使用cvtColor()函数进行转换将会由一些信息丢失。函数可以做下面类型的转换,需要说明的是在opencv2.x时颜色空间转换code用的宏定义是CV_前缀开头,而在opencv3.x版本其颜色空间转换code宏定义更改为COLOR_开头,而经验证,2.4.13版本中opencv同事支持这两种形式的写法。故下面表格会将两种code类型同时列出,以供参考:
这里列出的类型并不齐全,但是对于一般的图像处理已经够用。需要特别说明的是BGR–>GRAY的转换是我们常用的转换格式,其转换公式如下:
$$\gamma=0.299*R +0.587*G + 0.114*B$$
介绍一下BGRA格式图片,BGRA是代表Blue(蓝色),Green(绿色)、Red(红色)、和Alpha的色彩空间。虽然它有时候被描述为一个颜色空间,但是它其实是BGR模型附加了额外的信息,可以属于任何一种BGR颜色空间。Alpha参数一般用作不透明度参数,如果一个像素的alpha通道数值为0%,那它就是完全透明的也就是肉眼不可见,而数值为100%则意味着一个完全不透明的像素,传统的数字图像就是alpha值为100%.
2.1.4 示例程序
import cv2 import numpy as np import os ''' 1.读写图像文件 ''' #通过二维numpy数组创建一个黑色的正方形图像 img = np.zeros((3,3),dtype=np.uint8) #输出 每一个像素都是8位整数 范围0-255 图片大小为3x3 print(img) #[[0 0 0] # [0 0 0] # [0 0 0]] print(img.shape) #(3, 3) #利用cvtColor()函数将图像转换为blue-green-red(BGR)格式 img = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) #输出维度为3x3x3 表明图像大小为3x3 有三个通道 每个像素由一个三元数组表示(B,G,R) print(img) # [[[0 0 0] # [0 0 0] # [0 0 0]] # [[0 0 0] # [0 0 0] # [0 0 0]] # [[0 0 0] # [0 0 0] # [0 0 0]]] print(img.shape) #(3, 3, 3) #把png图像转换为jpeg格式 root = '.\image' file = os.path.join(root,'test.bmp') #加载OpenCV图像最简单的方式是使用imread函数,该函数会返回一副图片,这幅图片是一个数组(根据imread()输入参数的不同,该图像可能是一个二维数组,也可能是三维数组) #在默认情况下,即使文件是灰度格式,imread()函数也会返回BGR格式的图像 #BGR和RGB所表示的色彩空间相同,字节顺序相反 img = cv2.imread(file) #读bmp格式取图片 cv2.imwrite('test.jpg',img) #保存成jpg格式 #按照指定参数读取图片 加载bmp文件作为灰度图像(丢失颜色信息) gray_image = cv2.imread(file,cv2.IMREAD_GRAYSCALE) #保存为灰度的jpg图像 cv2.imwrite('test_gray.jpg',gray_image)
2.2 图像与原始字节之间的转换
一个OpenCV图像一般是numpy.array类型的二维或者三维数组。8位的灰度图像是一个含有字节值得二维数组,维度为 $height * width$,24位的BGR是一个三维数组 维度为$height * width * channel$。
2.2.1 图像展示
图像展示函数原型:
cv2.imshow(winname,mat)
该函数用来显示图像,窗口会自动调整为图像大小:
- 第一个参数是窗口的名字。
- 第二个参数是要输出的图像。
imshow()在用于指定的窗口显示图像时,如果窗口用cv2.WINDOW_ATTOSIZE创建,那么显示图像原始大小。否则将图像进行缩放以适合窗口。而imshow()函数缩放图像取决与图像深度:
- 如果载入图像是8位无符号类型(8-bis unsigned),就显示图像本身。
- 如果图像是16位无符号类型(16-bist unsigned)或32位无整型(32-bit integer),则使用像素值除以256.也就是说将像素值范围在[0,255x256]之间的元素映射到(0,255]范围内。
- 如果载入图像是32位浮点型(32-bit floating-point),像素值要乘以255.也就是说像素值范围在[0,1]映射到[0,255]。
2.2.2 键盘绑定函数
cv2.waitKey(ms)
'''
2.图像与原始字节之间的转换
'''
img = cv2.imread(file) #读bmp格式取图片
print('图像{0}的维度为{1}'.format(file,img.shape))
#显示的转换为一维的python bytearray格式
byte_array = bytearray(img) #图像.\image\test.bmp的维度为(45, 50, 3)
print('转换之后的维度为:',len(byte_array),type(byte_array)) #转换之后的维度为: 6750 <class 'bytearray'>
#bytearray含有恰当顺序的字节,可以通过显示转换和重构 得到numpy.array形式的图像
img = np.asarray(byte_array).reshape(45,50,3)
cv2.imshow('window 1',img)cv2.waitKey(10) #等候10ms
'''
一个详细的例子 将含有随机字节的bytearray转换为灰度图像和BGR图像
'''
#随机生成120,000个字节的数组
random_byte_array = bytearray(os.urandom(120000)) #生成随机字节
#转换成numpy.array类型
byte_array = np.asarray(random_byte_array,dtype=np.uint8)
#把数组转换成 400 x 300的灰度图像
gray_image = byte_array.reshape(300,400)
cv2.imwrite('test_gray.png',gray_image)
#把数组转换成 400 x 100的BGR图像
bgr_image = byte_array.reshape(100,400,3)
cv2.imwrite('test_bgr.png',bgr_image)
2.3 使用numpy.array访问图像数据
亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。
日期 | 姓名 | 金额 |
---|---|---|
2023-09-06 | *源 | 19 |
2023-09-11 | *朝科 | 88 |
2023-09-21 | *号 | 5 |
2023-09-16 | *真 | 60 |
2023-10-26 | *通 | 9.9 |
2023-11-04 | *慎 | 0.66 |
2023-11-24 | *恩 | 0.01 |
2023-12-30 | I*B | 1 |
2024-01-28 | *兴 | 20 |
2024-02-01 | QYing | 20 |
2024-02-11 | *督 | 6 |
2024-02-18 | 一*x | 1 |
2024-02-20 | c*l | 18.88 |
2024-01-01 | *I | 5 |
2024-04-08 | *程 | 150 |
2024-04-18 | *超 | 20 |
2024-04-26 | .*V | 30 |
2024-05-08 | D*W | 5 |
2024-05-29 | *辉 | 20 |
2024-05-30 | *雄 | 10 |
2024-06-08 | *: | 10 |
2024-06-23 | 小狮子 | 666 |
2024-06-28 | *s | 6.66 |
2024-06-29 | *炼 | 1 |
2024-06-30 | *! | 1 |
2024-07-08 | *方 | 20 |
2024-07-18 | A*1 | 6.66 |
2024-07-31 | *北 | 12 |
2024-08-13 | *基 | 1 |
2024-08-23 | n*s | 2 |
2024-09-02 | *源 | 50 |
2024-09-04 | *J | 2 |
2024-09-06 | *强 | 8.8 |
2024-09-09 | *波 | 1 |
2024-09-10 | *口 | 1 |
2024-09-10 | *波 | 1 |
2024-09-12 | *波 | 10 |
2024-09-18 | *明 | 1.68 |
2024-09-26 | B*h | 10 |
2024-09-30 | 岁 | 10 |
2024-10-02 | M*i | 1 |
2024-10-14 | *朋 | 10 |
2024-10-22 | *海 | 10 |
2024-10-23 | *南 | 10 |
2024-10-26 | *节 | 6.66 |
2024-10-27 | *o | 5 |
2024-10-28 | W*F | 6.66 |
2024-10-29 | R*n | 6.66 |
2024-11-02 | *球 | 6 |
2024-11-021 | *鑫 | 6.66 |
2024-11-25 | *沙 | 5 |
2024-11-29 | C*n | 2.88 |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了