day16 - 提取图像前景

文章介绍了如何利用OpenCV中的cv2.findContours函数检测图像轮廓,并通过绘制轮廓和创建掩码来提取图像的前景。首先,将图像转为二值图像,然后找到轮廓,接着在掩码上绘制轮廓并进行图像与运算以提取前景。
摘要由CSDN通过智能技术生成

在我们平时使用购物软件是会发现通常在搜索框右侧都会有一个相机的标志,这个标志是可以让用户通过图片来搜索自己需要购买的内容。拍照购物将用户拍摄的商品与商品图库的图像进行对比,找到最为相似的商品。但是由于用户拍摄的图像是任意的随机的,不可能与商家的商品图完全吻合,复杂的商品背景对拍照购物造成了很大的影响,商品与背景图像的分离技术成为了技术的关键。

本期我们来学习使用图像轮廓相关的技术来实现图像前景的提取。

完成本期内容,你可以:

  • 了解图像轮廓的基本定义
  • 了解图像轮廓检测与边缘检测的区别
  • 学会提取图像的轮廓并绘制轮廓

若要运行案例代码,你需要有:

  • 操作系统:Ubuntu 16 以上 或者 Windows10

  • 工具软件:VScode 或者其他源码编辑器

  • 硬件环境:无特殊要求

  • 核心库:python 3.6.13, opencv-contrib-python 3.4.11.39,opencv-python 3.4.2.16


判断图形轮廓

OpenCV中提供了cv2.findContours()函数可以通过计算图像梯度来判断出图像的边缘。

函数原型:contours, hierarchy = cv2.findContours( image, mode, method)

contours为返回的轮廓。hierarchy为返回的图像的拓扑信息(轮廓层次)。

参数描述如下:

  • contours:返回的轮廓。
  • hierarchy:图像的拓扑信息(轮廓层次)。
  • image:原始图像。
  • mode:轮廓检索模式。
  • method:轮廓的近似方法
mode参数含义
cv2.RETR_EXTERNAL只检测外轮廓
cv2.RETR_LIST检测所有轮廓,轮廓不建立等级
cv2.RETR_CCOMP检测所有轮廓,建立两个等级的轮廓
cv2.RETR_TREE检测所有轮廓,建立等级树轮廓
method参数含义
cv2.CHAIN_APPROX_NONE存储所有的轮廓点
cv2.CHAIN_APPROX_SIMPLE压缩存储
cv2.CHAIN_APPROX_TC89_L1使用ten-Chinl chain 近似算法
cv2.CHAIN_APPROX_TC89_KCOS使用ten-Chinl chain 近似算法

绘制图像轮廓

OpenCV中提供了cv2.drawContours()函数来绘制图像轮廓。

函数原型:image=cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])

image为目标图像,绘制了边缘的原始图像。

参数描述如下:

  • image:待绘制轮廓图像。
  • contours:需要绘制的轮廓。
  • contourIdx:需要绘制的边缘索引。
  • color:绘制的颜色,用 BGR 格式表示。
  • thickness:可选参数,表示绘制轮廓时所用的画笔粗细。
  • lineType:可选,绘制的线型。
  • hierarchy:对应函数cv2.findContours()所输出的层次信息。
  • maxLevel:该参数控制绘制的轮廓层次深度。
  • offset:偏移参数。

绘制多边形轮廓

OpenCV中提供了cv2.approxPolyDP()函数来绘制多边形轮廓。

函数原型:approxCurve = cv2.approxPolyDP( curve, epsilon, closed )

approxCurve为逼近多边形点集;

参数描述如下:

  • curve:是轮廓。
  • epsilon:精度,原始轮廓的边界点与逼近多边形边界之间的最大距离。
  • closed:逻辑值。该值为真时,逼近多边形是封闭的;否则,逼近曲线是不封闭的。

具体步骤

使用图像轮廓相关技术提取图像前景。

请添加图片描述

请添加图片描述

步骤一:创建项目工具

创建项目名为提取图像前景,项目根目录下新建code文件夹储存代码,新建dataset文件夹储存数据,项目结构如下:

提取图像前景                             # 项目名称
├── code                               # 储存代码文件
├── dataset                            # 储存数据文件

注:如项目结构已存在,无需再创建。

步骤二:获取轮廓并绘制

  1. 导入所需模块:OpenCV、NumPy ;
  2. 读取dataset文件夹下的dandelion.jpg 图片;
  3. 将原图像复制,用于绘制图像轮廓;
  4. 将图像转换为二值图像;
  5. 获取图像轮廓并绘制;

代码实现

# 导入OpenCV、numpy
import cv2
import numpy as np

o = cv2.imread('../dataset/dandelion.jpg')# 读取原图
img = o.copy() # 复制图像
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)  # 原图从彩图变成单通道灰度图像
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)  # 灰度图像转化为二值图像,阈值为127,最大值为255
# 获取二值化图像中的轮廓以及储存轮廓层次数据
contours, hierarchy = cv2.findContours(binary,
                                          cv2.RETR_LIST,
                                          cv2.CHAIN_APPROX_SIMPLE)
