一起学opencv-python一(opencv安装和简介和图像和视频的读取与保存)

版权声明: https://blog.csdn.net/qq_41740705/article/details/82688215

opencv就是Open Source Computer Vision Library,就是一个开源的计算机视觉库。

 

我们先来下载opencv,这里我默认你们已经把环境配置好了,不会配置的到前面的教程里面看吧。下面三个模块是和opencv相关的,opencv-python是必须要安装的。opencv-contrib-python是一个扩展的模块,有很多功能,比如图片拼接,CNN人脸识别,OCR等。pytesseract是谷歌的一个开源的OCR的一个库。

 

安装opencv

 

那我们就都安装一下吧,这里说一下如果你下的是anaconda,把pip全部换成conda就可以,当然安装anaconda也还是可以用pip的,这个前面的教程都是讲过的。下面是anaconda如何安装:

anaconda的时候需要注意,输入opencv-python是没有的。提示找不到这个包。

 

直接输入opencv就可以。

 

这个是直接安装了三个包,在python里面导入也没有问题。

 

 

 

上面两个库安装失败的原因都是库的名字不对,其实我们上面已经安装了三个包,其中有一个libopencv,我觉得这个应该就是opencv的一些库,下面是看一下opencv的版本。

 

pip安装(下anaconda,pip配置到环境变量里也可以用的):

我没有卸载上面用anaconda安的opencv,直接接着用pip安装。

 

你们第一次用pip安装应该是会有一个进度条,我是安装过然后卸载了,这是重新安装,上次安装还留下了一些文件,所以这么快,也没有进度条。看到pip安装的版本是3.4.2,在python里面导入也确实是3.4.2的。那么接着安装另外两个,

 

不过速度有点感人啊78kB/s,因为用的是国外的源,那么下面我们来换源,参考了https://blog.csdn.net/lambert310/article/details/52412059

我在c:/user/lenovouser里面创建了一个pip。

 

然后在里面新建一个pip.ini,把上面文章里的复制进去。

 

然后保存。下载最后一个模块。

 

确实是换成了清华的源,速度快了十几倍,957kB/s。我们就用pip安装的3.4.2版本的吧,把用anaconda安装的卸载掉。

 

opencv简介

 

opencv有很多模块,竖着的是一些比较高级或者说专业的模块,横着的是一些基础模块,高级模块是基于基础模块的,俗话说的好,基础不牢,地动山摇,这些基础模块都学不好的话,高级模块更没有办法去学习。其中蓝色的两个imagcodecs和videoI/O分别是管理图像和视频的输入输出的模块,imagcodecs负责图像的编解码,videoI/O负责视频的输入输出,这两个模块opencv都封装了很高级的api来供我们使用。core,顾名思义,是一个比较核心的模块,像素级别的运算都在这里面。image processing模块中包含了很多内容,后面主要学习的就是这个模块,然后如果你想专业一点深入一点,可以继续学习竖着的专业的模块,比如对象检测,这里要稍微说一下检测和识别,拿人脸为例,人脸检测只是检测出来说这里有一张人脸,但是是谁不清楚,而人脸识别深入一步,要识别出来这个人脸是谁。high-level gui模块就是一些gui呗,右边红色的扩展模块大概就是在opencv-contrib-python里面,左边的这些是在opencv-python里面有的。

图像的加载与保存

首先了解一图像在计算机里面如何存储的。

 

图像是由一个一个像素点矩阵排列组成的。

 

如果是灰度图,那么图像是有一个通道,每一个像素点有一个灰度值,组成一个矩阵,如果是彩色图,有BGR三个颜色通道,每一个像素点上有一个强度值,在0-255之间,可以用一个字节来存,那么就有三个矩阵。这里先推荐一个opencv函数库查询。

函数库查询:https://blog.csdn.net/weixin_40427089/article/details/81365076

下面会用到的先列出来:

 

 

cv2.waitKey()是一个键盘绑定函数。它的参数是以毫秒为单位的时间。该函数等待任何键盘事件的指定毫秒。如果您在该时间内按任意键,程序将继续。如果为0,则无限期等待键击,这个意思就是说如果没有外部键盘敲击,就一直卡在这一行,不会执行cv2.waitKey()下面的代码。下面还参考了https://www.jianshu.com/p/7fcfc6253c81

 

也就是namedWindow就是设置窗口大小的一个函数。下面来操作一下。

 

我看到有的人用pycharm的说加载不出来,可以去

https://www.bilibili.com/video/av30953498?spm_id_from=333.338.__bofqi.15

21分钟左右看看能不能解决,反正我的sublime是没有一点毛病。因为namedWindow默认是cv2.WINDOW_AUTOSIZE。所以其实有没有namedWindow也是可以的,并且不给namedWindow函数的第二个参数,默认也是cv2.WINDOW_AUTOSIZE,所以图片的大小是没有办法拖动边框改变大小的,并且我们按键盘上的任意一个键都可以关掉窗口。下面我们添加一个函数namedWindow并且给第二个参数cv2.WINDOW_NORMAL。那么就来看一看效果,这里由于上面的图片太大,录制的gif超过了3M,我换了一个比较小的图片。

 

效果也就是拖动边框可以改变图片的大小。看到里面还有一些其它的信息。

 

p的类型是numpy.ndarray。

 

Numpy库中的矩阵模块为ndarray(n维数组)对象,有很多属性:T,data, dtype,flags,flat,imag,real,size等。shape打印出来的元组有三个元素,说明是三维数组,(150,200,3)中三个数字代表水平像素为200,垂直为150,(也就是200列,150行)3是表示有三个通道。size是大小,90000=150×200×3。dtype是数组每一格元素的存储类型,是unint8,也就是无符号整数8位二进制,因为0-255可以用8bits装下。opencv里面矩阵运算和矩阵存储用到的就是numpy,其实上面安装opencv的时候numpy就是一个依赖库,所以后面的内容会有很多numpy的内容。我下面来试一下namedWindow是不是能放在imshow后面呢?

 

