目录

前言

一、需求分析

二、概要设计

2.1 基本原理

2.2 界面设计

三、详细设计

3.1 系统流程图

3.2 数据集

3.3 代码实现

3.3.1 利用deeplabV3模型分割

3.3.2 利用grabCut分割

3.3.3 Alpha Blending图像融合

3.3.4 UI界面

四、实验结果与分析

总结


前言

记录记录计算机视觉期末大作业,利用OpenCV实现了人像的前后景分割,GrabCut可以实现所有类型的图像分割,DeeplavbV3模型调用飞桨的deeplabv3p_xception65_humanseg,该模型只能用于人像抠图。

环境:python3.8.5,pycharm,OpenCV库


一、需求分析

现实生活中,我们经常会遇到将图像前景和背景分开的情况,比如证件照背景替换。在一幅图像中,人们可能只对其中的部分目标感兴趣,这些目标通常占据一定的区域,并且在某些特性上和临近的图像有差别。因此我们需要将图像前景与背景分割,以便用于产品检验,目标提取,图像融合等方面。所以系统的设计应具有如下方面:

(1)系统的输入;

用户点击选择图片按钮,将一张需要分割的图片读入系统。

(2)系统的输出;

通过分割算法将分割所得前景图像显示在界面上,用户可对结果图进行背景替换或保存。

(3)系统实现的功能。

系统实现了利用百度开源库deeplabv3+和grabCut实现了图像前景和背景的分割,利用Alpha blending实现了背景替换,Poisson Blending实现两幅图像的融合,通过pyqt设计UI界面实现了图像的点击操作。

二、概要设计

2.1 基本原理

(1)百度开源库deeplabV3+

通过查阅资料新了解了deeplabV3+:DeeplabV3+语义分割领域模型效果非常好的方法。DeeplabV3+主要在原有模型的基础上引入了可任意控制编码器提取特征的分辨率,通过在Encoder部分加入大量空洞卷积平衡精度和耗时。在不损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。

空洞卷积:

图 2-1 空洞卷积示意图

加入了空洞卷积,调整filters的接受野,如上图所示,左图中标准卷积中的卷积核大小为 3x3,其感受野也为 3x3,在卷积核中间插入 0 之后变为右图空洞卷积,其中实际参与计算的卷积核大小仍为 3x3,而感受野已经扩大到了 5x5。感受野增大后可以检测分割大目标,另一方面分辨率高了可以精确定位目标。

DeeplabV3+的模型介绍:

图2-2 DeeplabV3模型

输入一张图片,首先进入Encoder进行特征提取,利用深度卷积神经网络可以得到两个特征层,浅层特征送入Decoder,对深层特征利用不同膨胀率的膨胀卷积进行更深层次的特征提取,不同膨胀率的膨胀卷积提高了网络的感受野,之后对堆叠的特征进行过滤后送入Decoder,经过上采样和原来的浅层特征卷积结果融合,再次进行3x3特征特取,最后将输出图像调整到和输入图像一样,得到最终结果。

(2)图像分割:grabCut算法

graph Cut算法示意图:

图2-3 graph Cut算法示意图

Grabcut是基于图割(graph cut)实现的图像分割算法,它需要用户输入一个矩形框作为分割目标位置,实现对目标与背景的分割,位于框内部的属于前景,框外面的属于背景。Graph cut 算法是根据该像素点灰度值,在前景和背景中的灰度值直方图所占的比例来计算前景和背景概率的,求某个像素点lp与相邻像素点lq之间的(灰度值)差异,lp-lq的值越大,两个像素之间的边越是应该是割边。在Grab cut 中,不是以灰度为基准,而是以BGR三通道衡量两像素的相似性,采用欧式距离计算两个像素之间的差异。在计算区域项时,采用了高斯混合模型,在多个模型计算式,选取概率最大的一个。区域项反映的是,像素样本集合的整体特性,边界项反映的是两个像素之间的差异。在经过处理得到的掩膜中有四个值,分别表示前景,背景,可能前景,可能背景,合并前景和可能前景得到分割结果。

2.2 界面设计

界面由三部分组成,左侧是功能按钮区,包括开始分割、保存、背景替换、拍摄图像按钮,中间是图像显示区,有original Image 和result Image;下面是图片选择按钮和运行时间显示区。下图所示:

图2-4 初始化界面

图2-5 grabCut分割示例

三、详细设计

3.1 系统流程图

