2021-08-27 分割之后mask在原图中提取出来(语义分割—实例分割)

1.生成分割后的mask

原图和mask如下:
在这里插入图片描述

2.mask二值化

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np


# 获取图片
def getimg():
    return Image.open("2.png")
    

def showimg(img, isgray=False):
    plt.axis("off")
    if isgray == True:
        plt.imshow(img, cmap='gray')
    else:
        plt.imshow(img)
    plt.show()

im5 = getimg()
im5 = np.array(im5.convert('L'))
im5 = np.where(im5[...,:] < 165, 0, 255) #根据设置的阈值来进行黑白分类
showimg(Image.fromarray(im5), True)

生成如图:
在这里插入图片描述

3. mask二值化后取反

import os
from PIL import Image
import numpy as np

def resize(imgPath, savePath):
    files = os.listdir(imgPath)
    files.sort()
    print('****************')
    print('input :', imgPath)
    print('start...')
    for file in files:
        fileType = os.path.splitext(file)
        if fileType[1] == '.png':
            new_png = Image.open(imgPath + '/' + file)  # 打开图片
            # new_png = new_png.resize((20, 20),Image.ANTIALIAS) #改变图片大小
            matrix = 255 - np.asarray(new_png)  # 图像转矩阵 并反色
            new_png = Image.fromarray(matrix)  # 矩阵转图像
            new_png.save(savePath + '/' + file)  # 保存图片
    print('down!')
    print('****************')

if __name__ == '__main__':
    # 待处理图片地址
    dataPath = 'G:\\666\\2\\'
    # 保存图片的地址
    savePath = 'G:\\666\\2\\'
    resize(dataPath, savePath)

如图:
在这里插入图片描述

4.把mask分割后的图像提取出来

import os
import cv2
import numpy as np
#im1 原图  im2 mask图(背景是黑色,前景是白色)
im1_path = 'G:/666/1/'
im2_path = 'G:/666/2/'

num = len(os.listdir(im1_path))
for i in range(num):

    img1 = cv2.imread(os.path.join(im1_path, os.listdir(im1_path)[i]))
    img2 = cv2.imread(os.path.join(im2_path,os.listdir(im2_path)[i]), cv2.IMREAD_GRAYSCALE)
    h,w,c = img1.shape
    img3 = np.zeros((h,w,4))
    img3[:,:,0:3] = img1
    img3[:,:,3] = img2
    #这里命名随意,但是要注意使用png格式
    cv2.imwrite('G:/666/3/' + '%s.png' % os.listdir(im1_path)[i], img3)

生成图像:
在这里插入图片描述
上面这种出来是透明背景32位的,并不是白色!!!!
另一种出来版本是黑色背景:

import cv2

person = cv2.imread("1.png")
# back = cv2.imread("背景图")
#这里将mask图转化为灰度图
mask = cv2.imread("6.png",cv2.IMREAD_GRAYSCALE)
#将背景图resize到和原图一样的尺寸
# back = cv2.resize(back,(person.shape[1],person.shape[0]))
#这一步是将背景图中的人像部分抠出来,也就是人像部分的像素值为0
# scenic_mask =~mask
# scenic_mask = scenic_mask  / 255.0
# back[:,:,0] = back[:,:,0] * scenic_mask
# back[:,:,1] = back[:,:,1] * scenic_mask
# back[:,:,2] = back[:,:,2] * scenic_mask
#这部分是将我们的人像抠出来,也就是背景部分的像素值为0
mask = mask / 255.0
person[:,:,0] = person[:,:,0] * mask
person[:,:,1] = person[:,:,1] * mask
person[:,:,2] = person[:,:,2] * mask
#这里做个相加就可以实现合并
# result = cv2.add(back,person)

cv2.imwrite("3.jpg", person)

出图如下:
在这里插入图片描述
如果加上背景的话:(像素黑的就是0,随便附加颜色)

import cv2

person = cv2.imread("1.png")
back = cv2.imread("0.png")
#这里将mask图转化为灰度图
mask = cv2.imread("6.png",cv2.IMREAD_GRAYSCALE)
#将背景图resize到和原图一样的尺寸
back = cv2.resize(back,(person.shape[1],person.shape[0]))
#这一步是将背景图中的人像部分抠出来,也就是人像部分的像素值为0
scenic_mask =~mask
scenic_mask = scenic_mask  / 255.0
back[:,:,0] = back[:,:,0] * scenic_mask
back[:,:,1] = back[:,:,1] * scenic_mask
back[:,:,2] = back[:,:,2] * scenic_mask
#这部分是将我们的人像抠出来,也就是背景部分的像素值为0
mask = mask / 255.0
person[:,:,0] = person[:,:,0] * mask
person[:,:,1] = person[:,:,1] * mask
person[:,:,2] = person[:,:,2] * mask
#这里做个相加就可以实现合并
result = cv2.add(back,person)

