其他分享
首页 > 其他分享> > 使用coco数据集建立赋值黏贴篡改数据集

使用coco数据集建立赋值黏贴篡改数据集

作者:互联网

为了能够训练赋值黏贴篡改检测网络,我们需要建立一个复制黏贴篡改数据集,为了简单起见,我们使用coco数据集来进行构建。

第一步,建立json文件文件

这里我为了能够按照自己的思路写程序,将coco的json文件格式做了点修改,代码如下

import json
import time
"""
file = open("instances_val2017.json", "r")
img_info = json.load(file)
print(img_info.keys())
tmp_dict = {}
tmp_dict["categories"] = img_info["categories"][:2]
tmp_dict = json.dumps(tmp_dict, indent=4)
"""
#tmp_dict = json.loads(tmp_dict)
#print(tmp_dict)
#img_info = json.dumps(img_info, indent=4)
#print(img_info)

# 获取类别信息
# 第一个返回值是列表
# 第二个返回值是字典
def get_cate():
    file = open("instances_val2017.json", "r")
    img_info = json.load(file)
    tmp_dict = {}
    tmp_dict["categories"] = img_info["categories"]
    #tmp_dict = json.dumps(tmp_dict, indent=4)
    list = tmp_dict["categories"]
    cate = []
    # 第一个位置是背景
    cate.append("background")
    cate_dict = {}
    for item in list:
        cate.append(item["name"])
        cate_dict[item["name"]] = item["id"]

    print(cate)
    print(cate_dict)
    return cate, cate_dict

""""""""""""""""""""""""""""
我自定义的数据格式
{
    "images":{
        "(file_name)":{
            "height": int,
            "width":  int,
            "id":     int,
            "annotation": {
                "segmentation":[
                    [
                    int,
                    int,
                    ...
                    ]
                ],
                "iscrowd": int,
                "bbox":[
                    int,
                    int,
                    int,
                    int
                ],
                "category_id": int,
            }
        }
    }
}

算法步骤:
1.找出所有的filename和对应的id
2.对于每张图片,找寻他的所有标注信息
"""""""""""""""""""""""""""""""""""
def get_info(read_file, dump_file):
    # 保存信息的字典
    img_anno = {}
    img_anno["images"] = {}
    file = open(read_file, "r")
    img_info = json.load(file)
    tmp_dict = {}
    tmp_dict["images"] = img_info["images"]
    # 读取所有的图片信息,建立键值对
    images_list = tmp_dict["images"]
    for item in images_list:
        file_name = item["file_name"]
        height = item["height"]
        width = item["width"]
        img_id = item["id"]
        # 建立键值对
        img_anno["images"][file_name] = {}
        img_anno["images"][file_name]["height"] = height
        img_anno["images"][file_name]["width"] = width
        img_anno["images"][file_name]["img_id"] = img_id
        # 标注信息的值是列表,里面每个元素都是一个字典
        img_anno["images"][file_name]["annotations"] = []
    print("读取完所有图片信息✿✿ヽ(°▽°)ノ✿")
    # 看看结果
    #print("一共加载了%d张图片信息✿✿ヽ(°▽°)ノ✿"%len(img_anno["images"].keys()))
    #tmp = json.dumps(img_anno, indent=4)
    #print(tmp)
    st = time.time()
    # 接下来根据图片id查找他的标注信息
    tmp_dict["annotations"] = img_info["annotations"]
    list_anno = tmp_dict["annotations"]
    num = 0
    for key in img_anno["images"]:
        # print(key)
        tmp_dict = img_anno["images"][key]
        image_id = tmp_dict["img_id"]
        for item in list_anno:
            img_id = item["image_id"]
            if(image_id == img_id):
                tmp_dict["annotations"].append(item)
                # 将使用过的标注信息删除
                list_anno.remove(item)
        num = num + 1
        if(num%1000 == 0):
            print("读取完%d张图片信息,时间:%ds"%(num, time.time()-st))

    #tmp = json.dumps(img_anno, indent=4)
    #print(tmp)

    # 保存json文件
    filename = dump_file
    with open(filename, "w") as f:
        json.dump(img_anno, f, indent=4)

    return img_anno





if __name__ == "__main__":
    #get_cate()
    read_file = "instances_train2017.json"
    dump_file = "instances_train"
    get_info(read_file, dump_file)