首先读取图像并进行USM锐化,增强图像细节,便于提取前景;手动选择目标前景区域ROI,进行grabCut图像分割,提取前景ROI区域的二值图像;将得到的前景ROI区域二值图像利用形态学滤波进行开运算消除细微干扰,接着与锐化图像进行与运算得到前景图像。

图2-6 grabCut图像分割示意图

Alpha Blending图像融合实现:读入分割得到的前景图像,分离出alpha掩膜,对掩膜腐蚀过滤掉其中白点,对腐蚀图像膨胀消除噪声,利用alpha掩膜对前景和背景进行加权,得到融合结果图像。

图2-7 Alpha Blending流程图

3.2 数据集

选取作为分割和融合测试的数据集如下,可任选电脑上图片进行测试:

3.3 代码实现

3.3.1 利用deeplabV3模型分割

将图像路径传入函数,调用飞桨训练模型实现分割,保存分割的前景图像,将轮廓图像进行阈值处理,图像腐蚀去除噪声,再进行图像膨胀处理恢复原来形状,删除累计分割结果,减少存储。

# 导入库
from PIL import Image
import numpy as np
import cv2
import os
# PaddleHub是基于PaddlePaddle生态下的预训练模型管理和迁移学习工具
# 可以结合预训练模型更便捷地开展迁移学习工作,通过PaddleHub,可以便捷地获取PaddlePaddle生态下的所有预训练模型
import paddlehub as hub
import matplotlib.pyplot as plt
import matplotlib.image as mpingdef img_remove(remove_img_path):# 删除原有路径中.jpg格式文件for root, dirs, files in os.walk(remove_img_path):for file in files:file_path = os.path.join(root, file)if str(file_path.split('.')[-1]).upper() == 'PNG':os.remove(file_path)print('删除完成')# 用matplotlib显示中文,避免乱码
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号def paddle_cut_Image(imgPath):"""利用deeplabv3p分割图像"""# 1.获取图片路径,传入模型test_img_path = imgPath# 2.调用飞桨训练模型# 调用飞桨的deeplabv3p_xception65_humanseg,该模型用于人像抠图moddle = hub.Module(name="deeplabv3p_xception65_humanseg")# 训练模型并预测模型,打印结果(获取到抠图人像)result = moddle.segmentation(images=[cv2.imread(test_img_path)], visualization=True,output_dir='../humanseg_output')# 3.保存抠出的前景图像paddle_fore_img = mping.imread(result[0]['save_path'])mping.imsave("paddle_output/paddle_output.png", paddle_fore_img)# 4.保存轮廓图像res_image = Image.fromarray(np.uint8(result[0]['data']))path = "paddle_mask/paddle_mask.png"res_image.save(path)# 加载保存的轮廓并显示,接着对其进行二值化处理,然后进行图像的腐蚀膨胀操作,得到输出结果,根据结果调整参数值。counter_img_path = pathimg_counter = cv2.imread(counter_img_path)# 灰度图像img_gray = cv2.cvtColor(img_counter, cv2.COLOR_BGR2GRAY)# 阈值处理,图像二值化(ret:阈值,thresh1:阈值化后的图像)ret, thresh1 = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY)# getStructuringElement( ) 返回指定形状和尺寸的结构元素kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))# 图像腐蚀,去除了噪声,但是会压缩图像。erode = cv2.erode(thresh1, kernel, iterations=2)# 对腐蚀的图像膨胀处理,可以去除噪声,并且保持原有形状dilate = cv2.dilate(erode, kernel, iterations=2)cv2.imwrite(path, dilate)# cv2.imshow('dilate',dilate)# # cv2.imshow('erode',erode)# # cv2.imshow('gray_img',img_gray)# # cv2.imshow('binary_img',thresh1)# # cv2.imshow('counter_img',img_counter)# cv2.waitKey(0)# cv2.destroyAllWindows()# 5.清理文件夹残存图像remove_img_path = r'/humanseg_output'img_remove(remove_img_path)current_working_dir = os.getcwd()paddle_fore_img_path = os.path.join(current_working_dir, "paddle_output\paddle_output.png")return paddle_fore_img_path

3.3.2 利用grabCut分割

对图像进行USM锐化增强:通过增加图像边缘的对比度来锐化并给图像添加细节。USM锐化增强方法(Unsharpen Mask):

1.先对原图高斯模糊,用原图减去系数x高斯模糊的图像

