本章测试程序

OpenCV安装

  1. 利用anaconda低版本Python,例如 Python 3.6.13

    Terminal
    $conda create --name 新环境名 python=版本号
    $conda activate 环境名 // 切换python版本
    $conda deactivate // 退出当前Python环境,回到默认环境
    $conda info --envs // 查看虚拟环境
    $conda remove -n 环境名 --all // 删除虚拟环境
  2. 将安装的Python添加到jupyter中, 一定要切换回基础环境,再向 jupyter 中添加内核

    Terminal
    $conda activate python36 // 切换到新环境
    $pip install ipykernel // 安装该版本的内核
    $conda deactivate // 注意:一定要切换换回基础环境
    $python -m ipykernel install --name python36 // 将新环境的内核添加到 jupyter 中
    $jupyter kernelspec list // 查看添加的内核
    Available kernels:
    python3 D:\Program\anaconda3\share\jupyter\kernels\python3
    python36 C:\ProgramData\jupyter\kernels\python36
    $jupyter kernelspec remove 内核名 // 移除内核
  3. 在指定Python版本的环境中安装 OpenCV opencv-contrib-python直接用最新版,SIFT 的专利已经过期,用之前的3.4.1版本,可能有问题。opencv-python也可以直接用最新版

    Terminal
    $pip install opencv-python opencv-contrib-python // 直接装最新的
    $pip install opencv-python==版本号 opencv-contrib-python==版本号 // 选择版本

OpenCV 界面

PYTHON
# 导入 OpenCV
import cv2

# 创建窗口,
cv2.namedWindow('window',cv2.WINDOW_NORMAL)

# 更改窗口:window_autosize,设置大小无用
cv2.resizeWindow('window',width=800,height=600)

# 展示窗口、图片等
cv2.imshow('window',0)

# 等待按键
# 1. 将窗口堵塞。等带按键、并会返回按键的ASCII码
# 2. 可以设置等待的时间,单位 ms
# 3. 等待时间为 0 ,则为一直等待 
key = cv2.waitKey(0)

# ord():获取字符的ASCII码
# key & 0xFF:将 int 类型的低字节给提去出来,因为ASCII码为一字节
if key & 0xFF == ord('q'):
    # 销毁窗口
    cv2.destroyAllWindows()

图像基本操作

图像的输入与输出

PYTHON
# 读取图片
cv2.imread(图片路径,flags)

# 显示图片
cv2.imshow('名字',image)

# 图片保存
cv2.imwrite(保存路径)

# 图片显示函数
def showImage(name:str,image):
    """ 显示图片的函数 """
    cv2.imshow(name,image)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
  • imread的 flags
    • cv2.IMREAD_COLOR:以彩色读取
    • cv2.IMREAD_GRAYSCALE:以灰度图形式读取(黑白图片)

图片的数组本质

  • 图片数据类型: 读取的图片类型为 <class 'numpy.ndarray'>,即图片其实是一个数据
    • 数组类型: uint8,一字节的无符号整数
    • 数组维度: 三维,[高度像素,宽度像素,RGB值]

[!note|style:flat]

  • OpenCV读取的图片,其通道顺序为:B、G、R;并非一般的R、G、B
  • 根据图片的数组本质,就能通过 numpy 自定义纯色图片:blackImage = np.zeros(shape=(height,width,3),dtype=np.uint8)
PYTHON
# 裁剪图片:将原图片的高度 100 - 200 的像素;宽度 50 - 100 的像素。提取出来
img[ 100:200,50:100,: ]

# RGB 通道的拆分:结果为:高度像素 x 宽度像素 的二维数组
b,g,r = cv2.split(img)
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]

# 合并多个被拆分出来的通道:将三个二维数组,组合成三维的数组
img = cv2.merge((b,g,r)) 

# 单通道图片
b = img[:,:,0]
g = img[:,:,1] * 0
r = img[:,:,2] * 0
imgB = cv2.merge((b,g,r)) 

# 纯色图片
blackImage = np.zeros(shape=(380,640,3),dtype=np.uint8)
whiteImage = np.full(shape=(10,10,4),fill_value=255,dtype=np.uint8)

修改像素尺寸

作用: 图像数据本质上就是一个「三维矩阵」,在对多个图像进行数学运算时,就需要同步矩阵维度。

