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

上一篇博客【「图像 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)

    


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过51单片机控制28byj48步进电机按角度正反转旋转

一、前言 本项目基于STC89C52单片机&#xff0c;通过控制28BYJ-48步进电机实现按角度正反转旋转的功能。28BYJ-48步进电机是一种常用的电机&#xff0c;精准定位和高扭矩输出&#xff0c;适用于许多小型的自动化系统和机械装置。 在这个项目中&#xff0c;使用STC89C52单片机…

1822_使用python内置的库进行日期序列的生成

使用python的内置的库进行日期序列的生成 用到的库介绍 datetime 实现这样的功能其实只需要这一个库就够了&#xff0c;但是网络上找到的例程很多都额外增加了对time库的引用。只能说&#xff0c;这样不会出现错误&#xff0c;但是这样肯定会有一些计算资源上的消耗。 #!/u…

QT之多个界面相互切换 (stackedWidget控件)

TOC Chapter1 QT之多个界面相互切换 (stackedWidget控件) 原文链接 stackedWidget控件&#xff1a; 可以自由在多个widget切换&#xff0c;可以通过点击顶部菜单&#xff0c;显示不同界面&#xff0c;在实际开发中应用很广泛。 QStackedWidget是一个堆栈窗口控件&#xff0c…

字符型液晶显示器LCD 1602的显示控制(Keil+Proteus)

前言 趁机把LCD 1602的实验完成了&#xff0c;那个电路图有几个地方没弄懂&#xff0c;但是去掉也没有报错&#xff0c;就没管了。 LCD1602_百度百科 (baidu.com)https://baike.baidu.com/item/LCD1602/6014393?frge_ala LCD1602液晶显示屏通过电压来改变填充在两块平行板之…

“宽带中国”工具变量—海拔标准差数据集

参照刘传明&#xff08;2020&#xff09;、金环&#xff08;2021&#xff09;、胡浩然&#xff08;2023&#xff09;等的做法&#xff0c;将地级市-海拔标准差数据&#xff0c;作为“宽带中国”试点政策的工具变量 ➤相关性&#xff1a;地形起伏度会影响网络基础设施建设&…

京东数据平台:2023年Q3季度黄金市场数据分析

继9月国内黄金市场持续上涨后&#xff0c;进入10月中下旬后&#xff0c;黄金行情再度反转&#xff0c;多家品牌金饰价格再次突破600元/克&#xff0c;达到611元/克。 今年以来&#xff0c;黄金行情不断走俏&#xff0c;销售市场也有明显增长。根据鲸参谋平台的数据显示&#xf…

AI:60-基于深度学习的瓜果蔬菜分类识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

【LearnOpenGL基础入门——1】OpenGL简介

目录 一.OpenGL是什么 二.渲染模式 三.前置知识 四.写在最后 一.OpenGL是什么 我们首先先了解一下OpenGL到底是什么。一般我们认为是包含了一系列可以操作图形、图像的函数的一套API。然而&#xff0c;OpenGL本身并不是一个API&#xff0c;它仅仅是一个由Khronos组织制定并…

SwiftUI 代码调试之都是“变心”惹的祸

0. 概览 这是一段非常简单的 SwiftUI 代码&#xff0c;我们将 Item 数组传递到子视图并在子视图中对其进行修改&#xff0c;修改的结果会立即在主视图中反映出来。 不幸的是&#xff0c;当我们修改 Item 名称时却发现不能连续输入&#xff1a;每次敲一个字符键盘都会立即收起并…

LeetCode 热题100——链表专题

一、俩数相加 2.俩数相加&#xff08;题目链接&#xff09; 思路&#xff1a;这题题目首先要看懂&#xff0c;以示例1为例 即 342465807&#xff0c;而产生的新链表为7->0->8. 可以看成简单的从左向右&#xff0c;低位到高位的加法运算&#xff0c;4610&#xff0c;逢…

YOLOv5源码中的参数超详细解析(5)— 验证部分(val.py)参数解析

