与OpenCV的爱恨情仇

一. 配置opencv

1.最近在用Python学习OpenCV,因为本人之前一直用的Pycharm编译器,后来了解到了Anaconda这个神器,就通过Anaconda来下载各种安装包,再和Pycharm连接就可以完成相应的配置。

2.Anaconda的NAVIGATOR软件相当于图形化操作界面,从直接的命令好操作转化为了图形化操作,我新建了一个VirtualEnvironment虚拟环境,python版本设置的为3.6(因为好像opencv和python3.7不兼容),然后点击Installed,将其选为Uninstalled,再search Packages里面寻找需要下载的安装包就可以了。
在这里插入图片描述
3.下载好之后进入Pycharm,点击Files,选择settings,再Project Interpreter中选择Add,再选择Anaconda文件夹下的envs文件夹里的python.exe
在这里插入图片描述
在这里插入图片描述
4.配置好之后输入下面一段代码进行测试:

import cv2

img = cv2.imread("C:\\Users\\Tony.Hsu\\Desktop\\cat.jpg", 1)

cv2.imshow("1", img)

cv2.waitKey()

得到如下结果
在这里插入图片描述

2.Opencv的一些模块

1.【core】核心模块
OpenCV基本数据结构
动态数据结构
绘图函数
数组操作相关函数
辅助功能与系统函数和宏
与OpenGL的互操作

2.【imgproc】Imaging与Processing两个单词的缩写的组合。图像处理模块。
线性和非线性的图像滤波
图像的几何变换
其他(Miscellaneous)图像转换
直方图相关
结构分析和形状描述
运动分析和对象跟踪
特征检测
目标检测等内容

3.【features2d】2D功能框架
特征检测和描述
特征检测器(Feature Detectors)通用接口
描述符检测器(Descriptor Extrators)通用接口
描述匹配器(Descriptor Matches)通用接口
通用描述符(Generic Descriptor)匹配器通用接口
关键点绘制函数和匹配功能绘制函数

4.【FLANN】—— Fast Library for Approximate Nearest Neighbors,高维的近似近邻快速搜索算法库,包含两个部分:
快速近似最近邻搜索
聚类

5.【gpu】——运用GPU加速的计算机视觉模块

6.【legacy】——一些已经废弃的代码库,保留下来作为向下兼容,包含如下相关的内容:
运动分析
期望最大化
直方图
平面细分(C API)
特征检测和描述(Feature Detection and Description)
描述符提取器(Descriptor Extractors)的通用接口
通用描述符(Generic Descriptor Matchers)的常用接口
匹配器

7.【ML】——Machine Learning,机器学习模块, 基本上是统计模型和分类算法,包含如下内容:
统计模型 (Statistical Models)
一般贝叶斯分类器 (Normal Bayes Classifier)
K-近邻 (K-NearestNeighbors)
支持向量机 (Support Vector Machines)
决策树 (Decision Trees)
提升(Boosting)
梯度提高树(Gradient Boosted Trees)
随机树 (Random Trees)
超随机树 (Extremely randomized trees)
期望最大化 (Expectation Maximization)
神经网络 (Neural Networks)
MLData

8.【nonfree】,也就是一些具有专利的算法模块 ,包含特征检测和GPU相关的内容。最好不要商用,可能会被告哦。其中SIFT特征点的检测和处理都在此模块中。
9.【objdetect】——目标检测模块,包含Cascade Classification(级联分类)和Latent SVM这两个部分。

10.【ocl】——即OpenCL-accelerated Computer Vision,运用OpenCL加速的计算机视觉组件模块

11.【photo】——也就是Computational Photography,包含图像修复和图像去噪两部分

12.【stitching】——images stitching,图像拼接模块,包含如下部分:
拼接流水线
特点寻找和匹配图像
估计旋转
自动校准
图片歪斜
接缝估测
曝光补偿
图片混合

13.【video】——视频分析组件,该模块包括运动估计,背景分离,对象跟踪等视频处理相关内容。

注:具体内容可参考以下文章:
https://blog.csdn.net/zmdsjtu/article/details/54924727