2.再把值Scale到0~255的RGB像素范围

3.公式:(原图像-w*高斯模糊)/(1-w);w表示权重(0.1~0.9),默认0.6

优点:可以去除一些细小细节的干扰和噪声,比卷积更真实。

读取图像并进行USM锐化,增强图像细节,便于提取前景;手动选择目标前景区域ROI,进行grabCut图像分割,提取前景ROI区域的二值图像;将得到的前景ROI区域二值图像利用形态学滤波进行开运算消除细微干扰,接着与锐化图像进行与运算得到前景图像。

import os
import cv2
import numpy as npdef img_usm(img):# 对图像进行USM锐化增强:通过增加图像边缘的对比度来锐化并给图像添加细节# sigma = 5、15、25# 模糊图像(img:原图像,高斯核(等于0则根据sigmaX和sigmaY计算得出),标准差)blur_img = cv2.GaussianBlur(img, (0, 0), 5)# cv.addWeighted(图1,权重1, 图2, 权重2, gamma修正系数, dst可选参数, dtype可选参数)usmimg = cv2.addWeighted(img, 1.5, blur_img, -0.5, 0)cv2.convertScaleAbs(usmimg,usmimg)return usmimgdef img_grab_Cut(original_img,usmimg,rect):"""进行grabCut图像分割"""# 掩码图像,如果使用掩码进行初始化,那么mask保存初始化掩码信息;# 在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中,然后再传入grabCut函数;在处理结束之后,mask中会保存结果mask = np.zeros(usmimg.shape[:2], np.uint8)  # 初始化蒙版图像bgdModel = np.zeros((1, 65), np.float64)  # 背景模型fgdModel = np.zeros((1, 65), np.float64)  # 前景模型cv2.grabCut(usmimg, mask, rect, bgdModel, fgdModel, 20, cv2.GC_INIT_WITH_RECT)  # 函数返回值为mask,bgdModel,fgdModel# 提取前景ROI区域二值图像foreground = np.zeros(original_img.shape[:3],np.uint8)foreground_roi = np.zeros(original_img.shape[:3], np.uint8)height = original_img.shape[0]width = original_img.shape[1]for row in range(height):for col in range(width):if mask[row,col] == 1 or mask[row,col] == 3:foreground_roi[row,col] = [255,255,255]cv2.imwrite('grabcut_mask/mask.png', foreground_roi)# 将得到的前景ROI区域二值图像进行开运算消除细微干扰后,和锐化图像进行与( and )操作,得到锐化后的前景区域# cv2.getStructuringElement:返回指定形状和尺寸的结构元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))# cv2.morphologyEx:形态学滤波,cv2.MORPH_OPEN:开运算(open):先腐蚀后膨胀的过程。开运算可以用来消除小黑点cv2.morphologyEx(foreground_roi, cv2.MORPH_OPEN, kernel)cv2.bitwise_and(foreground_roi, usmimg, foreground)return foregrounddef main(imgPath):# 读取图像img = cv2.imread(imgPath)img2 = update_img_resize(img)# usm锐化usmimg = img_usm(img2)cv2.imshow("mask image", usmimg)rect = cv2.selectROI("mask image", usmimg, fromCenter=False, showCrosshair=False)print(rect)print(rect[0],rect[1],rect[2],rect[3])# 进行grabCut图像分割grabcut_img= img_grab_Cut(img2,usmimg, rect)# print(grabcut_img.shape,grabcut_img.dtype)print("分割完成")cv2.imwrite('grabcut_output/test.png', grabcut_img)  # 写入图片current_working_dir = os.getcwd()grab_fore_img_path = os.path.join(current_working_dir, "grabcut_output\\test.png")return grab_fore_img_pathdef update_img_resize(img):"""修改图像尺寸"""# result_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)result_img = cv2.resize(img,dsize=(480,640))return result_imgif __name__ == '__main__':main()

3.3.3 Alpha Blending图像融合

读入分割得到的前景图像,分离出alpha掩膜,对掩膜腐蚀过滤掉其中白点,腐蚀消除噪声的同时会压缩图像,接着对腐蚀图像膨胀,恢复原来形状,将alpha的值归一化在0~1之间作为加权系数,利用alpha掩膜对前景和背景进行加权,得到融合结果图像。

