「图像 cv2.seamlessClone」无中生有制造数据

news2024/12/26 11:06:24

上一篇博客【「图像 merge」无中生有制造数据 】写的是图片直接融合,此方法生成的图片相对而言比较生硬,虽然目标图片已经透明化处理过了,但是生成的图片依旧很假

在这里插入图片描述

除了上述上述的图片叠加融合之外,还有一种更加自然的融合方法,就是 cv2.seamlessClone ,生成的效果图如下图所示
但是 cv2.seamlessClone 并不是万能的,需要根据实际情况测试,页根据目标模版的制作效果有很大关系

注意!
此方法融合图片时,目标区域不能按照目标的边缘进行透明化抠图,需要包含一部分的边缘信息,不然融合效果会很差

在这里插入图片描述

在这里插入图片描述

此算法的 目标图透明化处理/抠图处理与 【「图像 merge」无中生有制造数据 】一致,相关代码已附在博客中,自行移步查看

#  !/usr/bin/env  python
#  -*- coding:utf-8 -*-
# @Time   :  2023.10
# @Author :  绿色羽毛
# @Email  :  lvseyumao@foxmail.com
# @Blog   :  https://blog.csdn.net/ViatorSun
# @Note   :



import os
import cv2
import random
from random import sample
import numpy as np
import argparse




def read_label_txt(label_dir):
    labels = []
    with open(label_dir) as fp:
        for f in fp.readlines():
            labels.append(f.strip().split(' '))
    return labels

def rescale_yolo_labels(labels, img_shape):
    height, width, nchannel = img_shape
    rescale_boxes = []
    for box in list(labels):
        x_c = float(box[1]) * width
        y_c = float(box[2]) * height
        w = float(box[3]) * width
        h = float(box[4]) * height
        x_left = x_c - w * .5
        y_left = y_c - h * .5
        x_right = x_c + w * .5
        y_right = y_c + h * .5
        rescale_boxes.append([box[0], int(x_left), int(y_left), int(x_right), int(y_right)])
    return rescale_boxes

def xyxy2xywh(image, bboxes):
    height, width, _ = image.shape
    boxes = []
    for box in bboxes:
        if len(box) < 4:
            continue
        cls = int(box[0])
        x_min = box[1]
        y_min = box[2]
        x_max = box[3]
        y_max = box[4]
        w = x_max - x_min
        h = y_max - y_min
        x_c = (x_min + x_max) / 2.0
        y_c = (y_min + y_max) / 2.0
        x_c = x_c / width
        y_c = y_c / height
        w = float(w) / width
        h = float(h) / height
        boxes.append([cls, x_c, y_c, w, h])
    return boxes

def cast_color(img, value):
    img_t = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(img_t)
    # 增加图像对比度
    v2 = np.clip(cv2.add(2*v,value),0,255)
    img2 = np.uint8(cv2.merge((h,s,v2)))
    img_cast = cv2.cvtColor(img2,cv2.COLOR_HSV2BGR)             # 改变图像对比度
    return img_cast

def brightness(img, value):
    img_t = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(img_t)
    # 增加图像亮度
    v1 = np.clip(cv2.add(1*v,value),0,255)
    img1 = np.uint8(cv2.merge((h,s,v1)))
    img_brightness = cv2.cvtColor(img1,cv2.COLOR_HSV2BGR)       # 改变图像亮度亮度
    return img_brightness



