OpenCV-Python 学习笔记

OpenCV-Python 学习笔记

Part1 图像基本操作


图像操作

图像像素点区间0~255,表示亮度
RGB彩色图像的颜色通道(红、绿、蓝),灰度图像只有一个通道
cv2.IMREAD_COLOR:彩色图像
cv2.IMREAD_GRAYSCALE:灰度图像

##导入工具包
import cv2  #opencv读取格式为BGR
import matplotlib.pyplot as plt  #绘图
import numpy as np
cv2.imread('图片路径名称')  #读取一张图像,可以在后面加cv2.IMREAD_GRAYSCALE读取灰度图像
cv2.imshow('窗口名称', 显示的图像)   #图像的显示,也可以创建多个窗口
cv2.waitKey(0)  #等待时间,毫秒级,0表示按任意键终止
cv2.destroyAllWindows()
cv2.imwrite('名称', 图像)   #图像保存
img.shape   #(h, w, c)
img.shape[0] = height: 480
img.shape[1] = width: 640
img.shape[2] = channel: 3
img.size  #读取像素点个数

视频操作

import cv2  #opencv读取格式为BGR
import matplotlib.pyplot as plt  #绘图
import numpy as np
#cv2.VideoCapture可以捕获摄像头,用数字0,1来表示不同设备
#如果是视频文件,直接指定好路径即可
vc = cv2.VideoCapture('F:\ProgramData\object\videos\gaokong\高空作业.mp4')

#检查打开是否正确
if vc.isOpened():
    open, frame = vc.read()   #vc.read返回两个值,第一个为bool值;第二个为当前帧图像
else:
    open = False
# 把视频转为灰度视频
while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow('result', gray)
        if cv2.waitKey(10) & 0xFF == 27: #27对应退出键
            break
vc.release()
cv2.destroyAllWindows()

边界填充

  • cv2.BORDER_CONSTANT 填充边界时使用常数填充
  • cv2.BORDER_REPLICATE: 使用边界最接近的像素填充,也就是用边缘像素填充
  • cv2.BORDER_REFLECT, 反射法,是指对图像的像素两边进行复制
  • cv2.BORDER_REFLECT101: 反射法,把边缘的像素作为轴,对称的复制
  • cv2.BORDER_WRAP: 用另一边的像素进行填充
img_new = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType = xxx)  #xxx为边界填充类型,如:复制法,反射法,外包装法,常量法

Part2 形态学操作


腐蚀erode(可以看做扩大黑色区域)

img = cv2.imread('图片名称')
kernel = np.ones((3,3),np.uint8)
#kernel卷积核大小,越大腐蚀越强;iterations操作的迭代次数
img_erosion = cv2.erode(img, kernel, iterations = 1)
cv2.imshow('img_erosion', img_erosion)
cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv.destroyAllWindows()  #销毁所有窗口

膨胀dilate(可以看做扩大白色区域)

img = cv2.imread('图片名称')
kernel = np.ones((5,5),np.uint8)
#kernel卷积核大小,越大膨胀越强;iterations操作的迭代次数
img_dilate = cv2.dilate(img, kernel, iterations = 1)
cv2.imshow('img_dilate', img_dilate)
cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv.destroyAllWindows()  #销毁所有窗口

OpenCV提供了一个函数getStructuringElement,可以获取常用的结构元素的形状:矩形(包括线形)、椭圆(包括圆形)及十字形,是一种更加简便的方法实现一个kernel
参数:

cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
def getStructuringElement(shape, ksize, anchor=None): # real signature unknown; restored from __doc__

第一个参数shape:表示内核的形状,有三种形状可以选择
矩形:MORPH_RECT;
交叉形:MORPH_CORSS;
椭圆形:MORPH_ELLIPSE;
第二个参数ksize:是内核的尺寸(n,n)
第三个参数anchor:锚点的位置
返回值:
getStructuringElement函数会返回指定形状和尺寸的结构元素。


开运算(先腐蚀再膨胀,分离物体,消除小区域)

img = cv2.imread('图片名称')
kernel = np.ones((5,5),np.uint8)
#morphologyEx形态学操作,MORPH_OPEN开运算
img_open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('img_open', img_open)
cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv.destroyAllWindows()  #销毁所有窗口

闭运算(先膨胀再腐蚀,消除/“闭合"物体里面的小黑洞)

img = cv2.imread('图片名称')
kernel = np.ones((3,3),np.uint8)
#morphologyEx形态学操作,MORPH_CLOSE闭运算
img_close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('img_close', img_close)
cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv.destroyAllWindows()  #销毁所有窗口

梯度运算(膨胀-腐蚀)

img = cv2.imread('图片名称')
kernel = np.ones((3,3),np.uint8)
#morphologyEx形态学操作,MORPH_GRADIENT梯度运算
img_gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('img_gradient', img_gradient)
cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv.destroyAllWindows()  #销毁所有窗口

礼帽与黑帽

礼帽 = 原始输入 - 开运算结果
黑帽 = 闭运算结果 - 原始输入

img_tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)  #礼帽
img_blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)  #黑帽