from Img_Segmentation import grabCut3
import cv2def alpha_blending(fore_img_path,bg_img_path):"""Alpha_Blending"""# foreGroundImage = cv2.imread('../paddle_output/paddle_output.png', -1)foreGroundImage = cv2.imread(fore_img_path, -1)foreGroundImage = grabCut3.update_img_resize(foreGroundImage)# 先将通道分离b, g, r, a = cv2.split(foreGroundImage)# 得到PNG图像前景部分,在这个图片中就是除去Alpha通道的部分foreground = cv2.merge((b, g, r))# 得到PNG图像的alpha通道,即alpha掩模alpha = cv2.merge((a, a, a))# 腐蚀膨胀过滤掉图中的白点erode_alpha = cv2.erode(alpha, None, iterations=1)  # 图像被腐蚀后,去除了噪声,但是会压缩图像。alpha = cv2.dilate(erode_alpha, None, iterations=1)  # 对腐蚀过的图像,进行膨胀处理,可以去除噪声,并且保持原有形状# background = cv2.imread(r'D:\python\RRJ\pycharmproject\Practice\chep2\bdd\green.png')background = cv2.imread(bg_img_path)background = grabCut3.update_img_resize(background)# 因为下面要进行乘法运算故将数据类型设为float,防止溢出foreground = foreground.astype(float)background = background.astype(float)cv2.imwrite("alpha/alpha.png", alpha)# 将alpha的值归一化在0-1之间,作为加权系数alpha = alpha.astype(float) / 255# cv2.imshow("alpha", alpha)# cv2.waitKey(0)# 将前景和背景进行加权,每个像素的加权系数即为alpha掩模对应位置像素的值,前景部分为1,背景部分为0foreground = cv2.multiply(alpha, foreground)background = cv2.multiply(1.0 - alpha, background)outImage = cv2.add(foreground, background)save_path = fore_img_pathcv2.imwrite(save_path, outImage)# cv2.imshow("outImg", outImage / 255)# cv2.waitKey(0)return save_path

3.3.4 UI界面

