1. 图像与原始字节之间的转换

从概念上讲,一个字节能表示0到255的整数。目前,对于多有的实时图像应用而言,虽然有其他的表示形式,但一个像素通常由每个通道的一个字节表示。

一个OpenCV图像是.array类型的二维或三维数组。8位的灰度图像是一个含有字节值的二维数组。一个24位的BGR图像是一个三维数组,它也包含了字节值。可使用表达式访问这些值,如image[0,0]或image[0,0,0]。第一个值代表像素的y坐标啊或行,0表示顶部;第二个值是像素的x坐标或列,0表示最左边;第三个值(如果可用的话)表示颜色通道。如,对于一个左上角有白色像素的8位灰度图像而言,image[0,0]的值为255. 对于一个左上角有蓝色像素的24位BGR图像而言,image[0,0]是[255,0,0]。

可以用另外一个表示,如image[0,0]或image[0,0]=128,还可表示成image.item((0,0))或image.setitem((0,0),128)。对于单像素操作,第二种表示方式更有效。

若一幅图像的每个通道为8位,则可将其显示转换为标准的一维Python bytearray格式:

byteArray = bytearray(image)

反之,bytearray含有恰当顺序的字节,可以通过显示转换和重构,得到numpy.array形式的图像:

garyImage = numpy.array(garyByteArray ).reshape(height, width)

bgrImage = numpy.array(bgrByteArray ).reshape(height, width, 3)

下面介绍将含有随机字节的bytearray转换为灰度图像和BGR图像:

importcv2importnumpy as npimportos#创建一个120000个随机字节的数组

randomByteArray = bytearray(os.urandom(120000)) #os.urandom(n) 返回n个随机byte值的string,作为加密使用

flatNumpyArray =np.array(randomByteArray)#将数组转换为400 x 300的灰度图像

garyImage = flatNumpyArray.reshape(300, 400)

cv2.imwrite('randomGary.png', garyImage)#将数组转换为400 x 300的彩色图像

bgrImage = flatNumpyArray.reshape(100, 400, 3)

cv2.imwrite('randomColor.png', bgrImage)

运行该程序,将会在程序所在目录中生成两张灰度图像(如下所示)。尺寸分别为400 x 100,400 x 400

使用Python标准的os.urandom()函数可随机生成原始字节,随后会把该字节转换为NumPy数组。需要注意的是,诸如numpy.random.randint(0, 256, 120000).reshape(400, 300)语句也能直接(并且更高效地)随机生成NumPy数组。使用os.urandom()函数的原因是该语句有助于展示原始字节的转换。

2. 使用numpy.array访问图像数据

加载OpenCV图像最简单的方式是使用imread()函数,该函数会返回一幅图像,这幅图像是一个数组(根据imread()函数输入参数的不同,该图像可能是二维数组,也可能是三维数组)。

y.array结构针对数组操作有很好的优化,它允许某些块(bulk)操作,这些操作在通常的Python中不可用这些特定的.array操作在OpenCV的图像处理中会很方便。利用numpy.array函数来转换数组比用普通的Python数组转换要快得多。

importcv2importnumpy as np

img= cv2.imread('flower.jpg')

img[0,0]= [255, 255, 255]

cv2.imshow('my image', img)

cv2.waitKey()

在图像左上方会出现一个白点。

假设想要改变一个特定像素的蓝色值,numpy.array提供了item()方法。该函数有3个参数:x(或左)位置,y(或顶部)位置以及(x,y)位置的数组索引(注意,在BGR图像中,某一位置的数据是按B,G,R的顺序保存的三元数组),该函数能返回索引函数的值。另一个方法是通过itemset()函数可设置指定像素在指定通道的值(itemset()有两个参数:一个三元组(x,y和索引)和要设定的值)。如下例子将坐标(150,120)的当前蓝色值127变为255

importcv2importnumpy as np

img= cv2.imread('flower.jpg')print(img.item(150, 120, 0)) # 打印当前坐标点的蓝色值

img.itemset((150, 120, 0), 255)print(img.item(150, 120, 0))

建议使用内置的滤波器和方法来处理整个图像,上述方法只适合于处理特定的小区域。

下面介绍操作通道:将指定通道(B,G,R)的所有值置为0.(注:通过循环来处理Python数组的效率非常低,应该尽量避免这样的操作。使用数组索引可以高效地操作像素。像素操作是一个高代价的低效操作,特别是在视频数据处理时,会发现要等很久才能得到结果。可用索引(indexing)来解决该问题)

以下代码可将图像所有的G(绿色)值设为0

importcv2importnumpy as np

img= cv2.imread('flower.jpg')

img[:, :,1] =0

cv2.imshow('my image', img)