cv2.imwrite("88.jpg", result)

在这里插入图片描述

5.把mask分割后的图像可视化出来同步

# 将分割图和原图合在一起
from PIL import Image
import matplotlib.pyplot as plt

# image1 原图
# image2 分割图
image1 = Image.open("1.png")
image2 = Image.open("6.png")

image1 = image1.convert('RGBA')
image2 = image2.convert('RGBA')

# 两幅图像进行合并时,按公式:blended_img = img1 * (1 – alpha) + img2* alpha 进行
image = Image.blend(image1, image2, 0.3)
image.save("test1.png")
image.show()

在这里插入图片描述

抠图小结:

1.opencv抠图 (扣出背景是黑色,24位)

######################  opencv抠出来

import cv2

person = cv2.imread(r"G:\666BASNet-master\test_data\1\2.png")
person_ori = person.copy()
# back = cv2.imread("背景图")
#这里将mask图转化为灰度图
mask = cv2.imread(r"G:\666BASNet-master\test_data\2\2.png",cv2.IMREAD_GRAYSCALE)
#将背景图resize到和原图一样的尺寸
# back = cv2.resize(back,(person.shape[1],person.shape[0]))
#这一步是将背景图中的人像部分抠出来,也就是人像部分的像素值为0
# scenic_mask =~mask
# scenic_mask = scenic_mask  / 255.0
# back[:,:,0] = back[:,:,0] * scenic_mask
# back[:,:,1] = back[:,:,1] * scenic_mask
# back[:,:,2] = back[:,:,2] * scenic_mask
#这部分是将我们的人像抠出来,也就是背景部分的像素值为0
mask = mask / 255.0
person[:,:,0] = person[:,:,0] * mask
person[:,:,1] = person[:,:,1] * mask
person[:,:,2] = person[:,:,2] * mask
#这里做个相加就可以实现合并
# result = cv2.add(back,person)
diffImg2 = cv2.subtract(person, person_ori)


# cv2.imwrite(r"G:\666BASNet-master\test_data\out\opencv_out.png", person)
# cv2.imwrite(r"G:\666BASNet-master\test_data\out_1.png", diffImg2)
cv2.imwrite(r"G:\666BASNet-master\test_data\4\2.png", person)

效果:

原图:24位在这里插入图片描述
mask:24位在这里插入图片描述
opencv扣出效果:背景是黑色的,24位
在这里插入图片描述

2.pillow抠图 (扣出背景是黑色,24位)

######################  pillow抠出来
from PIL import Image
import numpy as np

#目标地址
target=r'G:\666(抠图之后测试)\0.png'  #原图24位

#二值图地址
decorate=r'G:\666(抠图之后测试)\6.png' #背景黑 目标白 24位

class ImageCut:
    def cover(self, target, decorate):

        # 分别打开2张图片
        image_target = Image.open(target)
        image_decorate = Image.open(decorate)

        # todo 校验图片长宽相等
        image_target_width = image_target.width
        image_target_height = image_target.height

        image_decorate_width = image_decorate.width
        image_decorate_height = image_decorate.height

        # 对比像素点
        for h in range(image_target_height):
            for w in range(image_target_width):
                # 打印该图片的所有点
                # print(image_decorate.getpixel((w, h)), end=" ")
                # 判断像素点是否为约定好的  255, 255, 255--白色
                if (image_decorate.getpixel((w, h)) !=(255, 255, 255)):
                    # 设定目标图片像素点为 255, 255, 255 & 0, 0, 0
                    image_target.putpixel((w, h), (0, 0, 0))
            print('\n')
        # 保存处理后的图片
        img = np.array(image_target)
        print(img)
        # diffImg2 = cv2.subtract(img, target)

        # im3 = PIL.ImageChops.subtract(img, target, scale=1.0, offset=0)

        # print(im3)
        image_target.save(r"G:\666(抠图之后测试)\0608_out.png")


#调用
ImageCut().cover(target,decorate)

原图24位——mask24位-——抠图24位
在这里插入图片描述
3.提取白色背景的抠图

import os
from PIL import Image
import numpy as np
import cv2
import time
import warnings

warnings.filterwarnings("ignore")



def koutu24(prediction_dir, savePath):  # 获取24位
	files = os.listdir(prediction_dir)
	files.sort()
	print('****************')
	print('input :', prediction_dir)
	print('start to 24bit...')
	for file in files:
		fileType = os.path.splitext(file)
		if fileType[1] == '.png':
			new_png = Image.open(prediction_dir + '/' + file)  # 打开图片
			# new_png = new_png.resize((20, 20),Image.ANTIALIAS) #改变图片大小
			matrix = 255 - np.asarray(new_png)  # 图像转矩阵 并反色
			# new_png = Image.fromarray(matrix)  # 矩阵转图像
			img1 = cv2.imread(image_dir + file)
			image = cv2.add(img1, matrix)
			cv2.imwrite(savePath + '\\' + file, image)  # 保存图片
	print('down!')
	print('****************')