import os
import time
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtCore import Qtfrom Img_Segmentation import grabCut3, paddle_Image, poisson_blending, takephotos
from Img_Segmentation import Alpha_Blendingglobal imgNamepath
global flagclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("图像分割")# # 给MainWindow设置图标# MainWindow.setWindowIcon(QIcon(r'D:\\download\\xj.ico'))  # 路径错误找不到问题所在## # 给MainWindow设置背景图片# palette = QPalette()# palette.setBrush(QPalette.Background, QBrush(QPixmap('D:\\python\\RRJ\\pycharmproject\\Practice\\chep2\\bdd'#                                                      '\\blue_bg.jpg')))# MainWindow.setPalette(palette)MainWindow.resize(1232, 852)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.widget = QtWidgets.QWidget(self.centralwidget)self.widget.setGeometry(QtCore.QRect(10, 0, 1211, 791))self.widget.setStyleSheet("border:1px solid black;\n")self.widget.setObjectName("widget")self.label = QtWidgets.QLabel(self.widget)self.label.setGeometry(QtCore.QRect(0, 0, 1211, 101))self.label.setStyleSheet("font: 24pt \"Arial\";\n""color:rgb(255, 170, 0);\n""text-aligen:center;")self.label.setObjectName("label")self.label_2 = QtWidgets.QLabel(self.widget)self.label_2.setGeometry(QtCore.QRect(260, 180, 431, 451))self.label_2.setStyleSheet("background-color:rgb(255, 255, 255);")self.label_2.setText("原始图像显示区")self.label_2.setAlignment(Qt.AlignCenter)self.label_2.setStyleSheet("font: 14pt \"Arial\";\n")self.label_2.setObjectName("label_2")self.label_3 = QtWidgets.QLabel(self.widget)self.label_3.setGeometry(QtCore.QRect(750, 180, 431, 451))self.label_3.setStyleSheet("background-color:rgb(255, 255, 255);")self.label_3.setText("结果显示区")self.label_3.setAlignment(Qt.AlignCenter)self.label_3.setStyleSheet("font: 14pt \"Arial\";\n")self.label_3.setObjectName("label_3")self.label_4 = QtWidgets.QLabel(self.widget)self.label_4.setGeometry(QtCore.QRect(370, 130, 181, 41))self.label_4.setStyleSheet("border:0px;\n""font: 14pt \"Arial\";\n")self.label_4.setObjectName("label_4")self.label_5 = QtWidgets.QLabel(self.widget)self.label_5.setGeometry(QtCore.QRect(890, 130, 131, 41))self.label_5.setStyleSheet("font: 14pt \"Arial\";\n""border:0px;")self.label_5.setObjectName("label_5")self.pushButton = QtWidgets.QPushButton(self.widget)self.pushButton.setGeometry(QtCore.QRect(261, 660, 150, 51))self.pushButton.setStyleSheet("font: 12pt \"Arial\";")self.pushButton.setObjectName("pushButton")self.lineEdit = QtWidgets.QLineEdit(self.widget)self.lineEdit.setGeometry(QtCore.QRect(410, 660, 771, 51))self.lineEdit.setStyleSheet("font: 12pt \"Arial\";\n")self.lineEdit.setObjectName("lineEdit")self.pushButton_2 = QtWidgets.QPushButton(self.widget)self.pushButton_2.setGeometry(QtCore.QRect(261, 720, 150, 51))self.pushButton_2.setStyleSheet("font: 12pt \"Arial\";")self.pushButton_2.setObjectName("pushButton_2")self.lineEdit_2 = QtWidgets.QLineEdit(self.widget)self.lineEdit_2.setGeometry(QtCore.QRect(410, 720, 771, 51))self.lineEdit_2.setStyleSheet("font: 12pt \"Arial\";\n")self.lineEdit_2.setObjectName("lineEdit_2")self.label_6 = QtWidgets.QLabel(self.widget)self.label_6.setGeometry(QtCore.QRect(0, 100, 221, 691))self.label_6.setText("")self.label_6.setObjectName("label_6")self.pushButton_3 = QtWidgets.QPushButton(self.widget)self.pushButton_3.setGeometry(QtCore.QRect(30, 200, 151, 51))self.pushButton_3.setStyleSheet("font: 14pt \"Arial\";")self.pushButton_3.setObjectName("pushButton_3")self.pushButton_4 = QtWidgets.QPushButton(self.widget)self.pushButton_4.setGeometry(QtCore.QRect(30, 290, 151, 51))self.pushButton_4.setStyleSheet("font: 14pt \"Arial\";\n")self.pushButton_4.setObjectName("pushButton_4")self.pushButton_5 = QtWidgets.QPushButton(self.widget)self.pushButton_5.setGeometry(QtCore.QRect(30, 460, 151, 51))self.pushButton_5.setStyleSheet("font: 14pt \"Arial\";")self.pushButton_5.setObjectName("pushButton_5")self.pushButton_6 = QtWidgets.QPushButton(self.widget)self.pushButton_6.setGeometry(QtCore.QRect(30, 550, 151, 51))self.pushButton_6.setStyleSheet("font: 14pt \"Arial\";")self.pushButton_6.setObjectName("pushButton_6")self.pushButton_7 = QtWidgets.QPushButton(self.widget)self.pushButton_7.setGeometry(QtCore.QRect(30, 370, 151, 51))self.pushButton_7.setStyleSheet("font: 14pt \"Arial\";")self.pushButton_7.setObjectName("pushButton_7")self.pushButton_8 = QtWidgets.QPushButton(self.widget)self.pushButton_8.setGeometry(QtCore.QRect(30, 640, 151, 51))self.pushButton_8.setStyleSheet("font: 14pt \"Arial\";")self.pushButton_8.setObjectName("pushButton_8")MainWindow.setCentralWidget(self.centralwidget)self.menubar = QtWidgets.QMenuBar(MainWindow)self.menubar.setGeometry(QtCore.QRect(0, 0, 1232, 26))self.menubar.setObjectName("menubar")MainWindow.setMenuBar(self.menubar)self.statusbar = QtWidgets.QStatusBar(MainWindow)self.statusbar.setObjectName("statusbar")MainWindow.setStatusBar(self.statusbar)self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)# 按钮关联函数self.pushButton.clicked.connect(self.openImage)self.pushButton_3.clicked.connect(self.start_paddle_Image)self.pushButton_4.clicked.connect(self.start_grabcut)self.pushButton_5.clicked.connect(self.saveImage)self.pushButton_6.clicked.connect(self.img_poisson_blend)self.pushButton_7.clicked.connect(self.take_pictures)self.pushButton_8.clicked.connect(self.alpha_blending_img)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "图像分割"))self.label.setText(_translate("MainWindow", "                                     图像分割及图像融合系统"))self.label_4.setText(_translate("MainWindow", "     original Image"))self.label_5.setText(_translate("MainWindow", "result Image"))self.pushButton.setText(_translate("MainWindow", "选择图片"))self.pushButton_2.setText(_translate("MainWindow", "运行时间"))self.pushButton_3.setText(_translate("MainWindow", "开始分割"))self.pushButton_4.setText(_translate("MainWindow", "grabCut"))self.pushButton_5.setText(_translate("MainWindow", "保   存"))self.pushButton_6.setText(_translate("MainWindow", "图像融合"))self.pushButton_7.setText(_translate("MainWindow", "拍摄图像"))self.pushButton_8.setText(_translate("MainWindow", "背景替换"))# 选择本地图片上传def openImage(self):global imgNamepath  # 这里为了方便别的地方引用图片路径,将其设置为全局变量# 弹出一个文件选择框,第一个返回值imgName记录选中的文件路径+文件名,第二个返回值imgType记录文件的类型# QFileDialog就是系统对话框的那个类第一个参数是上下文,第二个参数是弹框的名字,第三个参数是默认打开的路径,第四个参数是需要的格式imgNamepath, imgType = QFileDialog.getOpenFileName(self.centralwidget, "选择图片","D:\\python\\RRJ\\pycharmproject\\Practice\\chep2\\bdd2","*.jpg;;*.png;;All Files(*)")# 通过文件路径获取图片文件,并设置图片长宽为label控件的长、宽# img = QtGui.QPixmap(imgNamepath).scaled(self.label_2.width(), self.label_2.height())imgShow = QtGui.QPixmap(imgNamepath)self.label_2.setScaledContents(True)self.label_2.setPixmap(imgShow)# 显示所选图片的路径self.lineEdit.setText(imgNamepath)# 执行分割def start_paddle_Image(self):tstart = time.time()global flagflag = 1pdcut_img_path = paddle_Image.paddle_cut_Image(imgNamepath)pdcut_img = QPixmap(pdcut_img_path)self.label_3.setScaledContents(True)self.label_3.setPixmap(pdcut_img)tend = time.time()result = tend - tstartself.lineEdit_2.setText(str('%.3f' % float(result)) + 's')# grabCut_imgdef start_grabcut(self):tstart = time.time()global flagflag = 2gb_img_path = grabCut3.main(imgNamepath)# print(pdcut_img_path)gb_img = QPixmap(gb_img_path)self.label_3.setScaledContents(True)self.label_3.setPixmap(gb_img)tend = time.time()result = tend - tstartself.lineEdit_2.setText(str('%.3f' % float(result)) + 's')# 保存图片到本地(第二种方式:首先提取相对应Qlabel中的图片,然后打开一个保存文件的弹出框,最后保存图片到选中的路径)def saveImage(self):# 提取Qlabel中的图片img = self.label_3.pixmap().toImage()# print(type(img))fpath, ftype = QFileDialog.getSaveFileName(self.centralwidget, "保存图片", "d:\\", "*.png;;*.jpg;;All Files(*)")img.save(fpath)# 图像泊松融合def img_poisson_blend(self):tstart = time.time()self.openImage()if self.label_3.text() == "结果显示区":src_img = cv2.imread(imgNamepath)else:# 提取Qlabel中的图片src_img = self.label_3.pixmap().toImage()# 判断路径是否存在,如果不存在则新建path = "D:\\python\\RRJ\\pycharmproject\\Image_Segmentation\\PyQtImgZCQ\\"if not os.path.exists(path):os.mkdir(path)# 因为不知道怎么将<class 'numpy.ndarray'>转换为<class 'PyQt5.QtGui.QPixmap'>类型,因此采用暂存再读出的方式path = os.path.join(path, 'ZC.png')src_img.save(path)src_img = cv2.imread(path)# src_img = cv2.cvtColor(src_img,cv2.COLOR_RGB2BGR)poisson_img_path = poisson_blending.img_Poisson_Blending(src_img, imgNamepath)# pyqt5从路径读取图片imgShow = QPixmap(poisson_img_path)self.label_3.setScaledContents(True)self.label_3.setPixmap(imgShow)tend = time.time()result = tend - tstartself.lineEdit_2.setText(str('%.3f' % float(result)) + 's')# 拍摄照片def take_pictures(self):global imgNamepathimgNamepath = takephotos.take_photos()print(imgNamepath)show_take_img = QPixmap(imgNamepath)self.label_2.setScaledContents(True)self.label_2.setPixmap(show_take_img)# 背景替换def alpha_blending_img(self):tstart = time.time()self.openImage()fore_imgpath = ''if self.label_3.text() == "结果显示区":src_img = cv2.imread(imgNamepath)else:# 提取Qlabel中的图片src_img = self.label_3.pixmap().toImage()# 判断路径是否存在,如果不存在则新建path = "D:\\python\\RRJ\\pycharmproject\\Image_Segmentation\\PyQtImgZCQ\\"if not os.path.exists(path):os.mkdir(path)# 因为不知道怎么将<class 'numpy.ndarray'>转换为<class 'PyQt5.QtGui.QPixmap'>类型,因此采用暂存再读出的方式path = os.path.join(path, 'ZC.png')src_img.save(path)fore_imgpath = path# src_img = cv2.imread(path)Alpha_img_path = ''if flag == 1:Alpha_img_path = Alpha_Blending.alpha_blending(fore_imgpath, imgNamepath)if flag == 2:Alpha_img_path = Alpha_Blending.alpha_blending2(fore_imgpath, imgNamepath)# pyqt5从路径读取图片imgShow = QPixmap(Alpha_img_path)self.label_3.setScaledContents(True)self.label_3.setPixmap(imgShow)tend = time.time()result = tend - tstartself.lineEdit_2.setText(str('%.3f' % float(result)) + 's')