3.使用opencv读写图像及视频

A.理论基础

参考文章:http://www.cnblogs.com/ivan-count/
https://blog.csdn.net/qq_18995069/article/details/82772944
https://blog.csdn.net/wsp_1138886114/article/details/84798977
一、Mat imread(const string& filename,int flags=1),用于读取图片
1、参数介绍
filename:载入的图片的路径名。支持如下类型文件的载入
JPEG文件 - *.jpeg, *.jpg, *.jpe
JPEG 2000文件- *.jp2
PNG图片 - *.png
便携文件格式- *.pbm, *.pgm, *.ppm
Sun rasters光栅文件 - *.sr, *.ras
TIFF 文件 - *.tiff, *.tif
Windows位图 - .bmp,.dib
flags:int类型的flags,为载入标识,它指定一个加载图像的颜色类型。可以看到它自带缺省值1.所以有时候这个参数在调用时我们可以忽略。如果在调用时忽略这个参数,就表示载入三通道的彩色图像。
常用标志符:
CV_LOAD_IMAGE_COLOR——等价取值为1,将图像转化为彩色
CV_LOAD_IMAGE_UNCHANGED——等价取值为-1
CV_LOAD_IMAGE_GRAYSCALE——等价取值为0,将图像转化为灰度
CV_LOAD_IMAGE_ANYDEPTH——等价取值为2,当载入图像深度为16位或32位,返回对应深度的图像,否则转化为8位图像返回
CV_LOAD_IMAGE_ANYCOLOR——等价取值为4,无损的源图像

当输入有冲突时,采用较小数字值。CV_LOAD_IMAGE_COLOR|CV_LOAD_IMAGE_ANYCOLOR将载入三通道图;CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR将载入最真实无损的源图像。

若以数值表示,则:
flags>0返回一个3通道的彩色图像
flags=0返回灰度图像
flags<0返回包含Alpha通道的加载图像

当以彩色载入时,通道顺序为BGR(蓝、绿、红),而非RGB。

二、void imshow(const string& winname,InputArray mat),用于显示一副图像
1、参数介绍
winname:const string&类型的winname,填需要显示的窗口标识名称。
mat:InputArray 类型的mat,填需要显示的图像。

2、注意事项
如果窗口用CV_WINDOW_AUTOSIZE(默认值)创建的,那么imshow将显示图像原始大小,否则将进行缩放以适应窗口:

如果载入的图像是8位无符号类型(8-bit unsigned),就显示图像本来的样子。
如果图像是16位无符号类型(16-bit unsigned)或32位整型(32-bit integer),便用像素值除以256。也就是说,值的范围是[0,255 x 256]映射到[0,255]。
如果图像是32位浮点型(32-bit floating-point),像素值便要乘以255。也就是说,该值的范围是[0,1]映射到[0,255]。

三、void namedWindow(const string& winname, int flags=WINDOW_AUTOSIZE),用于创建窗口
1、参数介绍
name:const string&型的name,即填被用作窗口的标识符的窗口名称。
flags:int 类型的flags ,窗口的标识,可以填如下的值:

WINDOW_NORMAL,可改变窗口大小
WINDOW_AUTOSIZE(值为1),窗口大小会自动调整以适应所要显示的图像,且用户无法手动调整
WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL。

2、其他
一般情况下,该函数有默认值WINDOW_AUTOSIZE,一般情况下,这个函数我们填一个变量就行了。
namedWindow函数的作用是,通过指定的名字,创建一个可以作为图像和进度条的容器窗口。如果具有相同名称的窗口已经存在,则函数不做任何事情。

可以自行手动关闭窗口并释放空间:destroyWindow()或destroyAllWindows()。但是程序退出时,所有窗口将被系统自动关闭。

四、bool imwrite(const string& filename, InputArray img,const vector&params=vector()),用于输出图像到文件
1、参数介绍
filename:const string&类型的filename,填写要写入的文件名,需带上后缀,即文件类型名。
img:InputArray类型的img,需要输出的图像,一般为Mat类型。
params:const vector&类型的params,表示为特定格式保存的参数编码,它有默认值vector(),所以一般情况下不需要填写。