def random_add_patches_on_objects(image, template_lst, rescale_boxes, mask_lst, paste_number):

    img = image.copy()

    new_bboxes = []
    cl = 0

    random.shuffle(rescale_boxes)

    for rescale_bbox in rescale_boxes[:int(len(rescale_boxes) * 0.2)]:      # 待ps图像 目标框中
        num_p = random.randint(0, 50) % len(template_lst)           # 随机挑选 原图和mask
        p_img = template_lst[num_p]
        mask = mask_lst[num_p]
        bbox_h, bbox_w, bbox_c = p_img.shape

        obj_xmin = rescale_bbox[1]
        obj_ymin = rescale_bbox[2]
        obj_xmax = rescale_bbox[3]
        obj_ymax = rescale_bbox[4]
        obj_w = obj_xmax - obj_xmin + 1         # 目标框尺寸
        obj_h = obj_ymax - obj_ymin + 1

        new_bbox_w = bbox_w
        new_bbox_h = bbox_h

        while not (bbox_w < obj_w and bbox_h < obj_h):                  # 如果目标框小于 mask尺寸,对mask进行缩放以确保可以放进 bbox中
            new_bbox_w = int(bbox_w * random.uniform(0.5, 0.8))
            new_bbox_h = int(bbox_h * random.uniform(0.5, 0.8))
            bbox_w, bbox_h = new_bbox_w, new_bbox_h
            
        success_num = 0
        while success_num < paste_number:

            center_search_space = [obj_xmin, obj_ymin, obj_xmax - new_bbox_w - 1, obj_ymax - new_bbox_h - 1] # 选取生成随机点区域

            if center_search_space[0] >= center_search_space[2] or center_search_space[1] >= center_search_space[3]:
                print('============== center_search_space error!!!! ================')
                success_num += 1
                continue

            new_bbox_x_min = random.randint(center_search_space[0], center_search_space[2])  # 随机生成点坐标
            new_bbox_y_min = random.randint(center_search_space[1], center_search_space[3])
            new_bbox_x_left, new_bbox_y_top, new_bbox_x_right, new_bbox_y_bottom = new_bbox_x_min, new_bbox_y_min, new_bbox_x_min + new_bbox_w - 1, new_bbox_y_min + new_bbox_h - 1
            new_bbox = [cl, int(new_bbox_x_left), int(new_bbox_y_top), int(new_bbox_x_right), int(new_bbox_y_bottom)]
            success_num += 1
            new_bboxes.append(new_bbox)

            mask = cv2.resize(mask, (new_bbox_w, new_bbox_h)) 
            p_img = cv2.resize(p_img, (new_bbox_w, new_bbox_h))

            center = (int(new_bbox_w / 2), int(new_bbox_h / 2))

            img[new_bbox_y_top:new_bbox_y_bottom, new_bbox_x_left:new_bbox_x_right] = cv2.seamlessClone(
                    p_img,
                    image[new_bbox_y_top:new_bbox_y_bottom, new_bbox_x_left:new_bbox_x_right],
                    mask, center, cv2.MONOCHROME_TRANSFER) # NORMAL_CLONE 、MIXED_CLONE 和 MONOCHROME_TRANSFER
                    
    return img, new_bboxes




if __name__ == "__main__":
    # 用来装载参数的容器
    parser = argparse.ArgumentParser(description='PS')
    # 给这个解析对象添加命令行参数
    parser.add_argument('-i', '--images', default= '/media/yinzhe/DataYZ/DataSet/DataSet/bag_model',type=str, help='path of images')
    parser.add_argument('-t', '--templates', default= '/media/yinzhe/DataYZ/DataSet/DataSet/bag_mask',type=str, help='path of templates')
    parser.add_argument('-s', '--saveImage',default= '/media/yinzhe/DataYZ/DataSet/DataSet/bag_save3', type=str, help='path of ')
    parser.add_argument('-n', '--num', default=5, type=str, help='number of img')

    args = parser.parse_args()  # 获取所有参数

    
    templates_path = args.templates
    images_path = args.images
    save_path = args.saveImage
    num = int(args.num)
    template_paths = []

    if not os.path.exists(save_path):
        os.makedirs(save_path)

    for t_path in os.listdir(templates_path):
        template_paths.append(t_path)

    # template_paths = random.shuffle(template_paths) #打乱顺序
    for image_path in os.listdir(images_path) :
        if "txt" in image_path:
            continue
        image = cv2.imread(os.path.join(images_path, image_path))
        pre_name = image_path.split('.')[0]
        labels = read_label_txt(os.path.join(images_path, pre_name + ".txt"))

        if image is None or len(labels) == 0:
            print("empty image !!! or empty label !!!")
            continue

        # yolo txt转化为x1y1x2y2
        rescale_labels = rescale_yolo_labels(labels, image.shape)  # 转换坐标表示

        template_path = sample(template_paths, num)


        template_lst = []
        mask_lst = []

        for i in range(num):
            template = cv2.imread(os.path.join(templates_path, template_path[i]), cv2.IMREAD_UNCHANGED)
            print(template.shape[2])
            if (template.shape[2] != 4):        # RGB alpha
                break

            alpha = template[:, :, 3]
            p_img = cv2.cvtColor(template, cv2.COLOR_BGRA2BGR)

            if (p_img is None):
                print("empty p image !!!", template_path[i])
                continue
            
            mask = np.where(alpha>0, 255, 0)  #满足大于0的值保留,不满足的设为0
            mask = mask.astype(np.uint8)

            mask_lst.append(mask)
            template_lst.append(p_img)

        for i in range(num):

            img, bboxes = random_add_patches_on_objects(image, template_lst, rescale_labels, mask_lst, 1)

            boxes = xyxy2xywh(img, bboxes)
            img_name = pre_name + '_' + str(i) + '.jpg'
            print('handle img:', img_name)
            cv2.imwrite(os.path.join(save_path, img_name), img)

            with open(os.path.join(save_path, img_name[:-4] + ".txt"), 'a') as f:
                for box in boxes:

                    mess = str(3) + " " + str(box[1]) + " " + str(box[2]) + " " + str(box[3] * 0.6) + " " + str(box[4]* 0.6) + "\n"
                    f.write(mess)

    


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1163446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 性能优化之直接使用成员变量 VS 拷贝副本

