opencv图像操作

opencv图像操作

opencv库

import cv2

读取图像

  •  cv2.imread(img_path)
    
     #cv2.IMREAD_COLOR:彩色图像
     #cv2.IMREAD_GRAYSCALE:灰色图像
    
  • OpenCV 中彩色图像使用 BGR 格式,而 PIL、PyQt、matplotlib 等库使用的是 RGB 格式。

展示图片

cv2.imshow('img_name',img)
  • 可以创建多个窗口
  • 读出来的图像是numpy.ndarray格式
  • 一般展示图像函数
  • def cv_show(name,img):
    
      cv2.imshow(name,img)
      cv2.waitKey(0)   #括号中为窗口展示的时间,单位是毫秒,0表示按下任意键关闭
      cv2.destroyAllWindows() #括号中为窗口展示的时间
    

读取视频

cv2.VideoCapture(video_path)
  • 检查是否正确打开

  •   if vc.isOpened():
          open,frame=vc.read()
      else:
          open=False
    
  • 在正确打开时展示视频

  •   while open:
          ret,frame=cv.read()
          gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
          cv2.imshow('result',gray)
          if  cv2.waitKey(10) & 0xFF==27:
              break
      cv.release()
      cv2.destroyAllWindows()
    

基本操作

截取图像的部分
  • test=img[0:200,0:200]
    
颜色通道提取
  • 
    b,g,r=cv2.split(img)
    
边界填充
  • 
    cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE)
    
    # BORDER_REPLICATE:复制法,复制最边缘像素
    # BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制
    # BORDER_REFLECT_101:反射法,以最边缘像素为轴
    # BORDER_WRAP:外包装法
    # BORDER_CONSTANT:常量法
    
数值计算
  • 直接相加:超过255的部分为 num-255-1
    • img=inmg+常数
    • img=img1+img2
  • 函数相加:超过255的部分取255
    • cv2.add(img1,img2)
图像融合
  • res=cv2.addWeighted(img1,a,img2,b,c)
    #其中生成的图像为f=ax+by+c,a和b为0-1之间的数
    

形态学操作

腐蚀操作
  • 作用:将图像的边界点消除,是图像沿着边界向内收缩,也可以将小于指定结构体的部分去除,可除倒刺

  • 
    kernel=np.ones((5,5),np.uint8)
    erosion=cv2.erode(img,kernel,iterations=1)
    # kernel为腐蚀核
    # iterations为腐蚀次数
    
膨胀操作
  • 与腐蚀操作相反,对图像的边界进行扩张

  • kernel=np.ones((5,5),np.uint8)
    dilate=cv2.dilate(img,kernel,iterations=1)
    # kernel为腐蚀核
    # iterations为腐蚀次数
    
开运算
  • 先腐蚀,再膨胀

  • 可用于去噪、计数

  • kernel=np.ones((5,5),np.uint8)
    opening=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
    # cv2.MORPH_OPEN表示开运算
    
闭运算
  • 先膨胀,再腐蚀

  • 有助于关闭前景物体内部的小孔,或去除物体上的小黑点,还可以将不同的前景进行连接

  • kernel=np.ones((5,5),np.uint8)
    closing=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
    # cv2.MORPH_CLOSE表示开运算
    
梯度计算
  • 梯度=膨胀-腐蚀

  • 可得到原始图的轮廓

  • kernel=np.ones((5,5),np.uint8)
    gradient=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
    
礼帽
  • 原始图-开运算结果

  • 可以获取图像的噪声信息,或者得到比原始图边缘信息更亮的边缘信息

  • kernel=np.ones((5,5),np.uint8)
    tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
    
黑帽
  • 闭运算结果-原始图

  • 获取图像内部的小孔,或前景中的小黑点,或者得到比原始图像的边缘更暗的边缘部分

  • kernel=np.ones((5,5),np.uint8)
    blackhat=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
    

图像梯度

Sobel算子