对于JPEG格式,参数从0到100,表示图片质量(CV_IMWRITE_JPEG_QUALITY)
对于PNG格式,表示压缩级别(CV_IMWRITE_PNG_COMPRESSION)从0~9.较高的值意味着更小的尺寸和更长的压缩时间,默认为3.
对于PPM、PGM或PBM格式,表示一个二进制格式标识(CV_IMWRITE_PXM_BINARY),取值为0或1,默认为1.

五.OpenCV提供的接口VideoCapture,用于视频的读取

  • < VideoCaputrue object > = cv2.VideoCapture(filename)------功能:打开视频文件,参数filename:视频文件名。
  • < VideoCaputrue object > = cv2.VideoCapture(index)------功能:打开相机设备,参数index:相机设备ID,当只有一个相机时,给0即可。
  • retval =cv2.VideoCapture. isOpened()------功能:判断视频捕获是否初始化成功。初始化成功返回true。之前调用过VideoCapture的构造函数或者VideoCapture::open()函数成功,就会返回true。
  • retval=cv2.VideoCapture.open(filename)/cv2.VideoCapture.open(index)------功能:打开视频文件或者相机设备进行视频捕获。
  • retval = cv2.VideoCapture.get(propId)------功能:得到相机/视频文件的各种属性。propId常见取值如下:
cv2.CAP_PROP_POS_MSEC:视频文件的当前位置(ms)

cv2.CAP_PROP_POS_FRAMES:从0开始索引帧,帧位置。

cv2.CAP_PROP_POS_AVI_RATIO:视频文件的相对位置(0表示开始,1表示结束)

cv2.CAP_PROP_FRAME_WIDTH:视频流的帧宽度。

cv2.CAP_PROP_FRAME_HEIGHT:视频流的帧高度。

cv2.CAP_PROP_FPS:帧率

cv2.CAP_PROP_FOURCC:编解码器四字符代码

cv2.CAP_PROP_FRAME_COUNT:视频文件的帧数

cv2.CAP_PROP_FORMAT: retrieve()返回的Mat对象的格式。

cv2.CAP_PROP_MODE:后端专用的值,指示当前捕获模式

cv2.CAP_PROP_BRIGHTNESS:图像的亮度,仅适用于支持的相机

cv2.CAP_PROP_CONTRAST:图像对比度,仅适用于相机

cv2.CAP_PROP_SATURATION:图像饱和度,仅适用于相机

cv2.CAP_PROP_HUE:图像色调,仅适用于相机

cv2.CAP_PROP_GAIN:图像增益,仅适用于支持的相机

cv2.CAP_PROP_EXPOSURE:曝光,仅适用于支持的相机

cv2.CAP_PROP_CONVERT_RGB:布尔标志,指示是否应将图像转换为RGB。
  • retval = cv2.VideoCapture.set(propId,value)------功能:设置属性,第一个参数是选择属性类型,第二个参数是值。其中一些值可以使用 cap.set(propId,value) 进行修改,value是修改后的值。
    例如:通过cap.get(3)和cap.get(4)来检查帧的宽度和高度,默认的值是640x480。现修改为320x240,使用ret = cap.set(3, 320)和ret = cap.set(4, 240)。
  • retval,image= cv2.VideoCapture.read([,image])-------功能:抓取,解码并返回下一个视频帧。返回值为true表明抓取成功。该函数是组合了grab()和retrieve(),这是最方便的方法。如果没有帧,该函数返回false,并输出空图像。
  • retval, image = cv2.VideoCapture.retrieve([, image[, flag]])-------功能:解码并返回抓取的视频帧。
  • retval = cv2.VideoCapture.grab()------功能:从视频文件或相机中抓取下一帧。true为抓取成功。该函数主要用于多摄像头时。
  • none = cv2.VideoCapture.release()------功能:关闭视频文件或相机设备

