程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

第一节、初识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:
  1. cv2.IMREAD_COLOR=1:读入一副彩色图像,将图像转化为三通道BGR彩色图像。图像的透明度会被忽略,这是默认参数;
  2. cv2.IMREAD_GRAYSCALE=0:将加载的图像转换为单通道灰度图;
  3. cv2.IMREAD_UNCHANGED = -1: 已经废除,不再使用;
  4. cv2.IMREAD_ANYDEPTH=2: 若载入图像深度为16位或32为就返回其对应深度,否则将图像转换为8位图像;
  5. cv2.IMREAD_ANYCOLOR=4: 保持图像原格式,可以读取任意可能的彩色格式;
  6. 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 typeRange
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
 一张图片的像素值范围是[0,255],因此默认类型是uint8。在上面表中需要注意的是float32类型,它的范围是[-1,1]或[0,1]之间。详细内容可以参考:python数字图像处理(4):图像数据类型及颜色空间转换

对于线性变换来说,这些取值范围是无关紧要的。但是对于非线性转换,输入的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) 
需要指出的是它的时间尺度是毫 秒级。函数等待特定的几毫秒,看是否有键盘输入。特定的几毫秒之内,如果 按下任意键,这个函数会返回按键的ASCII 码值,程序将会继续运行。如果没 有键盘输入,返回值为-1,如果我们设置这个函数的参数为0,那它将会无限期的等待键盘输入。它也可以被用来检测特定键是否被按下。
复制代码
'''
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-30I*B1
2024-01-28*兴20
2024-02-01QYing20
2024-02-11*督6
2024-02-18一*x1
2024-02-20c*l18.88
2024-01-01*I5
2024-04-08*程150
2024-04-18*超20
2024-04-26.*V30
2024-05-08D*W5
2024-05-29*辉20
2024-05-30*雄10
2024-06-08*:10
2024-06-23小狮子666
2024-06-28*s6.66
2024-06-29*炼1
2024-06-30*!1
2024-07-08*方20
2024-07-18A*16.66
2024-07-31*北12
2024-08-13*基1
2024-08-23n*s2
2024-09-02*源50
2024-09-04*J2
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-26B*h10
2024-09-3010
2024-10-02M*i1
2024-10-14*朋10
2024-10-22*海10
2024-10-23*南10
2024-10-26*节6.66
2024-10-27*o5
2024-10-28W*F6.66
2024-10-29R*n6.66
2024-11-02*球6
2024-11-021*鑫6.66
2024-11-25*沙5
2024-11-29C*n2.88
posted @   大奥特曼打小怪兽  阅读(14845)  评论(1编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
如果有任何技术小问题,欢迎大家交流沟通,共同进步

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)。

了解更多

点击右上角即可分享
微信分享提示