python使用opencv进行数据特征融合

p y t h o n 使 用 o p e n c v 进 行 数 据 特 征 融 合 python使用opencv进行数据特征融合 python使opencv

缺陷库准备

V1

import os
import json
import base64
import numpy as np
from PIL import Image
from labelme import utils
import cv2
''''

1.读取标签json和原图

'''
json_path = r".\annotations\38.json"
img_path = r".\images\38.bmp"
label_name_to_value = {'_background_': 0}


json_data = json.load(open(json_path))
with open(img_path, 'rb') as f:
    imageData = f.read()
    imageData = base64.b64encode(imageData).decode('utf-8')
img = utils.img_b64_to_arr(imageData)


''''

2.根据json,获取描边的最小外接矩形,然后进行抠图,获取原图和mask

'''
'''
构建类名和label的字典-label_name_to_value
'''
for shape in json_data['shapes']:
    # 获取类名,不同类名则添加
    label_name = shape['label']
    if label_name in label_name_to_value:
        label_value = label_name_to_value[label_name]
    else:
        label_value = len(label_name_to_value)
        label_name_to_value[label_name] = label_value
        # classes=1,2,3...   label_value=1,2,3...
        print('Found new class name:{}/ value: {}'.format(label_name, label_value))

# 构建mask
lbl, _ = utils.shapes_to_label(img.shape, json_data['shapes'], label_name_to_value)
lbl = lbl*255
lbl = lbl.astype(np.uint8)
cv2.imwrite(r"./label_masks/mask.jpg",lbl)
# 获取区域轮廓
contours, hierarchy = cv2.findContours(lbl, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 轮廓线提取外接矩形
offset = 10
for c in contours:
    if len(c) < 10:  # 去除外轮廓
        continue
    # 找到边界坐标
    x, y, w, h = cv2.boundingRect(c)  # 计算点集最外面的矩形边界
    # cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 红,画框

    crop = img[y-offset:y + h+offset, x-offset:x + w+offset]
    mask = lbl[y-offset:y + h+offset, x-offset:x + w+offset]
    cv2.imwrite('./defects/crop.jpg', crop)
    cv2.imwrite('./masks/mask.jpg', mask)


V2

import os
import json
import base64
import numpy as np
from PIL import Image
from labelme import utils
import cv2
import time
from utils import *

def generate_defect(json_path,img_path,root_path):
    label_name_to_value = {'_background_': 0}
    # json数据
    json_data = json.load(open(json_path))
    with open(img_path, 'rb') as f:
        imageData = f.read()
        imageData = base64.b64encode(imageData).decode('utf-8')
    # 图像数据
    img = utils.img_b64_to_arr(imageData)

    img_name = os.path.basename(img_path).split('.')[0]   #输出为 class1.py
    ''''

    2.根据json,获取描边的最小外接矩形,然后进行抠图,获取原图和mask

    '''
    '''
    构建类名和label的字典-label_name_to_value
    '''
    for index_shape,shape in enumerate(json_data['shapes']):
        # 获取类名,不同类名则添加
        label_name = shape['label']
        label_groupid = shape['group_id']
        if label_name in label_name_to_value:
            label_value = label_name_to_value[label_name]
        else:
            label_value = len(label_name_to_value)
            label_name_to_value[label_name] = label_value
            # classes=1,2,3...   label_value=1,2,3...
            print('Found new class name:{}/ value: {}'.format(label_name, label_value))

        # 构建mask
        lbl, _ = utils.shapes_to_label(img.shape, json_data['shapes'], label_name_to_value)
        lbl = lbl * 255
        lbl = lbl.astype(np.uint8)
        # 生成label—mask
        cv2.imwrite(os.path.join(root_path, "label_masks", "label_masks"+"_"+str(time.time())+ ".jpg"), lbl)
        # 获取区域轮廓
        contours, hierarchy = cv2.findContours(lbl, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        # 轮廓线提取外接矩形
        offset = 10
        for c in contours:
            if len(c) < 10:  # 去除外轮廓
                continue
            # 找到边界坐标
            x, y, w, h = cv2.boundingRect(c)  # 计算点集最外面的矩形边界
            # cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 红,画框
            crop = img[y - offset:y + h + offset, x - offset:x + w + offset]
            mask = lbl[y - offset:y + h + offset, x - offset:x + w + offset]
            # 判断所在目录下是否有该文件夹,若没有则创建目录
            dir_defect_path = os.path.join(root_path,"defects",label_name+"_"+str(label_groupid)+"_"+img_name+"_"+str(index_shape))
            die_mask_path = os.path.join(root_path,"masks",label_name+"_"+str(label_groupid)+"_"+img_name+"_"+str(index_shape))
            if not os.path.exists(dir_defect_path):
                os.mkdir(dir_defect_path)
            if not os.path.exists(die_mask_path):
                os.mkdir(die_mask_path)
            cv2.imwrite(os.path.join(dir_defect_path,label_name+"_"+str(label_groupid)+".jpg"), crop)
            cv2.imwrite(os.path.join(die_mask_path,label_name+"_"+str(label_groupid)+".jpg"), mask)

def generate_defects(defect_repo_path):

    ''''
    1.读取标签json和原图
    '''
    annotations_path = os.path.join(defect_repo_path,"annotations")
    images_path = os.path.join(defect_repo_path,"images")
    anns = get_files_path(annotations_path)
    anns.sort()
    imgs = get_files_path(images_path)
    imgs.sort()
    for i in range(len(anns)):
        generate_defect(json_path=anns[i],img_path=imgs[i],root_path=defect_repo_path)


if __name__ == '__main__':
    generate_defects(r"D:\workplace\python\RealAug\defects_repo");

2Augmentor缺陷库数据增强

V1

# '''
# 步骤 1.创建管道Pipeline实例
# '''
# # 设置原图路径
# p = Augmentor.Pipeline(r"defects/异色_1_1")
# # 设置标签mask路径
# p.ground_truth(r"masks/异色_1_1")
# # 设置生成增强数据样本数量
# sample_num = 10
# '''
# 设置标志位
# '''
# # 1、旋转
# is_rotate = True
#
# # 2、缩放
# is_zoom = True
#
# # 3、裁剪
# is_crop = False
#
# # 4、翻转
# is_flip = False
#
# # 5、亮度增强/减弱
# is_brightness = True
#
# # 6、颜色增强/减弱
# is_color = True
#
# # 7、对比度增强/减弱
# is_contrast = False
#
# # 8、错切形变
# is_sheer = False
#
# # 9、透视形变
# is_skew = False
#
# # 10、弹性扭曲
# is_distortion = False
#
# # 11、随机区域擦除
# is_erasing = False
#
# '''
# 设置参数范围
# '''
#
# # 1、旋转
# rotate_max_left_rotation = 60
# rotate_max_right_rotation = 60
# # 2、缩放
# zoom_min_factor = 0.5
# zoom_max_factor = 2
# # 3、裁剪
# crop_percentage_area=0.8
# # 4、翻转
#
# # 5、亮度增强/减弱
# brightness_min_factor=0.7
# brightness_max_factor=1.2
# # 6、颜色增强/减弱
# color_min_factor=0.0
# color_max_factor=1.5
# # 7、对比度增强/减弱
# contrast_min_factor=0.7
# contrast_max_factor=1.2
# # 8、错切形变
# sheer_max_shear_left=15
# sheer_max_shear_right=15
# # 9、透视形变
# skew_tilt_magnitude = 1
# skew_corner_magnitude = 0.5
# # 10、弹性扭曲
# distortion_grid_height=5
# distortion_grid_width=16
# distortion_magnitude=8
# # 11、随机区域擦除
# erasing_rectangle_area = 0.5
#
#
# '''
# 步骤 2:向管道添加数据增强(执行概率+参数范围)操作
# '''
# # 设置处理概率
# process_probability = 1
# # 1、旋转
# if is_rotate:
#     # 1.1 不带裁剪的旋转
#     p.rotate_without_crop(probability=process_probability, max_left_rotation=rotate_max_left_rotation, max_right_rotation=rotate_max_right_rotation)
#     # # 1.2 带裁剪的旋转
#     # p.rotate(probability=process_probability, max_left_rotation=25, max_right_rotation=25)
#     # # 1.3 旋转90°
#     # p.rotate_random_90(probability=process_probability)
#
# # 2、缩放   zoom_min_factor=0.5   zoom_max_factor=2
# if is_zoom:
#     p.zoom(probability=process_probability, min_factor=zoom_min_factor, max_factor=zoom_max_factor)
#
# # 3、裁剪   crop_percentage_area=0.8
# if is_crop:
#     # 3.1 按大小裁剪
#     # p.crop_by_size(probability=1, width=1000, height=1000)
#     # 3.2 从区域中心裁剪
#     # p.crop_centre(probability=1,percentage_area=0.8)
#     # 3.3 随机裁剪
#     p.crop_random(probability=process_probability, percentage_area=crop_percentage_area, randomise_percentage_area=True)
#
# # 4、翻转
# if is_flip:
#     # # 4.1 水平翻转
#     # p.flip_left_right(probability=process_probability)
#     #
#     # # 4.2 上下翻转
#     # p.flip_top_bottom(probability=process_probability)
#     # 4.3 随机翻转
#     p.flip_random(probability=process_probability)
#
# # 5、亮度增强/减弱   brightness_min_factor=0.7  brightness_max_factor=1.2
# if is_brightness:
#     p.random_brightness(probability=process_probability, min_factor=brightness_min_factor, max_factor=brightness_max_factor)
#
# # 6、颜色增强/减弱  color_min_factor=0.0    color_max_factor=1.5
# if is_color:
#     p.random_color(probability=process_probability, min_factor=color_min_factor, max_factor=color_max_factor)
#
# # 7、对比度增强/减弱  contrast_min_factor=0.7  contrast_max_factor=1.2
# if is_contrast:
#     p.random_contrast(probability=process_probability, min_factor=contrast_min_factor, max_factor=contrast_max_factor)
#
# # 8、错切形变  sheer_max_shear_left=15  sheer_max_shear_right=15
# if is_sheer:
#     p.shear(probability=process_probability,max_shear_left=sheer_max_shear_left,max_shear_right=sheer_max_shear_right)
#
# # 9、透视形变  skew_tilt_magnitude = 1  skew_corner_magnitude = 0.5
# if is_skew:
#     # 9.1 垂直方向透视形变
#     p.skew_tilt(probability=process_probability, magnitude=skew_tilt_magnitude)
#     # 9.2 斜四角方向透视形变
#     p.skew_corner(probability=process_probability, magnitude=skew_corner_magnitude)
#
# # 10、弹性扭曲   distortion_grid_height=5 distortion_grid_width=16  distortion_magnitude=8
# if is_distortion:
#     p.random_distortion(probability=process_probability, grid_height=distortion_grid_height, grid_width=distortion_grid_width, magnitude=distortion_magnitude)
#
# # 11、随机区域擦除  erasing_rectangle_area = 0.5
# if is_erasing:
#     p.random_erasing(probability=process_probability, rectangle_area=erasing_rectangle_area)
#
#
# '''
# 步骤 3:生成数据增强后的图像和标签mask
# '''
# # 设置生成个数
# p.sample(sample_num)
# # 对每个图像做一次数据增强操作
# p.process()

V2

import Augmentor
from utils import *
def enhance_defect(defect_dirpath, mask_dirpath, cfg ="",sample_num=3):
    '''
    步骤 1.创建管道Pipeline实例
    '''
    # 设置原图路径
    p = Augmentor.Pipeline(defect_dirpath)
    # 设置标签mask路径
    p.ground_truth(mask_dirpath)
    # 设置生成增强数据样本数量
    sample_num = sample_num
    '''
    设置标志位
    '''
    # 1、旋转
    is_rotate = True

    # 2、缩放
    is_zoom = True

    # 3、裁剪
    is_crop = False

    # 4、翻转
    is_flip = False

    # 5、亮度增强/减弱
    is_brightness = False

    # 6、颜色增强/减弱
    is_color = False

    # 7、对比度增强/减弱
    is_contrast = False

    # 8、错切形变
    is_sheer = False

    # 9、透视形变
    is_skew = False

    # 10、弹性扭曲
    is_distortion = False

    # 11、随机区域擦除
    is_erasing = False

    '''
    设置参数范围
    '''

    # 1、旋转
    rotate_max_left_rotation = 60
    rotate_max_right_rotation = 60
    # 2、缩放
    zoom_min_factor = 0.5
    zoom_max_factor = 2
    # 3、裁剪
    crop_percentage_area = 0.8
    # 4、翻转

    # 5、亮度增强/减弱
    brightness_min_factor = 0.7
    brightness_max_factor = 1.2
    # 6、颜色增强/减弱
    color_min_factor = 0.0
    color_max_factor = 1.5
    # 7、对比度增强/减弱
    contrast_min_factor = 0.7
    contrast_max_factor = 1.2
    # 8、错切形变
    sheer_max_shear_left = 15
    sheer_max_shear_right = 15
    # 9、透视形变
    skew_tilt_magnitude = 1
    skew_corner_magnitude = 0.5
    # 10、弹性扭曲
    distortion_grid_height = 5
    distortion_grid_width = 16
    distortion_magnitude = 8
    # 11、随机区域擦除
    erasing_rectangle_area = 0.5

    '''
    步骤 2:向管道添加数据增强(执行概率+参数范围)操作
    '''
    # 设置处理概率
    process_probability = 1
    # 1、旋转
    if is_rotate:
        # 1.1 不带裁剪的旋转
        p.rotate_without_crop(probability=process_probability, max_left_rotation=rotate_max_left_rotation,
                              max_right_rotation=rotate_max_right_rotation)
        # # 1.2 带裁剪的旋转
        # p.rotate(probability=process_probability, max_left_rotation=25, max_right_rotation=25)
        # # 1.3 旋转90°
        # p.rotate_random_90(probability=process_probability)

    # 2、缩放   zoom_min_factor=0.5   zoom_max_factor=2
    if is_zoom:
        p.zoom(probability=process_probability, min_factor=zoom_min_factor, max_factor=zoom_max_factor)

    # 3、裁剪   crop_percentage_area=0.8
    if is_crop:
        # 3.1 按大小裁剪
        # p.crop_by_size(probability=1, width=1000, height=1000)
        # 3.2 从区域中心裁剪
        # p.crop_centre(probability=1,percentage_area=0.8)
        # 3.3 随机裁剪
        p.crop_random(probability=process_probability, percentage_area=crop_percentage_area,
                      randomise_percentage_area=True)

    # 4、翻转
    if is_flip:
        # # 4.1 水平翻转
        # p.flip_left_right(probability=process_probability)
        #
        # # 4.2 上下翻转
        # p.flip_top_bottom(probability=process_probability)
        # 4.3 随机翻转
        p.flip_random(probability=process_probability)

    # 5、亮度增强/减弱   brightness_min_factor=0.7  brightness_max_factor=1.2
    if is_brightness:
        p.random_brightness(probability=process_probability, min_factor=brightness_min_factor,
                            max_factor=brightness_max_factor)

    # 6、颜色增强/减弱  color_min_factor=0.0    color_max_factor=1.5
    if is_color:
        p.random_color(probability=process_probability, min_factor=color_min_factor, max_factor=color_max_factor)

    # 7、对比度增强/减弱  contrast_min_factor=0.7  contrast_max_factor=1.2
    if is_contrast:
        p.random_contrast(probability=process_probability, min_factor=contrast_min_factor,
                          max_factor=contrast_max_factor)

    # 8、错切形变  sheer_max_shear_left=15  sheer_max_shear_right=15
    if is_sheer:
        p.shear(probability=process_probability, max_shear_left=sheer_max_shear_left,
                max_shear_right=sheer_max_shear_right)

    # 9、透视形变  skew_tilt_magnitude = 1  skew_corner_magnitude = 0.5
    if is_skew:
        # 9.1 垂直方向透视形变
        p.skew_tilt(probability=process_probability, magnitude=skew_tilt_magnitude)
        # 9.2 斜四角方向透视形变
        p.skew_corner(probability=process_probability, magnitude=skew_corner_magnitude)

    # 10、弹性扭曲   distortion_grid_height=5 distortion_grid_width=16  distortion_magnitude=8
    if is_distortion:
        p.random_distortion(probability=process_probability, grid_height=distortion_grid_height,
                            grid_width=distortion_grid_width, magnitude=distortion_magnitude)

    # 11、随机区域擦除  erasing_rectangle_area = 0.5
    if is_erasing:
        p.random_erasing(probability=process_probability, rectangle_area=erasing_rectangle_area)

    '''
    步骤 3:生成数据增强后的图像和标签mask
    '''
    # 设置生成个数
    p.sample(sample_num)
    # 对每个图像做一次数据增强操作
    p.process()




def enhance_defects(defect_repo_path,cfg,sample_num,is_delete=True):
    import os
    defects_path = os.path.join(defect_repo_path,"defects")
    masks_path = os.path.join(defect_repo_path,"masks")
    defects = get_dirs_path(defects_path)
    defects.sort()
    masks = get_dirs_path(masks_path)
    masks.sort()

    if is_delete:
        for i in defects:
            deletedir(os.path.join(i,"output"))


    for i in range(len(defects)):
        enhance_defect(defect_dirpath=defects[i],mask_dirpath=masks[i],cfg=cfg,sample_num=sample_num)



if __name__ == '__main__':
    enhance_defects(defect_repo_path=r"D:\workplace\python\RealAug\defects_repo",cfg="",sample_num=3,is_delete=True)
#

单个特征融合

V1

import cv2
import numpy as np
from math import sqrt
from PIL import Image
# 原图
img_back = Image.open(r".\images\85.bmp")
img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
# 贴图
img_obj = cv2.imread(r"./defects/crop.jpg")
# 掩膜,确定贴图的ROI区域(0表示不需要的区域,255表示需要贴合的区域)
mask = cv2.imread(r"./masks/mask.jpg",0)
# 获取原图宽高
width,height,channels = img_back.shape
# 粘贴位置
loaction = (height//2,width//2)
# 进行贴合
normal_clone = cv2.seamlessClone(img_obj,img_back,mask,loaction,cv2.NORMAL_CLONE)
normal_clone = cv2.seamlessClone(img_obj,normal_clone,mask,(height//4,width//2),cv2.NORMAL_CLONE)
# 显示贴合位置
# cv2.rectangle(normal_clone, loaction, (height//2+100,width//2+100), (255, 0, 255), -1)
# 保存贴合图
cv2.imwrite("./out/normal_clone.jpg",normal_clone)
# 获取mask原图
raw_img = cv2.imread(r"D:\workplace\python\RealAug\label_masks\mask.jpg",0)
# 获取mask的宽高
w,h = mask.shape
# 获取贴合起始位置
start_x = int(width//2 -w/2)
start_y = int(height//2 - h/2)
# mask进行贴合
for i in range(w):
    for j in range(h):
        raw_img[start_x + i, start_y + j] = mask[i, j]
# 保存label_mask
cv2.imwrite("label_mask.jpg",raw_img)

在这里插入图片描述

V2

import cv2
import numpy as np
from math import sqrt
from PIL import Image
import os

def single_feat_merge(imgobj_path, imgback_path, mask_path, out_dir, loaction=(500,500)):
    '''
    1.生成特征融合图
    '''
    # 1.确定贴图
    img_obj = cv2.imread(imgobj_path)
    # 2.确定原图
    img_back = Image.open(imgback_path)
    img_name = os.path.basename(imgback_path)
    img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
    # 3.确定mask掩膜,即贴图的ROI区域(0表示不需要的区域,255表示需要贴合的区域)
    mask = cv2.imread(mask_path, 0)
    # 4.确定位置
    loaction = loaction
    # 5.确定融合方式
    seamlessClone_style = cv2.NORMAL_CLONE
    # 6.进行融合
    img_back = cv2.seamlessClone(img_obj, img_back, mask, loaction, seamlessClone_style)
    # 显示贴合位置
    # cv2.rectangle(normal_clone, loaction, (height//2+100,width//2+100), (255, 0, 255), -1)
    # 7.保存贴合图
    if not os.path.exists(os.path.join(out_dir,"images")):
        os.mkdir(os.path.join(out_dir,"images"))
    cv2.imwrite(os.path.join(out_dir,"images",img_name), img_back)
    '''
    2.生成label图
    '''
    # 获取mask原图,读取灰度图
    # raw_img = cv2.imread(r"D:\workplace\python\RealAug\label_masks\mask.jpg", 0)
    label_img = np.zeros([img_back.shape[0],img_back.shape[1]],dtype=np.uint8)
    # 获取mask的宽高
    w, h = mask.shape
    # 获取贴合起始位置
    start_x = int(width // 2 - w / 2)
    start_y = int(height // 2 - h / 2)
    # mask进行贴合
    for i in range(w):
        for j in range(h):
            label_img[start_x + i, start_y + j] = mask[i, j]
    # 保存label_mask
    if not os.path.exists(os.path.join(out_dir,"masks")):
        os.mkdir(os.path.join(out_dir,"masks"))
    cv2.imwrite(os.path.join(out_dir,"masks",img_name), label_img)


def feat_merge(imgback_path, imgobj_paths, mask_paths, loactions, out_dir):
    # 读取原图
    img_back = Image.open(imgback_path)
    img_name = os.path.basename(imgback_path)
    img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
    # 初始化label_mask
    label_img = np.zeros([img_back.shape[0],img_back.shape[1]],dtype=np.uint8)

    # 特征列表
    feats_list = []
    for i in imgobj_paths:
        feats_list.append(cv2.imread(i))
    # 标签列表
    masks_list = []
    for i in mask_paths:
        masks_list.append(cv2.imread(i,0))
    # 位置列表
    loactions_list = loactions

    # 进行融合
    for i in range(len(feats_list)):
        # 1.原图融合
        img_back = cv2.seamlessClone(feats_list[i], img_back, masks_list[i], loactions_list[i], cv2.NORMAL_CLONE)
        # 2.label_mask融合
        # 获取mask的宽高
        w, h = masks_list[i].shape
        # 获取贴合起始位置(***?)
        start_x = int(loactions_list[i][0] - w / 2)
        start_y = int(loactions_list[i][1] - h / 2)
        # 遍历进行mask进行贴合
        for i_w in range(w):
            for j_h in range(h):
                # mask进行贴合
                label_img[start_x + i_w, start_y + j_h] = masks_list[i][i_w, j_h]

    # 保存贴合图
    if not os.path.exists(os.path.join(out_dir,"images")):
        os.mkdir(os.path.join(out_dir,"images"))
    cv2.imwrite(os.path.join(out_dir,"images",img_name), img_back)

    # 保存label_mask
    if not os.path.exists(os.path.join(out_dir,"masks")):
        os.mkdir(os.path.join(out_dir,"masks"))
    cv2.imwrite(os.path.join(out_dir,"masks",img_name), label_img)

def feats_merge():
    imgback_path = r"D:\workplace\python\RealAug\images\34.bmp"
    imgobj_paths = [r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\dc_1_34_0_original_dc_1.jpg_3c10e17f-522a-4b1c-bd33-41f5be9aaa2b.jpg",r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\dc_1_34_0_original_dc_1.jpg_9b6565f0-31de-4484-b93f-8907b1b57a18.jpg"]
    mask_paths = [r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\_groundtruth_(1)_dc_1_34_0_dc_1.jpg_3c10e17f-522a-4b1c-bd33-41f5be9aaa2b.jpg",r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\_groundtruth_(1)_dc_1_34_0_dc_1.jpg_9b6565f0-31de-4484-b93f-8907b1b57a18.jpg"]
    loactions = [(500,500),(1000,1000)]
    feat_merge(imgback_path=imgback_path, imgobj_paths=imgobj_paths, mask_paths=mask_paths, loactions=loactions, out_dir=r"D:\workplace\python\RealAug\enhance")

if __name__ == '__main__':
    feats_merge()

V3

import cv2
import numpy as np
from PIL import Image
import os
import random
from utils import *
import tqdm
from labelme import utils
import json
import os
import glob
import cv2
import json

def generate_segjson(label_mask_path, raw_json_path, group_id,out_dir):
    json_data = json.load(open(raw_json_path))
    raw_json_name = os.path.basename(raw_json_path)
    '''
    1.读取图像,获取图像的宽高
    '''
    mask_lbl = cv2.imread(label_mask_path, 0)

    '''
    2.findcontour,获取mask的所有点
    '''
    contours, hierarchy = cv2.findContours(mask_lbl, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 分割点集列表
    list_polygon_points = []
    # 遍历所有轮廓,进行筛选
    for c in contours:
        # 去除非轮廓
        if len(c) < 100:
            continue
        '''
        生成分割任务的分割json
        '''
        # 去除轮廓c的中间维度
        points = c[:, 0, :]
        list_polygon_points.append(points)

    '''
    3.对分割任务的分割json文件进行赋值
    '''

    shapes = list(json_data['shapes'])

    # 遍历所有轮廓
    for index_countour in list_polygon_points:
        shape = {}
        shape['points'] = index_countour.tolist()
        shape['label'] = "dc"
        shape['group_id'] = group_id
        shape['shape_type'] = "polygon"
        # 添加一个点位轨迹
        shapes.append(shape)

    json_data['shapes'] = shapes
    '''
    4.生成json
    '''
    # 存json
    if not os.path.exists(os.path.join(out_dir, 'annotations')):
        os.mkdir(os.path.join(out_dir, 'annotations'))
    json_file = os.path.join(out_dir,'annotations' ,raw_json_name)
    with open(json_file, 'w') as f:
        json.dump(json_data, f, indent=2)



def feat_merge(imgback_path,label_json_path, imgobj_paths, mask_paths, loactions, group_id,out_dir):
    # 创建输出目录
    if not os.path.exists(out_dir):
        os.mkdir(out_dir)

    # 读取原图
    img_back = Image.open(imgback_path)
    img_name = os.path.basename(imgback_path).split(".")[0]
    img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
    # 初始化label_mask    h  w
    # json数据
    # json_data = json.load(open(label_json_path))
    # label_name_to_value = {'_background_': 0}
    # for index_shape,shape in enumerate(json_data['shapes']):
    #     # 获取类名,不同类名则添加
    #     label_name = shape['label']
    #     label_groupid = shape['group_id']
    #     if label_name in label_name_to_value:
    #         label_value = label_name_to_value[label_name]
    #     else:
    #         label_value = len(label_name_to_value)
    #         label_name_to_value[label_name] = label_value
    #         # classes=1,2,3...   label_value=1,2,3...
    #         print('Found new class name:{}/ value: {}'.format(label_name, label_value))
    #
    # lbl, _ = utils.shapes_to_label(img_back.shape, json_data['shapes'], label_name_to_value)
    # lbl = lbl * 255
    # label_img = lbl.astype(np.uint8)

    label_img = np.zeros([img_back.shape[0],img_back.shape[1]],dtype=np.uint8)
    # 特征列表
    feats_list = []
    for i in imgobj_paths:
        feats_list.append(cv2.imread(i))
    # 标签列表
    masks_list = []
    for i in mask_paths:
        masks_list.append(cv2.imread(i,0))
    # 位置列表
    loactions_list = loactions
    # 成功融合个数
    success_merge_num = 0
    # 进行融合
    for i in range(len(loactions)):
        # 1.label_mask融合
        # 获取mask的宽高
        h, w = masks_list[i].shape
        # 获取贴合起始位置(***?)
        start_x = int(loactions_list[i][0] - w / 2)
        start_y = int(loactions_list[i][1] - h / 2)
        # 如果起始位置小于0,则跳过
        if start_x < 0 or start_y < 0:
            continue
        # 遍历进行mask进行贴合
        for i_w in range(w):
            for j_h in range(h):
                # mask进行贴合
                try:
                    label_img[start_y + j_h, start_x + i_w] = masks_list[i][j_h, i_w]
                except Exception as exp:
                    print(exp)
        # 2.原图融合
        try:
            img_back = cv2.seamlessClone(feats_list[i], img_back, masks_list[i], loactions_list[i], cv2.NORMAL_CLONE)
            success_merge_num = success_merge_num +1
            if success_merge_num == len(feats_list):
                break
        except Exception as exp:
            print(exp)

    # 保存贴合图
    if not os.path.exists(os.path.join(out_dir,"images")):
        os.mkdir(os.path.join(out_dir,"images"))
    cv2.imwrite(os.path.join(out_dir,"images",img_name+".jpg"), img_back)

    # 保存label_mask
    if not os.path.exists(os.path.join(out_dir,"masks")):
        os.mkdir(os.path.join(out_dir,"masks"))
    cv2.imwrite(os.path.join(out_dir,"masks",img_name+".jpg"), label_img)

    # 生成分割json
    generate_segjson(label_mask_path=os.path.join(out_dir,"masks",img_name+".jpg"), raw_json_path=label_json_path, group_id=group_id, out_dir=out_dir)


def generate_locations(raw_img_path,sample_num,x_offset = 300,y_offset=300):
    img_back = cv2.imread(raw_img_path , 0)
    # 在这里进行筛选
    # 简单阈值分割确定ROI区域,非ROI区域进行去除
    '''
    1.阈值分割
    2.获取最小外接矩形的x,y,x,y
    3.设置offset
    4.判定随机生成的坐标是否在此范围内
    '''
    # 固定阈值(核心)
    # ret, th1 = cv2.threshold(img_back, 30, 255, cv2.THRESH_BINARY)
    # contours, hierarchy = cv2.findContours(th1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # lens_contour = []
    # for c in contours:
    #      lens_contour.append(len(c))
    # lens_c_value = max(lens_contour)  # 最大值
    # max_contour_index = lens_contour.index(lens_c_value)  # 最大值索引
    # x1, y1, w, h = cv2.boundingRect(contours[max_contour_index])  # 计算点集最外面的矩形边界
    # x2 = x1+w
    # y2 = y1+h
    y1 = 0
    x1 = 0
    y2 = img_back.shape[0]  # h
    x2 = img_back.shape[1]  # w
    # 偏置 (***重要)
    x1_new = x1 + x_offset
    y1_new = y1 + y_offset
    x2_new = x2 - x_offset
    y2_new = y2 - y_offset
    # 粘贴位置
    locations = []
    for index_3dd in range(sample_num):
        # 如果 右下角坐标小于0
        locations.append((int(random.uniform(x1_new, x2_new)), int(random.uniform(y1_new, y2_new))))
    return locations

def feats_merge(img_paths="images",anno_json_path="annotations",defects_masks_path="defects_repo/defects",group_id=1,defects_num=3,out_dir=r"D:\workplace\python\RealAug\enhance"):
    imgs_list = get_files_path(img_paths)
    imgs_list.sort()
    anno_json_list = get_files_path(anno_json_path)
    anno_json_list.sort()
    for index_imgpath ,img_path in enumerate(tqdm.tqdm(imgs_list)):
        # 原图路径
        imgback_path = img_path
        # 对应json路径
        label_json_path = anno_json_list[index_imgpath]
        # 融合点位集合
        loactions_list = generate_locations(raw_img_path=imgback_path,sample_num=100,x_offset=800,y_offset=700)
        # 特征图路径集合
        imgobj_paths = [r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\dc_1_34_0_original_dc_1.jpg_3c10e17f-522a-4b1c-bd33-41f5be9aaa2b.jpg",r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\dc_1_34_0_original_dc_1.jpg_9b6565f0-31de-4484-b93f-8907b1b57a18.jpg"]
        # 特征图mask路径集合
        mask_paths = [r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\_groundtruth_(1)_dc_1_34_0_dc_1.jpg_3c10e17f-522a-4b1c-bd33-41f5be9aaa2b.jpg",r"D:\workplace\python\RealAug\defects_repo\defects\dc_1_34_0\output\_groundtruth_(1)_dc_1_34_0_dc_1.jpg_9b6565f0-31de-4484-b93f-8907b1b57a18.jpg"]
        # 进行融合
        feat_merge(imgback_path=imgback_path, label_json_path=label_json_path,imgobj_paths=imgobj_paths, mask_paths=mask_paths, loactions=loactions_list, group_id=group_id,out_dir=out_dir)



if __name__ == '__main__':
    feats_merge(img_paths="images",anno_json_path="annotations",defects_masks_path="defects_repo/defects", group_id=1, defects_num=3)






随机生成坐标点

import numpy as np
# 贴合缺陷个数
point_num = 10
'''
随机生成坐标
'''
width = 1200
height = 800
X = np.random.rand(1, point_num) * width
X = X.flatten()
Y = np.random.rand(1, point_num) * height
Y = Y.flatten()
points = []
for i in range(len(X)):
    points.append((int(X[i]),int(Y[i])))
print(points)
# print(Y)

随机多特征融合

'''

1.读取标签json和原图,获取

'''
import cv2
import numpy as np
from math import sqrt
from PIL import Image
# 原图
img_back = Image.open(r".\images\85.bmp")
img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
# 贴图
img_obj = cv2.imread(r"./defects/crop.jpg")
# 掩膜,确定贴图的ROI区域(0表示不需要的区域,255表示需要贴合的区域)
mask = cv2.imread(r"./masks/masks.jpg")
# 贴合缺陷个数
point_num = 100
'''
随机生成坐标
'''
# 获取原图宽高
width,height,channels = img_back.shape
X = np.random.rand(1, point_num) * width
X = X.flatten()
Y = np.random.rand(1, point_num) * height
Y = Y.flatten()
# 粘贴位置
points = []
for i in range(len(X)):
    # 在这里进行筛选
    # 简单阈值分割确定ROI区域,非ROI区域进行去除
    points.append((int(X[i]),int(Y[i])))
# print(points)
# print(Y)
# 进行贴合
for i_location in points:
    try:
        img_back = cv2.seamlessClone(img_obj, img_back, mask, i_location, cv2.NORMAL_CLONE)
        cv2.imwrite("./out/normal_clone.jpg", img_back)
    except Exception as e:
        print(e)

5生成融合后分割json

import os
import glob
import cv2
import json
'''
1.读取图像,获取图像的宽高
'''
mask_lbl = cv2.imread(r"D:\workplace\python\RealAug\label_masks\label_mask.jpg",0)

'''
2.findcontour,获取mask的所有点
'''
contours, hierarchy = cv2.findContours(mask_lbl, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# cv2.drawContours(mask_lbl,contours,-1,(0,0,255),3)
# 检测框label列表
list_rect = []
# 分割点集列表
list_polygon_points = []
# 遍历所有轮廓,进行筛选
for c in contours:
    # 去除非轮廓
    if len(c) < 10:
        continue
    '''
    生成检测任务的检测json
    '''
    # 计算点集最外面的矩形边界,用于生成检测json
    x, y, w, h = cv2.boundingRect(c)
    list_rect.append((x, y, w, h))
    '''
    生成分割任务的分割json
    '''
    # 去除轮廓c的中间维度
    points = c[ :, 0, :]
    list_polygon_points.append(points)


'''
3.对分割任务的分割json文件进行赋值
'''
# json文件
json_str = {}
# 版本
json_str['version'] = "0.0.1"
# flags
json_str['flags'] = {}
# 所有点位
shapes = []
# 宽高
width, height = mask_lbl.shape
# 图像路径
imagePath = ""
# 图像数据
imageData = ""
# 类别名称
cls_name = "dc"
# id号
group_id = 1
# 遍历所有轮廓
for index_countour in list_polygon_points:
    shape = {}
    shape['points'] = index_countour.tolist()
    shape['label'] = cls_name
    shape['group_id'] = group_id
    shape['shape_type'] = "polygon"
    # 添加一个点位轨迹
    shapes.append(shape)


json_str['shapes'] = shapes
json_str['imagePath'] = imagePath
json_str['imageData'] = imageData
json_str['imageHeight'] = height
json_str['imageWidth'] = width

'''
4.生成json
'''
json_file = os.path.join("./", 'out1.json')
with open(json_file, 'w') as f:
    json.dump(json_str, f, indent=2)


{
  "version": "0.0.1",
  "flags": {},
  "shapes": [
    {
      "points": ,
      "label": "dc",
      "group_id": 1,
      "shape_type": "polygon"
    },
    {
      "points": ,
      "label": "dc",
      "group_id": 1,
      "shape_type": "polygon"
    }
  ],
  "imagePath": "",
  "imageData": "",
  "imageHeight": 5120,
  "imageWidth": 2000
}

6生成融合后检测json

import os
import cv2
import json
'''
1.读取图像,获取图像的宽高
'''
mask_lbl = cv2.imread(r"D:\workplace\python\RealAug\label_masks\label_mask.jpg",0)
width, height = mask_lbl.shape
image_data = None
img_path = ""

'''
2.findcontour,获取mask的所有点
'''
contours, hierarchy = cv2.findContours(mask_lbl, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# cv2.drawContours(mask_lbl,contours,-1,(0,0,255),3)
# 检测框label列表
list_rect = []
# 分割点集列表
list_polygon_points = []
# 遍历所有轮廓,进行筛选
for c in contours:
    # 去除非轮廓
    if len(c) < 10:
        continue
    '''
    生成检测任务的检测json
    '''
    # 计算点集最外面的矩形边界,用于生成检测json
    x, y, w, h = cv2.boundingRect(c)
    # 左上角点和右下角点
    list_rect.append([x, y, w, h])


'''
3.对检测任务的检测json文件进行赋值
'''
json_res = []
# json文件
json_str = {}
# 所有点位
annotations = []
# 宽高
width, height = mask_lbl.shape
# 图像路径
imagePath = ""
# 图像数据
imageData = ""
# 类别名称
cls_name = "dc"
# id号
group_id = 1
# 遍历所有轮廓
for index_rect in list_rect:
    annotation = {}
    annotation['label'] = cls_name
    annotation['group_id'] = group_id
    coordinates = {}
    coordinates['x'] =  index_rect[0]
    coordinates['y'] = index_rect[1]
    coordinates['width'] = index_rect[2]
    coordinates['height'] = index_rect[3]
    annotation['coordinates'] = coordinates

    # 添加一个点位轨迹
    annotations.append(annotation)

json_str['image'] = "Image"
json_str['annotations'] = annotations
json_str['isReasoned'] = False

json_res.append(json_str)
'''
4.生成json
'''
json_file = os.path.join("./", 'out_rect.json')
with open(json_file, 'w') as f:
    json.dump(json_res, f, indent=2)

[
  {
    "image": "Image",
    "annotations": [
      {
        "label": "dc",
        "group_id": 1,
        "coordinates": {
          "x": 2904,
          "y": 1392,
          "width": 128,
          "height": 104
        }
      },
      {
        "label": "dc",
        "group_id": 1,
        "coordinates": {
          "x": 2496,
          "y": 948,
          "width": 131,
          "height": 107
        }
      }
    ],
    "isReasoned": false
  }
]

Frm1_缺陷录入

import tkinter as tk
import tkinter.font as tkFont
from utils import *
import cv2
import json
import base64
import numpy as np
from PIL import Image
from labelme import utils


class App1:
    def __init__(self, root):
        #setting title
        root.title("undefined")
        #setting window size
        width=660
        height=541
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        root.geometry(alignstr)
        root.resizable(width=False, height=False)

        self.GLineEdit_865=tk.Entry(root)
        self.GLineEdit_865["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_865["font"] = ft
        self.GLineEdit_865["fg"] = "#333333"
        self.GLineEdit_865["justify"] = "center"
        self.GLineEdit_865_content = tk.StringVar()
        self.GLineEdit_865["textvariable"] = self.GLineEdit_865_content

        self.GLineEdit_865.place(x=60,y=50,width=260,height=30)



        self.GLineEdit_758=tk.Entry(root)
        self.GLineEdit_758["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_758["font"] = ft
        self.GLineEdit_758["fg"] = "#333333"
        self.GLineEdit_758["justify"] = "center"

        self.GLineEdit_758_content = tk.StringVar()
        self.GLineEdit_758["textvariable"] = self.GLineEdit_758_content
        self.GLineEdit_758.place(x=60,y=100,width=260,height=30)

        GButton_409=tk.Button(root)
        GButton_409["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        GButton_409["font"] = ft
        GButton_409["fg"] = "#000000"
        GButton_409["justify"] = "center"
        GButton_409["text"] = "选取json"
        GButton_409.place(x=370,y=50,width=156,height=30)
        GButton_409["command"] = self.GButton_409_command

        GButton_674=tk.Button(root)
        GButton_674["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        GButton_674["font"] = ft
        GButton_674["fg"] = "#000000"
        GButton_674["justify"] = "center"
        GButton_674["text"] = "选取原图"
        GButton_674.place(x=370,y=100,width=156,height=30)
        GButton_674["command"] = self.GButton_674_command

        GButton_287=tk.Button(root)
        GButton_287["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        GButton_287["font"] = ft
        GButton_287["fg"] = "#000000"
        GButton_287["justify"] = "center"
        GButton_287["text"] = "录入缺陷"
        GButton_287.place(x=370,y=160,width=159,height=30)
        GButton_287["command"] = self.GButton_287_command


    def GButton_409_command(self):
        '''
        json文件
        :return:
        '''
        print("command")
        self.jsonfile_path = openfile()
        print(self.jsonfile_path)
        self.GLineEdit_865_content.set(self.jsonfile_path)




    def GButton_674_command(self):
        '''
        原图文件
        :return:
        '''
        print("command")
        self.img_path = openfile()
        print(self.img_path)
        self.GLineEdit_758_content.set(self.img_path)



    def GButton_287_command(self):
        '''
        录入缺陷
        :return:
        '''
        ''''
        1.读取标签json和原图
        '''
        json_path = self.GLineEdit_865_content.get()
        img_path = self.GLineEdit_758_content.get()
        label_name_to_value = {'_background_': 0}

        # json数据
        json_data = json.load(open(json_path))
        with open(img_path, 'rb') as f:
            imageData = f.read()
            imageData = base64.b64encode(imageData).decode('utf-8')
        # 图像数据
        img = utils.img_b64_to_arr(imageData)

        ''''

        2.根据json,获取描边的最小外接矩形,然后进行抠图,获取原图和mask

        '''
        '''
        构建类名和label的字典-label_name_to_value
        '''
        for shape in json_data['shapes']:
            # 获取类名,不同类名则添加
            label_name = shape['label']
            if label_name in label_name_to_value:
                label_value = label_name_to_value[label_name]
            else:
                label_value = len(label_name_to_value)
                label_name_to_value[label_name] = label_value
                # classes=1,2,3...   label_value=1,2,3...
                print('Found new class name:{}/ value: {}'.format(label_name, label_value))

        # 构建mask
        lbl, _ = utils.shapes_to_label(img.shape, json_data['shapes'], label_name_to_value)
        lbl = lbl * 255
        lbl = lbl.astype(np.uint8)
        # 生成label—mask
        cv2.imwrite(r"./label_masks/crop11.jpg", lbl)
        # 获取区域轮廓
        contours, hierarchy = cv2.findContours(lbl, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        # 轮廓线提取外接矩形
        offset = 10
        for c in contours:
            if len(c) < 10:  # 去除外轮廓
                continue
            # 找到边界坐标
            x, y, w, h = cv2.boundingRect(c)  # 计算点集最外面的矩形边界
            # cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 红,画框

            crop = img[y - offset:y + h + offset, x - offset:x + w + offset]
            mask = lbl[y - offset:y + h + offset, x - offset:x + w + offset]
            cv2.imwrite('./defects/crop11.jpg', crop)
            cv2.imwrite('./masks/crop11.jpg', mask)


if __name__ == "__main__":
    root = tk.Tk()
    app = App1(root)
    root.mainloop()

Frm2_缺陷增强

Frm3_选取融合

import cv2
import numpy as np
from PIL import Image
import os
import random
from utils import *
import tqdm
from labelme import utils
import json
import os
import glob
import cv2
import json

def generate_segjson(label_mask_path, raw_json_path, group_id,out_dir):
    json_data = json.load(open(raw_json_path))
    raw_json_name = os.path.basename(raw_json_path)
    '''
    1.读取图像,获取图像的宽高
    '''
    mask_lbl = cv2.imread(label_mask_path, 0)

    '''
    2.findcontour,获取mask的所有点
    '''
    contours, hierarchy = cv2.findContours(mask_lbl, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 分割点集列表
    list_polygon_points = []
    # 遍历所有轮廓,进行筛选
    for c in contours:
        # 去除非轮廓
        if len(c) < 100:
            continue
        '''
        生成分割任务的分割json
        '''
        # 去除轮廓c的中间维度
        points = c[:, 0, :]
        list_polygon_points.append(points)

    '''
    3.对分割任务的分割json文件进行赋值
    '''

    shapes = list(json_data['shapes'])

    # 遍历所有轮廓
    for index_countour in list_polygon_points:
        shape = {}
        shape['points'] = index_countour.tolist()
        shape['label'] = "dc"
        shape['group_id'] = group_id
        shape['shape_type'] = "polygon"
        # 添加一个点位轨迹
        shapes.append(shape)

    json_data['shapes'] = shapes
    '''
    4.生成json
    '''
    # 存json
    if not os.path.exists(os.path.join(out_dir, 'annotations')):
        os.mkdir(os.path.join(out_dir, 'annotations'))
    json_file = os.path.join(out_dir,'annotations' ,raw_json_name)
    with open(json_file, 'w') as f:
        json.dump(json_data, f, indent=2)



def feat_merge(imgback_path,label_json_path, imgobj_paths, mask_paths, loactions, group_id,out_dir):
    # 创建输出目录
    if not os.path.exists(out_dir):
        os.mkdir(out_dir)

    # 读取原图
    img_back = Image.open(imgback_path)
    img_name = os.path.basename(imgback_path).split(".")[0]
    img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
    # 初始化label_mask    h  w
    # json数据
    # json_data = json.load(open(label_json_path))
    # label_name_to_value = {'_background_': 0}
    # for index_shape,shape in enumerate(json_data['shapes']):
    #     # 获取类名,不同类名则添加
    #     label_name = shape['label']
    #     label_groupid = shape['group_id']
    #     if label_name in label_name_to_value:
    #         label_value = label_name_to_value[label_name]
    #     else:
    #         label_value = len(label_name_to_value)
    #         label_name_to_value[label_name] = label_value
    #         # classes=1,2,3...   label_value=1,2,3...
    #         print('Found new class name:{}/ value: {}'.format(label_name, label_value))
    #
    # lbl, _ = utils.shapes_to_label(img_back.shape, json_data['shapes'], label_name_to_value)
    # lbl = lbl * 255
    # label_img = lbl.astype(np.uint8)

    label_img = np.zeros([img_back.shape[0],img_back.shape[1]],dtype=np.uint8)
    # 特征列表
    feats_list = []
    for i in imgobj_paths:
        feats_list.append(cv2.imread(i))
    # 标签列表
    masks_list = []
    for i in mask_paths:
        masks_list.append(cv2.imread(i,0))
    # 位置列表
    loactions_list = loactions
    # 成功融合个数
    success_merge_num = 0
    # 进行融合
    for i in range(len(loactions)):
        # 1.label_mask融合
        # 获取mask的宽高
        h, w = masks_list[i].shape
        # 获取贴合起始位置(***?)
        start_x = int(loactions_list[i][0] - w / 2)
        start_y = int(loactions_list[i][1] - h / 2)
        # 如果起始位置小于0,则跳过
        if start_x < 0 or start_y < 0:
            continue
        # 遍历进行mask进行贴合
        for i_w in range(w):
            for j_h in range(h):
                # mask进行贴合
                try:
                    label_img[start_y + j_h, start_x + i_w] = masks_list[i][j_h, i_w]
                except Exception as exp:
                    print(exp)
        # 2.原图融合
        try:
            img_back = cv2.seamlessClone(feats_list[i], img_back, masks_list[i], loactions_list[i], cv2.NORMAL_CLONE)
            success_merge_num = success_merge_num +1
            if success_merge_num == len(feats_list):
                break
        except Exception as exp:
            print(exp)

    # 保存贴合图
    if not os.path.exists(os.path.join(out_dir,"images")):
        os.mkdir(os.path.join(out_dir,"images"))
    cv2.imwrite(os.path.join(out_dir,"images",img_name+".jpg"), img_back)

    # 保存label_mask
    if not os.path.exists(os.path.join(out_dir,"masks")):
        os.mkdir(os.path.join(out_dir,"masks"))
    cv2.imwrite(os.path.join(out_dir,"masks",img_name+".jpg"), label_img)

    # 生成分割json
    generate_segjson(label_mask_path=os.path.join(out_dir,"masks",img_name+".jpg"), raw_json_path=label_json_path, group_id=group_id, out_dir=out_dir)


def generate_locations(raw_img_path,sample_num,x_offset = 300,y_offset=300):
    img_back = cv2.imread(raw_img_path , 0)
    # 在这里进行筛选
    # 简单阈值分割确定ROI区域,非ROI区域进行去除
    '''
    1.阈值分割
    2.获取最小外接矩形的x,y,x,y
    3.设置offset
    4.判定随机生成的坐标是否在此范围内
    '''
    # 固定阈值(核心)
    # ret, th1 = cv2.threshold(img_back, 30, 255, cv2.THRESH_BINARY)
    # contours, hierarchy = cv2.findContours(th1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # lens_contour = []
    # for c in contours:
    #      lens_contour.append(len(c))
    # lens_c_value = max(lens_contour)  # 最大值
    # max_contour_index = lens_contour.index(lens_c_value)  # 最大值索引
    # x1, y1, w, h = cv2.boundingRect(contours[max_contour_index])  # 计算点集最外面的矩形边界
    # x2 = x1+w
    # y2 = y1+h
    y1 = 0
    x1 = 0
    y2 = img_back.shape[0]  # h
    x2 = img_back.shape[1]  # w
    # 偏置 (***重要)
    x1_new = x1 + x_offset
    y1_new = y1 + y_offset
    x2_new = x2 - x_offset
    y2_new = y2 - y_offset
    # 粘贴位置
    locations = []
    for index_3dd in range(sample_num):
        # 如果 右下角坐标小于0
        locations.append((int(random.uniform(x1_new, x2_new)), int(random.uniform(y1_new, y2_new))))
    return locations

def feats_merge(img_paths="images",anno_json_path="annotations",defects_masks_path="defects_repo/defects",group_id=1,defects_num=3,out_dir=r"D:\workplace\python\RealAug\enhance"):
    '''
    批量缺陷融合
    :param img_paths:
    :param anno_json_path:
    :param defects_masks_path:
    :param group_id:
    :param defects_num:
    :param out_dir:
    :return:
    '''

    '''
    1.缺陷选择
    '''
    # 获取可供选择缺陷列表
    support_selected_defect_dirs = get_dirs_path(defects_masks_path)
    support_defect_dirs = []
    # 使用group_id进行删选
    for defect_dir in support_selected_defect_dirs:
        if os.path.basename(defect_dir).split("_")[1] == str(group_id):
            support_defect_dirs.append(defect_dir)
    # 随机获取缺陷
    enhance_defect_dirs =  random.choices(support_defect_dirs,k=defects_num)
    imgobj_paths = []
    mask_paths = []
    for enhance_defect_dir in enhance_defect_dirs:
        defect_file_paths = get_files_path(os.path.join(enhance_defect_dir,"output"))
        defect_file_paths.sort()
        imgobj_paths.append(defect_file_paths[0])
        num = int(len(defect_file_paths) / 2)
        mask_paths.append(defect_file_paths[num])

    '''
    2.确定原图和json路径
    '''
    # 原图路径
    imgs_list = get_files_path(img_paths)
    imgs_list.sort()
    # json路径
    anno_json_list = get_files_path(anno_json_path)
    anno_json_list.sort()

    '''
    3.批量融合
    '''
    for index_imgpath ,img_path in enumerate(tqdm.tqdm(imgs_list)):
        # 原图路径
        imgback_path = img_path
        # 对应json路径
        label_json_path = anno_json_list[index_imgpath]
        # 点位集合
        loactions_list = generate_locations(raw_img_path=imgback_path,sample_num=100,x_offset=800,y_offset=700)
        # 进行融合
        feat_merge(imgback_path=imgback_path, label_json_path=label_json_path,imgobj_paths=imgobj_paths, mask_paths=mask_paths, loactions=loactions_list, group_id=group_id,out_dir=out_dir)



if __name__ == '__main__':
    feats_merge(img_paths=r"D:\defects_repo\images",anno_json_path=r"D:\defects_repo/annotations",defects_masks_path=r"D:\defects_repo/defects", group_id=1, defects_num=3,out_dir=r"D:\enhance")






import cv2
import numpy as np
from PIL import Image
import os
import random
from utils import *
import tqdm
from labelme import utils
import json
import os
import glob
import cv2
import json

def generate_segjson(label_mask_path, raw_json_path, group_id,out_dir):
    json_data = json.load(open(raw_json_path))
    raw_json_name = os.path.basename(raw_json_path)
    '''
    1.读取图像,获取图像的宽高
    '''
    mask_lbl = cv2.imread(label_mask_path, 0)

    '''
    2.findcontour,获取mask的所有点
    '''
    contours, hierarchy = cv2.findContours(mask_lbl, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 分割点集列表
    list_polygon_points = []
    # 遍历所有轮廓,进行筛选
    for c in contours:
        # 去除非轮廓
        if len(c) < 100:
            continue
        '''
        生成分割任务的分割json
        '''
        # 去除轮廓c的中间维度
        points = c[:, 0, :]
        list_polygon_points.append(points)

    '''
    3.对分割任务的分割json文件进行赋值
    '''

    shapes = list(json_data['shapes'])

    # 遍历所有轮廓
    for index_countour in list_polygon_points:
        shape = {}
        shape['points'] = index_countour.tolist()
        shape['label'] = "dc"
        shape['group_id'] = group_id
        shape['shape_type'] = "polygon"
        # 添加一个点位轨迹
        shapes.append(shape)

    json_data['shapes'] = shapes
    '''
    4.生成json
    '''
    # 存json
    if not os.path.exists(os.path.join(out_dir, 'annotations')):
        os.mkdir(os.path.join(out_dir, 'annotations'))
    json_file = os.path.join(out_dir,'annotations' ,raw_json_name)
    with open(json_file, 'w') as f:
        json.dump(json_data, f, indent=2)



def feat_merge(imgback_path,label_json_path, imgobj_paths, mask_paths, loactions, group_id,out_dir):
    '''
    缺陷融合
    :param imgback_path:
    :param label_json_path:
    :param imgobj_paths:
    :param mask_paths:
    :param loactions:
    :param group_id:
    :param out_dir:
    :return:
    '''
    # 创建输出目录
    if not os.path.exists(out_dir):
        os.mkdir(out_dir)

    # 读取原图
    img_back = Image.open(imgback_path)
    img_name = os.path.basename(imgback_path).split(".")[0]
    img_back = cv2.cvtColor(np.asarray(img_back), cv2.COLOR_RGB2BGR)
    label_img = np.zeros([img_back.shape[0],img_back.shape[1]],dtype=np.uint8)
    # 特征列表
    feats_list = []
    for i in imgobj_paths:
        feats_list.append(cv2.imread(i))
    # 标签列表
    masks_list = []
    for i in mask_paths:
        masks_list.append(cv2.imread(i,0))
    # 位置列表
    loactions_list = loactions
    # 成功融合个数
    success_merge_num = 0
    # 进行融合
    for i in range(len(loactions)):
        # 1.label_mask融合
        # 获取mask的宽高
        h, w = masks_list[i].shape
        # 获取贴合起始位置(***?)
        start_x = int(loactions_list[i][0] - w / 2)
        start_y = int(loactions_list[i][1] - h / 2)
        # 如果起始位置小于0,则跳过
        if start_x < 0 or start_y < 0:
            continue
        # 遍历进行mask进行贴合
        for i_w in range(w):
            for j_h in range(h):
                # mask进行贴合
                try:
                    label_img[start_y + j_h, start_x + i_w] = masks_list[i][j_h, i_w]
                except Exception as exp:
                    print(exp)
        # 2.原图融合
        try:
            img_back = cv2.seamlessClone(feats_list[i], img_back, masks_list[i], loactions_list[i], cv2.NORMAL_CLONE)
            success_merge_num = success_merge_num +1
            if success_merge_num == len(feats_list):
                break
        except Exception as exp:
            print(exp)

    # 保存贴合图
    if not os.path.exists(os.path.join(out_dir,"images")):
        os.mkdir(os.path.join(out_dir,"images"))
    cv2.imwrite(os.path.join(out_dir,"images",img_name+".jpg"), img_back)

    # 保存label_mask
    if not os.path.exists(os.path.join(out_dir,"masks")):
        os.mkdir(os.path.join(out_dir,"masks"))
    cv2.imwrite(os.path.join(out_dir,"masks",img_name+".jpg"), label_img)

    # 生成分割json
    generate_segjson(label_mask_path=os.path.join(out_dir,"masks",img_name+".jpg"), raw_json_path=label_json_path, group_id=group_id, out_dir=out_dir)


def generate_locations(raw_img_path,sample_num,x_offset = 300,y_offset=300,is_hard=False):
    # 读取原图
    img_back = cv2.imread(raw_img_path , 0)
    # 粘贴位置
    locations = []
    # 在这里进行筛选
    # 简单阈值分割确定ROI区域,非ROI区域进行去除
    '''
    1.阈值分割
    2.获取最小外接矩形的x,y,x,y
    3.设置offset
    4.判定随机生成的坐标是否在此范围内
    '''
    if is_hard:
        y1 = 0
        x1 = 0
        y2 = img_back.shape[0]  # h
        x2 = img_back.shape[1]  # w
        # 偏置 (***重要)
        x1_new = x1 + x_offset
        y1_new = y1 + y_offset
        x2_new = x2 - x_offset
        y2_new = y2 - y_offset

        for index_3dd in range(sample_num):
            # 如果 右下角坐标小于0
            locations.append((int(random.uniform(x1_new, x2_new)), int(random.uniform(y1_new, y2_new))))
    else:
        # 固定阈值(核心)
        ret, th1 = cv2.threshold(img_back, 30, 255, cv2.THRESH_BINARY)
        contours, hierarchy = cv2.findContours(th1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        lens_contour = []
        for c in contours:
             lens_contour.append(len(c))
        lens_c_value = max(lens_contour)  # 最大值
        max_contour_index = lens_contour.index(lens_c_value)  # 最大值索引
        z = np.random.random(size=[len(contours[max_contour_index]), 999])
        # 轮廓点
        max_contour = contours[max_contour_index]
        # 可视化轮廓
        img_back = cv2.imread(raw_img_path)
        # imag = cv2.drawContours(img_back, contours, max_contour_index, (0, 255, 0), 3)
        # cv2.imwrite("testtetste.jpg",imag)
        xx = max_contour[:,0,0]
        yy = max_contour[:,0,1]
        # 生成凸轮廓内点
        x = (z / sum(z)).T.dot(xx)
        y = (z / sum(z)).T.dot(yy)
        for i_x in range(sample_num):
            index_points = int(random.uniform(0, 999))
            locations.append((int(x[index_points]),int(y[index_points])))
        # # 可视化点
        # for point in locations:
        #     cv2.circle(img_back, point, 3, (255, 0, 0), 3)
        # cv2.imwrite("testtetste.jpg",img_back)
        # int(random.uniform(x1_new, x2_new))
        # int(random.uniform(y1_new, y2_new))
        
    return locations

def feats_merge(img_paths="images",anno_json_path="annotations",defects_masks_path="defects_repo/defects",group_id=1,defects_num=3,out_dir=r"D:\workplace\python\RealAug\enhance"):
    '''
    批量缺陷融合
    :param img_paths:
    :param anno_json_path:
    :param defects_masks_path:
    :param group_id:
    :param defects_num:
    :param out_dir:
    :return:
    '''

    '''
    1.缺陷选择
    '''
    # 获取可供选择缺陷列表
    support_selected_defect_dirs = get_dirs_path(defects_masks_path)
    support_defect_dirs = []
    # 使用group_id进行删选
    for defect_dir in support_selected_defect_dirs:
        if os.path.basename(defect_dir).split("_")[1] == str(group_id):
            support_defect_dirs.append(defect_dir)
    # 随机获取缺陷
    enhance_defect_dirs =  random.choices(support_defect_dirs,k=defects_num)
    # 缺陷路径集合
    imgobj_paths = []
    # mask路径集合
    mask_paths = []
    # 缺陷和mask进行Append赋值
    for enhance_defect_dir in enhance_defect_dirs:
        defect_file_paths = get_files_path(os.path.join(enhance_defect_dir,"output"))
        defect_file_paths.sort()
        mask_paths.append(defect_file_paths[0])
        num = int(len(defect_file_paths) / 2)
        imgobj_paths.append(defect_file_paths[num])
    '''
    2.确定原图和json路径
    '''
    # 原图路径
    imgs_list = get_files_path(img_paths)
    imgs_list.sort()
    # json路径
    anno_json_list = get_files_path(anno_json_path)
    anno_json_list.sort()

    '''
    3.批量融合
    '''
    for index_imgpath ,img_path in enumerate(tqdm.tqdm(imgs_list)):
        # 原图路径
        imgback_path = img_path
        # 对应json路径
        label_json_path = anno_json_list[index_imgpath]
        # 点位集合
        loactions_list = generate_locations(raw_img_path=imgback_path,sample_num=100,x_offset=800,y_offset=700,is_hard=False)
        # 进行融合
        feat_merge(imgback_path=imgback_path, label_json_path=label_json_path,imgobj_paths=imgobj_paths, mask_paths=mask_paths, loactions=loactions_list, group_id=group_id,out_dir=out_dir)



if __name__ == '__main__':
    feats_merge(img_paths=r"D:\defects_repo\images",anno_json_path=r"D:\defects_repo/annotations",defects_masks_path=r"D:\defects_repo/defects", group_id=1, defects_num=3,out_dir=r"D:\enhance")






  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值