OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)

文章来源基于OpenCV的区域分割、轮廓检测和阈值处理

介绍

OpenCV是一个用于图像处理、分析、机器视觉方面的开源函数库。该库的所有代码都经过优化,计算效率很高,因为,它更专注于设计成为一种用于实时系统的开源库。opencv采用C语言进行优化,而且,在多核机器上面,其运行速度会更快。它的一个目标是提供友好的机器视觉接口函数,从而使得复杂的机器视觉产品可以加速面世。该库包含了横跨工业产品检测、医学图像处理、安防、用户界面、摄像头标定、三维成像、机器视觉等领域的超过500个接口函数。同时,由于计算机视觉与机器学习密不可分,该库也包含了比较常用的一些机器学习算法。或许,很多人知道,图像识别、机器视觉在安防领域有所应用。但,很少有人知道,在航拍图片、街道图片(例如google street view)中,要严重依赖于机器视觉的摄像头标定、图像融合等技术。
      近年来,在入侵检测、特定目标跟踪、目标检测、人脸检测、人脸识别、人脸跟踪等领域,opencv可谓大显身手,而这些,仅仅是其应用的冰山一角。

假设我们需要从输入帧中检测到一个目标。我们可以在框架中 定义一个子区域作为整个检测区域,一般有下面三个步骤:

  • 定义感兴趣的区域
  • 在ROI区域中检测轮廓
  • 阈值检测轮廓轮廓线

ROI定义

我们感兴趣的对象所在的帧内的子区域称为感兴趣区域(ROI)。

在输入整个帧中定义ROI的过程称为ROI分割。

OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)_第1张图片

图1 ROI区域

 我们选择框架中的特定区域,并以矩形方法提供其尺寸,以便它将在框架上绘制矩形的ROI,如图1所示。

轮廓定义:轮廓表示用来限制对象形状的轮廓。

在将ROI框架设为阈值后,找到轮廓效果最佳。

阈值定义::阈值分割时图像分割的一种简单形式,这是将RGB图像或者灰度图像转化为二进制图像的过程。

 

OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)_第2张图片

图2二进制阈值图像

通过对RGB图像进行阈值处理,程序较容易找到轮廓,因为由于ROI中感兴趣对象的颜色将成为黑色或者白色,因此图像分割可以较容易实现 。

对框架进行阈值处理并检测到轮廓之后,我们应用凸包技术对围绕对象点的紧密拟合凸边界进行设置。如图3所示。

OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)_第3张图片

图3凸包技术检测的图像

可以遮盖ROI以仅显示被检测到的轮廓本身覆盖的目标。

Mask定义

首先我们从物理的角度来看看mask到底是什么过程。
在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),其作用是:在硅片上选定的区域中对一个不透明的图形模板遮盖,继而下面的腐蚀或扩散将只影响选定的区域以外的区域。
图像掩膜与其类似,用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。

OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)_第4张图片

因此,基本上在这里我们将掩盖ROI的背景。为此,首先我们将修复ROI的背景。然后,在固定背景之后,我们将从框架中减去背景,并用wewant背景(这里是一个简单的黑色框架)替换它。

mask的结果如图4所示

OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)_第5张图片

图4 Mask图像

code:

Code运行:通过python运行,选择合适的背景条件,按b键,电脑相机开始捕捉目标,进行拟合,按r键获取当前的目标可以保存图像。

import cv2
import numpy as np
import copy
import math

x=0.5  # start point/total width
y=0.8  # start point/total width
threshold = 60  # BINARY threshold
blurValue = 7  # GaussianBlur parameter
bgSubThreshold = 50
learningRate = 0

# variables
isBgCaptured = 0   # whether the background captured

def removeBG(frame): #Subtracting the background
    fgmask = bgModel.apply(frame,learningRate=learningRate)

    kernel = np.ones((3, 3), np.uint8)
    fgmask = cv2.erode(fgmask, kernel, iterations=1)
    res = cv2.bitwise_and(frame, frame, mask=fgmask)
    return res

# Camera
camera = cv2.VideoCapture(0)
camera.set(10,200)



while camera.isOpened():
    ret, frame = camera.read()
    frame = cv2.bilateralFilter(frame, 5, 50, 100)  # smoothening filter
    frame = cv2.flip(frame, 1)  # flip the frame horizontally
    cv2.rectangle(frame, (int(x * frame.shape[1]), 0),
                 (frame.shape[1], int(y * frame.shape[0])), (255, 0, 0), 2) #drawing ROI
    cv2.imshow('original', frame)

    #  Main operation
    if isBgCaptured == 1:  # this part wont run until background captured
        img = removeBG(frame)
        img = img[0:int(y * frame.shape[0]),
                    int(x * frame.shape[1]):frame.shape[1]]  # clip the ROI
        cv2.imshow('mask', img)

        # convert the image into binary image
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        blur = cv2.GaussianBlur(gray, (blurValue, blurValue), 0)
        cv2.imshow('blur', blur)
        ret, thresh = cv2.threshold(blur, threshold, 255, cv2.THRESH_BINARY) #thresholding the frame
        cv2.imshow('ori', thresh)


        # get the coutours
        thresh1 = copy.deepcopy(thresh)
        contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #detecting contours
        length = len(contours)
        maxArea = -1
        if length > 0:
            for i in range(length):  # find the biggest contour (according to area)
                temp = contours[i]
                area = cv2.contourArea(temp)
                if area > maxArea:
                    maxArea = area
                    ci = i

            res = contours[ci]
            hull = cv2.convexHull(res) #applying convex hull technique
            drawing = np.zeros(img.shape, np.uint8)
            cv2.drawContours(drawing, [res], 0, (0, 255, 0), 2) #drawing contours 
            cv2.drawContours(drawing, [hull], 0, (0, 0, 255), 3) #drawing convex hull
    
        cv2.imshow('output', drawing)

    # Keyboard OP
    k = cv2.waitKey(10)
    if k == 27:  
        camera.release()
        cv2.destroyAllWindows()
        break
    elif k == ord('b'):  # press 'b' to capture the background
        bgModel = cv2.createBackgroundSubtractorMOG2(0, bgSubThreshold)
        isBgCaptured = 1
        print( 'Background Captured')
    elif k == ord('r'):  # press 'r' to reset the background
        bgModel = None
        isBgCaptured = 0
        print ('Reset BackGround')
    

自己尝试的结果:

OpenCV学习—基于OpenCV的区域分割、轮廓检测和阈值处理(python)_第6张图片

你可能感兴趣的:(opencv学习,opencv)