资讯详情

OpenCV笔记

OpenCV笔记

基础

import cv2 as cv import numpy as np import matplotlib.pyplot as plt 

图像

  • 读取图像

    img = cv.imread(filename [,flags]) """ filename: 工作路径 flags: 标志,阅读图像的方式 cv.IMREAD_COLOR:彩色图像(BGR),忽略透明度,默认标志,1 cv.IMREAD_GRAYSCALE: 灰度模式,0 cv.IMREAD_UNCHANGED: 包括alpha通道,-1 """ 
  • 显示图像

    cv.imshow(winname, mat) """ winname: 窗口名称 mat: 图像 """ 常与cv.waitKey()和cv.destroyAllWindows()搭配使用 
  • 保存图像

    cv.imwrite(filename,img [,params]) """ filename:文件名 img: 图像需要保存 """ 
  • 可结合Matplotlib

视频

  • 捕获视频

    cap = cv.VideoCapture(filename [,apiPreference]) cap = cv.VideoCapture(index [,apiPreference]) """ filename: 视频文件名称、图像序列、视频流URL index: 视频捕获设备ID,默认打开默认摄像头 """  cap.isOpened()  # 判断是否初始化是真的;否则,使用cap.open()打开  ret, frame = cap.read()  # ret为布尔值,如果读取帧,则为真 
  • 保存视频

    out = cv.VideoWriter(filename,fourcc,fps,frameSize [,isColor]) """ filename: 文件名 fourcc:4字符编解码器代码用于压缩帧,fourcc = cv.VideoWriter_fourcc(*'XVID') fps:视频流的帧率 frameSize:视频帧大小 isColor:灰度编码为0,否则颜色 """ out.write(frame) 

绘制函数

  • 线

    img = cv.line(img, pt1, pt2, color[, thickness[, lineType[
             
              , shift
              ]
              ]
              ]
              ) 
              """ img: 图片 pt1:第一个点 pt2:第二个点 color:线条颜色 thickness:线条粗细 lineType:线条类型 shift:点坐标中的小数位数 """ img 
              = np
              .zeros
              (
              (
              512
              , 
              512
              , 
              3
              )
              , np
              .uint8
              ) img 
              = cv
              .line
              (img
              , 
              (
              0
              , 
              0
              )
              , 
              (
              511
              , 
              511
              )
              , 
              [
              255
              , 
              0
              , 
              0
              ]
              , 
              5
              ) 
             
  • 矩形

    img = cv.rectangle(	img,pt1,pt2,color [,thickness [,lineType [,shift]]])
    """ img: 图片 pt1:第一个点 pt2:对角顶点 color:矩形颜色 thickness:矩形线条粗细,负则填充 lineType:线条类型 shift:点坐标中的小数位数 """
    img = cv.rectangle(img, (384, 0), (510, 128), [0, 255, 0], 3)
    
  • img = cv.circle(img,center,radius,color [,thickness [,lineType [,shift]]])
    """ img: 图片 center: 圆心 radius:半径 color:圆颜色 thickness:圆线条粗细,负则填充 lineType:线条类型 shift:中心坐标和半径中的小数位数 """
    img = cv.circle(img, (447, 63), 63, (0, 0, 255), -1)
    
  • 椭圆

    img = cv.ellipse(img,center,axes,angle,startAngle,endAngle,color [,thickness [,lineType [,shift]]])
    """ img: 图片 center: 椭圆中心 axes:长短半轴,(长半轴,短半轴) angle:旋转角,负角度(顺时针) startAngle:椭圆弧起始角度(以焦点) endAngle:椭圆弧终止角度(以焦点) color:椭圆颜色 thickness:椭圆线条粗细,负则填充 lineType:线条类型 shift:中心坐标和轴值的小数位数 """
    img = cv.ellipse(img, (256, 256), (100, 50), 0, 45, 225, 255, -1)
    
  • 多边形

    img = cv.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]])
    """ img: 图片 pts: 多边形的数组 isClosed:折线是否闭合,假则最后一点不与源点相连 color:折线颜色 thickness:折线线条粗细 lineType:线条类型 shift:顶点坐标中的小数位数 """
    pts = np.array([[10, 5], [20, 30], [70, 20], [50,10]], np.int32)
    pts = pts.reshape((-1, 1, 2))
    img = cv.polylines(img, [pts], True, (0, 255, 255))
    

