• opencv计算机视觉学习笔记三


    第四章 深度估计和分割

    1 捕获深度摄像头的帧

    深度图  灰度  每个像素都是摄像头到物体表面的距离 毫米

    点云图  彩色  每种颜色对应一个维度空间  米

    视差图  灰度  每个像素代表物体表面的立体视差 近大远小

    有效深度掩模一个给定像素的深度信息是否有效

    2 从视差图中得到掩模

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2016/12/1 10:16
    # @Author  : Retacn
    # @Site    : 深度摄像头数据的处理
    # @File    : depth.py
    # @Software: PyCharm
    __author__ = "retacn"
    __copyright__ = "property of mankind."
    __license__ = "CN"
    __version__ = "0.0.1"
    __maintainer__ = "retacn"
    __email__ = "zhenhuayue@sina.com"
    __status__ = "Development"
    
    import numpy as np
    
    
    #设备
    CAP_OPENNI=900
    CAP_OPENNI_ASUS=910
    
    #通道(基于浮点数的距离)
    CAP_OPENNI_DEPTH_MAP=0
    
    #会得到bgr图像
    CAP_OPENNI_POINT_CLOUD_MAP=1
    
    #XYZ
    CAP_OPENNI_DISPARITY_MAP=2
    
    #
    CAP_OPENNI_DISPARITY_MAP_32F=3
    CAP_OPENNI_VALID_DEPTH_MASK=4
    
    CAP_OPENNI_BGR_IMAGE=5
    CAP_OPENNI_GRAY_IMAGE=6
    
    #生成掩模
    def createMedianMask(disparityMap,#视差图
                         validDepthMask,#有效深度掩模
                         rect=None):#矩形
        if  rect is not None:
            x,y,w,h=rect
            disparityMap=disparityMap[y:y+h,x:x+w]
            validDepthMask=validDepthMask[y:y+h,x:x+w]
        #得到中值
        median=np.median(disparityMap)
        #生成掩模,逐像素进行布尔操作
        return np.where((validDepthMask==0) | (abs(disparityMap-median)<12),#值为真假的数组,当有效视差与平均视差>=12,看作噪声
                        1.0,#为真时,数组相应元素为该值
                        0.0)#为假时,为该值

    3 对复制操作进行掩模

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2016/12/1 10:22
    # @Author  : Retacn
    # @Site    : 矩形区域复制
    # @File    : rects.py
    # @Software: PyCharm
    __author__ = "retacn"
    __copyright__ = "property of mankind."
    __license__ = "CN"
    __version__ = "0.0.1"
    __maintainer__ = "retacn"
    __email__ = "zhenhuayue@sina.com"
    __status__ = "Development"
    
    import cv2
    import numpy as np
    from Three import utils
    
    #对复制操作执行掩模
    def copyRect(src,
                 dst,
                 srcRect,
                 dstRect,
                 mask=None,#掩模参数,掩模要和图像有相同的通道数
                 interpolation=cv2.INTER_LINEAR):#插值方法为线性插值
        x0,y0,w0,h0=srcRect
        x1,y1,w1,h1=dstRect
    
        #如果掩模为空,则执行复制操作
        if mask is None:
            dst[y1:y1+h1,x1:x1+w1]=cv2.resize(src[y0:y0+h0,y0:y0+h0],#源图像
                                              (w1,h1),#目标图像
                                              interpolation=interpolation)#插值方法
        else:
            #如果掩模为单通道,则复制通道
            if not utils.isGray(src):
                mask=mask.repeat(3).reshape(h0,w0,3)
            dst[y1:y1+h1,x1:x1+w1]=np.where(cv2.resize(mask,(w1,h1),interpolation=cv2.INTER_NEAREST),
                                            cv2.resize(src[y0:y0+h0,x0:x0+w0],(w1,h1),interpolation=interpolation),
                                            dst[y1:y1 + h1, x1:x1 + w1]
                                            )
    
    #一组矩形的循环交换
    def swqpRects(src,dst,rects,masks=None,interpolation=cv2.INTER_LINEAR):
        if dst is not src:
            dst[:]=src
    
        numRects=len(rects)
        if numRects<2:
            return
    
        if masks is None:
            masks=[None]*numRects
    
        x,y,w,h=rects[numRects-1]
        temp=src[y:y+h,x:x+w].copy()
    
        i=numRects-2
        while i>=0:
            copyRect(src,dst,rects[i],rects[i+1],masks[i],interpolation)
            i-=1
        copyRect(temp,dst,(0,0,w,h),rects[0],masks[numRects-1],interpolation)

     4 使用普通摄像头进行深试评估

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2016/12/1 11:40
    # @Author  : Retacn
    # @Site    : 使用普通摄像头进行深试估计
    # @File    : commonCamera2Depth.py
    # @Software: PyCharm
    __author__ = "retacn"
    __copyright__ = "property of mankind."
    __license__ = "CN"
    __version__ = "0.0.1"
    __maintainer__ = "retacn"
    __email__ = "zhenhuayue@sina.com"
    __status__ = "Development"
    
    import cv2
    import numpy as np
    
    def update(val=0):
        stereo.setBlockSize(cv2.getTrackbarPos('window_size','disparity'))
        stereo.setUniquenessRatio(cv2.getTrackbarPos('uniquenessRatio','disparity'))
        stereo.setSpeckleWindowSize(cv2.getTrackbarPos('speckleWindowSize','disparity'))
        stereo.setSpeckleRange(cv2.getTrackbarPos('speckleRange','disparity'))
        stereo.setDisp12MaxDiff(cv2.getTrackbarPos('disp12MaxDiff','disparity'))
        print('computing disparity...')
        disp = stereo.compute(imgL, imgR).astype(np.float32) / 16.0
        cv2.imshow('left', imgL)
        cv2.imshow('disparity', (disp - min_disp) / num_disp)
    
    if __name__=='__main__':
        windows_size=5 #一个匹配块的大小,大于1的奇数
        min_disp=16 #最小视差值
        num_disp=192-min_disp #最大视差值和最小视差值的差
        blockSize=windows_size
        uniquenessRatio=1
        speckleRange=3 #每个已连接部分的最大视差变化
        speckleWindowSize=3 #平滑视差区域的最大窗口尺寸
        disp12MaxDiff=200
        P1=600 #控制视差图平滑度有第一个参数
        P2=2400#第二个参数,值越大视差图越平滑
    
        #读入图像
        imgL=cv2.imread('../imgl.jpg')
        imgR=cv2.imread('../imgr.jpg')
    
        cv2.namedWindow('disparity')
        cv2.createTrackbar('speckleRange','disparity',speckleRange,50,update)
        cv2.createTrackbar('window_size','disparity',windows_size,21,update)
        cv2.createTrackbar('speckleWindowSize','disparity',speckleWindowSize,200,update)
        cv2.createTrackbar('uniquenessRatio','disparity',uniquenessRatio,50,update)
        cv2.createTrackbar('disp12MaxDiff','disparity',disp12MaxDiff,250,update)
    
        stereo=cv2.StereoSGBM_create(minDisparity=min_disp,
                                     numDisparities=num_disp,
                                     blockSize=blockSize,
                                     uniquenessRatio=uniquenessRatio,
                                     speckleRange=speckleRange,
                                     speckleWindowSize=speckleWindowSize,
                                     disp12MaxDiff=disp12MaxDiff,
                                     P1=P1,
                                     P2=P2)
    
        update()
        cv2.waitKey()

    5 使用分水岭和grabcut算法进行物体分割

     A 使用brabcut进行前景检测

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2016/12/2 11:17
    # @Author  : Retacn
    # @Site    : 使用grubCut进行前景检测
    # @File    : grabcutNew.py
    # @Software: PyCharm
    __author__ = "retacn"
    __copyright__ = "property of mankind."
    __license__ = "CN"
    __version__ = "0.0.1"
    __maintainer__ = "retacn"
    __email__ = "zhenhuayue@sina.com"
    __status__ = "Development"
    
    import cv2
    import numpy as np
    import sys
    
    # 定义颜色
    BLUE = [255, 0, 0# rectangle color
    RED = [0, 0, 255# PR BG
    GREEN = [0, 255, 0# PR FG
    BLACK = [0, 0, 0# sure BG
    WHITE = [255, 255, 255# sure FG
    
    DRAW_BG = {'color': BLACK, 'val': 0}
    DRAW_FG = {'color': WHITE, 'val': 1}
    DRAW_PR_FG = {'color': GREEN, 'val': 3}
    DRAW_PR_BG = {'color': RED, 'val': 2}
    
    # 设置标志位
    rect = (0, 0, 1, 1# 隔离对像矩形
    drawing = False  # 绘制标志位
    rectangle = False  # 矩形绘制标志
    rect_over = False  # 检查隔离矩形是否绘制
    rect_or_mask = 100  # 掩模模式
    value = DRAW_FG  #
    thickness = # 画笔宽度
    
    
    # 自定义鼠标回调函数
    def onmouse(event, x, y, flags, param):
        # 定义全局变量
        global img, img2, drawing, value, mask, rectangle, rect, rect_or_mask, ix, iy, rect_over
    
        # 绘制隔离矩形
        if event == cv2.EVENT_RBUTTONDOWN:  # 鼠标右健按下,开始绘制矩形
            rectangle = True
            ix, iy = x, y
    
        elif event == cv2.EVENT_MOUSEMOVE:  # 鼠标移动事件
            if rectangle == True# 绘制矩形
                img = img2.copy()
                cv2.rectangle(img# 源图像
                              (ix, iy)# 开始点
                              (x, y)# 结束点
                              BLUE# 画笔颜色
                              2# 画笔宽度
                rect = (min(ix, x), min(iy, y), abs(ix - x), abs(iy - y))
                rect_or_mask = 0
    
        elif event == cv2.EVENT_RBUTTONUP:  # 右键抬起
            rectangle = False  # 设置标志位,矩形绘制完成
            rect_over = True
            cv2.rectangle(img, (ix, iy), (x, y), BLUE, 2)
            rect = (min(ix, x), min(iy, y), abs(ix - x), abs(iy - y))
            rect_or_mask=0
            print('按下 n , 开始绘制')
    
        #绘制隔离圆形
        if event==cv2.EVENT_LBUTTONDOWN: #左键按下
            if rect_over==False:
                print("请先绘制圆形")
            else:
                drawing=True
                cv2.circle(img,(x,y),thickness,value['color'],-1)
                cv2.circle(mask,(x,y),thickness,value['color'],-1)
    
        elif event==cv2.EVENT_MOUSEMOVE:
            if drawing==True:
                cv2.circle(img, (x, y), thickness, value['color'], -1)
                cv2.circle(mask, (x, y), thickness, value['color'], -1)
    
        elif event==cv2.EVENT_LBUTTONUP:
            if drawing==True:
                drawing=False
                cv2.circle(img, (x, y), thickness, value['color'], -1)
                cv2.circle(mask, (x, y), thickness, value['color'], -1)
    
    if __name__ == '__main__':
        fileName = '../test1.jpg'
    
        img = cv2.imread(fileName)
        img2 = img.copy()
        mask = np.zeros(img.shape[:2], dtype=np.uint8)
        output = np.zeros(img.shape, np.uint8)
    
        # 定义输入输出窗口
        cv2.namedWindow("output")
        cv2.namedWindow('input')
        #输出窗口注册鼠标事件
        cv2.setMouseCallback('input', onmouse)
        cv2.moveWindow('input',img.shape[1]+10,90)
    
        print("操作指南:
    ")
        print('使用鼠标右健在源图像中绘制矩形
    ')
    
        while(1):
            #显示图像
            cv2.imshow('output',output)
            cv2.imshow('input',img)
            k=0xFF&cv2.waitKey(1)
    
            if k==27: #ESC键退出
                break
            elif k==ord('0'):#绘制背景
                print("左键绘制background标识区域 
    ")
                value=DRAW_BG
            elif k==ord('1'):#绘制前景
                print('左键绘制foreground标识区域 
    ')
                value=DRAW_FG
            elif k==ord('2'):
                value=DRAW_PR_BG
            elif k == ord('3'):
                value = DRAW_PR_FG
            elif k==ord('s'):# 保存图像
                bar=np.zeros((img.shape[0],5,3),np.uint8)
                res=np.hstack((img2.bar,img,bar,output))
                cv2.imwrite('grabcut_output.png',res)
                print('保存图像')
            elif k==ord('r'):#重置
                print('开始重置 
    ')
                rect = (0, 0, 1, 1)
                drawing = False
                rectangle = False
                rect_or_mask = 100
                rect_over = False
                value = DRAW_FG
                img = img2.copy()
                mask = np.zeros(img.shape[:2], dtype=np.uint8)
                output = np.zeros(img.shape, np.uint8)
            elif k == ord('n'):  # 图像截取
                print(""" For finer touchups, mark foreground and background after pressing keys 0-3
                       and again press 'n' 
    """)
                if (rect_or_mask == 0):  # 设置掩模
                    bgdmodel = np.zeros((1, 65), np.float64)
                    fgdmodel = np.zeros((1, 65), np.float64)
                    cv2.grabCut(img2, mask, rect, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_RECT)
                    rect_or_mask = 1
                elif rect_or_mask == 1# 设置掩模
                    bgdmodel = np.zeros((1, 65), np.float64)
                    fgdmodel = np.zeros((1, 65), np.float64)
                    cv2.grabCut(img2, mask, rect, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_MASK)
    
            mask2 = np.where((mask == 1) + (mask == 3), 255, 0).astype('uint8')
            output = cv2.bitwise_and(img2, img2, mask=mask2)
    
        cv2.destroyAllWindows()

    B 使用分水岭算法进行图像分割

    示例代码如下:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2016/12/2 12:21
    # @Author  : Retacn
    # @Site    : 使用分水岭算法进行图像分割
    # @File    : watershed.py
    # @Software: PyCharm
    __author__ = "retacn"
    __copyright__ = "property of mankind."
    __license__ = "CN"
    __version__ = "0.0.1"
    __maintainer__ = "retacn"
    __email__ = "zhenhuayue@sina.com"
    __status__ = "Development"
    
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img =cv2.imread('../test1.jpg')
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    #转换为灰度图,设置阈值
    ret,thresh=cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    
    kernel=np.ones((3,3),np.uint8)
    opening=cv2.morphologyEx(thresh,#源图像
                             cv2.MORPH_OPEN, #开运算
                             kernel, #核
                             iterations=2)#迭代次数
    
    #取得确定的前景区域
    sure_bg=cv2.dilate(opening,kernel,iterations=3)
    dist_transform=cv2.distanceTransform(opening,cv2.DIST_L2,5)
    ret,sure_fg=cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
    
    sure_fg=np.uint8(sure_fg)
    unknown=cv2.subtract(sure_bg,sure_fg)
    
    ret,markers=cv2.connectedComponents(sure_fg)
    markers=markers+1
    markers[unknown==255]=0
    
    markers=cv2.watershed(img,markers)
    img[markers==-1]=[255,0,0]
    plt.imshow(img)
    plt.show()
  • 相关阅读:
    Linux部署之NFS方式安装系统
    VMware Workstation Pro学习探索(Linux,Docker)
    sqlserver最大内存设置太小导致无法启动sql服务
    Docker下安装Sqlserver(mssql)
    docker错误:net/http: TLS handshake timeout;解决方案
    Linux和Docker常用命令
    Linux及Docker学习记录
    .net core视图预编译
    oracle的一些简单语法
    Oracle安装连接常见错误
  • 原文地址:https://www.cnblogs.com/retacn-yue/p/6194155.html
Copyright © 2020-2023  润新知