• opencv模块学习


    一、简介

    '''
    分辨率(resolution,港台称之为解析度)就是屏幕图像的精密度,是指显示器所能显示的像素的多少。由于屏幕上的点、线和面都是由像素组成的,显示器可显示的像素越多,画面就越精细,同样的屏幕区域内能显示的信息也越多,所以分辨率是个非常重要的性能指标之一。可以把整个图像想象成是一个大型的棋盘,而分辨率的表示方式就是所有经线和纬线交叉点的数目。
    1、图象分辨率(PPI)
    图像分辨率(ImageResolution):指图像中存储的信息量。这种分辨率有多种衡量方法,典型的是以每英寸的像素数(PPI,pixelperinch)来衡量;当然也有以每厘米的像素数(PPC,pixelpercentimeter)来衡量的。图像分辨率决定了图像输出的质量,而图像分辨率和图象尺寸(高宽)的值一起决定文件的大小,且该值越大图形文件所占用的磁盘空间也就越多。图像分辨率以比例关系影响着文件的大小,即文件大小与其图像分辨率的平方成正比。如果保持图像尺寸不变,将图像分辨率提高一倍,则其文件大小增大为原来的四倍。
    2、扫描分辨率(SPI)
    扫描分辨率:指在扫描一幅图像之前所设定的分辨率,它将影响所生成的图像文件的质量和使用性能,它决定图像将以何种方式显示或打印。如果扫描图像用于640×480像素的屏幕显示,则扫描分辨率不必大于一般显示器屏幕的设备分辨率,即一般不超过120DPI。但大多数情况下,扫描图像是为了在高分辨率的设备中输出。如果图像扫描分辨率过低,会导致输出的效果非常粗糙。反之,如果扫描分辨率过高,则数字图像中会产生超过打印所需要的信息,不但减慢打印速度,而且在打印输出时会使图像色调的细微过渡丢失。一般情况下,图像分辨率应该是网屏分辨率的2倍,这是目前中国大多数输出中心和印刷厂都采用的标准。然而实际上,图像分辨率应该是网幕频率的1.5倍,关于这个问题,恐怕会有争议,而具体到不同的图像本身,情况也确实各不相同。要了解详细内容,请看《网屏角度及输出分辨率》。可能有很多朋友没有明白这其中是如何计算的,下面笔者就简单的讲解一下PPI的计算方法。首先,我们先了解一下什么叫PPI,PPI是英文Pixelsperinch的缩写,意思就是每英寸所拥有的像素(Pixel)数目,搞清楚了PPI是什么意思,我们就能很容易理解PPI的计算方式了,我们需要首先算出手机屏幕的对角线等效像素,然后除以对角线(我们平常所说的手机屏幕尺寸就是说的手机屏幕对角线的长度),就可以得到PPI了。准确的计算公示大家可以参照下图。比较有意思的是,根据公式计算出来的iPhone4的PPI为330,要比苹果官方公布的326要高一点点。
    3、网屏分辨率(LPI)
    网屏分辨率(ScreenResolution):又称网幕频率(是印刷术语),指的是印刷图像所用的网屏的每英寸的网线数(即挂网网线数),以(LPI)来表示。例如,150LPI是指每英寸加有150条网线。
    4、设备分辨率
    设备分辨率(DeviceResolution):又称输出分辨率,指的是各类输出设备每英寸上可产生的点数,如显示器、喷墨打印机、激光打印机、绘图仪的分辨率。这种分辨率通过DPI来衡量,目前,PC显示器的设备分辨率在60至120DPI之间。而打印设备的分辨率则在360至2400DPI之间。
    5、图像的位分辨率
    图像的位分辨率(BitResolution):又称位深,是用来衡量每个像素储存信息的位数。这种分辨率决定可以标记为多少种色彩等级的可能性。一般常见的有8位、16位、24位或32位色彩。有时我们也将位分辨率称为颜色深度。所谓“位”,实际上是指“2”的平方次数,8位即是2的八次方,也就是8个2相乘,等于256。所以,一幅8位色彩深度的图像,所能表现的色彩等级是256级。
    6、打印机的分辨率
    某台为360DPI,是指在用该打印机输出图像时,在每英寸打印纸上可以打印出360个表征图像输出效果的色点。表示打印机分辨率的这个数越大,表明图像输出的色点就越小,输出的图像效果就越精细。打印机色点的大小只同打印机的硬件工艺有关,而与要输出图像的分辨率无关。
    7、扫描仪的分辨率
    要从三个方面来确定:光学部分、硬件部分和软件部分。也就是说,扫描仪的分辨率等于其光学部件的分辨率加上其自身通过硬件及软件进行处理分析所得到的分辨率。光学分辨率是扫描仪的光学部件在每平方英寸面积内所能捕捉到的实际的光点数,是指扫描仪CCD的物理分辨率,也是扫描仪的真实分辨率,它的数值是由CCD的像素点除以扫描仪水平最大可扫尺寸得到的数值。分辨率为1200DPI的扫描仪,其光学部分的分辨率只占400~600DPI。扩充部分的分辨率,是通过计算机对图像进行分析,对空白部分进行科学填充所产生的(由硬件和软件所生成,这一过程也叫“插值”处理)。光学扫描与输出是一对一的,扫描到什么,输出的就是什么。经过计算机软硬件处理之后,输出的图像就会变得更逼真,分辨率会更高。目前市面上出售的扫描仪大都具有对分辨率的软、硬件扩充功能。有的扫描仪广告上写9600×9600DPI,这只是通过软件"插值"所得到的最大分辨率,并不是扫描仪真正光学分辨率。所以对扫描仪来讲,其分辨率有光学分辨率(或称光学解析度)和最大分辨率之说。我们说某台扫描仪的分辨率高达4800DPI(这个4800DPI是光学分辨率和软件差值处理的总和),是指用扫描仪输入图像时,在1平方英寸的扫描幅面上,可采集到4800×4800个像素点(Pixel)。1英寸见方的扫描区域,用4800DPI的分辨率扫描后生成的图像大小是4800Pixel×4800Pixel。在扫描图像时,扫描分辨率设得越高,生成的图像的效果就越精细,生成的图像文件也就越大,但插值成分也越多。关于扫描仪、打印机、显示器的分辨率对扫描仪、打印机及显示器等硬件设备来说,其分辨率用每英寸上可产生的点数即DPI(DotsPerInch)来度量。
    8、显示器的分辨率
    显示装置能有效辨别的最小的示值差。显示器的分辨率为80DPI,是指在显示器的有效显示范围内,显示器的显像设备可以在每英寸荧光屏上产生80个光点。举个例子来说,一台14英寸的显示器(荧光屏对角线长度为14英寸),其点距为0.28mm,那么:显示器分辨率=25.39956mm/inch÷0.28mm/Dot≈90DPI(1inch=2.539999918cm)。显示器出厂时一般并不标出表征显示器分辨率的DPI值,只给出点距,我们根据上述公式即可算出显示器的分辨率。根据我们算出的DPI值,我们进而可以推算出显示器可支持的最高显示模式。假设该14英寸显示器荧光屏有效显示范围的对角线长度为11.5英寸,因显示器的水平方向和垂直方向的显示比例为4:3,故可设有效显示范围水平宽度为4x英寸,垂直高度为3x英寸,根据数学上的勾股定理,可得x=11.5÷5=2.3英寸。所以有效显示范围宽度为2.3×4=9.2英寸,垂直高度为2.3×3=6.8英寸。最高显示模式约为:800(9.2×90)×600(6.8×90),这时是用一个点(Dot)表示一个像素(pixel)。上面主要讲述了扫描仪、打印机和显示器的设备分辨率。特别提醒:设备分辨率与用该设备处理的图像的分辨率是两个既有联系又有区别的概念。测量仪器方面的分辨率。
    9、数码相机的分辨率
    数码相机分辨率的高低决定了所拍摄的影像最终能够打印出高质量画面的大小,或在计算机显示器上所能够显示画面的大小。数码相机分辨率的高低,取决于相机中CCD(ChargeCoupledDevice:电荷耦合器件)芯片上像素的多少,像素越多,分辨率越高。由此可见,数码相机的最大分辨率也是由其生产工艺决定的,但用户可以调整到更低分辨率以减少照片占用的空间。就同类数码相机而言,最大分辨率越高,相机档次越高。但高分辨率的相机生成的数据文件很大,对加工、处理的计算机的速度、内存和硬盘的容量以及相应软件都有较高的要求。数码相机像素水平的高低与最终所能打印一定分辨率照片的尺寸,可用以下方法简单计算:假如彩色打印机的分辨率为NDPI,数码相机水平像素为M,最大可打印出的照片为M÷N英寸。比如,打印机的分辨率为300DPI,那么水平像素为3600的数码相机,其所摄的影像文件不作插值处理能够打印出的最大照片尺寸为12英寸(3600÷300)。很显然,要打印出尺寸越大的数码照片,就需要越高像素水平的数码相机。计算显示尺寸的方法与打印尺寸的方法相同。
    10、投影机的分辨率
    投影机的分辨率有两种常见的表示方式,一种是以电视线(TV线)的方式表示,另一种是以像素的方式表示。以电视线表示时,其分辨率的含义与电视相似,这种分辨率表示方式主要是为了匹配接入投影机的电视信号而提供的。以像素方式表示时通常表示为1024×768等形式,从某种意义上讲这种分辨率的限制是对输入投影机的VGA信号的行频及场频作一定要求。当VGA信号的行频或场频超过这个限制后,投影机就不能正常投显了。
    11、商业印刷领域的分辨率
    在商业印刷领域,分辨率以每英寸上等距离排列多少条网线即LPI(LinesPerInch)表示。在传统商业印刷制版过程中,制版时要在原始图像前加一个网屏,这一网屏由呈方格状的透明与不透明部分相等的网线构成。这些网线也就是光栅,其作用是切割光线解剖图像。由于光线具有衍射的物理特性,因此光线通过网线后,形成了反映原始图像影像变化的大小不同的点,这些点就是半色调点。一个半色调点最大不会超过一个网格的面积,网线越多,表现图像的层次越多,图像质量也就越好。因此商业印刷行业中采用了LPI表示分辨率。
    12、电视的分辨率
    在电视工业中,分辨率指的是在荧光屏等于像高的距离内人眼所能分辨的黑白条纹数,单位是电视线(TV线)。我们国家采用的电视标准是PAL制式,它规定每秒25帧,每帧625扫描行。由于采用了隔行扫描方式,625行扫描线分为奇数行和偶数行,这分别构成了每一帧的奇、偶两场,由于在每一帧中电子束都要从上面开始扫描,因此存在着电子束从终点回到起点的扫描逆程期,在这期间被消隐的扫描行是不可能分解图像的。扫描逆程期约占整个扫描时间的8%,因此625行中用于扫描图像的有效行数只有576行,由此推导出图像在垂直方向上的分辨率为576点。按现行4∶3宽高比的电视标准,图像在水平方向上的分辨率应为576×4/3=768点,这就得到了768×576这一常见的图像大小。另外,在计算机视频捕捉时,我们还会遇到遵循CCIR601标准的PAL制式图像尺寸,其大小为720×576。对于我们还能接触到的NTSC制式来讲,它规定每秒30帧,每帧525行,同样采用了隔行扫描方式,每一帧由两场组成,其图像大小是720×486。日本的D端子,采用了类似计算机的多针D型插接头,用来直接传输数字图像信号,根据传输数字信号的规格不同,D端子已经形成了一个系列的型号。目前有D1、D2、D3、D4、D5,系列序号越高,传输数据的规格越高。
    13、鼠标的分辨率
    鼠标的分辨率是指每移动一英寸能检测出的点数,分辨率越高,质量也就越高。以前鼠标的分辨率通常为100DPI,现在的鼠标分辨率从200DPI到1000DPI不等。高分辨率的鼠标通常用于制图和精确计算机绘图等。
    14、触摸屏的分辨率
    触摸屏的分辨率是指将屏幕分割成可识别的触点数目。通常用水平和垂直方向上的触点数目来表示,如32×32。有的人认为触摸屏的分辨率越高越好,其实并非如此,在选用触摸屏时应根据具体用途加以考虑。采用模拟量技术的触摸屏分辨率很高,可达到1024×1024,能胜任一些类似屏幕绘画和写字(手写识别)的工作。而在多数场合下,触摸技术的应用只是让人们用手触摸来选择软件设计的“按钮”,没有必要使用非常高的分辨率。例如在14英寸显示器上使用触摸屏时,显示区域的实际大小一般是25cm×18.5cm,一个分辨率为32×32的触摸屏就能把屏幕分割成1024个0.78cm×0.58cm(比一支香烟还细小)的触点。人的手指按压触摸屏的触点比香烟的直径大多了,所以这样一个触点就已经足够了。
    15、望远镜分辨率
    望远镜的分辨率,也可以说是光学透镜的分辨率。光具有波动性和粒子性,所以通过透镜汇聚的光线投射到感光元件上,如果两个像点距离很小,就会发生干涉,如右图。角度这个参数就是望远镜或者透镜的理论分辨率,一般用弧度表示。
    这个数值越小,也就是可以分辨的物体越细小,那么透镜的分辨率越高,这个角度与透镜的口径和所使用波长有关,理论计算可得最小分辨角:r=1.22λ/D,其中λ为观测波长,D为望远镜的口径,二者取同一单位时r的单位为弧度。对于目视观测,通常取λ为肉眼最敏感的550nm。这个数值是一个理论结果,实际上地面观测,受到气流,污染物,杂光等的影响也就达不到这个最好的效果,也就是分辨率要下降。对于人眼来讲,平均瞳孔直径7mm,有60角秒的分辨率,而对于口径116mm口径的小型望远镜,具有1角秒的分辨率。
    16、显微物镜的分辨率
    显微物镜的分辨率即物面上能分开的最短距离,由以下公式计算σ=0.61λ/NA其中σ为显微物镜分辨率,λ为光源波长,NA为显微物镜的数值孔径。
    17、显示器分辨率设置与疾病预防
    有研究显示,在800×600分辨率环境下工作的人,更有机会患上一些疾病,这与用手机打一天电话的效果是一样的。因此,有专家提示人们应将显示器分辨率设置为1024×768以上,这样可以挡住更多辐射。
    '''
    分辨率

    OpenCV安装
    pip install --upgrade setuptools
    pip install numpy Matplotlib
    pip install opencv-python

    二、定义
    三、结构分析

    和Python一样,当前的OpenCV也有两个大版本,OpenCV2和OpenCV3。相比OpenCV2,OpenCV3提供了更强的功能和更多方便的特性。不过考虑到和深度学习框架的兼容性,以及上手安装的难度,这部分先以2为主进行介绍。

    根据功能和需求的不同,OpenCV中的函数接口大体可以分为如下部分:

    '''
    1、core:核心模块,主要包含了OpenCV中最基本的结构(矩阵,点线和形状等),以及相关的基础运算/操作。
    2、imgproc:图像处理模块,包含和图像相关的基础功能(滤波,梯度,改变大小等),以及一些衍生的高级功能(图像分割,直方图,形态分析和边缘/直线提取等)。
    3、highgui:提供了用户界面和文件读取的基本函数,比如图像显示窗口的生成和控制,图像/视频文件的IO等。
    '''
    View Code

    如果不考虑视频应用,以上三个就是最核心和常用的模块了。针对视频和一些特别的视觉应用,OpenCV也提供了强劲的支持:

    '''
    1、video:用于视频分析的常用功能,比如光流法(Optical Flow)和目标跟踪等。
    2、calib3d:三维重建,立体视觉和相机标定等的相关功能。
    3、features2d:二维特征相关的功能,主要是一些不受专利保护的,商业友好的特征点检测和匹配等功能,比如ORB特征。
    4、object:目标检测模块,包含级联分类和Latent SVM
    5、ml:机器学习算法模块,包含一些视觉中最常用的传统机器学习算法。
    6、flann:最近邻算法库,Fast Library for Approximate Nearest Neighbors,用于在多维空间进行聚类和检索,经常和关键点匹配搭配使用。
    7、gpu:包含了一些gpu加速的接口,底层的加速是CUDA实现。
    8、photo:计算摄像学(Computational Photography)相关的接口,当然这只是个名字,其实只有图像修复和降噪而已。
    9、stitching:图像拼接模块,有了它可以自己生成全景照片。
    10、nonfree:受到专利保护的一些算法,其实就是SIFT和SURF。
    11、contrib:一些实验性质的算法,考虑在未来版本中加入的。
    12、legacy:字面是遗产,意思就是废弃的一些接口,保留是考虑到向下兼容。
    13、ocl:利用OpenCL并行加速的一些接口。
    14、superres:超分辨率模块,其实就是BTV-L1(Biliteral Total Variation – L1 regularization)算法
    15、viz:基础的3D渲染模块,其实底层就是著名的3D工具包VTK(Visualization Toolkit)。
    '''
    View Code

    四、范例分析

    1、存取图像:主要包含图像的读取、存储、图片模式的转换、格式的转换。

    #导入cv模块
    import cv2 as cv
    
    # 读取一张487x650分辨率的图像
    color_img1 = cv.imread('D:\picture\timg.jpg')
    print(color_img1.shape)            #(487, 650, 3)
    print(type(color_img))    #<type 'numpy.ndarray'>
    
    # 直接读取单通道灰度图
    color_img2 = cv.imread('D:\picture\timg.jpg',cv.IMREAD_GRAYSCALE)
    print(color_img2.shape)        #(487, 650)
    
    # 把单通道图片保存后,再读取,仍然是3通道,相当于把单通道值复制到3个通道保存
    cv.imwrite('D:\picture\stimg.jpg', color_img2)
    color_img3 = cv.imread('D:\picture\stimg.jpg')
    print(color_img3.shape)        #(487, 650, 3);stimg.jpg是灰色图。
    
    # cv2.IMWRITE_JPEG_QUALITY指定jpg质量,范围0到100,默认95,越高画质越好,文件越大
    cv.imwrite('D:\picture\sgtimg.jpg', color_img1, (cv.IMWRITE_JPEG_QUALITY, 80))
    
    # cv2.IMWRITE_PNG_COMPRESSION指定png质量,范围0到9,默认3,越高文件越小,画质越差
    cv.imwrite('D:\picture\sg.png', color_img1, (cv.IMWRITE_PNG_COMPRESSION, 5))
    View Code

    2、缩放,裁剪和补边:主要包括图片大小缩放(比例缩放、按指定值缩放)、局部裁剪、周边补色

    #导入cv模块
    import cv2 as cv
    
    # 读取一张原始图片
    img = cv.imread('D:\picture\timg.jpg')
    
    # 缩放成200x200的方形图像
    img_200x200 = cv.resize(img, (200, 200))
    
    # 不直接指定缩放后大小,通过fx和fy指定缩放比例,0.5则长宽都为原来一半
    # 等效于img_100x100 = cv2.resize(img, (100, 100)),注意指定大小的格式是(宽度,高度)
    # 插值方法默认是cv2.INTER_LINEAR,这里指定为最近邻插值
    img_100x100 = cv.resize(img_200x200, (0, 0), fx=0.5, fy=0.5,interpolation=cv.INTER_NEAREST)
    
    # 在上张图片的基础上,上下各贴50像素的黑边,生成300x300的图像
    img_200x100 = cv.copyMakeBorder(img_100x100, 50, 50, 0, 0,cv.BORDER_CONSTANT,value=(0, 0, 0))
    
    # 对照片中局部进行剪裁
    patch_img = img[220:550, -180:-50]
    cv.imwrite('img/cropped_img.jpg', patch_img)
    cv.imwrite('img/resized_200x200.jpg', img_200x200)
    cv.imwrite('img/resized_100x100.jpg', img_100x100)
    cv.imwrite('img/bordered_200x100.jpg', img_200x100)
    View Code

    3、色调,明暗,直方图和Gamma曲线:主要包含色度、饱和度、明暗的条件。

    import cv2 as cv
    img = cv.imread('D:\picture\timg.jpg')
    
    # 通过cv2.cvtColor把图像从BGR转换到HSV
    img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
    
    # H空间中,绿色比黄色的值高一点,所以给每个像素+15,黄色的树叶就会变绿
    turn_green_hsv = img_hsv.copy()
    turn_green_hsv[:, :, 0] = (turn_green_hsv[:, :, 0]+15) % 180
    turn_green_img = cv.cvtColor(turn_green_hsv, cv.COLOR_HSV2BGR)
    cv.imwrite('D:\picture\img\turn_green.jpg', turn_green_img)
    
    # 减小饱和度会让图像损失鲜艳,变得更灰
    colorless_hsv = img_hsv.copy()
    colorless_hsv[:, :, 1] = 0.5 * colorless_hsv[:, :, 1]
    colorless_img = cv.cvtColor(colorless_hsv, cv.COLOR_HSV2BGR)
    cv.imwrite('D:\picture\img\colorless.jpg', colorless_img)
    
    # 减小明度为原来一半
    darker_hsv = img_hsv.copy()
    darker_hsv[:, :, 2] = 0.5 * darker_hsv[:, :, 2]
    darker_img = cv.cvtColor(darker_hsv, cv.COLOR_HSV2BGR)
    cv.imwrite('D:\picture\img\darker.jpg', darker_img)
    View Code

    4、图像的仿射变换:主要包括缩放、旋转、剪切、翻转、平移,以及他们之间的组合

    #导入cv模块
    import cv2 as cv
    import numpy as np
    # =====================图像的仿射变换===============================
    # 仿射变换具体到图像中的应用,主要是对图像的缩放,旋转,剪切,翻转和平移的组合。
    
    # 读取一张原始照片
    img = cv.imread('D:\picture\src_400x600.jpg')
    
    # 沿着横纵轴放大1.6倍,然后平移(-150,-240),最后沿原图大小截取,等效于裁剪并放大
    M_crop_elephant = np.array([
    [1.6, 0, -150],
    [0, 1.6, -240]
    ], dtype=np.float32)
    
    img_elephant = cv.warpAffine(img, M_crop_elephant, (400, 600))
    cv.imwrite('D:\picture\img\lanka_elephant.jpg', img_elephant)
    
    # x轴的剪切变换,角度15°
    theta = 15 * np.pi / 180
    M_shear = np.array([
    [1, np.tan(theta), 0],
    [0, 1, 0]
    ], dtype=np.float32)
    
    img_sheared = cv.warpAffine(img, M_shear, (400, 600))
    cv.imwrite('D:\picture\img\lanka_safari_sheared.jpg', img_sheared)
    
    # 顺时针旋转,角度15°
    M_rotate = np.array([
    [np.cos(theta), -np.sin(theta), 0],
    [np.sin(theta), np.cos(theta), 0]
    ], dtype=np.float32)
    
    img_rotated = cv.warpAffine(img, M_rotate, (400, 600))
    cv.imwrite('D:\picture\img\lanka_safari_rotated.jpg', img_rotated)
    
    # 某种变换,具体旋转+缩放+旋转组合可以通过SVD分解理解
    M = np.array([
    [1, 1.5, -400],
    [0.5, 2, -100]
    ], dtype=np.float32)
    
    img_transformed = cv.warpAffine(img, M, (400, 600))
    cv.imwrite('D:\picture\img\lanka_safari_transformed.jpg', img_transformed)
    View Code

     5、基本绘图:可以在画面上绘制线段,圆,矩形和多边形等,还可以在图像上指定位置打印文字

    #coding=utf-8
    import cv2 as cv
    import numpy as np
    # 定义一块宽600,高400的画布,初始化为白色
    canvas = np.zeros((400, 600, 3), dtype=np.uint8) + 255
    
    # 画一条纵向的正中央的黑色分界线
    cv.line(canvas, (300, 0), (300, 399), (0, 0, 0), 2)
    
    # 画一条右半部份画面以150为界的横向分界线
    cv.line(canvas, (300, 149), (599, 149), (0, 0, 0), 2)
    
    # 左半部分的右下角画个红色的圆
    cv.circle(canvas, (200, 300), 75, (0, 0, 255), 5)
    
    # 左半部分的左下角画个蓝色的矩形
    cv.rectangle(canvas, (20, 240), (100, 360), (255, 0, 0), thickness=3)
    
    # 定义两个三角形,并执行内部绿色填充
    triangles = np.array([
    [(200, 240), (145, 333), (255, 333)],
    [(60, 180), (20, 237), (100, 237)]])
    cv.fillPoly(canvas, triangles, (0, 255, 0))
    
    # 画一个黄色五角星
    # 第一步通过旋转角度的办法求出五个顶点
    phi = 4 * np.pi / 5
    rotations = [[[np.cos(i * phi), -np.sin(i * phi)], [i * np.sin(phi), np.cos(i * phi)]] for i in range(1, 5)]
    pentagram = np.array([[[[0, -1]] + [np.dot(m, (0, -1)) for m in rotations]]], dtype=np.float)
    
    # 定义缩放倍数和平移向量把五角星画在左半部分画面的上方
    pentagram = np.round(pentagram * 80 + np.array([160, 120])).astype(np.int)
    
    # 将5个顶点作为多边形顶点连线,得到五角星
    cv.polylines(canvas, pentagram, True, (0, 255, 255), 9)
    
    # 按像素为间隔从左至右在画面右半部份的上方画出HSV空间的色调连续变化
    for x in range(302, 600):
        color_pixel = np.array([[[round(180*float(x-302)/298), 255, 255]]], dtype=np.uint8)
        line_color = [int(c) for c in cv.cvtColor(color_pixel, cv.COLOR_HSV2BGR)[0][0]]
        cv.line(canvas, (x, 0), (x, 147), line_color)
    
    # 如果定义圆的线宽大于半斤,则等效于画圆点,随机在画面右下角的框内生成坐标
    np.random.seed(42)
    n_pts = 30
    pts_x = np.random.randint(310, 590, n_pts)
    pts_y = np.random.randint(160, 390, n_pts)
    pts = zip(pts_x, pts_y)
    
    # 画出每个点,颜色随机
    for pt in pts:
        pt_color = [int(c) for c in np.random.randint(0, 255, 3)]
        cv.circle(canvas, pt, 3, pt_color, 5)
    
    # 在左半部分最上方打印文字
    cv.putText(canvas,
    'hostname just english',
    (5, 15),
    cv.FONT_HERSHEY_SIMPLEX,
    0.5,
    (0, 0, 0),
    1)
    cv.imshow('new', canvas)
    cv.waitKey()
    View Code

    6、相机功能:一个是VideoCapture,用于获取相机设备并捕获图像和视频,或是从文件中捕获。还有一个VideoWriter,用于生成视频。

      下面的代码会根据电脑摄像头捕捉到的信息,在img文件夹下生成一个save.avi的视频文件。

    #coding=utf-8
    #导入cv模块
    import time
    import cv2 as cv
    import os
    import sys
    
    interval = 1 # 捕获图像的间隔,单位:秒
    num_frames = 50 # 捕获图像的总帧数
    out_fps = 24 # 输出文件的帧
    # VideoCapture(0)表示打开默认的相机
    cap = cv.VideoCapture(0)
    # 获取捕获的分辨率
    size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),
            int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
    # 设置要保存视频的编码,分辨率和帧率
    video = cv.VideoWriter("D:\picture\img\save.avi",
                           cv.VideoWriter_fourcc('M', 'P', '4', '2'), # 视频编码格式参考 http://www.fourcc.org/codecs.php
                           out_fps,
                           size
    )
    # 对于一些低画质的摄像头,前面的帧可能不稳定,略过
    for i in range(42):
        cap.read()
    # 开始捕获,通过read()函数获取捕获的帧
    try:
        for i in range(num_frames):
            _, frame = cap.read()
            video.write(frame)
    # 如果希望把每一帧也存成文件,比如制作GIF,则允许下面的代码运行
    # filename = '{:0>6d}.png'.format(i)
    # cv.imwrite(filename, frame)
            print('Frame {} is captured.'.format(i))
            time.sleep(interval)
    except KeyboardInterrupt:
    # 捕获提前停止。方便后面使已经捕获好的部分视频可以顺利生成
        print('Stopped! {}/{} frames captured!'.format(i, num_frames))
    # 释放资源并写入视频文件
    video.release()
    cap.release()
    View Code

    7、视频文件功能:间隔读取视频文件中的每帧的图片。

    #coding=utf-8
    #导入cv模块
    import time,os,sys
    import cv2 as cv
    frame_path="D:\picture\img\frames"  # 存放视频截图的文件夹路径
    
    # 第二个输入参数是设定每隔多少帧截取一帧
    frame_interval = 1
    
    if not os.path.exists(frame_path):
        os.mkdir(frame_path)
    # 初始化一个VideoCapture对象
    cap = cv.VideoCapture()
    
    
    filepath = "D:\picture\img\save.avi"
    
    # VideoCapture::open函数可以从文件获取视频
    cap.open(filepath)
    
    # 获取视频帧数
    n_frames = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
    print(n_frames)
    # 同样为了避免视频头几帧质量低下,黑屏或者无关等
    for i in range(2):
        cap.read()
    
    for i in range(2,n_frames):  # 读取后面的帧数据
        ret, frame = cap.read()
        # 每隔frame_interval帧进行一次截屏操作
        if i % frame_interval == 0:
            imagepath = frame_path+'/video_test'+ str(i)+".jpg"
            print('导出 {}!'.format(imagepath))
            cv.imwrite(imagepath, frame)
    
    # 执行结束释放资源
    cap.release()
    View Code

    8、交互——播放图片:窗口播放图片、循环播放图片

    #coding=utf-8
    #导入cv模块
    import time,os,sys
    import cv2 as cv
    from itertools import cycle
    # =====================OpenCV窗口显示===============================
    img = cv.imread('D:\picture\img\test.jpg')
    cv.imshow('Window Title', img)
    cv.waitKey()
    # =====================OpenCV窗口循环===============================
    frame_path="D:\picture\img\frames"  # 图片的文件夹路径
    # 列出frames文件夹下的所有图片
    filenames = os.listdir(frame_path)
    
    # 通过itertools.cycle生成一个无限循环的迭代器,每次迭代都输出下一张图像对象
    img_iter = cycle([cv.imread(os.sep.join([frame_path, x])) for x in filenames])
    
    key = 0
    while key & 0xFF != 27:
        cv.imshow('window title', next(img_iter))
        key = cv.waitKey(500)  # cv.waitKey()参数不为零的时候则可以和循环结合产生动态画面
    View Code

    9、交互——鼠标事件:主要包括为窗口绑定鼠标事件的处理。

    #coding=utf-8
    #导入cv模块
    import time,os,sys
    import cv2
    from itertools import cycle
    
    # 定义鼠标事件回调函数
    def on_mouse(event, x, y, flags, param):
    
        # 鼠标左键按下,抬起,双击
        if event == cv2.EVENT_LBUTTONDOWN:
            print('左键按下 ({}, {})'.format(x, y))
        elif event == cv2.EVENT_LBUTTONUP:
            print('左键弹起 ({}, {})'.format(x, y))
        elif event == cv2.EVENT_LBUTTONDBLCLK:
            print('左键双击 ({}, {})'.format(x, y))
    
        # 鼠标右键按下,抬起,双击
        elif event == cv2.EVENT_RBUTTONDOWN:
            print('右键按下 ({}, {})'.format(x, y))
        elif event == cv2.EVENT_RBUTTONUP:
            print('右键弹起 ({}, {})'.format(x, y))
        elif event == cv2.EVENT_RBUTTONDBLCLK:
            print('右键双击 ({}, {})'.format(x, y))
    
        # 鼠标中/滚轮键(如果有的话)按下,抬起,双击
        elif event == cv2.EVENT_MBUTTONDOWN:
            print('中间键按下 ({}, {})'.format(x, y))
        elif event == cv2.EVENT_MBUTTONUP:
            print('中间键弹起 ({}, {})'.format(x, y))
        elif event == cv2.EVENT_MBUTTONDBLCLK:
            print('中间键双击 ({}, {})'.format(x, y))
    
        # 鼠标移动
        elif event == cv2.EVENT_MOUSEMOVE:
            print('移动到 ({}, {})'.format(x, y))
    
    # 为指定的窗口绑定自定义的回调函数
    cv2.namedWindow('window title')
    cv2.setMouseCallback('window title', on_mouse)  # 第一个参数为要绑定的窗口名称,第二个参数为要绑定的鼠标事件
    cv2.waitKey()
    View Code

    五、功能运用
    六、小结

  • 相关阅读:
    Ubuntu 16.04出现:Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    Apache Shiro教程
    Ubuntu 16.04安装磁盘占用分析器:ncdu
    Mac 10.12为打开终端增加快捷键(转)
    Mac下的裁剪快捷键
    Ubuntu 16.04安装WebStorm
    Ubuntu 16.04出现:"Failed to start /etc/rc.local Compatibility"的问题解决思路
    Ubuntu 16.04安装ntopng流量监控软件
    浅谈命令查询职责分离(CQRS)模式
    GC是如何回收SoftReference对象的
  • 原文地址:https://www.cnblogs.com/windyrainy/p/10844533.html
Copyright © 2020-2023  润新知