def koutu32(imgPath, savePath):  # 获取32位
	print('****************')
	print('input :', imgPath)
	print('start to 32bit...')
	num = len(os.listdir(imgPath))
	for i in range(num):
		img1 = cv2.imread(os.path.join(imgPath, os.listdir(imgPath)[i]))
		img2 = cv2.imread(os.path.join(prediction_dir, os.listdir(prediction_dir)[i]), cv2.IMREAD_GRAYSCALE)
		h, w, c = img1.shape
		img3 = np.zeros((h, w, 4))
		img3[:, :, 0:3] = img1
		img3[:, :, 3] = img2
		a = os.listdir(imgPath)[i]
		b = a.split(".")
		c = b[0]
		cv2.imwrite(savePath + '%s.png' % c, img3)
	print('down!')
	print('****************')


if __name__ == '__main__':
	# --------- 1. get image path and name ---------
	image_dir = './test_data/111/'  # 待分割图片输入./test_data/1/
	mask_dir = './test_data/222/'  # mask图 目标白 周围黑./test_data/2/

	savePath = './test_data/333/'  # 保存图片的地址'./test_data/3/

	files = os.listdir(image_dir)  # 会按顺序排列[1,2,3,4,.png]格式 刚开始需要把所有图片(1).(2).(3)……的形式,再重新按顺序排名
	i = 0

	for file in files:
		original = image_dir + os.sep + files[i]
		new = image_dir + os.sep + str(i + 1) + ".png"
		os.rename(original, new)
		i += 1

	koutu24(mask_dir, savePath)

效果展示:原图24位——mask24位——抠图24位
在这里插入图片描述

4. 比较提取出来的地方和原图,是否有差异,是否提取准确

比较图片差异代码:

#####################################比较图片差异 黑背景抠图-原图=像素0就是对的!!
import numpy as np
import cv2


def main():
    img1 = cv2.imread(r'G:\666BASNet-master\test_data\333\0608_out.png') # 扣出来的图
    img2 = cv2.imread(r'G:\666BASNet-master\test_data\333\1.png')  # 原图

    diffImg1 = cv2.subtract(img1, img2)
    diffImg2 = cv2.subtract(img2, img1)
    # diffImg3 = img1 - img2
    # diffImg4 = img2 - img1
    print(diffImg1)  # diffImg1 显示ndarray显示全零就是对的
    cv2.imwrite(r'G:\666BASNet-master\test_data\333\opencv_out.png', diffImg1)
    # cv2.imshow('subtract(img2,img1)', diffImg2)

    print(diffImg1)
    # cv2.imshow('img1 - img2', diffImg3)
    # cv2.imshow('img2 - img1', diffImg4)
    cv2.waitKey(0)

main()

debug看情况:
在这里插入图片描述
原图24位——>mask24位——>抠图黑背景+真实目标——>差异对比图(黑背景抠图-原图)全黑像素都为零就是对的

在这里插入图片描述
5.

import cv2
import os
import numpy as np

def koutu32(imgPath, prediction_dir,savePath):  #获取32位 透明色
	print('****************')
	print('input :', imgPath)
	print('start to 32bit...')
	num = len(os.listdir(imgPath))
	for i in range(num):
		img1 = cv2.imread(os.path.join(imgPath, os.listdir(imgPath)[i]))
		print(os.listdir(prediction_dir)[i])
		img2 = cv2.imread(os.path.join(prediction_dir, os.listdir(prediction_dir)[i]), cv2.IMREAD_GRAYSCALE)
		img3 = np.where(img2[..., :] < 0.5, 0, 255)
		h, w, c = img1.shape
		img4 = np.zeros((h, w, 4))
		img4[:, :, 0:3] = img1
		img4[:, :, 3] = img3
		a = os.listdir(imgPath)[i]
		b = a.split(".")
		c = b[0]
		cv2.imwrite(savePath + '%s.png' % c, img4)
	print('down!')
	print('****************')