六.OpenCV提供的接口VideoWriter,用于视频的保存

  • < VideoWriter object > = cv.VideoWriter( filename, fourcc, fps, frameSize[, isColor] )
    参数:
    filename:给要保存的视频起个名字
    fourcc:指定视频编解码器的4字节代码
    fps:帧率
    frameSize:帧大小
    isColor:如果为true,则视频为彩色,否则为灰度视频,默认为true

B.实现示例

1.opencv读取图像

import cv2
# 读取这个路径的图片,注意这里的路径必须全是英文,不能有中文
img = cv2.imread("C:\\Users\\Tony.Hsu\\Desktop\\cat.jpg")

# namedWindow函数,用于创建一个窗口,默认值为WINDOW_AUTOSIZE,一般输入情况我们只需要输入第一个变量
# 其实这一行代码没有也可以正常显示的(下面imshow会显示)
cv2.namedWindow("Cat")

# 在指定的窗口中显示一幅图像
# 若同时使用namedWindow和imshow函数,则两个函数的第一个参数名字必须相同。
cv2.imshow("Cat", img)

# 参数=0: (也可以是小于0的数值)一直显示,不会有返回值,若在键盘上按下一个键即会消失 ,则会返回一个按键对应的ascii码值
# 参数>0:显示多少毫秒,超过这个指定时间则返回-1
cv2.waitKey(0)

# 删除建立的全部窗口,释放资源
cv2.destroyAllWindows()

2.opencv打印图片属性并另存

import cv2
import numpy as np

# 输出图片属性

def get_image_info(image):  # 定义一个函数来输出图片的一些属性

    print(type(image))  # 显示图片类型 numpy类型的数组

    # 图像矩阵的shape属性表示图像的大小,shape会返回tuple元组,
    # 第一个元素表示矩阵行数,第二个元组表示矩阵列数,第三个元素是3,表示像素值由光的三原色组成

    print(image.shape)

    print(image.size)  # 图像大小

    print(image.dtype)  # 图像类型

    pixel_data = np.array(image)

    print(pixel_data)  # 图片矩阵

img = cv2.imread("C:\\Users\\Tony.Hsu\\Desktop\\cat.jpg")

cv2.namedWindow("cat1", cv2.WINDOW_NORMAL)

cv2.imshow("cat1", img)

get_image_info(img)

cv2.imwrite("C:\\Users\\Tony.Hsu\\Desktop\\cat1.jpg", img)  # 图片另存为其他地址,不要存到c盘,要权限

cv2.waitKey(0)

cv2.destroyAllWindows()

3.opencv读取视频

A.从摄像头中获取视频
创建一个VideoCapture对象。它的参数可以是设备索引或视频文件的名称(下面会讲到)。设备索引只是指定哪台摄像机的号码。0代表第一台摄像机、1代表第二台摄像机。之后,可以逐帧捕捉视频。最后释放捕获。

import cv2

# 获取摄像头0(本电脑摄像头)
cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()                        # 读取帧
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化展示
    cv2.imshow('frame', gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):          # 按‘q’退出
        break

# 释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()

B.读取视频文件
从文件中播放视频,更改相机索引与视频文件名。 在显示帧时,选择适当的cv2.waitKey()时间,如果该值太小,视频会非常快,如果它太大,视频会很慢(这可以用来慢动作显示视频)。 正常情况下,25-50毫秒即可。

import cv2

cap = cv2.VideoCapture('C:\\Users\\Tony.Hsu\\Pictures\\Camera Roll\\1.mp4')

while cap.isOpened():
    ret, frame = cap.read()
    cv2.imshow('frame', frame)
    if cv2.waitKey(50) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

4.opencv视频文件的保存

要想保存视频,首先是进行捕获视频,本次实现保存相机中捕获的视频。将视频保存,思路是首先创建VideoWriter类对象,需要指定一些参数,在windows下fourcc取值为DIVX,帧率一般给20,帧大小一般给640*480,创建对象后,采用write()函数保存帧,保存完后记得关闭VideoWriter类对象。

