使用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