if __name__ == '__main__':
	image_dir = 'F:\\1207garbage_classification\\test_smoking\\img_png\\'  # img原图路径
	prediction_dir = 'F:\\1207garbage_classification\\test_smoking\\mask\\'  # mask输出全黑路径(01)
	savePath = 'F:\\1207garbage_classification\\test_smoking\\img_out\\'  # 保存图片的地址
	os.makedirs(savePath, exist_ok=True)
	koutu32(image_dir, prediction_dir,savePath)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 44
    点赞
  • 326
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
### 回答1: 要训练自己的数据集,我们首先需要下载Mask R-CNN模型的代码和预训练的权重。我们可以从GitHub上的Mask R-CNN项目获得代码。将代码克隆到本地后,我们可以安装所需的依赖库。 接下来,我们需要准备我们自己的数据集。数据集应包含图像和相应的实例分割标注。标注可以是标记每个实例的掩码或边界框。确保标注与图像具有相同的文件名,并将它们保存在单独的文件夹。 一旦准备好数据集,我们需要将它们进行预处理,以便能够与Mask R-CNN模型兼容。为此,我们可以编写一个数据加载器,该加载器将图像和标注转换为模型可以处理的格式。 在准备好数据集和数据加载器后,我们可以开始训练模型。通过运行训练脚本,我们可以指定训练数据集的路径、模型的配置以及需要的其他参数。模型将针对给定的数据集进行迭代,逐步学习实例分割任务。 训练过程可能需要一定时间,具体取决于数据集的大小和复杂性。我们可以利用GPU加速来加快训练速度。 一旦训练完成,我们可以使用自己的数据集进行图像实例分割。导入训练好的模型权重,我们可以提供测试图像并获得模型对实例的分割结果。 总之,训练自己的数据集以进行图像实例分割需要下载Mask R-CNN代码和预训练权重。然后,准备和预处理数据集,并编写数据加载器。使用训练脚本进行模型训练,并在训练完成后使用自己的数据集进行图像实例分割。 ### 回答2: 要训练自己的数据集,首先需要下载并设置合适的数据集。可以从各种资源寻找与自己目标相关的图像数据集,并确保数据集包含正确的标注信息,例如每个图像的实例分割掩模。 接下来,我们需要安装并配置Mask R-CNN的开发环境。可以通过使用Python包管理工具pip来安装所需依赖,并下载Mask R-CNN代码库。然后,根据具体的数据集,需要进行一些配置调整,例如修改配置文件相关的参数设置,如类别数目、训练和验证数据集的路径等等。 接下来,将数据集准备成模型可接受的格式。一般来说,我们需要将数据集划分为训练集和验证集,并提供每个图像的标注信息。可以使用一些处理工具来将数据集进行预处理,将图像转换为模型可接受的格式,并将标注信息保存为对应的掩模图像。 接下来,我们可以开始训练模型了。通过运行相应的训练脚本,可以开始构建并训练Mask R-CNN模型。训练过程会根据指定的配置和数据集进行迭代更新,直到模型收敛或达到预设的迭代次数。可以根据具体的训练状态和需求来监控训练过程,并根据需要进行调整和优化。 最后,一旦训练完成,我们可以使用训练好的模型对新的图像进行实例分割。可以通过加载训练好的权重文件来恢复模型,并使用模型对输入图像进行预测和推断,得到每个实例的分割结果。可以将结果保存为掩模图像或直接可视化展示。 在整个训练过程,需要注意数据集的质量,合理调整模型的参数和配置,并进行适当的训练和验证策略,以获得更好的实例分割效果。 ### 回答3: Mask R-CNN 是一种用于图像实例分割深度学习模型,它结合了目标检测和语义分割的特点。在实际应用,我们需要将模型训练在自己的数据集上,以便能够准确地对我们感兴趣的目标进行实例分割。 首先,我们需要准备自己的数据集。这包括收集具有实例标注的图像,并将它们分成训练集和验证集。实例标注是指为每个图像的目标对象绘制边界框和遮罩,以指示目标的位置和形状。 接下来,我们需要下载并配置Mask R-CNN的代码库。这可以通过在GitHub上找到Mask R-CNN的实现并进行下载。下载完成后,我们需要根据自己的数据集修改代码的配置文件,以适应我们的数据集和实验需求。 然后,我们可以开始训练自己的数据集。通过运行训练脚本,并指定数据集路径、模型配置和训练参数,我们可以开始训练模型。训练过程需要一定的时间和计算资源,具体时间取决于数据集的规模和硬件条件。 在训练过程,模型会逐渐学习到目标的外观和形状特征,并生成准确的边界框和遮罩。可以通过查看训练过程的损失值和验证指标来监控模型的训练情况,并根据需要进行调整和优化。 最后,当模型训练完成后,我们可以使用它对新的图像进行实例分割。通过加载训练好的权重,并用模型进行预测,我们可以得到每个目标对象的边界框和遮罩。这些结果可以进一步用于目标跟踪、图像分析等应用。 综上所述,训练自己的数据集可以帮助我们将Mask R-CNN模型应用到我们关心的领域,并进行准确的图像实例分割。这需要准备数据集、下载代码库、修改配置文件、进行模型训练和应用预测等步骤。通过这一过程,我们可以获得针对自己数据集的个性化实例分割模型,以满足我们具体的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值