四、实验结果与分析

(1) 图像分割

图2-8 deeplabV3模型分割结果(1)

图2-9 grabCut分割结果(1)

图2-10 deeplabV3模型分割结果(2)

图2-11 grabCut分割结果(2)

                                                 图2-12 deeplabV3模型分割结果(3)

                                                  图2-13 grabCut分割结果(3)

通过对比可以看到,deeplabV3模型的分割结果十分优秀,不论是单人还是多人图像,都可以得到很好的效果,几乎没有锯齿痕迹。grabCut分割结果在简单证件照的时候效果和deeplabV3模型效果近似相同,但是在具有复杂背景和多人的情况下分割锯齿痕迹明显,且有分割前景缺失现象,而且在某些情形下前景区域不好手动标定。在grabCut设置迭代次数20的时候二者在运行时间上都较慢,时间复杂度高。

(2)图像融合

图2-14 Poisson Blending结果

利用OpenCV中的seamlessClone()函数实现,参数选择MIXED_CLONE,保留背景图像的细节,目标区域的梯度由原图像和背景图像组合计算得到,但是从结果来看是将两幅图像像素梯度计算进行了深度融合,不是单纯的背景替换,可以用于人物模糊等应用场景。

(3)背景替换(Alpha Blending)

图2-15 deeplabV3模型分割结果替换