前言:Hello大家好,我是小哥谈。YOLOv5是一种先进的目标检测算法,它可以实现快速和准确的目标检测。在YOLOv5源码中,train.py和detect.py文件讲完了之后,接着就是讲val.py文件了。本节课就结合源码对val.py文件进行逐行解析~!🌈 前期回顾: YOLOv5源码中的参数超详细解…

Hyper-V 安装windows10 虚拟机,且能调试窗口大小、与主机之间复制文件

1. 搜索栏--打开‘启动或关闭windows功能’-- 勾选 ‘ Hyper-V ’ 然后点击确定&#xff1b; 2. 搜索栏--打开‘ Hyper-V 快速创建’ ---本地安装源---更改安装源&#xff08;选择 对应的 windows.iso 镜像&#xff09;---创建镜像--启动虚拟机--&#xff08;到达&#xff09;P…

分布式训练原理总结(DP、PP、TP 、ZeRO)

文章目录 一、分布式训练基础知识1.1 集合通信、集合通信库1.2 通信模式1.2.1 Parameter Server&#xff08;2014&#xff09;1.2.2 Ring-AllReduce&#xff08;2017&#xff09; 1.3 同步范式1.4 大模型训练的目标公式 二、数据并行2.1 DataParallel&#xff08;DP)2.2 Distri…

学习视频剪辑:批量添加srt字幕,让视频更生动

随着社交媒体的普及&#xff0c;视频制作变得越来越重要。无论是记录生活&#xff0c;还是分享知识&#xff0c;视频都是一个非常有力的工具。但是&#xff0c;如何让您的视频更生动、更吸引人呢&#xff1f;通过学习视频剪辑&#xff0c;您可以使您的视频更具有吸引力。而在这…

在搜索引擎中屏蔽csdn

csdn是一个很好的技术博客&#xff0c;里面信息很丰富&#xff0c;我也喜欢在csdn上做技术笔记。 但是CSDN体量太大&#xff0c;文章质量良莠不齐。当在搜索引擎搜索技术问题时&#xff0c;搜索结果中CSDN的内容占比太多&#xff0c;导致难以从其他优秀的博客平台中获取信息。因…

Java 多线程的三大特性

在JAVA中&#xff0c;线程有原子性、可见性和有序性三大特性。 1.原子性 1.1 定义 对于涉及共享变量的操作&#xff0c;若该操作从其执行线程以外的任意线程来看都是不可分割的&#xff0c;那么我们就说该操作具有原子性。它包含以下两层含义&#xff1a; 访问&#xff08;读、…

基于若依的ruoyi-nbcio流程管理系统增加仿钉钉流程设计(六)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 这节主要讲条件节点与并发节点的有效性检查&#xff0c;主要是增加这两个节点的子节点检查&#xff0c;因为…

如何在 Unbuntu 下安装配置 Apache Zookeeper

简介 Zookeeper 是 apache 基金组织下的项目&#xff0c;项目用于简单的监控和管理一组服务&#xff0c;通过简单的接口就可以集中协调一组服务&#xff0c;如配置管理&#xff0c;信息同步&#xff0c;命名&#xff0c;分布式协调。 准备工作 Ubuntu 23.04 或者 20.04访问…

pycharm插件推荐:一款能够根据上下文自动提示帮写代码的AI插件

直接上插件&#xff1a; 这个插件有多牛&#xff01;他能够根据注释帮你直接补全代码&#xff08;只需要你按一下tab键&#xff09;&#xff0c;甚至还有学习的能力。 如下&#xff1a; 我注释写完后&#xff0c;一回车就模糊的写出了预计的代码&#xff0c;只要我按下tab键…

利用大语言模型(LLM )提高工作效率

日常工作就是面向 google/ 百度编程&#xff0c;除了给变量命名是手动输入&#xff0c;大多时候就是通过搜索引擎拷贝别人的代码&#xff0c;或者找到旧项目一段代码拷贝过来使用。这无疑是开发人员的真实写照&#xff1b;然而&#xff0c;通过搜索引擎搜索答案&#xff0c;无疑…