鼠标绘画

  • 鼠标事件

    events = [i for i in dir(cv) if 'EVENT' in i]
    print(events)
    # ['EVENT_FLAG_ALTKEY', 'EVENT_FLAG_CTRLKEY', 'EVENT_FLAG_LBUTTON', 'EVENT_FLAG_MBUTTON', 'EVENT_FLAG_RBUTTON', 'EVENT_FLAG_SHIFTKEY', 'EVENT_LBUTTONDBLCLK', 'EVENT_LBUTTONDOWN', 'EVENT_LBUTTONUP', 'EVENT_MBUTTONDBLCLK', 'EVENT_MBUTTONDOWN', 'EVENT_MBUTTONUP', 'EVENT_MOUSEHWHEEL', 'EVENT_MOUSEMOVE', 'EVENT_MOUSEWHEEL', 'EVENT_RBUTTONDBLCLK', 'EVENT_RBUTTONDOWN', 'EVENT_RBUTTONUP']
    
  • 鼠标回调函数

    cv.setMouseCallback(winname, onMouse, userdata=0)
    """ winname:窗口名 onMouse:鼠标事件的回调函数 userdata:传递给回调函数的可选参数 """
    def draw_circle(event, x, y, flags, param):
         """鼠标回调函数"""
         if event == cv.EVENT_LBUTTONDBLCLK:
             cv.circle(img, (x, y), 100, (255, 0, 0), -1)
    
    
    img = np.zeros((512, 512, 3), np.uint8)
    cv.namedWindow('image')
    cv.setMouseCallback('image', draw_circle)
    while(1):
        cv.imshow('image', img)
        if cv.waitKey(20) == 27:
            break
    cv.destroyAllWindows()
    

轨迹栏作调色板

核心操作

图像的基本操作

  • 读取和修改像素值

    px = img[100, 100]  # [157, 166, 200]
    # 获得蓝色像素
    blue = img[100, 100, 0]  # 157
    # 修改像素值
    img[100, 100] = [255, 255, 255]
    # 更好的获取和修改方法
    img.item(10, 10, 2)  # 59 获取红色像素
    img.itemset((10, 10, 2), 100)  # 修改红色像素值
    
  • 读取图像属性

    img.shape  # (342, 548, 3) 行、列、通道
    img.size  # 562248 所有像素值
    img.dtype  # uint8 数据类型
    
  • 图像感兴趣区域(ROI)

    roi = img[280: 340, 330: 390]
    
  • 分离合并图像通道

    # 分离
    b, g, r = cv.split(img)  # 很费时的操作
    b = img[:,:,0]
    # 合并
    img = cv.merge((b, g, r))
    
  • 生成图像边框(填充 Padding)

    dst = cv.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]])
    """ src: 源图像 top,bottom,left,right:上下左右宽度像素值 borderType: cv.BORDER_CONSTANT:恒定值 cv.BORDER_REFLECT: fedcba|abcdefgh|hgfedcb cv.BORDER_REFLECT_101 or cv.BORDER_DEFAULT: gfedcb|abcdefgh|gfedcba cv.BORDER_REPLICATE:aaaaaa|abcdefgh|hhhhhhh cv.BORDER_WRAP:cdefgh|abcdefgh|abcdefg value:颜色值,如果类型为cv.BORDER_CONSTANT """
    