Part3 模板匹配

参考链接
模板匹配:模板在原图像上从原点开始滑动,计算模板与图像被覆盖区域的差别程度,差别程度的计算方法在OpenCV中有6种,然后将每次计算的结果放入一个矩阵中,作为结果输出。
模板匹配函数 cv.matchTemplate()
可以通过以下代码来提取最小值最大值及其所在位置

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) #result为输出矩阵

加入原图形是AxB大小,模板是axb大小,则输出的矩阵是(A-a+1)x(B-b+1)大小
最终以 min_loc, max_loc 作为左上角坐标,axb作为长和宽来画框。

methods introduce
cv2.TM_SQDIFF 平方差匹配法 即模板图像像素减去覆盖的源图像像素的差的平方和为对应矩阵的点的值。如果值越接近0,说明匹配程度越高。
cv2.TM_CCORR 相关匹配法 采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。
cv2.TM_CCOEFF 相关系数匹配法 将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。
cv2.TM_SQDIFF_NORMED 归一化平方差匹配法
cv2.TM_CCORR_NORMED 归一化相关匹配法
cv2.TM_CCOEFF_NORMED 归一化相关系数匹配法
# 列表中所有的6种比较方法
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
 'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']

多对象匹配源码

import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('./data/Mario.png')
cv2.imshow('img', img_rgb)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('./data/Mario_coin.png',0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) #修改模板匹配方法,当前为相关系数匹配法,越接近1越好
threshold = 0.8  #阈值
loc = np.where(res >= threshold)
##*表示可选参数,zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
for pt in zip(*loc[::-1]):  
    cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (255, 0, 0), 2)
cv2.imshow('res',img_rgb)
cv2.waitKey(0)

Part4 图片合成为视频

# -*- coding: UTF-8 -*-
import glob
import os
import cv2
import time

# 图片合成视频
def picvideo(path, size):
    filelist = os.listdir(path)  # 获取该目录下的所有文件名
    filelist.sort(key=lambda x: int(x[:-4]))  ##文件名按数字排序
    '''
    fps:
    帧率:1秒钟有n张图片写进去[控制一张图片停留5秒钟,那就是帧率为1,重复播放这张图片5次] 
    如果文件夹下有50张 534*300的图片,这里设置1秒钟播放5张,那么这个视频的时长就是10秒
    '''
    fps = 10
    file_path = r"./video/1/" + '1' + ".mp4"  # 导出路径
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')  # 不同视频编码对应不同视频格式(例:'I','4','2','0' 对应avi格式)

    video = cv2.VideoWriter(file_path, fourcc, fps, size)

    for item in filelist:
        if item.endswith('.jpg'):  # 判断图片后缀是否是.png
            item = path + '/' + item
            img = cv2.imread(item)  # 使用opencv读取图像,直接返回numpy.ndarray 对象,通道顺序为BGR ,注意是BGR,通道值默认范围0-255。
            video.write(img)  # 把图片写进视频

    video.release()  # 释放

picvideo(r'./video/1/img', (1920, 1080))

Part5 视频分解为图片

# 1. 导入需要的包和模块
import cv2
import numpy as np
import os

# 2. 读取视频,获取视频的帧率、宽度和高度三个参数
cap = cv2.VideoCapture('./outputvideo/12-x.avi')

# isOpened() -> retval
# .   @brief Returns true if video capturing has been initialized already.
isOpened = cap.isOpened()

fps = cap.get(cv2.CAP_PROP_FPS)  # 帧率<每秒中展示多少张图片>
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 获取宽度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 获取高度
print(fps, width, height)


# 3. 定义转换函数,当视频打开时进行分解操作并重命名文件保存
def changeToPics():
    i = 0
    while isOpened:
        i = i + 1
        # read([, image]) -> retval, image
        # .   @brief Grabs, decodes and returns the next video frame.
        (flag, frame) = cap.read()  # 读取每一张 flag<读取是否成功> frame<内容>
        filename = str(i) + '.jpg'
        if flag:  # 读取成功的话
            cv2.imwrite(r'./outputvideo/pictures' + os.sep + filename, frame, [cv2.IMWRITE_JPEG_QUALITY, 100])
            # 写入文件,1 文件名 2 文件内容 3 质量设置
        else:
            break
    print("convert successfully!!!")


# 4. 调用函数
changeToPics()

你可能感兴趣的:(笔记,opencv,python)