第二步,根据图片和json文档信息选取复制黏贴的物体

目录结构如下

img :存放原始图片

img_t :存放篡改后的图像

info:存放被复制物体的信息

mask_s:被赋值物体的mask

mask_t:黏贴物体的mask

tmp_img:从原图中将目标物体抠出来的图

这一步我们的主要目的是从图片中选取复制的物体

import json
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
import random
import torchvision.transforms as tfs

"""
获取coco图像中的物体,绘制mask,并且抠图
"""

# 原始图片地址
PREFIX = "coco/img/"
# 源物体mask
PREFIX_MASK_S = "coco/mask_s/"
# 图片信息地址
PREFIX_INFO = "coco/info/"
# 抠图结果
PREFIX_TMP = "coco/tmp_img/"
# json文件
JSON_FILE = "instances_val.json"

def change_geshi(seg_list):
    output = []
    tmp = seg_list[0]
    for i in range(len(tmp)//2):
        point = []
        point.append(tmp[2*i])
        point.append(tmp[2*i+1])
        output.append(point)

    #output = np.array(output, np.int32)
    return output


def get_random(max):
    return random.randint(0,max)


def getMask_s(img_name, f):
    img = cv2.imread(PREFIX + img_name)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    file = open(JSON_FILE, "r")
    img_info = json.load(file)
    tmp_dict = img_info["images"]
    info = tmp_dict[img_name]
    img_height = info["height"]
    img_width = info["width"]
    anno_list = info["annotations"]
    if(len(anno_list)==0):
        return 0
    idx = get_random(len(anno_list)-1)

    item = anno_list[idx]
    # 每个item都是一个字典
    bbox = item["bbox"]
    center_x = int(float(bbox[0]))
    center_y = int(float(bbox[1]))
    width = int(float(bbox[2]))
    height = int(float(bbox[3]))
    seg_points = item["segmentation"]
    if(isinstance(seg_points, dict)):
        return 0
    seg_points = change_geshi(seg_points)
    seg_points = np.array(seg_points, np.int32)


    mask = np.zeros_like(img)
    cv2.fillPoly(mask, [seg_points], (255, 255, 255))
    if(width<(int(img_width)//2) or height<(int(height)//2)):
        #cv2.imwrite(PREFIX_MASK_S + img_name.split(".")[0]+".png", mask)

        # 从原图中把物体抠出来
        img = tfs.ToTensor()(img)
        mask = tfs.ToTensor()(mask)
        # mask不为0的地方为1
        mask[~(mask==0)] = 1


        img = img*mask
        img = tfs.ToPILImage()(img)
        img.save(PREFIX_TMP + img_name.split(".")[0]+".png")
        print(PREFIX_TMP + img_name.split(".")[0]+".png")
        mask = mask[0]
        mask = tfs.ToPILImage()(mask)
        mask.save(PREFIX_MASK_S + img_name.split(".")[0] + ".png")
        print(PREFIX_MASK_S + img_name.split(".")[0] + ".png")

        # 源物体信息
        info_mask_s = PREFIX_MASK_S+img_name.split(".")[0]+".png"+" "+\
                        str(int(img_width))+" "+str(int(img_height))+" "\
                      +" "+str(width)+" "+str(height)+\
                      " "+str(center_x)+" "+str(center_y) + "\n"

        f.write(info_mask_s)
    else:
        print("所选目标太大o( ̄ヘ ̄o#)")
        # 删除源图片
        # os.remove(PREFIX + img_name)

    #img_add = cv2.addWeighted(mask, 0.3, img, 0.7, 0)
    #plt.imshow(img_add)
    #plt.show()



def boot():
    # 获取所有img的mask_s
    with open(PREFIX_INFO+"mask_s.txt", "w") as f:
        list_img = os.listdir(PREFIX)
        for img in list_img:
            getMask_s(img, f)

if __name__ == "__main__":
    boot()

第三步,对被赋值物体进行操作后黏贴

对物体进行操作的方法如下:

(1)对物体水平翻转

(2)以一定概率对物体垂直翻转

(3)以一定缩放率缩小物体

(4)将物体图片填充为原来的形状,并且黏贴到原图上

import torch
import numpy as np
import os
import matplotlib.pyplot as plt
import cv2
import torchvision.transforms as tfs
import torch.nn.functional as f
from PIL import Image
"""
根据抠图和源图进行复制黏贴篡改
"""

# 原始图片地址
PREFIX = "coco/img/"
# 篡改后图片存放地址
PREFIX_T = "coco/img_t/"
# 源物体mask
PREFIX_MASK_S = "coco/mask_s/"
# 目标物体mask
PREFIX_MASK_T = "coco/mask_t/"
# 图片信息地址
PREFIX_INFO = "coco/info/"
# 抠图结果
PREFIX_TMP = "coco/tmp_img/"

def tensor(img):
    return tfs.ToTensor()(img)

def PIL(img):
    return tfs.ToPILImage()(img)

def resize(input, factor=0.5):
    return f.interpolate(input, scale_factor=factor)

# 读取图片信息,并且进行左右和上下镜像
# 然后随机缩小并填充图片
# 返回三个参数,第一个参数是原图
# 第二个参数是处理后的抠图信息
# 第三个参数是处理后的mask信息
# 都是tensor格式的
def readImg(filename):
    # 源图片
    img = Image.open(PREFIX + filename.split(".")[0]+".jpg")
    # 目标物体的mask
    mask_s = Image.open(PREFIX_MASK_S + filename)
    # 抠图信息
    img_tmp = Image.open(PREFIX_TMP + filename)

    # 记录下原图信息参数
    img = tensor(img)
    height = img.shape[1]
    width = img.shape[2]

    # 对抠图信息和目标物体mask操作

    # 左右翻转
    img_tmp = img_tmp.transpose(Image.FLIP_LEFT_RIGHT)
    mask_s = mask_s.transpose(Image.FLIP_LEFT_RIGHT)

    # 以一般的概率上下翻转
    b = torch.rand(1).item()
    if(b>0.5):
        img_tmp = img_tmp.transpose(Image.FLIP_TOP_BOTTOM)
        mask_s = mask_s.transpose(Image.FLIP_TOP_BOTTOM)

    img_tmp = tensor(img_tmp)
    mask_s = tensor(mask_s)

    # 进行缩小
    factor = torch.rand(1).item()
    factor = np.clip(factor, a_max=0.95, a_min=0.6)
    print(factor)
    img_tmp = resize(img_tmp, factor.__float__())
    mask_s = resize(mask_s, factor.__float__())

    # 进行扩大,扩大成和源图一样大小
    # 填充的list分别是 左右上下 的填充数量
    img_tmp = f.pad(img_tmp, [0, width-img_tmp.shape[2], 0, height-img_tmp.shape[1]], value=0.)
    mask_s = f.pad(mask_s, [0, width-mask_s.shape[2], 0, height-mask_s.shape[1]], value=0.)

    """
    plt.subplot(1,3,1), plt.imshow(PIL(img))
    plt.subplot(1,3,2), plt.imshow(PIL(img_tmp))
    plt.subplot(1,3,3), plt.imshow(PIL(mask_s))
    plt.show()

    print(img.shape)
    print(img_tmp.shape)
    print(mask_s.shape)
    """
    return PIL(img), PIL(img_tmp), PIL(mask_s)

# 对图片进行复制黏贴篡改,并且保存图片和篡改的mask信息
def tamper(img, img_tmp, mask_t):
    img = tensor(img)
    img_tmp = tensor(img_tmp)
    mask_t = tensor(mask_t)
    img = img*~(mask_t==1)
    img = img+img_tmp
    return PIL(img), PIL(mask_t)


def boot():
    list_img = os.listdir(PREFIX_TMP)
    for item in list_img:
        img, img_tmp, mask_t = readImg(item)
        img_t, mask_t = tamper(img, img_tmp, mask_t)
        # 保存图片
        img_t.save(PREFIX_T + item)
        mask_t.save(PREFIX_MASK_T + item)
        print(PREFIX_T + item)
        print(PREFIX_MASK_T + item)


if __name__ == "__main__":
    boot()

经过这三步,我们的数据就做好了,下面来看看效果吧

原图

篡改图片

标签:tmp,img,item,mask,篡改,dict,file,coco,黏贴
来源: https://blog.csdn.net/haohulala/article/details/112059268