PYTHON
# (width, height):直接指定需要的像素值
# fx,fy:当设定(width, height)为(0,0)时,fx与fy分别表示图片两个方向上的缩放比列
cv2.resize(img, Tuple[width, height], fx, fy)
cv2.resize(img,(0,0),fx=1.5,fy=1)

视频的基本操作

视频本质

视频本质上就是由一个图片的数组加音频组合而成的文件。视频播放时,就是按照一定时间间隔依次读取图片数组中的图片并显示。这个时间间隔为帧数,即一秒钟中能显示多少张图片。

视频输入与输出

视频文件读取

PYTHON
import cv2
# 读取视频
video = cv2.VideoCapture('视频路径')

# 视频读取
while video.isOpened():
    # 读取一帧
    flag,frame = video.read()

    # 显示
    if flag == True:
        cv2.imshow('video',frame)

    # 控制播放速度:以 60 帧的速度进行图片显示
    if cv2.waitKey(1000 // 60) == ord('q'):
        break 

# 释放
video.release()
cv2.destroyAllWindows()

摄像头捕获

PYTHON
import cv2
# 调用摄像头,抓取图片。设备连接的摄像头从 0 开始编号
video = cv2.VideoCapture(0)

# 视频读取
while video.isOpened():
    
    # 读取一帧
    flag,frame = video.read()

    # 显示
    if flag == True:
        cv2.imshow('video',frame)

    # 控制播放速度:以 60 帧的速度进行图片显示
    if cv2.waitKey(1000 // 60) == ord('q'):
        break 

# 释放
video.release()

cv2.destroyAllWindows()

视频保存

PYTHON
import cv2
# 调用摄像头,抓取图片。设备连接的摄像头从 0 开始编号
video = cv2.VideoCapture(0)

# 视频保存格式
videoForm = cv2.VideoWriter_fourcc(*'mp4v')

# 保存视频的类,输入参数为:
# 保存路径,保存格式,保存的视频帧数,(宽度像素,高度像素) 
videoSave = cv2.VideoWriter('./asset/capture.mp4',videoForm,24,(640, 480))

# 视频读取
while video.isOpened():

    # 读取一帧
    flag,frame = video.read()

    # 是否读取成功
    if flag == True:
        # 显示
        cv2.imshow('video',frame)
        # 保存
        videoSave.write(frame)

    # 控制播放速度:以 60 帧的速度进行图片显示
    if cv2.waitKey(1000 // 24) == ord('q'):
        break 

# 释放
videoSave.release()
video.release()

cv2.destroyAllWindows()
  • 帧数:视频输出的帧率由 cv2.VideoWriter 所指定,而cv2.waitKey(1000 // 24)规定的是摄像头拍照的帧数,该值的上限由摄像头所决定,硬件不行,设置多大都没用。

  • 摄像头的像素:

    PYTHON
    import cv
    # 读取视频
    video = cv2.VideoCapture(0)
    
    # 读取一帧
    flag,frame = video.read()
    
    # 查看像素
    print(frame)

回调函数

作用: 当某一个「事件」发生,就能马上执行对应处理程序,例如,点击鼠标右键,可以弹出菜单。处理程序靠「回调函数」实现,即当发生某个事件时,就会调用某个函数。

PYTHON
import cv2
import numpy as np

# 定义鼠标回调函数
# event:事件类型
# x,y:鼠标所在像素值
# userdata:用户传入数据
def mouse_callback(event,x,y,flags,userdata:any):
    if event == cv2.EVENT_LBUTTONDOWN:
        print(event,x,y,flags,userdata)

# 创建窗口
cv2.namedWindow('Event Test',cv2.WINDOW_NORMAL)
cv2.resizeWindow('Event Test',width=640,height=380)

# 鼠标事件指定回调函数
cv2.setMouseCallback('Event Test',mouse_callback,"userdata")

# 生成一个背景图片
bg = np.zeros((380,640,3),dtype=np.uint8)

while True:
    cv2.imshow('Event Test',bg)
    if cv2.waitKey(0) == ord('q'):
        break

cv2.destroyAllWindows()

[!note|style:flat] 只有在cv2.imshow()中显示了一张「像素图片」后,mouse_callback中的(x,y)才能正确的输出鼠标的位置坐标值。

License

Author: 海拉鲁的三角

Link: http://localhost:1313/artificial_intelligence/posts/computervision/foundationoperation/

License: MIT

只要学不死,就往死里学