赞
踩
在之前的博客中我介绍了图像篡改任务和深度学习解决双图篡改问题的一般性思路,这篇博客讲讲对于双图篡改检测任务如何做数据集。
深度学习是数据驱动的模型,数据集的制作有着举足轻重的作用,在双图检测篡改任务中,模型的输入是 possible donor(潜在供体图像)和 query (查询)图像、对应的 mask 以及判断是否篡改的标签 0 或者 1,如下图所示的三种情况输入[1],前面两种是 postive, 第三种是 negative。
以第一种情况为例,相同的篡改区域是前景部分,制作模型的输入数据。原始数据为 coco 数据,总体思路如下:
1. 一个文件夹放所有的 raw 图片,一个文件夹放所有的 mask;
2. 对于 raw 图片均分成3份,第一份为 p, 第二份为 q, 第三份为 world;
3. 随机选择 mask 文件夹中的一个 mask ,crop mask 找到 mask 的 ROI, 将 ROI 做随机定位,制作新的 mask,对于同一个 mask 做两个 ROI 位置不一样的新的 mask,这样是为了保证 p 和 q 的篡改区域不同;
4. 随机选择 world 文件夹中的一个 world 图片, 两个 mask 从world 中扣取相同的图像,拼接到 p 和 q 上面。
- """
- fig_path 为原始图片路径
- mask_paht 为 mask 图片路径
- 把 fig_path 路径文件夹下面的图片等分3份,命名 p, q, world
- 随机选取 mask 图片一张和 world 的图片一张,根据 mask 抠出 world 图片上面的一个随机区域,拼接到 p 和 q 中的每对图片上面
- 此时篡改的区域是来自 world 的抠图,相同的区域是前景
- """
-
-
- import cv2
- import numpy as np
- import os
-
-
- fig_path = "D:/AAAASXQ/SDL/raw_data/fig"
- mask_path = "D:/AAAASXQ/SDL/raw_data/mask"
- out_path = "D:/AAAASXQ/SDL/data_for_model_pos1"
- try:
- os.makedirs(os.path.join(out_path, 'p'))
- os.makedirs(os.path.join(out_path, 'p_maske'))
- os.makedirs(os.path.join(out_path, 'q'))
- os.makedirs(os.path.join(out_path, 'q_mask'))
- except:
- pass
- out_p_path = os.path.join(out_path, 'p')
- out_pmask_path = os.path.join(out_path, 'p_maske')
- out_q_path = os.path.join(out_path, 'q')
- out_qmask_path = os.path.join(out_path, 'q_mask')
-
-
- p_list = os.listdir(fig_path)
- mask_list = os.listdir(mask_path)
- len_mask = len(mask_list)
-
- l = len(pro_list)
- l1 = int(l/3)
-
- p = p_list[:l1]
- q = p_list[l1: 2*l1]
- world = p_list[2*l1:]
-
- len_world = len(world)
-
-
- def two(fig_path, mask_path, k):
-
- # 生成两张原始 mask,后面增加随机篡改区域
- mask1 = np.zeros((256, 256))
- mask2 = np.zeros((256, 256))
-
- # 获取 mask 的 ROI
- n = np.random.randint(len_mask)
- mask = cv2.imread(os.path.join(mask_path, mask_list[n]),-1)
- mask = cv2.resize(mask, (256, 256), interpolation=cv2.INTER_NEAREST)
- y = mask.sum(axis=1)
- y_top = (y != 0).argmax(axis=0)
- y_btm = (y != 0).cumsum(axis=0).argmax(axis=0)
- x = mask.sum(axis=0)
- x_left = (x != 0).argmax(axis=0)
- x_right = (x != 0).cumsum(axis=0).argmax(axis=0)
- maskROI = mask[y_top:y_btm+1, x_left:x_right+1]
-
- # 读取待篡改图片两张(按照顺序),分别来自 p 和 q
- # 读取抠图对象图片一张(随机),来自 world
- fig1 = cv2.imread(os.path.join(fig_path, p[k]))
- fig1 = cv2.resize(fig1, (256, 256), interpolation=cv2.INTER_CUBIC)
- fig2 = cv2.imread(os.path.join(fig_path, q[k]))
- fig2 = cv2.resize(fig2, (256, 256), interpolation=cv2.INTER_CUBIC)
- w = cv2.imread(os.path.join(fig_path, world[np.random.randint(len_world)]))
- w = cv2.resize(w, (256, 256), interpolation=cv2.INTER_CUBIC)
-
- # 生成 p 的 mask
- try:
- x1_begin = np.random.randint(256 - maskROI.shape[0] - 1)
- y1_begin = np.random.randint(256 - maskROI.shape[1] - 1)
- except:
- x1_begin = 1
- y1_begin = 1
-
- mask1[x1_begin:x1_begin + maskROI.shape[0], y1_begin:y1_begin + maskROI.shape[1]] = maskROI
- mask1 = mask1.astype(np.uint8)
- mask1_inv = cv2.bitwise_not(mask1)
-
- # 生成 q 的 mask
- try:
- x2_begin = np.random.randint(256 - maskROI.shape[0] - 1)
- y2_begin = np.random.randint(256 - maskROI.shape[1] - 1)
- except:
- x2_begin = 11
- y2_begin = 11
-
- mask2[x2_begin:x2_begin + maskROI.shape[0], y2_begin:y2_begin + maskROI.shape[1]] = maskROI
- mask2 = mask2.astype(np.uint8)
- mask2_inv = cv2.bitwise_not(mask2)
-
- # 生成篡改后的 p
- img1 = cv2.bitwise_and(w, w, mask=mask1)
- img11 = cv2.bitwise_and(fig1, fig1, mask=mask1_inv)
- pfig = cv2.add(img1, img11)
-
- # 生成篡改后的 q
- w[x2_begin:x2_begin + maskROI.shape[0], y2_begin:y2_begin + maskROI.shape[1], :] = w[x1_begin:x1_begin + maskROI.shape[0], y1_begin:y1_begin + maskROI.shape[1], :]
- img2 = cv2.bitwise_and(w, w, mask=mask2)
- img22 = cv2.bitwise_and(fig2, fig2, mask=mask2_inv)
- qfig = cv2.add(img2, img22)
-
- return pfig, mask1, qfig, mask2
-
-
- fig_path = fig_path
- mask_path = mask_path
-
- for i in range(100): # 循环制作100次
- print(i)
- for j in range(l1): # 遍历每个 p 图片
- k = j
- try:
- p, mask1, q, mask2 = two(fig_path, mask_path, k)
- cv2.imwrite(out_p_path + '/' + str(i) + '_' + str(j) + '_' + 'p.jpg', p)
- cv2.imwrite(out_pmask_path + '/' + str(i) + '_' + str(j) + '_' + 'p_mask.png', mask1)
- cv2.imwrite(out_q_path + '/' + str(i) + '_' + str(j) + '_' + 'q.jpg', q)
- cv2.imwrite(out_qmask_path + '/' + str(i) + '_' + str(j) + '_' + 'q_mask.png', mask2)
- except:
- print('error',' ',i, j)
- pass
篡改后的 probe 和 query:
对应的 mask:
最重要的缺点在于拼接的图像没有逻辑......明眼人一看就知道图像是篡改过的,哪还需要算法做判断。。。后续训练的模型对于真实场景的判断效果可能有限。然而如果是手工制作逼真的篡改图像,想必成本是非常高的。
采用分割数据集做训练数据,这样至少保证 P 中的图像是真实的。数据集做缩放、旋转等数据增广操作。
参考资料:
[1] Y. Wu, W. Abd-Almageed, and P. Natarajan, “Deep matching and validation network: An end-to-end solution to constrained image splicing localization and detection,” in Proc. 25th ACM Int. Conf. Multimedia, Oct. 2017, pp. 1480–1502.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。