# 在复制得到的图像上绘制轮廓
cv2.drawContours(img, contours, -1, (0, 0, 255), 2)

步骤三:提取图像前景

  1. 创建一张与原始图像大小相同值为0的数组(黑色图像)作为掩码;
  2. 在掩码中绘制出实心轮廓,颜色为白色;
  3. 将原始图像与掩码图像进行与运算,获取前景;

代码实现

# 创建原始图像大小相同的值为0的数组(黑色图像)
mask=np.zeros(o.shape,np.uint8) 
# 在mask中绘制出实心轮廓,颜色为白色
mask=cv2.drawContours(mask,contours,-1,(255,255,255),-1) 
# 将mask和原始图像进行计算,获取前景
loc=cv2.bitwise_and(o,mask)  

步骤四:结果展示

  1. 展示出绘制了图像轮廓的图像;
  2. 展示出掩码图像;
  3. 展示提取的前景图像;

代码实现

cv2.imshow("contours",img)
cv2.imshow("mask" ,mask)
cv2.imshow("foreground" ,foreground)
cv2.waitKey()
cv2.destroyAllWindows()

使用图像轮廓相关的技术来实现提取图像的前景,主要是因为绘制图像轮廓时可以绘制实心轮廓,在通过一张掩码图像来进行图像运算,根据之前讲过的图像运算的规律,可以将图像的前景提取出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用OpenCV图像背景提取出来的方法有很多,下面介绍两种常用的方法: 方法一:基于差分法的背景提取 基于差分法的背景提取是一种简单直接的方法。该方法通过将当前帧图像和背景帧图像进行像素级别的差分,得到背景和前景的差异,从而实现背景的提取。 1. 读取背景帧图像和当前帧图像。 2. 将两幅图像转换为灰度图像,并进行高斯滤波。 3. 对两幅图像进行差分运算,得到差分图像。 4. 对差分图像进行二值化处理,得到前景掩码。 5. 对前景掩码进行形态学处理,去除噪声。 6. 将前景掩码与当前帧图像进行按位与操作,得到提取后的背景图像。 代码示例: ``` #include <opencv2/opencv.hpp> using namespace cv; int main() { // 读取背景帧图像和当前帧图像 Mat bg_frame = imread("bg.png"); Mat cur_frame = imread("cur.png"); // 将两幅图像转换为灰度图像,并进行高斯滤波 Mat bg_gray, cur_gray; cvtColor(bg_frame, bg_gray, COLOR_BGR2GRAY); cvtColor(cur_frame, cur_gray, COLOR_BGR2GRAY); GaussianBlur(bg_gray, bg_gray, Size(5, 5), 0); GaussianBlur(cur_gray, cur_gray, Size(5, 5), 0); // 对两幅图像进行差分运算,得到差分图像 Mat diff; absdiff(bg_gray, cur_gray, diff); // 对差分图像进行二值化处理,得到前景掩码 Mat fg_mask; threshold(diff, fg_mask, 30, 255, THRESH_BINARY); // 对前景掩码进行形态学处理,去除噪声 Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5)); morphologyEx(fg_mask, fg_mask, MORPH_OPEN, kernel); // 将前景掩码与当前帧图像进行按位与操作,得到提取后的背景图像 Mat bg_extracted; cur_frame.copyTo(bg_extracted, fg_mask); // 显示结果 imshow("Background Extracted", bg_extracted); waitKey(0); return 0; } ``` 方法二:基于混合高斯模型的背景提取 基于混合高斯模型的背景提取是一种常用的背景提取方法,该方法通过对每个像素建立一个混合高斯模型,对当前帧图像进行建模,并从中提取出背景。 1. 创建BackgroundSubtractorMOG2对象。 2. 读取视频帧图像,调用BackgroundSubtractorMOG2对象的apply函数进行背景提取。 3. 对背景掩码进行形态学处理,去除噪声。 4. 将背景掩码与当前帧图像进行按位与操作,得到提取后的背景图像。 代码示例: ``` #include <opencv2/opencv.hpp> using namespace cv; int main() { // 创建BackgroundSubtractorMOG2对象 Ptr<BackgroundSubtractorMOG2> pMOG2 = createBackgroundSubtractorMOG2(); // 读取视频帧图像,调用BackgroundSubtractorMOG2对象的apply函数进行背景提取 VideoCapture cap("video.avi"); Mat frame, fg_mask, bg_extracted; while (true) { cap >> frame; if (frame.empty()) break; pMOG2->apply(frame, fg_mask); morphologyEx(fg_mask, fg_mask, MORPH_OPEN, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); frame.copyTo(bg_extracted, fg_mask); imshow("Background Extracted", bg_extracted); waitKey(30); } return 0; } ``` 以上两种方法都可以用于背景提取,具体选择哪种方法取决于实际需求和应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值