cv2.waitKey()

运行结果为:

通过NumPy数组的索引访问原始像素,还可设定感兴趣区域(Region Of Interest, ROI)。一旦设定了该区域,就可以执行许多操作,例如,将该区域与变量绑定,然后设定第二个区域,并将第一个区域的值分配给第二个区域(将图像的一部分拷贝到该图像的另一个位置):

importcv2importnumpy as np

img= cv2.imread('flower.jpg')

roi= img[0:100, 0:100]

img[100:200, 100:200] =roi # 此处需考虑所用图像的尺寸,不能超过,并确保两个区域的大小一样

cv2.imshow('my image', img)

cv2.waitKey()

运行结果为:

此外,还可使用numpy.array来获得图像其他属性。

shape:NumPy返回包含宽度、高度和通道数(如果图像是彩色的)数组,这在调试图像类型时很有用;如果图像是单色或灰度的,将不包含通道值;

size:该属性是指图像像素的大小;

datatype:该属性会得到图像的数据类型(通常为一个无符号整数类型的变量和该类型占的位数,比如unit8类型)

importcv2importnumpy as np

img= cv2.imread('flower.jpg')print(img.shape)print(img.size)print(img.dtype)

运行结果为:

(220, 252, 3)

166320

uint8

3.视频文件的读/写

OpenCV提供了VideoCapture类和VideoWriter类来支持各种格式的视频文件。支持的格式类型会因系统的不同而变化,但应该都支持AVI格式。在到达视频文件末尾之前,VideoCapture类可通过read()函数来获取新的帧,每帧都是一幅基于BGR格式的图像。

可将一幅图像传递给VideoWriter类的write()函数,该函数会将这幅图像加到VideoWriter类所指向的文件中。

如下示例读取AVI文件的帧,并采用YUV颜色编码将其写入另一帧中:

importcv2

videoCapture= cv2.VideoCapture('myvideo.avi')

fps=videoCapture.get(cv2.CAP_PROP_FPS)

size=(int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))

videoWriter= cv2.VideoWriter('MyOutputVid.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)

success, frame=videoCapture.read()whilesuccess: # 循环直到所有帧结束

videoWriter.write(frame)

success, frame= videoCapture.read()

要特别注意:必须要为VideoWriter类的构造函数指定视频文件名,这个文件名对应的文件若存在,会被覆盖。也必须指定视频编解码器。编解码器的可用性根据系统不同而不同。下面是一些常用选项:

cv2.VideoWriter_force('I', '4', '2', '0'):该选项是一个未压缩的YUV颜色编码,是4:2:0色度子采样。这种编码有很好的兼容性,但会产生较大文件,文件扩展名为.avi。

cv2.VideoWriter_force('P', 'I', 'M', '1'):该选项是MPEG-1编码类型,文件扩展名为.avi。

cv2.VideoWriter_force('X', 'V', 'I', 'D'):该选项是MPEG-4编码类型,如果希望得到的视频大小为平均值,推荐使用此选项,文件扩展名为.avi。

cv2.VideoWriter_force('T', 'H', 'E', 'O'):该选项是Ogg Vorbis,文件扩展名应为.ogv。

cv2.VideoWriter_force('F', 'L', 'V', '1'):该选项是一个Flash视频,文件扩展名应为.flv。

帧速率和帧大小也必须要指定,因为需要从另一个视频文件复制视频帧,这些属性可以通过VideoCapture类的get()函数得到。

4. 捕获摄像头的帧

VideoCapture类可以获得摄像头的帧流。但对摄像头而言,通常不是用视频的文件名来构造VideoCapture类,而是需要传递摄像头的设备索引(device index)。

下面的例子会捕获摄像头10秒的视频信息,并将其写入一个AVI文件中:

importcv2

cameraCapture=cv2.VideoCapture(0)

fps= 30size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))