图2-16  grabCut分割结果替换

总结

此次实验我实现利用opencv和百度开源库实现了图像分割与图像融合,对图割法有了更多了解,也体会了图割法在实际问题中的使用,grabCut是基本图割法的基础上增加迭代次数和高斯混合模型计算区域项,理论上迭代次数越多分割效果越好,是以牺牲时间复杂度来换取正确率,但是正式操作的时候需要人为标定前景区域,有容易出现误操作和前景难以准备标出的现象,导致分割结果不好。同时发现发现了语义分割领域一个十分优秀的模型deeplabV3,了解了它的基本理解,调用模型测试了分割结果确实相当优秀,主要问题是在cpu情况下运行相对较慢。在这次课设中我也学到了pyqt制作图形化界面的相关操作,也了解了更多Opencv中图像操作函数,但还存在一些不足,主要在于没有自己实现算法流程,缺乏对算法的深入理解,ui界面设置的不够流畅,无法避免实际应用中的误操作。

详细代码:github


python计算机视觉-- 基于OpenCV的图像分割和图像融合系统相关推荐

  1. Python 毕业设计 - 基于 opencv 的人脸识别上课考勤系统,附源码

    一.简介 这个人脸识别考勤签到系统是基于大佬的人脸识别陌生人报警系统二次开发的. 项目使用Python实现,基于OpenCV框架进行人脸识别和摄像头硬件调用,同时也用OpenCV工具包处理图片.交互界 ...

  2. Python基于Opencv的鱼群密度速度检测系统(源码&教程)

    1.研究背景 智慧渔业是大数据.物联网与人工智能等现代信息技术驱动下的渔业发展新模式,是水产养殖业供给侧结构性改革的重要方式,涉及养殖环境监测.生物环境监测与生物状态监测这几大方面的应用与需求.本文从 ...

  3. Python基于OpenCV的指针式表盘检测系统(附带源码&技术文档)

    1.背景 指针式机械表盘具有安装维护方便.结构简单.防电磁干扰等诸多优点, 目前广泛应用于工矿企业.能源及计量等部门.随着仪表数量的增加及精密仪表技术的发展,人工判读已经不能满足实际应用需求.随着计算 ...

  4. 案例-使用python实现基于opencv的车辆识别

    写在开头,接触opencv也有很长一段时间了,中间还接触了halcon.但都是基于C++实现,发现如果有什么idea,还是使用python可以快速实现.基于C++版本的后期会有更新. 首先,这个案例是 ...

  5. 基于opencv和pillow实现人脸识别系统(附demo)

    更多python教程请到友情连接: 菜鸟教程https://www.piaodoo.com 初中毕业读什么技校 http://cntkd.net 茂名一技http://www.enechn.com p ...

  6. grads 相关系数_基于小波变换的多聚焦图像融合算法

    引用本文 孟强强, 杨桄, 童涛, 张俭峰. 基于小波变换的多聚焦图像融合算法[J]. 国土资源遥感, 2014,26(2): 38-42 MENG Qiangqiang, YANG Guang, T ...

  7. 第 11 章 基于小波技术进行图像融合--MATLAB人工智能深度学习模块

    matlab实现基于小波技术进行图像融合–人工智能深度学习模块 该案例相对简单.实现程序 % MAINFORM MATLAB code for MainForm.fig % MAINFORM, by ...

  8. 【matlab】机器学习与人工智能期末课设,基于 K-means 聚类算法的图像区域分割系统

    基于 K-means 聚类算法的图像区域分割系统主要由两部分组成,分别是登录界面和主界面.用户登录模块负责用户的登录功能,用户输入账号和密码正确后,进入主界面,失败则跳出弹窗,提示用户登录失败.这是用 ...

  9. 计算机毕业设计Python+uniapp基于微信小程序某企业考勤系统(小程序+源码+LW)

    计算机毕业设计Python+uniapp基于微信小程序某企业考勤系统(小程序+源码+LW) 该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程 项目运行 环境配置: Pychram社区版+ ...

