OpenCV3计算机视觉Python语言实现(二):处理文件、摄像头和图形用户界面
来源:互联网 发布:mac chrome flash 发热 编辑:程序博客网 时间:2024/06/11 23:29
- 2.1 基本I/O脚本
- 2.1.1 读/写图像文件
- 2.1.2 图像和原始字节之间的转换
- 2.1.3使用numpy.array()访问图像数据
- 2.1.4 视频文件的读写
- 2.1.5 捕获摄像头的帧
- 2.1.6 在窗口显示图像
- 2.1.7 在窗口显示摄像头帧
- 2.2 Cameo项目(人脸跟踪和图像处理)
- 2.3 Cameo-面向对象设计
安装
从网址:http://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv
下载opencv-whl文件
pip install wheelpip install ****.whl
大多数常用的OpenCV函数都在cv2模块中。可能会遇到其他基于cv2.cv模块的,这些都是传统版本,Python模块被成为cv2并不是表示该模块针对OpenCV2.x.x版本的,而是因为该模块引入了一个更好的API接口,它们采用了面向对象的编程方式,这与以前的cv模块有所不同,以前的cv模块更多采用面向过程化的编程方式。
2.1 基本的I/O脚本
2.1.1 读/写图像文件
OpenCV的imread()函数和imwrite()函数能支持各种静态图像文件。不管哪种格式,每个像素都会有一个值,但不同格式的表示像素的方式不同。如:通过numpy数组来创建一个黑色的正方形图像:
img=numpy.zeros((4,2),dtype=numpy.uint8)# dtype=uint8表示每个像素都由一个8位整数来表示,即每个像素值的范围是0~255
cv2.cvtColor函数:将该图像转换成BGR模式或者RGB模式
import cv2imgBGR=cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)print imgBGR,imgBGR.shape# img.shape():返回HxWxC.img为4行2列的二维数组。imgBGR.shape=(4,2,3),4页*2行*3列,其中每一个行的3列分别代表BGR值或BGR值.
取值img[0,0,0]或img[0][0]:第一个值表示y坐标或行,0表示顶部;第二个值表示像素的x坐标或者列;第三个值表示颜色通道
# 图像的读取、显示、保存import cv2img=cv2.imread('lena.jpg')# 读取第二个参数表示以什么方式读入,将图像以灰度图像读入:cv2.imread('./lena.jpg',cv2.IMREAD_GRAYSCALE)第二个参数省略时,默认Opencv以BGR的格式读入cv2.imshow('lena_img',img)cv2.waitKey(0)# cv2.waitKey(0)是一个键盘绑定函数。需要指出的是它的时间尺度是毫秒级。函数等待特定的几毫秒,看是否有键盘输入。特定的几毫秒之内,如果按下任意键,这个函数会返回按键的ASCII码,程序会继续运行。如果没有键盘输入,返回为-1,如果我们设置这个函数的参数为0,那么会无限期的等待键盘输入。它也可以被用来检测特定键是都被按下。cv2.destoryAllWindows()# 关闭所有打开的窗口。也可以通过cv2.destoryWindows(windowsName)来关闭指定的窗口cv2.imwrite('lena2.png',img)# imwrite()要求图像为BGR或者灰度格式
2.1.2 图像和原始字节之间的转换:bytearray()函数
若一幅图像的通道有8位,则可将其显示转换成标准的一维Python bytearray格式:
import numpy as npbyteArray=bytearray(image)print len(byteArray) # 输出为HxWxC# 由字节转换成图像grayImage=np.array(byteArray).reshape(height,width)bgrImage=np.array(byteArray).reshape(height,width,3)# 随机生成字节import osrandomByteArray=bytearray(os.urandom(120000))flatNumpyArray=numpy.array(randomByteArray) # OpenCV图像是.array类型的二维或者三维数组,因此转换成array"bgrImage=flatNumpyArray.reshape(200,200,3)cv2.imshow("bgrImage",bgrImage)
2.1.3使用numpy.array()访问图像数据
访问数组中特定位置的值使用np.array()提供的item(),设置特定位置的值:itemset()
import cv2import numpy as nplenaImage = cv2.imread('lena.jpg')print lenaImage.item(150, 120, 0)// 访问特定位置lenaImage.itemset((150, 120, 0), 255) // 设置特定位置的值
通过循环处理数组的效率很低,采用索引的方式来解决这个问题:
import cv2import numpy as npimg = cv2.imread('lena.jpg') img[:,:,1]=0 img[:,:,1] = 0 // 将所有的G通道设置为0img[0:100,0:100,:] // 得到图像从左上角开始100*100的区域三个通道值img[0,0]=[0,0,0] // 将黑色BGR值赋给图像第0行第0列的三通道值
其他属性
print img.shape // 返回图像H,W,C的数组print img.size // 返回图像像素的大小print img.dtype // 得到图像的数据类型(通常为一个无符号整数类型的变量和该类型占的位数,比如uint8)
2.1.4 视频文件的读写
OpenCV提供了VideoCapture和VideoWriter类来支持各种视频的读写。在达到视频文件末尾之前,VideoCapture都会通过read()来获取新的一帧,每一帧都是基于BGR格式的图像;
可将一幅图像传递给VideoWriter类的write()函数,该函数会将这副图像加到VideoWriter类所指向的文件。
import cv2videoCapture = cv2.VideoCapture('meipai.mp4')fps = videoCapture.get(cv2.CAP_PROP_FPS) # 帧速率,fps帧/秒size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), \ int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))print size # (854,480)注意此时的size为WxHvideoWriter = cv2.VideoWriter('meipai.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)success, frame = videoCapture.read()print frame.shape # (480,854,3) 此时为读取到的每一张图片大小HxWxCwhile success: # success为bool型,当读到末尾的时候为空 videoWriter.write(frame) success, frame = videoCapture.read()
videoWriter类的构造函数需要指定视频编解码器。编解码器根据系统的不同而不同,一下是常用的一些选项:
- cv2.VideoWriter_fourcc('I','4','2','0'):该选项是一个未压缩的YUV颜色编码,是4:2:0色度子采样。这种编码有很好的兼容性,但会产生较大的文件,扩展名为avi- cv2.VideoWriter_fourcc('P','I','M','1'):该选项是MPEG-1编码类型,扩展名为avi- cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'):MPEG-4编码,如果希望得到的视频大小为平均值,推荐使用此选项,扩展名avi- cv2.VideoWriter_fourcc('T', 'H', 'E', 'O'):该选项是Ogg Vorbis,扩展名是avi- cv2.VideoWriter_fourcc('F', 'L', 'V', '1'):该选项是一个Flash视频,扩展名为.flv
2.1.5 捕获摄像头的帧
import cv2cameraCapture = cv2.VideoCapture(0)size = (int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), \ int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))fps = 30 # 假定帧速率为30videoWriter = cv2.VideoWriter("MyOutputVideo.avi", \ cv2.VideoWriter_fourcc("I", "4", "2", "0"), fps, size)success, frame = cameraCapture.read()numFrameRemaining = 10 * fps - 1while success and numFrameRemaining > 0: videoWriter.write(frame) success, frame = cameraCapture.read() numFrameRemaining -= 1cameraCapture.release()
2.1.6 在窗口显示图像
2.1.7 在窗口显示摄像头帧
import cv2clicked = Falsedef onMouse(event, x, y, flags, param): global clicked if event == cv2.EVENT_LBUTTONUP: clicked = TruecameraCapture = 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 not clicked and cv2.waitKey(1) == -1:#没达到停止条件时 cv2.imshow("MyWindow", frame) success, frame = cameraCapture.read()cv2.destroyAllWindows()cameraCapture.release()
- cv2.waitKey():获取键盘输入,参数为等待键触发的时间,单位毫秒,其返回值为-1(表示没有被键盘按下)或ASCII码。
- setMouseCallback()获取鼠标输入
opencv的窗口函数和waitKey函数相互以阿里。Opencv的窗口只有在调用waitKey函数时才会更新,waitkey函数只有在opencv窗口成为活动窗口时才能捕获输入信息。
在一些系统中,waitKey()的返回值可能比ASCII码的值更大(在Linux系统中,如果Opencv使用GTK作为后端的GUI库,就会出现一个众所周知的bug
在所有的系统中,可以通过读取返回值的最后一个字节来保证只提取ASCII码,具体代码如下:
keycode = cv2.waitKey(1)if keycode != -1: keycode &= 0xFF
2.2-2.3 cameo项目(人脸跟踪和图像处理)
1.manager.py
manager.py# -*-coding:utf-8-*-import cv2from cv2 import *import numpyimport timeclass CaptureManager(object): def __init__(self, capture, previewWindowManager=None, \ shouldMirrorPreview=False): self.previewWindowManager = previewWindowManager self.shouldMirrorPreview = shouldMirrorPreview # 注意大多数成员(member)变量为非公有变量,这类变量名前会加一个下划线进行标识。 self._capture = capture self._channel = 0 self._enteredFrame = False self._frame = None self._imageFilename = None self._videoFilename = None self._videoEncoding = None self._videoWriter = None self._startTime = None self._framesElapsed = long(0) self._fpsEstimate = None # 关于@符号的含义可以参考链接:https://www.zhihu.com/question/26930016 @property def channel(self): return self._channel @channel.setter def channel(self, value): if self._channel != value: self._channel = value self._frame = None @property def frame(self): if self._enteredFrame and self._frame is None: _, self._frame = self._capture.retrieve() return self._frame @property def isWritingImage(self): return self._imageFilename is not None @property def isWritingVideo(self): return self._videoFilename is not None def enterFrame(self): """Capture the next frame,if any.""" # But first ,check that any previous frame was exited. assert not self._enteredFrame, 'previous enteredFrame() had no matching exitFrame()' if self._capture is not None: self._enteredFrame = self._capture.retrieve() def exitFrame(self): """Draw to the window,write to files,Release the frame.""" # Check whether ant grabbed frame is retrievable. # The getter may retrieve and cache the frame if self._frame is None: self._enteredFrame = False return # Update the FPS estimate and related variables if self._framesElapsed == 0: self._startTime = time.time() else: timeElapsed = time.time() - self._startTime self._fpsEstimate = int(self._framesElapsed / timeElapsed) self._framesElapsed += 1 # Draw to the Window,if any. if self.previewWindowManager is not None: if self.shouldMirrorPreview: mirroredFrame = numpy.fliplr(self._frame).copy() self.previewWindowManager.show(mirroredFrame) else: self.previewWindowManager.show(self._frame) # Write to the image file,if any. if self.isWritingImage: cv2.imwrite(self._imageFilename, self._frame) self._imageFilename = None # Write to the video file,if any. self._writeVideoFrame() # Release the Frame self._frame = None self._enteredFrame = False def writeImage(self, filename): """write the next exited frame to an image frame""" self._imageFilename = filename def startWritingVideo(self, filename, encoding=cv2.VideoWriter_fourcc("I", "4", "2", "0")): """start writing exited frames to a video file""" self._videoFilename = filename self._videoEncoding = encoding print self._videoEncoding def stopWritingVideo(self): """Stop writing exited frames to a video file""" self._imageFilename = None self._videoEncoding = None self._videoWriter = None def _writeVideoFrame(self): if not self.isWritingVideo: return if self._videoWriter is None: fps = self._capture.get(cv2.CAP_PROP_FPS) if fps == 0.0: # the capture fps is unknow ,so ues an estimate. if self._framesElapsed < 20: # wait until more frames elapse so that the estimate is stable return else: fps = self._fpsEstimate size = (int(self._capture.get(cv2.CAP_PROP_FRAME_WIDTH)), \ int(self._capture.get(cv2.CAP_PROP_FRAME_HEIGHT))) # self._videoWriter = cv2.VideoWriter(self._videoFilename, self._videoEncoding, fps, size) print "self._videoEncoding:",self._videoEncoding self._videoWriter = cv2.VideoWriter(self._videoFilename, self._videoEncoding, fps, size) print self._frame self._videoWriter.write(self._frame)class WindowManager(object): def __init__(self, windowName, keypressCallback=None): self.keypressCallback = keypressCallback self._windowName = windowName self._isWindowCreated = False @property def isWindowCreated(self): return self._isWindowCreated def createdWindow(self): cv2.namedWindow(self._windowName) self._isWindowCreated = True def show(self, frame): cv2.imshow(self._windowName, frame) # cv2.waitKey(1) def destroyWindow(self): cv2.destroyWindow(self._windowName) self._isWindowCreated = False def processEvents(self): keycode = cv2.waitKey(1) if self.keypressCallback is not None and keycode != -1: # Discard any non-ASCII info encoded by GTK keycode &= 0xFF self.keypressCallback(keycode)
2.cameo.py
import cv2from managers import WindowManager, CaptureManagerimport filtersclass Cameo(object): def __init__(self): self._windowManger = WindowManager('Cameo', self.onKeypress) self._captureManger = CaptureManager(cv2.VideoCapture(0), self._windowManger, True) self._curveFilter=filters.BlurFilter() def run(self): """Run the main loop""" self._windowManger.createdWindow() while self._windowManger.isWindowCreated: self._captureManger.enterFrame() frame = self._captureManger.frame filters.strokeEdges(frame,frame) self._curveFilter.apply(frame,frame) self._captureManger.exitFrame() self._windowManger.processEvents() def onKeypress(self, keycode): """Handle a keypress. space -> Take a screenshot tab -> Start/stop recoding a screenshot escape -> Quit """ if keycode == 32: # space self._captureManger.writeImage("./screenshot.png") elif keycode == 9: # tab if not self._captureManger.isWritingVideo: self._captureManger.startWritingVideo('./screenshot.avi') else: self._captureManger.stopWritingVideo() elif keycode == 27: # escape self._windowManger.destroyWindow()if __name__ == '__main__': Cameo().run()
这里出现一个问题,录制的视频大小不为0,但是时长总是0.不知道是什么原因?每一帧都被后一帧覆盖掉了?还不懂,还望懂的小伙伴不吝赐教。
- OpenCV3计算机视觉Python语言实现(二):处理文件、摄像头和图形用户界面
- 《OpenCV3 计算机视觉 Python语言实现》——处理文件、摄像头和图形用户界面
- OpenCV3计算机视觉Python语言实现(三):使用OpenCV3处理图像
- opencv处理文件、摄像头和图形用户界面
- opencv3计算机视觉Python语言实现(原书第二版)第三章3.6节缺少BGRPortraCurveFilter()函数
- GUI图形用户界面(二)
- OpenCV3 python语言实现(1)
- 计算机视觉(二)
- 《opencv3编程入门》之一:图像处理、计算机视觉与opencv
- 【python下使用OpenCV实现计算机视觉读书笔记4】保存摄像头视频
- OpenCV 3计算机视觉:Python语言实现(原书第2版) pdf+项目源代码
- OpenCV 3计算机视觉:Python语言实现(原书第2版) pdf+项目源代码
- OpenCV 3计算机视觉 Python语言实现(第2版)(含示例代码)
- Python视觉处理(二)线检测
- python 实现GUI(图形用户界面)编程
- 计算机视觉,计算机图形学和数字图像处理
- Mahotas(Python 计算机视觉、图像处理库)安装
- Python计算机视觉Learning(二)-- Matplotlib类库
- $(document).ready(function(){}) 和$(function(){})的区别
- 将文本框中的数字转化为大写
- UVA 12096 The SetStack Computer STL集合集合操作
- SSM的Web程序执行过程(Spring SpringMVC Mybatis)
- Spark Streaming应用与实战全攻略
- OpenCV3计算机视觉Python语言实现(二):处理文件、摄像头和图形用户界面
- 一种Android分包策略推荐
- dubbo总结(1)——linux安装dubbo管理控制台
- EnableWindow(): 使某个控件或窗口可用
- 变量与零值的比较
- Round 2 A
- C++排序算法之位图法排序
- 一元加和减操作符
- shell下的第一个编程(不一样的1到100累加)