# cv2.VideoWriter_fourcc("I", "4", "2", "0")  .avi的未压缩的YUV颜色编码,文件较大
# cv2.VideoWriter_fourcc("P", "I", "M", "1")  .avi的MPEG-1编码类型
# cv2.VideoWriter_fourcc("X", "V", "I", "D")  .avi的MPEG-4编码类型
# cv2.VideoWriter_fourcc("T", "H", "E", "O")  .ogv的Ogg Vorbis
# cv2.VideoWriter_fourcc("F", "L", "V", "1")  .flv的flash视频

import cv2

cap = cv2.VideoCapture(0)               # 打开相机

# 创建VideoWriter类对象,
# 生成的视频格式设置为.avi(OpenCV只支持avi的格式,而且生成的视频文件不能大于2GB,而且不能添加音频)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# cv2.VideoWriter(视频名, 格式, 码率(fps), 帧的尺寸等参数)
out = cv2.VideoWriter('C:\\Users\\Tony.Hsu\\Desktop\\output.avi', fourcc, 20.0, (640, 480))

while cap.isOpened():
    ret, frame = cap.read()             # 捕获一帧图像
    if ret:                             # Python推荐简化此表达式 if ret == True:
        frame = cv2.flip(frame, 0)      # 沿x轴翻转,进行图像翻转, 1水平翻转、 0垂直翻转、-1水平垂直翻转
        out.write(frame)                # 保存帧

        cv2.imshow('frame', frame)       # 显示帧
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

cap.release()  # 关闭相机
out.release()
cv2.destroyAllWindows()

该行代码fourcc = cv2.VideoWriter_fourcc(* ’XVID’)可以改为fourcc = cv2.VideoWriter_fourcc(’X’,’V’,’I’,’D’),二者是等效的

4.计算总帧数

import cv2

video_cap = cv2.VideoCapture('C:\\Users\\Tony.Hsu\\Desktop\\output.avi')

frame_count = 0

all_frames = []

while True:

    ret, frame = video_cap.read()

    if ret is False:
        break

    all_frames.append(frame)

    frame_count = frame_count + 1

# The value below are both the number of frames

print(frame_count)

print(len(all_frames))

5.读取FPS

import cv2

if __name__ == '__main__':

    video = cv2.VideoCapture("C:\\Users\\Tony.Hsu\\Desktop\\output.avi")

    # Find OpenCV version

    (major_ver, minor_ver, subminor_ver) = cv2.__version__.split('.')

    if int(major_ver) < 3:

        fps = video.get(cv2.cv.CV_CAP_PROP_FPS)

        print("Frames per second using video.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))

    else:

        fps = video.get(cv2.CAP_PROP_FPS)

        print("Frames per second using video.get(cv2.CAP_PROP_FPS) : {0}".format(fps))

    video.release()

整体代码:

import cv2


def read_video(file_path):
    video_cap = cv2.VideoCapture(file_path)

    ### 获取视频的帧数 ###

    video_frameNum = 0

    # all_frames = []

    while (True):

        ret, frame = video_cap.read()

        if ret is False:
            break

        # all_frames.append(frame)

        video_frameNum = video_frameNum + 1

    ### 获取视频的FPS ###

    (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')  # Find OpenCV version

    if int(major_ver) < 3:

        video_FPS = video_cap.get(cv2.cv.CV_CAP_PROP_FPS)

    # print("Frames per second using video_cap.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))

    else:

        video_FPS = video_cap.get(cv2.CAP_PROP_FPS)

    # print("Frames per second using video_cap.get(cv2.CAP_PROP_FPS) : {0}".format(fps))

    video_cap.release()

    return video_frameNum, video_FPS


video_path = 'C:\\Users\\Tony.Hsu\\Desktop\\output.avi'

video_frameNum, video_FPS = read_video(video_path)  # 获取视频帧数

print(video_frameNum)

print(video_FPS)

参考博客:https://blog.csdn.net/yyy430/article/details/87866603

发布了13 篇原创文章 · 获赞 2 · 访问量 1842

猜你喜欢

转载自blog.csdn.net/SouthWooden/article/details/98031092