G x = − 1 0 1 − 2 0 2 − 1 0 − 1 ∗ A , G y = − 1 − 2 − 1 0 0 0 1 2 1 ∗ A G_x=\begin{matrix} -1&0&1\\ -2&0&2\\ -1&0&-1\\ \end{matrix} * A,G_y=\begin{matrix} -1&-2&-1\\ 0&0&0\\ 1&2&1\\ \end{matrix} * A Gx=121000121A,Gy=101202101A

  • dst=cv2.Sobel(src,ddepth,dx,dy,ksize)

    • ddepth:图像的深度
    • dx,dy表示水平和垂直方向
    • ksize为Sobel算子的大小
  • # 深度一般为cv2.CV_64F
    # ksize为核算子,大小为3
    
    # x方向求导,计算y方向梯度,获取垂直方向的边缘信息
    sobel_x=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
    # 计算绝对值
    sobelx=cv2.convertScaleAbs(sobel_x)
    
    # y方向求导,计算x方向梯度,获取水平方向边缘信息
    sobel_y=cv2.Soble(img,cv2.CV_64F,0,1,ksize=3)
    sobely=cv2.convertScaleAbs(sobel_y)
    
    # 当dx、dy均为1时求两个方向的梯度,获取两个方向的边缘信息
    sobelxy=cv2.addWeighted(soblex,0.5,sobley,0.5,0)
    
Scharr算子

G x = − 3 0 3 − 10 0 10 − 3 0 3 ∗ A , G y = − 3 − 10 − 3 0 0 0 3 10 3 ∗ A G_x=\begin{matrix} -3&0&3\\ -10&0&10\\ -3&0&3\\ \end{matrix} * A,G_y=\begin{matrix} -3&-10&-3\\ 0&0&0\\ 3&10&3\\ \end{matrix} * A Gx=31030003103A,Gy=30310010303A

  • Sobel中ksize=-1就是Scharr算子
  • dx=Scharr(src, ddpeth, dx=1, dy=0) 
    dy=Scharr(src, ddpeth, dx=0, dy=1) 
    Scharrxy=cv2.addWeighted(dx,0.5, dy,0.5,0)
    
Laplacian算子

G = 0 1 0 1 − 4 1 0 1 0 G=\begin{matrix} 0&1&0\\ 1&-4&1\\ 0&1&0\\ \end{matrix} G=010141010

  • lap=cv2.Laplacian(img,cv2.CV_64F)
    lap=cv2.convertScaleAbs(lap)
    

图像平滑

噪声类型
  • 椒盐噪声:黑、白像素随机出现
  • 脉冲噪声:白像素随机出现
  • 高斯噪声:噪声强度服从高斯分布
如何去噪声
  • 线性滤波器:高斯噪声
  • 中值滤波:椒盐噪声、脉冲噪声,原卷积核无值,放在图像中后把图像对应值取出从小到大排序,取中间值为该点值
均值滤波
  • 用卷积核框起来的区域的均值来代替中心点元素

  • 优缺点

    • 优点:算法简单,计算速度快
    • 缺点:在除噪声的同时去除了很多细节部分,将图像变得模糊
  • blur=cv2.blur(img,(3,3))
    
方框滤波
  • box=cv2.boxFilter(img,-1,(3,3),normalize=True)
    # -1表示保持原图像尺寸
    # normalize=True表示要进行归一化处理,要用邻域像素值的和除以面积
    # normalize=0时表示不需要进行归一化处理,直接使用邻域像素值的和。
    
  • 是均值滤波的一般形式,可以选择是均值代替中心点元素还是和代替中心点元素
高斯滤波
  • 是线性滤波器
  • 对整个图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他点加权平均后得到
  • 卷积核必须是奇数的
  • aussian=cv2.GaussianBlur(img,(3,3),1)
    # 1表示卷积核在水平方向上的标准差
    
中值滤波
  • 卷积核框起来的区域数值从小到大排序,选中间值作为中心点元素的值
  • median=cv2.medianBlur(img,5)
    # 5表示卷积核大小
    

图像阈值

  • ret,dst=cv2.threshold(src,thresh,maxval,type)

    • scr:输入图,只能输入单通道图像,一般为灰度图
    • dst:输出图
    • thresh:阈值
    • maxval:当像素超过阈值时赋予的值,根据type决定
    • type:二值化操作的类型,包含:
      • cv.THRESH_BINARY:超过阈值部分取maxval,否则0
      • cv.THRESH_BINARY_INV:THRESH_BINARY反转
      • cv.THRESH_TRUNC:大于阈值部分设置为阈值,否则0
      • cv.THRESH_TOZERO:大于阈值部分不变,否则0
      • cv.THRESH_TOZERO_INV:HRESH_TOZERO反转
  • ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
    ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
    ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
    ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
    
    # ret为使用的阈值
    # thresh为使用阈值后的图像
    

边缘检测

Canny边缘检测
  • v1=cv2.Canny(img,minVal,maxVal)
    # minVal、maxVal为大小阈值
    
  • 1、利用高斯一阶偏导核卷积

  • 2、计算每个点的梯度幅值和方向

  • 3、非极大值抑制

  • 4、连续与阈值

    • 定义高、低阈值
    • 高开始边缘曲线,低连续曲线
