zoukankan      html  css  js  c++  java
  • OPENCV学习笔记-第一天

    OPENCV

    工业应用还是Halcon https://www.mvtec.com/cn/products/halcon/documentation/

    安装 numpy、opencv-python、matplotlib 并检查

    import cv2 as cv  
    print( cv.__version__ )  
    

    静态图[ imread,imshow,imwrite ]

    ! 注意 :应当直接保存到文件运行,不要在宿主进程(如 cmd.exe)中运行

    import numpy as np
    import cv2 as cv
    img = cv.imread('',0)
    cv.imshow('frameTitle',img)
    cv.waitKey(0)
    cv.destroyAllWindows()
    
    • imread第二个参数是标志位:
      • cv.IMREAD_COLOR 1 加载彩色图像。任何图像的透明度都会被忽视。它是默认标志。
      • cv.IMREAD_GRAYSCALE 0 以灰度模式加载图像
      • cv.IMREAD_UNCHANGED -1 加载图像,包括alpha通道

    视频[暂时跳过]

    绘制

    bg=np.zeros((512,512,8),np.uint8)
    cv.line(bg,(0,0),(511,511),(255,0,0),5)
    
    • 线段: cv.line(图,起点,终点,BGR颜色,宽度-1表示填充否则表示宽度)
    • 矩形: cv.rectangle(图,左上角,右下角,BGR颜色,宽度)
    • 圆形: cv.circle(图,中心点,半径,BGR颜色,宽度-1表示填充否则表示宽度)
    • 椭圆: cv.ellipse(图,中心点,(长轴长,短轴长),逆时针转的角度,startAngle,endAngle,BGR颜色,宽度-1表示填充否则表示宽度)
    • 多边形: cv.polylines(图,点集,是否自动闭合,BGR颜色)
      - 点集是将 顶点坐标集合(如 [[1,2],[3,4],[5,6]])转换为ROWS12 的张量表示,一般使用reshape(-1,1,2)转换,例如
      points = np.array([[1,2],[3,4],[5,6],[7,8]],np.int32) points = points.reshape((-1,1,2)) cv.polylines(pic,[points],True,(255,255,0))
    • 文字: cv.putText(图片,文字,位置,字体,大小,颜色,厚度,线条类型)
      font = cv.FONT_HERSHEY_SIMPLEX cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)

    练习

    创建拖拽出圆或矩形的绘制面板

    import numpy as np
    import cv2 as cv
    import math
    
    drawStatus=False
    isRectangle=False
    ix,iy=-1,-1
    def click_callback(event,x,y,flags,param):
        global drawStatus,isRectangle,ix,iy
        if event == cv.EVENT_LBUTTONDOWN:
            drawStatus = True
            ix,iy=x,y
        elif event == cv.EVENT_MOUSEMOVE:
            if drawStatus==True:
                if isRectangle==True:
                    cv.rectangle(bg,(ix,iy),(x,y),(0,255,0),1)
                else:
                    cv.circle(bg,(ix,iy),math.trunc(math.fabs(x-ix)),(255,0,0),1)
        elif event == cv.EVENT_LBUTTONUP:
            drawStatus=False
            if isRectangle==True:
                cv.rectangle(bg,(ix,iy),(x,y),(0,255,0),1)
            else:
                cv.circle(bg,(ix,iy),math.trunc(math.fabs(x-ix)),(255,0,0),1)
    
    bg = np.zeros((512,512,3),np.uint8)
    cv.namedWindow('image')
    cv.setMouseCallback('image',click_callback)
    while(1):
        cv.imshow('image',bg)
        k = cv.waitKey(20)
        if k==77 | k==109:
            isRectangle = not isRectangle
        if cv.waitKey(20)==27:
            break
    cv.destroyAllWindows()
    
    

    控制栏

    • 创建控制栏 cv.createTrackbar(名称,窗体名,最小值,最大值,回调函数)
    • 获取控制栏值 cv.getTrackbarPos(名称)
    
    def donothing(arg):
        pass
    
    img = np.zeros((300,512,3),np.uint8)
    cv.namedWindow('image')
    cv.createTrackbar('B','image',0,255,donothing)
    cv.createTrackbar('G','image',0,255,donothing)
    cv.createTrackbar('R','image',0,255,donothing)
    
    
    while(1):
        cv.imshow('image',img)
        k = cv.waitKey(20)
        if k==27:
            break
        r = cv.getTrackbarPos('R','image')
        g = cv.getTrackbarPos('G','image')
        b = cv.getTrackbarPos('B','image')
        img[:]=[b,g,r]
    cv.destroyAllWindows()
    
    

    章节练习

    创建颜色和粗细可调的绘制面板

    
    r,g,b,width=0,0,0,1
    
    def donothing(val):
        pass
    
    img = np.zeros((300,512,3),np.uint8)
    cv.namedWindow('image')
    cv.createTrackbar('R','image',0,255,donothing)
    cv.createTrackbar('G','image',0,255,donothing)
    cv.createTrackbar('B','image',0,255,donothing)
    cv.createTrackbar('W','image',1,10,donothing)
    
    ix,iy=0,0
    drawStatus = False
    def click_callback(event,x,y,flags,arg):
        global drawStatus,ix,iy,width
        if event == cv.EVENT_LBUTTONDOWN:
            drawStatus = True
            ix,iy=x,y
        elif event == cv.EVENT_MOUSEMOVE:
            if drawStatus is True:
                print(img)
                cv.circle(img,(ix,iy),math.trunc(math.fabs(x-ix)),(b,g,r),width)
        elif event == cv.EVENT_LBUTTONUP:
            drawStatus = False
    
    cv.setMouseCallback('image',click_callback)
    while(1):
        cv.imshow('image',img)
        k = cv.waitKey(20)
        
        if k==27:
            break
        r = cv.getTrackbarPos('R','image')
        g = cv.getTrackbarPos('G','image')
        b = cv.getTrackbarPos('B','image')
        width = cv.getTrackbarPos('W','image')
    cv.destroyAllWindows()
    
    
    

    图像的基本操作

    • 像素编辑

      • 优化前
      img = cv.imread('pic.png')
      pos = img[100,100] '''位置100,100的像素'''
      blue = img[100,100,0] ''' 访问 100,100 处的 blue 像素 ,因为是BGR颜色,第0位是蓝色 '''
      img[100,100] = [200,0,0] '''修改像素'''
      
      • 优化后
      red = img.item(5,5,2)
      img.itemset((5,5,2),100) ''' 修改 5,5 处 红色 值为 100 '''
      
    • 图像属性

      • img.shape : 行,列和通道数的元组(如果图像是彩色的) ,如果是灰度(0)则不返回元组,常用来区别是否是灰度图
      • img.size : 像素总数
      • img.dtype : 图像数据类型
    • ROI(感兴趣区域)的编辑

      • 置换
      ball = img[280:340, 330:390]
      img[273:333, 100:160] = ball
      
    • 拆分通道(耗时操作)

      • 普通做法
       b,g,r = cv.split(img) >>> img = cv.merge((b,g,r))
       or
       b = img [:, :, 0]
      
      • 索引 例如将所有红色像素都设置为0
      img [:, :, 2] = 0
      
    • 边框

      cv.copyMakeBorder(图像,上,下,左,右,边框类型)
      
    • 图像加法

      • cv.add(img1,img2) 不推荐使用numpy的 img1+img2
    • 图像融合

      • dst = cv.addWeighted(img1,0.7,img2,0.3,0)
    • 融合练习

      img1 = cv.imread('1.png')
      img2 = cv.imread('2.png')
      
      cv.namedWindow('image')
      cv.namedWindow('combine')
      bg = np.zeros((300,521,3),np.uint8)
      cv.createTrackbar('Opacity_IMG1','image',0,100,lambda x:0)
      cv.createTrackbar('Opacity_IMG2','image',0,100,lambda x:0)
      
      while(1):
          cv.imshow('image',bg)
          k = cv.waitKey(20)
          if k==27:
              break
          op1 = cv.getTrackbarPos('Opacity_IMG1','image')
          op2 = cv.getTrackbarPos('Opacity_IMG2','image')
          img3 = cv.addWeighted(img1,op1/100,img2,op2/100,0)
          cv.imshow('combine',img3)
      cv.destroyAllWindows()
      

    对象追踪

    • 获取输入

      #cap = cv.VideoCapture(0) #实时视频流
      cap = cv.VideoCapture('blueBall.mp4') #视频流
      
    • 对hsv追踪时,需要先对BGR颜色转为hsv颜色,例如对于 BGR: 246,138,39 (hsv:106,215,246),使用下列参数追踪效果较好:

      121,128,72 - 253,248,255

    • 读取实时图像: _, frame = cap.read() ,其中 _ 表示是否可以继续读取,frame 表示当前一帧图像

    • 改变颜色空间 cv.cvtColor(图像/颜色, flag)

      • flag 常见的包括: COLOR_BGR2GRAY / COLOR_BGR2HSV

        可以使用 flags = [i for i in dir(cv) if i.startswith('COLOR_')] 获取所有flag

      • 当需要转换颜色时

        #例如颜色的  BGR = 10,11,12
        custom_color=np.uint8([[[10,11,12]]])
        hsv_volor=cv.cvtColor(custom_color,cv.COLOR_BGR2HSV)
        
    • 获取掩膜,可实现二值化操作

      • mask = cv.inRange(一帧hsv图像,hsv颜色左边界,hsv颜色右边界)
    • 合并图像和掩膜

      • res = cv.bitwise_and(inputFrame1,inputFrame2,outputFrame,mask=mask) ,可以使用多个掩膜合并同一个图像

    当前帧(frame)、掩膜(mask)、合并结果(res) 都可以实时预览,例如使用 cv.imshow('windowName',frame) 即可

    • 扩展 : 灰度化比例公式 :R * 0.3 + G * 0.59 + B * 0.11

    • 练习1:追踪蓝色小球

      cv.namedWindow('control')
      bg = np.zeros((300,600,6),np.uint8)
      cv.createTrackbar('LB','control',0,255,lambda x:0)
      cv.createTrackbar('LG','control',0,255,lambda x:0)
      cv.createTrackbar('LR','control',0,255,lambda x:0)
      
      cv.createTrackbar('HB','control',0,255,lambda x:0)
      cv.createTrackbar('HG','control',0,255,lambda x:0)
      cv.createTrackbar('HR','control',0,255,lambda x:0)
      
      while(1):
          cap = cv.VideoCapture('mixColor.mp4') #视频流
          while(cap.isOpened()):
              _, frame = cap.read()
              if not _:
                  break
              # 转换颜色空间 BGR 到 HSV
              hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
              # 定义HSV中蓝色的范围
              lb=cv.getTrackbarPos('LB','control')
              lg=cv.getTrackbarPos('LG','control')
              lr=cv.getTrackbarPos('LR','control')
              hb=cv.getTrackbarPos('HB','control')
              hg=cv.getTrackbarPos('HG','control')
              hr=cv.getTrackbarPos('HR','control')
              #print('low_bgr : %d,%d,%d'%(lb,lg,lr))
              #print('high_bgr : %d,%d,%d'%(hb,hg,hr))
              
              lower_blue = np.array([lb,lg,lr])
              upper_blue = np.array([hb,hg,hr])
      
              mask = cv.inRange(hsv, lower_blue, upper_blue)
              # 将掩膜和图像逐像素相加
              res = cv.bitwise_and(frame,frame, mask = mask)
              cv.imshow('frame',frame)
              cv.imshow('mask',mask)
              cv.imshow('res',res)
              k = cv.waitKey(5) & 0xFF
              if k == 27:
                  break
          cap.release()
          print('release')
      cv.destroyAllWindows()
      
    • 练习2:追踪红、蓝、绿多颜色

      
      cv.namedWindow('control')
      bg = np.zeros((300,512,3),np.uint8)
      cv.createTrackbar('Look_B','control',0,1,lambda x:0)
      cv.createTrackbar('Look_G','control',0,1,lambda x:0)
      cv.createTrackbar('Look_R','control',0,1,lambda x:0)
      
      cv.createTrackbar('B','control',0,255,lambda x:0)
      cv.createTrackbar('G','control',0,255,lambda x:0)
      cv.createTrackbar('R','control',0,255,lambda x:0)
      cv.createTrackbar('END','control',0,255,lambda x:0)
      
      #225 - 285
      #112.5 - 142.5
      b_min=np.array([105,190,130])
      b_max=np.array([116,255,255])
      
      #0 - 75
      g_min=np.array([40,40,0])
      g_max=np.array([83,255,255])
      
      #135 - 225
      #70-115
      r_min=np.array([160,60,0])
      r_max=np.array([225,255,180])
      
      while(1):
          cap = cv.VideoCapture('allColor.mp4')
          while(cap.isOpened()):
              _,frame = cap.read()
              if not _:
                  break
              k = cv.waitKey(5) & 0xff
              if k is 27:
                  break
              
              o_b=cv.getTrackbarPos('Look_B','control')
              o_g=cv.getTrackbarPos('Look_G','control')
              o_r=cv.getTrackbarPos('Look_R','control')
      
              b=cv.getTrackbarPos('B','control')
              g=cv.getTrackbarPos('G','control')
              r=cv.getTrackbarPos('R','control')
              #g_min=np.array([b,g,r])
              
              maskB,maskG,maskR=0,0,0
              resB,resG,resR,res=0,0,0,frame[:]
              hsv = cv.cvtColor(frame,cv.COLOR_BGR2HSV)
              if o_b is 1:
                  maskB = cv.inRange(hsv,b_min,b_max)
                  resB = cv.bitwise_and(frame,frame,mask=maskB)
              if o_g is 1:
                  maskG = cv.inRange(hsv,g_min,g_max)
                  resG = cv.bitwise_and(frame,res,mask=maskG)
              if o_r is 1:
                  maskR = cv.inRange(hsv,r_min,r_max)
                  resR = cv.bitwise_and(frame,frame,mask=maskR)
      
              dst = cv.addWeighted(resB,1,resG,1,0)
              dst = cv.addWeighted(dst,1,resR,1,0)
              
              if len(dst)==4:
                  cv.imshow('res',frame)
              else:
                  cv.imshow('res',dst)
              #cv.imshow('maskR',maskR)
              cv.imshow('frame',frame)
          cap.release()
          print('release')
          q = cv.waitKey(100) & 0xff
          if q is 27:
              break
      cv.destroyAllWindows()
      
      

      难点: 如何通过BGR确定HSV的范围。如果没有具体数值追踪,建议保存HSV色盘,通过实际检测确定范围


    几何变换 04/03/2020

    • 缩放

      • cv.resize(输入图像,(缩放后宽,缩放后高),fx=宽度缩放倍数,fy=高度缩放倍数,interpolation = 缩放模式) ,窗口一同变化

      缩放模式包括: cv.INTER_LINEAR(推荐) / cv.INTER_CUBIC(慢) / cv.INTER_AREA(默认)
      例如:cv.resize(img,fx=2,fy=0.5,interpolation=cv.INTER_LINEAR) 表示宽度放大一倍,高度缩小为原来的 1/2

    • 平移

      • cv.warpAffine(原图,移动参数,(行数rows,列数cols)) 仿射变换 warpAfine :( 是 warp-使 不是 wrap-包

            img = cv.imread('1.png',0)
            rows,cols=img.shape
            M = np.float32([[1,0,100],[0,1,50]])#转换矩阵
            res = cv.warpAffine(img,M,(rows,cols))
            cv.imshow('image',res)
        

        其中
        M[0] 表示X方向,M[0][2]表示向右平移量,M[0][1]表示逆时针斜向拉伸角度 45°,M[0][0]表示X方向缩放倍数 ;
        M[1] 表示Y方向,M[1][2]表示向下平移量,M[0][1]表示Y方向缩放倍数,M[0][0]表示顺时针斜向拉伸角度 45°;
        定义时应该考虑的是对应位置不冲突,因此:

        [[ X缩放,逆时针拉伸
        45°,X平移量 ] , [ 顺时针拉伸
        45°,Y缩放,Y平移量 ]]

      • 练习:在渲染窗口中使用鼠标控制缩放、移动图像

        
        img = cv.imread('1.png',1)
        rows,cols,x=img.shape
        cv.imshow('image',img)
        
        canMove=False
        ix,iy,res,res_move=0,0,img,img
        rrows,rcols,x=res.shape
        lenx,leny,M=0,0,np.float32([[1,0,0],[0,1,0]])#保存之前的平移量,防止回弹;或者直接用img接收warpAffine结果,但会改变原始图像
        def mouse_callback(event,x,y,flags,params):
            global canMove,ix,iy,lenx,leny,rows,cols,res,scale,img,rrows,rcols,res_move,M
            if event == cv.EVENT_LBUTTONDOWN:
                canMove=True
                ix,iy=x,y
            elif event == cv.EVENT_MOUSEMOVE:
                if canMove is True:
                    M = np.float32([[1,0,math.trunc(x-ix)+lenx],[0,1,math.trunc(y-iy)+leny]])
                    res_move = cv.warpAffine(res,M,(rrows,rcols))#img
                    cv.imshow('image',res_move)
            elif event == cv.EVENT_LBUTTONUP:
                canMove = False
                lenx+=(x-ix)
                leny+=(y-iy)
            elif event == cv.EVENT_MOUSEWHEEL:
                step = 10
                if flags>0:
                    rrows+=step
                    rcols+=step
                elif flags<0:
                    rrows-=step
                    rcols-=step
                
                res = cv.resize(img,(rrows,rcols),interpolation=cv.INTER_LINEAR)#放大后移动需返回当前窗体,否则一经置0无法恢复
                cv.imshow('image',res)
                
        cv.setMouseCallback('image',mouse_callback)
        
        
    • 旋转

      • cv.getRorationMatrix2D(中心点坐标,逆时针旋转角度,缩放倍数) 获取用于旋转的转换矩阵

        rows.cols=img.shape
        centerX,centerY=(rows-1)/2.0,(cols-1)/2.0
        M = cv.getRorationMatrix2D((centerX,centerY),90,1)#转换矩阵
        res = cv.warpAffine(img,M,(rows,cols))#最后一组参数是显示的大小,旋转后可能长宽不一,要全部显示可以适当扩大一些
        
    • 补充

      • matplotlib.pyplot 的 subplot 作用是在一个窗体绘制多幅图像
      • 定义 : matplotlib.subplot(rowsNum,colsNum,rowPlotOrder)
      • 示例:
        
        
        
        
    幼稚!你要是早来几个月你就知道被 @趣往 支配的恐惧了,那时候她就是幸运闪本人_____ @拆炸弹的文青 如是说
  • 相关阅读:
    hibernate--could not initialize proxy
    20160509-hibernate--继承映射
    CF1111C Creative Snap
    CF1097D Makoto and a Blackboard
    CF1091D New Year and the Permutation Concatenation
    CF1096D Easy Problem
    CF1076E Vasya and a Tree
    CF1081C Colorful Bricks
    CF1081E Missing Numbers
    CF1093D Beautiful Graph
  • 原文地址:https://www.cnblogs.com/logicmind/p/12624499.html
Copyright © 2011-2022 走看看