背景 刷到一个大佬的 CSDN 博客&#xff0c;仔细看了一下性能优化专栏。联想到我们的日常开发工作&#xff0c;由于业务比较简单&#xff0c;很容就忽略性能问题。但是&#xff0c;性能优化的一下常见思路&#xff0c;也早有耳闻。看了一个 Java 性能优化的方法 「减少操作指令…

最新版一媒体7.3、星媒体、皮皮剪辑,视频MD ,安卓手机剪辑去重神器+搬运脚本+去视频重软件工具

最新版一媒体app安卓版介绍&#xff1a; 这是一款功能强大的视频搬运工具&#xff0c;内置海量视频编辑工具&#xff0c;支持一键智能化处理、混剪、搬运、还能快速解析和去水印等等&#xff0c;超多实用功能等着您来体验&#xff01; 老牌手机剪辑去重神器&#xff0c;用过的…

导轨在数控机床中起哪些作用?

数控机床导轨是数控机床中重要的组成部分&#xff0c;其主要作用有以下几个方面&#xff1a; 1、导向和承载作用&#xff1a;数控机床的导轨是机床各部件运动的导向轨道&#xff0c;它引导机床各部件按照规定的轨迹和速度进行运动&#xff0c;同时承受和分散运动部件的重力和切…

The Sandbox 与 hi 建立合作伙伴关系

我们很高兴地宣布&#xff0c;Web 3 Neo-Banking 应用程序已正式宣布与 The Sandbox 达成合作。它将允许用户使用 hi 借记卡在店内和线上消费原生通证 SAND。 hi 为数百万人提供了一种新的 SAND 消费方式&#xff0c;使持卡人能够使用 hi 借记万事达卡在店内和线上的精选商户使…

VScode 全局搜索快捷键Ctrl+Shift+F失效 衝突

主要的原因是搜狗输入法的&#xff0c;简体和繁体的切换快捷键冲突了 去掉输入法的切换快捷键

CLion 2023.2.2(C ++ IDE智能代码编辑器)

CLion 2023是一款跨平台C/C集成开发环境&#xff08;IDE&#xff09;。它为Mac用户提供了高效的编程体验&#xff0c;帮助程序员们在Mac平台上进行C/C开发。 CLion 2023支持多种编译器和调试器&#xff0c;并具有强大的代码分析和导航功能。它还为用户提供了许多便捷的工具和插…

Cpolar和Qchan的使用与轻量级搭建:构建独特的个人图床并保护隐私

文章目录 前言1. Qchan网站搭建1.1 Qchan下载和安装1.2 Qchan网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar云端设置2.2 Cpolar本地设置 3. 公网访问测试总结 前言 图床作为云存储的一项重要应用场景&#xff0c;在大量开发人员的努力下&#xff0c;已经开发出大…

6.OsgEarth加载倾斜摄影

愿你出走半生,归来仍是少年&#xff01; 三维场景中常用的地表模型包含倾斜摄影&#xff0c;通过CC处理出来的倾斜摄影是一个通过文件夹进行分块的&#xff0c;然后通过元数据记录了其空间位置信息&#xff08;原点&#xff09;。 本文通过解析metadata.xml文件后进行多块情况的…

Handler原理机制解析,Android开发中的重要性

Handler在android程序开发中使用的非常频繁、我们知道android是不允许在子线程中更新UI的&#xff0c;这就需要借助Handler来实现&#xff0c;那么你是否想过为什么一定要这个这样子做呢&#xff1f;而且Handler的内部消息处理机制究竟是什么样的呢&#xff1f;Handler的原理是…

Redis(11)| 持久化AOF和RDB

