基于OpenCV的区域分割、轮廓检测和阈值处理
OpenCV是一个巨大的开源库,广泛用于计算机视觉,人工智能和图像处理领域。它在现实世界中的典型应用是人脸识别,物体检测,人类活动识别,物体跟踪等。
现在,假设我们只需要从整个输入帧中检测到一个对象。因此,代替处理整个框架,如果可以在框架中定义一个子区域并将其视为要应用处理的新框架,该怎么办。我们要完成一下三个步骤:
• 定义兴趣区
• 在ROI中检测轮廓
• 阈值检测轮廓轮廓线
什么是ROI?
简而言之,我们感兴趣的对象所在的帧内的子区域称为感兴趣区域(ROI)。
我们如何定义ROI?
在输入帧中定义ROI的过程称为ROI分割。
在“ ROI细分”中,(此处)我们选择框架中的特定区域,并以矩形方法提供其尺寸,以便它将在框架上绘制矩形的ROI。
(输出)蓝色矩形覆盖的区域是我们的投资回报率
现在,如果您也想绑定感兴趣的对象,那么我们可以通过在ROI中找到轮廓来实现。
什么是轮廓?
轮廓线是 表示或说是限制对象形状的轮廓。
如何在框架中找到轮廓?
对我而言,在将ROI框架设为阈值后,找到轮廓效果最佳。因此,要找到轮廓,手上的问题是-
什么是阈值?
阈值不过是图像分割的一种简单形式。这是将灰度或rgb图像转换为二进制图像的过程。例如
(这是RGB帧)
(这是二进制阈值帧)
因此,在对rgb帧进行阈值处理后,程序很容易找到轮廓,因为由于ROI中感兴趣对象的颜色将是黑色(在简单的二进制脱粒中)或白色(在如上所述的反向二进制脱粒中),因此分割(将背景与前景即我们的对象分开)将很容易完成。
在对框架进行阈值处理并检测到轮廓之后,我们应用凸包技术对围绕对象点的紧密拟合凸边界进行设置。实施此步骤后,框架应如下所示-
我们可以做的另一件事是,我们可以遮盖ROI以仅显示被检测到的轮廓本身覆盖的对象。再次-
什么是图像MASK?
图像MASK是隐藏图像的某些部分并显示某些部分的过程。这是图像编辑的非破坏性过程。在大多数情况下,它使您可以在以后根据需要调整和调整遮罩。通常,它是一种有效且更具创意的图像处理方式。
因此,基本上在这里我们将掩盖ROI的背景。为此,首先我们将修复ROI的背景。然后,在固定背景之后,我们将从框架中减去背景,并用wewant背景(这里是一个简单的黑色框架)替换它。
实施上述技术,我们应该得到如下输出:
(背景被遮罩以仅捕获对象)
这是所说明技术的理想实现的完整代码。
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')
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Mysql 如何实现全文检索,关键词跑分
- spring之操作数据库之使用NamedParameterJdbcTemplate(具名参数)
- 谷歌colab上安装百度paddlepaddle框架
- 谷歌colab运行paddlepaddle之手写数字识别
- 【python-leetcode112-树的深度遍历】路径总和
- spring之第一个spring程序
- 【python-leetcode437-树的深度遍历】路径总和Ⅲ
- 双指针--合并两个排序数组
- spring之事务的其它属性(隔离级别、回滚、只读、过期)(四)
- 二分查找
- 一文弄懂数组的和
- spring之基于xml文件来配置事务(五)
- hash算法的应用
- 树的遍历
- spring之事务的传播行为(三)