videoWriter= cv2.VideoWriter('MyOutputVid.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)

success, frame=cameraCapture.read()

numFramesRemaining= 10 * fps - 1

while success and numFramesRemaining >0:

videoWriter.write(frame)

success, frame=cameraCapture.read()

numFramesRemaining-= 1cameraCapture.release()

然而,VideoCapture类的get()方法不能反悔摄像头帧速率的准确值,它总是返回0。

为了针对摄像头创建合适的VideoWriter类,要么对帧速率做出假设,要么使用计时器来测量。摄像头的数量和顺序由系统决定,但OpenCV没有提供任何查询摄像头数量和属性的方法。如果使用无效索引构造了VideoCapture类,就不会得到帧,VideoCapture的read()函数会返回(false, None)。为了不让read()函数从没有正确打开的VideoCapture类中获取数据,可在执行该函数之后使用VideoCapture.isOpened方法做一个判断,该方法返回一个Boolean值。

当需要同步一组摄像头或一个多头摄像头(例如立体摄像头或Kinect)时,read()方法就不再适合了,可用grab()和retrive()方法代替它。对于一组摄像头,可以使用以下代码:

success0 =cameraCapture0.grab()

success1=cameraCapture1.grab()if success0 andsuccess1:

frame0=cameraCapture0.retrive()

frame1= cameraCapture1.retrive()

5. 在窗口显示图像

用imshow()函数实现显示图像的操作。imshow()函数有两个参数:显示图像的帧名字以及要显示的图像本身。

importcv2importnumpy as np

img= cv2.imread('flower.jpg')

cv2.imshow('my image', img)

cv2.waitKey()

cv2.destroyAllWindows() # 释放由OpenCV创建的所有窗口

6. 在窗口显示摄像头帧

OpenCV的namedWindow()、imshow()和DestoryWindow()函数允许指定窗口名来创建、显示和销毁(destroy)窗口。此外,任何窗口都可以通过waitKey()函数来获取键盘输入,通过setMouseCallback()函数来获取鼠标输入。以下代码可实时显示摄像头帧:

importcv2

clicked=FalsedefonMouse(event, x, y, flags, param):globalclickedif event ==cv2.EVENT_LBUTTONUP:

clicked=True

cameraCapture=cv2.VideoCapture(0)

cv2.namedWindow('MyWindow')

cv2.setMouseCallback('MyWindow', onMouse)print('showing camera feed. Click window or press any key to stop.')

success, frame=cameraCapture.read()while success and cv2.waitKey(1) == -1 and notclicked:

cv2.imshow('MyWindow', frame)

success, frame= cameraCapture.read()

cv2.destroyWindow('MyWindow')

cameraCapture.release()

waitKey()的参数为等待键盘触发的时间,单位为毫秒,其返回值为-1(表示没有键被按下)或ASCII码。另外,Python提供了一个标准函数ord(),该函数可以将字符转换为ASCII码。(注:在一些系统中,waitKey()的返回值可能比ASCII码的值更大(在Linux系统中,如果OpenCV使用GTK作为后端的GUI库,就会出现bug),在所有系统中,可以通过读取返回值的最后一个字节来保证肢体去ASCII码,代码为:

keycode = cv2.waitkey(1)

if keycode != -1:

keycode &= 0xff )

OpenCV的窗口函数和waitKey()函数相互依赖。OpenCV的窗口只有在调用waitKey()函数时才会更新,waitKey()函数只有在OpenCV窗口成为活动窗口时,才能捕获输入信息。

鼠标回调函数setMouseCallback()有5个参数,param是可选参数,它是setMouseCallback()函数的第三个参数,默认情况下,该参数是0.回调时间参数可以取如下的值,它们分别对应不同的鼠标事件。

cv2.EVENT_MOUSEMOVE:该事件对应鼠标移动

cv2.EVENT_LBUTTONDOWN:该事件对应鼠标左键按下

cv2.EVENT_RBUTTONDOWN:该事件对应鼠标右键按下

cv2.EVENT_MBUTTONDOWN:该事件对应鼠标中间键按下

cv2.EVENT_LBUTTONUP:该事件对应鼠标左键松开

cv2.EVENT_RBUTTONUP:该事件对应鼠标右键松开

cv2.EVENT_MBUTTONUP:该事件对应鼠标中间键松开

cv2.EVENT_LBUTTONDBLCLK:该事件对应双击鼠标左键

cv2.EVENT_RBUTTONDBLCLK:该事件对应双击鼠标右键

cv2.EVENT_MBUTTONDBLCLK:该事件随影双击鼠标中间键

鼠标回调的标志参数可能是以下事件的按位组合:

cv2.EVENT_FLAG_LBUTTON:该事件对应按下鼠标左键

cv2.EVENT_FLAG_RBUTTON:该事件对应按下鼠标右键

cv2.EVENT_FLAG_MBUTTON:该事件对应按下鼠标中间键

cv2.EVENT_FLAG_CTRLKEY:该事件对应按下Ctrl键

cv2.EVENT_FLAG_SHIFTKEY:该事件对应按下Shift键

cv2.EVENT_FLAG_ALTKEY:该事件对应按下Alt键

opencv3计算机视觉python百度云_OpenCV3计算机视觉Python语言实现笔记(二)相关推荐

  1. 前锋python百度云_关于python:使用索引在pandas DataFrame中设置特定单元格的值

    我创建了一个熊猫数据框架 df = DataFrame(index=['A','B','C'], columns=['x','y']) 得到了这个 x    y A  NaN  NaN B  NaN ...

  2. 3台云腾讯云开始hadoop学习之路笔记二

    3台云腾讯云开始hadoop学习之路笔记二(接上) 大三党开始学习hadoop之路了,菜鸟学习hadoop,有啥错误请大佬指教.由于自己电脑配置不够,只能买3台腾讯云服务器来学习了.以下笔记都是记录我 ...

  3. python百度云资源-Python开发视频百度云分享

    原标题:Python开发视频百度云分享 Python有很好的3D渲染库和游戏开发框架,有很多使用Python开发的游戏,如迪斯尼卡通城.黑暗之刃.常用PyGame.Pykyra等和一个PyWeek的比 ...

  4. python 百度云不限速_百度云不限速插件内置十几种网盘搜索!

    大家好,欢迎来到好软分享!度盘不限速,网盘搜索这种关键字大家不陌生吧,今天介绍一个厉害的神器,可以把这两个完美集合在一起,完爆其他任何软件 下面这个软件不陌生吧,目前为止还是最好用的百度云不限速工具, ...

  5. python 百度云搜索引擎入口_2016最新百度云网盘搜索引擎源码,附带Python爬虫+PHP网站+Xunsearch搜索引擎...

    源码简介 : 适用范围:百度云网盘 搜索引擎 源码,百度 搜索引擎 源码,网盘搜索 爬虫 源码 演示地址:(以截图为准) 运行环境:PHP.MYSQL 其他说明:分享的是一款 搜索引擎 源码,百度云盘 ...

  6. python百度云ocr文字识别软件_基于百度云的OCR识别(Python)

    2019年7月3日早上,在百度AI开发者大会上,一个来自山西的青年,将一瓶矿泉水浇在了同样来自山西的李彦宏身上. 可以回顾一下 https://b23.tv/av57665929/p1 ,着实让人一惊 ...

  7. appium python自动测试 百度网盘_S35 移动App Appium自动化测试教程Appium+Python 百度云...

    Python视频教程名称:移动App Appium自动化测试教程Appium+Python  Python视频教程 [IT视频教程网] it教程 ( l  w1 F: L" `, v 2 c ...

  8. python 百度云api_Python——调用百度云API实现图文识别

    这是奔跑的键盘侠的第117篇文章 前几天写的一篇<按键精灵二三事系列第九篇--图文识别+发邮件>,有小伙伴留言说,可以直接调用百度云平台AI的OCR图文识别接口,不用自己单独做字库.于是就 ...

  9. 百度云批量离线python程序

    有时下载一些资源时很慢,无意中发现百度云可以离线下载,利用这一功能可以将文件存到云盘里,这样再下载就快了, 有时要离线的资源多,一个个来太费手,就想能不能批量离线,可惜人家并没有提供这个功能. 曾看到 ...

最新文章

  1. linux ftp 记录,linux FTP vsftpd
  2. 「镁客·请讲」快仓杨威:赋予仓库灵魂,让智能仓库系统自我进化和迭代
  3. rabbitmq优先级队列
  4. MVC %%与%=%与区别
  5. 构建创业公司突击小团队
  6. 测试驱动javascript开发 -- 4.测试驱动开发过程(下)
  7. 利用 Sql 实现数据透视表功能
  8. 这么奇葩搞笑的代码注释你见过吗
  9. 数据结构(6)二叉树
  10. UART协议概述与实现
  11. 深入理解jQuery中的Deferred
  12. CentOS - thin web server for Ruby(centos下安装thin,运行rails)
  13. 深度神经网络 轻量化_正则化对深度神经网络的影响
  14. 如何删除“无法删除文件,无法读取源文件或磁盘”文件
  15. 闪迪ssd plus固态硬盘不识别开卡成功,慧荣SM2246XT量产教程
  16. android mb kb单位转换,存储单位的换算(KB, MB, GB)
  17. sap 双计量单位_SAP 基本计量单位更改(转载)
  18. 用计算机怎么计算税率表,个税计算器2016年税率表公式
  19. 两数之和——python
  20. 多个 EXCEL 文件如何合并成一个文件

热门文章

  1. 如何规范地使用双向(inout)信号?
  2. 感恩节,感谢2022的转变,有在好好生活!
  3. ArcGIS基于C#.NET的二次开发
  4. 深入探索Linux虚拟化KVM-Qemu分析之CPU虚拟化
  5. Vue项目中常见问题(23)动态展示Floor组件
  6. 豆瓣电台WP7客户端 开发记录5
  7. matlab 区域生长算法生成二值图像边界区域
  8. 英语四六级翻译5:红包
  9. 14、Spark_RDD算子——CombineByKey_ReduceByKey转换
  10. php服务器环境配置