一、AOF&#xff08;Append Only File&#xff09; Redis 每执行一条写操作命令&#xff0c;就把该命令以追加的方式写入到一个文件里&#xff0c;然后重启 Redis 的时候&#xff0c;先去读取这个文件里的命令&#xff0c;并且执行它。 注意&#xff1a;只会记录写操作命令&am…

YOLOv7输出COCOmAP指标:输出自定义数据集中small、medium、large大中小目标的mAP值S,M,L指标,适用于自定义数据集

💡更多改进内容📚可以点击查看:YOLO改进原创目录 | 老师联袂推荐🏆 💡🚀🚀🚀内含改进源代码,按步骤操作运行改进后的代码即可,内附代码💡更方便的统计更多实验数据,方便写作 芒果改进 | YOLOv5 输出自定义数据集中 S,M,L指标大中小目标的mAP值 点这篇链…

华山编程培训中心——工业相机飞拍

飞拍功能是一种高速运动图像采集技术&#xff0c;通过降低相机的曝光时间来拍摄快速移动的对象&#xff0c;以提高工作效率和加快生产速度。下面视频演示工业相机飞拍&#xff1a; 上位机控制工业相机飞拍演示 一. 飞拍对相机硬件的要求 全局快门相机&#xff1a;飞拍要求相机…

树结构及其算法-二叉查找树

目录 树结构及其算法-二叉查找树 C代码 树结构及其算法-二叉查找树 二叉树在建立的过程中是根据“左子树 < 树根 < 右子树”的原则建立的&#xff0c;因此只需从树根出发比较键值即可&#xff0c;如果比树根大就往右&#xff0c;否则往左而下&#xff0c;直到相等就找…

网易按照作者批量采集新闻资讯软件说明文档

大家好&#xff0c;我是淘小白~ 今天给大家介绍的爬虫软件是网易按照作者采集的软件 1、软件语言&#xff1a; Python 2、使用到的工具 Python selenium库、谷歌浏览器、谷歌浏览器驱动 3、文件说明&#xff1a; 4、配置文件说明&#xff1a; 5、环境配置 安装Python&am…

【Linux笔记】Linux进程概念与进程状态

【Linux笔记】Linux进程概念与进程状态 一、什么是进程1.1、进程的概念1.2、进程的描述 二、关于进程的一些基本操作2.1、查看进程2.2、杀进程2.3、获取进程id2.4、创建进程 三、进程状态3.1、普适操作系统中的进程状态3.2、具体到Linux操作系统中的进程状态 四、僵尸进程和孤儿…

创建ABAP数据库表和ABAP字典对象-使用基本类型增加账号字段03

新增字段 现在你将增加字段&#xff1a;account_number,基于基本类型 1.输入以下内容(包括句点)&#xff0c;然后选择“代码补全”(Ctrl空格): key account_number : abap.2.从下拉列表中选择numc(len)并指定len为8。另外&#xff0c;指定这个关键字段为not null: key accoun…

深入浅出理解深度可分离卷积(Depthwise Separable Convolution)

一、参考资料 详细且通俗讲解轻量级神经网络——MobileNets【V1、V2、V3】 详细且通俗讲解轻量级神经网络——MobileNets【V1、V2、V3】 卷积神经网络中的Separable Convolution 深度学习中常用的几种卷积&#xff08;下篇&#xff09;&#xff1a;膨胀卷积、可分离卷积&#…

postgresql 触发器如何生成递增序列号,从1开始,并且每天重置

大家好&#xff0c;我是三叔&#xff0c;许久不见&#xff0c;这期给大家介绍一下笔者在开发中遇到的业务处理&#xff1a;pgsql 创建触发器生成每日递增序列&#xff0c;并且第二天重置&#xff0c;根据不同的用户进行不同的控制。 1.创建生成递增序列的 table 表 -- 创建us…

新手必看的Facebook广告投放基础思路

一、广告账号要求 如果您还没有Facebook账号&#xff0c;那么第一步是准备Facebook账号。 1、配置正确的网络环境 Facebook账号需要在稳定安全的网络环境中运行&#xff0c;否则很容易导致封禁。像我们常用的是Maskfog指纹浏览器&#xff0c;可以通过自定义浏览器指纹与为环…

计算机网络第4章-网络层(1)

引子 网络层能够被分解为两个相互作用的部分&#xff1a; 数据平面和控制平面。 网络层概述 路由器具有截断的协议栈&#xff0c;即没有网络层以上的部分。 如下图所示&#xff0c;是一个简单网络&#xff1a; 转发和路由选择&#xff1a;数据平面和控制平面 网络层的作用…