非极大值抑制
  • IOU–交并比
    • 表示了bounding box 与 ground truth 的重叠度IOU=Area(A∩B)/Area(A∪B)
  • 算法流程
    • (1)将所有框的得分排序,选中最高分及其对应的框 ;
    • (2)遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值,我们就将框删除。(为什么要删除,是因为超过设定阈值,认为两个框的里面的物体属于同一个类别,比如都属于狗这个类别。我们只需要留下一个类别的可能性框图即可;
    • (3)从未处理的框中继续选一个得分最高的,重复上述过程。
双阈值检测
  • 梯度值>maxval:处理为边界
  • minval<梯度值<maxval:连有边界则保留,否则舍弃
  • 梯度值<minval:舍弃

图像轮廓

查找轮廓
  • cv2.findContours(img,mode,method)
    
    # 为了轮廓的准确性,需要先对图像进行二值化处理
    gray=cv2.cvtColor(img,cv2.COLOR_BGRA2GRAY)
    ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
    contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    # contours,hierarchy为返回图像的轮廓和层级
    '''
    - mode:轮廓检索模式
        - RETR_EXTERNAL:只检索最外面的轮廓
        - RETR_LIST:检索所有的轮廓,并将其保存到一条链表中
        - RETR_CCOMP:检索所有的轮廓,并将它们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界
        - RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次
    - method:轮廓逼近方法
        - CHAIN_APPROX_NONE:以freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
        - CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是函数只保留他们的终点部分
    '''
    
绘制轮廓
  • #传入绘制图像、轮廓、轮廓索引、颜色模式、线条厚度
    res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2) 
    #-1这个位置为轮廓顺序标号,-1代表绘制所有轮廓,2表示线条宽度
    
轮廓特征–面积和周长
  • # 选定最外层的轮廓
    cnt=contours[0]
    # 面积计算
    area=cv2.contourArea(cnt)
    # 周长计算
    length=cv2.arcLength(cnt,True)
    # 第二个参数指定形状是闭合轮廓(True)还是曲线。
    
轮廓近似
  • epsilon = 0.1*cv.arcLength(cnt,True) 
    approx = cv.approxPolyDP(cnt,epsilon,True)
    res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
    

模版匹配

  • 从左到右,从下到上

  • 计算相似度的方法:

    • TM_SQDIFF:计算平方不同,计算出来的值越小,越相关,对应数值为0
    • TM_CCORR:计算相关性,计算出来的值越大,越相关,对应数值为2
    • TM_CCOEFF:计算相关系数,计算出来的值越大,越相关,对应数值4
    • TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关,对应数值为1
    • TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关,对应数值为3
    • TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关,对应数值为5
  • 如果原图形大小是A✖️B,模版大小是a✖️b,则输出结果的矩阵是(A-a+1)✖️(B-b+1)

  • result=cv2.matchTemplate(img,templ(模版图),method)
    # 返回的是一个结果集,类型是单通道32浮点型,由每个位置的比较结果组成
    
查找最值
  • minVal,maxVal,minLoc,maxLoc=cv2.minMaxLoc(result)
    '''
    minVal:最小值,没有最小值返回NULL
    maxVal:最大值,没有最大值返回NULL
    minLoc:最小值位置,没有最小值返回NULL
    maxLoc:最大值位置,没有最大值返回NULL
    '''
    w,h=img[:2]#w,h是模版图的宽度和高度
    # 如果方法是TM_SQDIFF或TM_SQDIFF_NORMED,则取最小值
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
      top_left = min_loc
    else:
      top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)
    
多模版匹配
  • 
    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    img_rgb = cv.imread('mario.png')
    img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
    template = cv.imread('mario_coin.png',0)
    w, h = template.shape[::-1]
    res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where( res >= threshold)
    for pt in zip(*loc[::-1]):
      cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
    cv.imwrite('res.png',img_rgb)
    

图像金字塔

  • 高斯金字塔

    • 向下采样方法:缩小,从金字塔底部到最高处
      • 通过高斯核卷积
      • 将所有偶数行列去除
    • 向上采样方法:放大,从金字塔顶部到最低处
      • 将图像在每个方向上扩大为原来的2倍,新增行列填充0
      • 通过之前✖️4的内核卷积
  • 拉普拉斯金字塔

    • 最终图=原始图-向上采样(向下采样)
      • 低通滤波
      • 缩小尺寸
      • 放大尺寸
      • 图像相减
  • up=cv2.pyrUp(img)
    down=cv2.pyrDown(img)
    lap=img-up/down
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值