Python cv2 实现图像拼接——双图篡改任务数据准备(1)

    在之前的博客中我介绍了图像篡改任务深度学习解决双图篡改问题的一般性思路,这篇博客讲讲对于双图篡改检测任务如何做数据集。

1 概述

    深度学习是数据驱动的模型,数据集的制作有着举足轻重的作用,在双图检测篡改任务中,模型的输入是 possible donor(潜在供体图像)和 query (查询)图像、对应的 mask 以及判断是否篡改的标签 0 或者 1,如下图所示的三种情况输入[1],前面两种是 postive, 第三种是 negative。

                                              

2 实现思路

    

    以第一种情况为例,相同的篡改区域是前景部分,制作模型的输入数据。原始数据为 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 上面。

3 代码

"""
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

4 结果展示

    篡改后的 probe 和 query:

 

                                       

    对应的 mask:

                                       

5 缺点

    最重要的缺点在于拼接的图像没有逻辑......明眼人一看就知道图像是篡改过的,哪还需要算法做判断。。。后续训练的模型对于真实场景的判断效果可能有限。然而如果是手工制作逼真的篡改图像,想必成本是非常高的。

6 改进

    采用分割数据集做训练数据,这样至少保证 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.
 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值