看到效果是图片虽然可以显示出来,但是不能调节大小,说明namedWindow需要放在imshow前面才会起作用。下面再简单试一下waitKey()。

 

waitKey(1000)的效果是等待1000ms也就是1s才执行下一行代码,从这点来看,和延时函数的作用是一样的,但是waitKey(0)不是不延时,而是无限延时,并且正如waitKey函数起的名字一样,它除了wait还有Key,就是在延时时间内如果键盘上有键按下,那么也会执行下一行代码。我们加一段程序指定输入哪一个或者哪几个键才有效。

 

27就是ESC的ASCII码。ord('s')是求s的ASCII码。

 

下面我们来试一试:

 

看到没有问题,虽然上面有一个如果是64位机需要写成k = cv2.waitKey(0) & 0xFF,不过我没改也没有问题,这个和0xFF按位与其实就是取低八位的意思,因为esc和s的ASCII码都没有超过八位,所以是没有意义的,如果有超过8位的和0xFF按位与,就是取低8位,不过我没看出来这里为什么要和0xFF按位与。上面用到了一个imwrite,也很简单

 

中文翻译一下.号给搞成句号了。不过我发现waitKey其实并没有那么简单:

 

这个waitKey里面的参数默认就是0,填负数应该也按照0处理了。看上面的gif,还会发现一个问题就是,如果waitKey是python脚本里面最后一个waitKey,这个waitKey是有destroyAllWindows的功能的,再来看一下:

 

所以要想实现指定键销毁某一个窗口,那么就不能在最后一个waitKey后面,原因就是上面所说。最后,官方文档中还提供了一个matplotlib的例子,我也来试一下

 

可以用pip或者conda安装,不过这个已经安装过了,可能是opencv的依赖库?或者是安anaconda时安装的?不管了。这个安装也不难。

 

 

imread里面0的意思其实就是灰度图像,参看下图里的解释。

 

不能用彩色吗?

 

这是怎么回事?这是因为OpenCV加载的彩色图像处于BGR模式。但Matplotlib以RGB模式显示。因此,如果使用OpenCV读取图像,则Matplotlib中的彩色图像将无法正确显示,也就是通道对不上。那么问题来了,为什么opencv要采用BGR顺序的模式呢?这又是因为历史原因,早期的opencv开发者采用了BGR顺序,所以一直遗留下来了。那么早期的opencv开发者为什么要用BGR呢,因为那时的许多照相机生产厂家和软件开发商就是采用的BGR模式。能不能正常显示呢?是可以的,参考了https://blog.csdn.net/saltriver/article/details/78173219。

我们把BGR转换为RGB就可以了,只需要添加一句:img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

 

 

我们也是可以查看每一个像素点的值的。

 

用了一个np.array。这里面有省略号,因为太多了嘛,最里面的中括号里面有三个值,代表的应该就是BGR,外层的两个中括号里面装的是行和列,最外面的括号应该是每一行的像素点,中间的是每一列,应该是按照(150,200,3)这个顺序。

视频的读取和保存

1从摄像头读取

还是先来理解一些函数

 

 

官网的案例:

 

 

ret是一个返回值,frame是每一帧,我们这里刷新的很快,waitKey(1)就是大概1ms刷新一次,我们用一个while循环让每一帧连起来,看起来就是一个视频。我实际的代码是这个样子的:

 

首先里面用了一个flip,这个是翻转,为什么要翻转呢?因为摄像头的视角和我的视角是镜像的,我向左,出来的图像是向右的。

https://blog.csdn.net/jningwei/article/details/78753607

 

还有我把cap.release和cv2.destroyAllwindows()注释掉了,这两句可以不要,当然你加上也没有问题。看一下效果:

链接: https://pan.baidu.com/s/16Uf8NVu7TLFLPoktLrGueA 密码: 1gvu(这里因为太大了,所以gif不能插入,请到网盘看一下,至于b站视频投稿这个方式,gif不能上传,其它格式处理时间太长了,b站动态也不能发大于8M的,将就一下这么看吧)

这个摄像头的窗口用右上角其实时可以关闭的,但是为什么又出现了呢?这是因为有一个while循环,而waitKey是和键盘绑定的,鼠标的这个事件它是不识别的,只有我们按q的时候,就跳出了循环。

2从文件播放视频

人眼的视觉暂留时间大概是0.1s,也就是说小于10fps(每秒小于10帧),我们就会感觉到明显的不连贯,卡顿。25ms一帧完全没有问题。下面的waitKey(1)就更不用说了。

 

 

视频的保存

 

 

 

那么我们下面就演示一个过程,就是用摄像头录制一段视频,然后读取。

 

 

我们看一下效果:

链接: https://pan.baidu.com/s/195gqEZ0wnEAmZ06-hDqqwA 密码: zynu

看到报错了。

 

这个错误原因其实是因为视频播放结束了,然后frame就是一个Nonetype,所以会违背size.width和size.height都大于0的要求,准确地说用地是断定(Assertion),Assert后面的值为假就会报错。

 

我修改了一下:

 

就没有问题了,看一下效果:

链接: https://pan.baidu.com/s/1lXBgOVBZMC729zCuHPmt4Q 密码: cqg6

细心的人可能注意到了我上面的代码tab和空格是混用的,但是没有报错,我们最好还是统一,这个我暂时说不清楚,不过如果和代码挨着的都是空格,好像就没有问题。这一讲先到这里。

猜你喜欢

转载自blog.csdn.net/qq_41740705/article/details/82688215