图像的算术运算

  • 图像相加

    • cv.add为饱和运算(建议使用),numpy为取模运算
    x = np.uint8([250])
    y = np.uint8([100])
    print(cv.add(x, y))  # 255 建议使用
    print(x + y)  # 94
    
  • 图像融合(Image Blending)

    # 加权相加以达到图片融合
    dst = cv.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
    """ src1、src2:相加数组 alpha:1的权重 beta:2的权重 gamma:偏置 """
    dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)
    
  • 逐位运算(Bitwise Operations)

    • 通常在提取部分图片时使用
    • 包括
      • cv.bitwise_and:
        • dst(I)=src1(I)∧src2(I)if mask(I)≠0
        • dst(I)=src1(I)∧src2if mask(I)≠0,通道数与src1相同
        • dst(I)=src1∧src2(I)if mask(I)≠0,通道数与src2相同
      • cv.bitwise_or:
        • dst(I)=src1(I)∨src2(I)if mask(I)≠0
        • dst(I)=src1(I)∨src2if mask(I)≠0,通道数与src1相同
        • dst(I)=src1∨src2(I)if mask(I)≠0,通道数与src2相同
      • cv.bitwise_not:dst(I)=¬src(I)
      • cv.bitwise_xor:
        • dst(I)=src1(I)⊕src2(I)if mask(I)≠0
        • dst(I)=src1(I)⊕src2if mask(I)≠0,通道数与src1相同
        • dst(I)=src1⊕src2(I)if mask(I)≠0,通道数与src2相同
    dst	= cv.bitwise_and(src1, src2[, dst[, mask]])
    """ src1,src2:数组或标量 mask:掩膜 """
    img1 = cv.imread('messi5.jpg')
    img2 = cv.imread('opencv-logo-white.png')
    # 创建ROI
    rows, cols, channels = img2.shape
    roi = img1[0: rows, 0: cols]
    # 创建掩膜和反向掩膜
    img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
    ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
    mask_inv = cv.bitwise_not(mask)
    # 在ROI过滤出标志位置(黑色)
    img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
    # 取出标志
    img2_fg = cv.bitwise_and(img2,img2,mask = mask)
    # 合并
    dst = cv.add(img1_bg,img2_fg)
    img1[0:rows, 0:cols ] = dst
    
    cv.imshow('res',img1)
    cv.waitKey(0)
    cv.destroyAllWindows()
    

性能测试和提升技术

  • 性能测试

    e1 = cv.getTickCount()
    # 需要执行的代码
    e2 = cv.getTickCount()
    time = (e2 - e1) / cv.getTickFrequency()
    
  • 优化默认

    cv.useOptimized()  # True
    cv.setUseOptimized(False)  # 关闭优化
    
  • 性能优化技术

    • 尽量避免使用循环
    • 尽量矢量化,NumpyOpenCV都对其进行了优化
    • 利用缓存一致性
    • 尽量少复制数组

图像处理

改变色彩空间

  • 改变色彩空间

    • 有150多种色彩空间变换方法,比较常用的是BGR<->GRAYBGR<->HSV
    • HSV,色相Hue∈[0, 179],饱和度Saturation∈[0, 255],明度Value∈[0, 255]
    dst	= cv.cvtColor(src, code[, dst[, dstCn]])
    """ src:8位或16位无符号或单精度浮点图像 code:色彩空间变换码 dstCn:最终图片通道数,默认自动 """
    code = [i for i in dir(cv) if i.startswith('COLOR_')]
    
  • 物体追踪

    • 获取视频的每一帧图像
    • 转化成HSV色彩空间
    • 阈值过滤HSV图像
    • 可以追踪物品,进行其他操作
    cap = cv.VideoCapture(0)
    while True:
        # 获取一帧图片
        _, frame = cap.read()
        # 将BGR-->HSV(色相,饱和度,明度)
        hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
        # 在HSV中,定义蓝色的范围
        lower_blue = np.array([110, 50, 50])
        upper_blue = np.array([130, 255, 255])
        # 过滤HSV图像获得蓝色掩膜
        mask = cv.inRange(hsv, lower_blue, upper_blue)
        # bitwise_and 掩膜和原始图像
        res = cv.bitwise_and(frame, frame, mask=mask)
        cv.imshow('frame', frame)
        cv.imshow('mask', mask)
        cv.imshow('res', res)
        if cv.waitKey(5) == 27:
            break
    cap.release()
    cv.destroyAllWindows()
    
    • 如何找到HSV的值用于追踪
    green = np.uint8([[[0, 255, 0]]])
    hsv_green = cv.cvtColor(green, cv.COLOR_BGR2HSV)
    print(hsv_green)  # [[[ 60 255 255]]]
    

图像的几何变换(Geometric Transformations)

锐单商城 - 一站式电子元器件采购平台