最新文章

  1. 你了解的技术宅是这样吗?
  2. python 学习笔记 12 -- 写一个脚本获取城市天气信息
  3. T-SQL DISTINCT
  4. SAP UI5里使用jQuery.ajax采用同步的方式读取数据
  5. c语言课程设计 性别,【图片】发几个C语言课程设计源代码(恭喜自己当上技术小吧主)【东华理工大学吧】_百度贴吧...
  6. Codeforces Codeforces Round #383 (Div. 2) E (DFS染色)
  7. c语言程序优化设计,C程序设计语言的教学策略优化设计
  8. 【转】75个最佳Web设计资源
  9. 树形图,多层级目录等其他名称待补充……
  10. linux常用文件及作用总结(profile/.bashrc等)
  11. 转iOS逆向工程:Reveal查看任意app的高级技巧!
  12. python 安装impala包
  13. 公众号900篇文章分类和索引
  14. Xshell6及Xftp6的使用
  15. Android裁剪图片为圆形
  16. java中的守护线的应用_JVM中的守护线程示例详解
  17. Indicator Stickynotes - Ubuntu 桌面便签小工具
  18. Oracle查询语句及实例
  19. 【纪中受难记】——Day17:本来能AK
  20. kali渗透实战02---获取内网QQ相册

热门文章

  1. python如何进行进制转换
  2. c语言程序设计课程设计心得体会,C语言课程设计的心得体会
  3. 假定在使用CSMA/CD协议的10Mb/s以太网中某个站在发送数据时检测到碰撞,执行退避算法时选择了随机数r=100。试问这个站需要等待多长时间后才能再次发送数据?如果是100Mb
  4. 内存马查杀工具FindShell试用
  5. 深度解析:信创产业全景图
  6. 电脑无法正常关机,只能强制关机问题
  7. 如何避免高分低能(机器人工程专业)
  8. MS CASTEP学习(5)
  9. 至芯FPGA培训中心-1天FPGA设计集训(赠送FPGA开发板)
  10. 浅谈“游戏行业第三方支付平台“