Python-opencv: 自动制作copymove数据集

该博客介绍了一种使用Python实现CopyMove图像篡改的方法,通过读取图片和mask,调整并复制mask中的物体到图像的另一位置,从而创建篡改图像。过程中涉及了图像处理技术,包括PIL和OpenCV库的使用,以及如何根据mask进行图像操作。最终代码实现了随机篡改物体的位置和大小,并保存篡改图像及其相关mask。
摘要由CSDN通过智能技术生成

问题描述:粗略的制作一幅copymove篡改图片

输入:一幅真实图片,和一个mask图。(可以选择一些分割数据集,mask正好是物体)

输出:一幅一幅copymove篡改图片,和篡改的mask。

导入:

import numpy as np
import cv2
from PIL import Image

读取:

 # 读取图片和mask
    img_1 = cv2.imread(path1)
    mask = cv2.imread(mask_path)

    # 获取图片大小,保证mask和图片大小一致
    h, w, c = img_1.shape
    mask = cv2.resize(mask, (w, h))

制作mask

 # 因为是copymove,从原mask赋值给另一个mask,调整大小后,粘贴会和原mask大小一致的一个全黑图像。
    # 然后就得到mask2。即mask为原mask,mask1为将mask调整大小后的mask,mask2为和mask大小一致的全黑图像。
    # 将mask1粘贴至mask2的一个位置。得到的mask2为和mask形状一致,但是mask2中的物体大小和位置发生变化。
    mask1 = cv2.resize(mask, (200, 200))
    mask2 = np.zeros_like(mask)
    mask2 = Image.fromarray(cv2.cvtColor(mask2, cv2.COLOR_BGR2RGB))
    mask1 = Image.fromarray(cv2.cvtColor(mask1, cv2.COLOR_BGR2RGB))
    mask2.paste(mask1, (50, 50))
    mask2.show()
    mask2 = np.asarray(mask2)

根据mask抠图:

 # 根据mask,获取要复制的物体image_mask1,然后将image_mask1调整大小,大小和mask1大小一致。
    # 然后再粘贴到一个全黑的大小和原mask大小一致的mask3中。
    # 也就是说,mask2为篡改物体的掩码图,mask3对应位置的篡改的物体。
    image_mask1 = cv2.bitwise_and(img_1, mask)
    image_mask1 = cv2.resize(image_mask1, (200, 200))
    mask3 = np.zeros_like(mask)
    mask3 = Image.fromarray(mask3)
    image_mask1 = Image.fromarray(image_mask1)
    mask3.paste(image_mask1, (50, 50))
    mask3 = np.asarray(mask3)

    # 通过mask2,将原图像的相应位置的像素减掉。
    # 得到的diffImg
    diffImg1 = cv2.subtract(img_1, mask2)

粘贴:

 # 将mask3和diffImg1相加,得到最后的篡改图。
    image_need = cv2.addWeighted(diffImg1, 1, mask3, 1, 0)
    cv2.imshow("image_need", image_need)
    cv2.waitKey(0)
    image_need = Image.fromarray(cv2.cvtColor(image_need, cv2.COLOR_BGR2RGB))

效果图:

篡改mask:

 

 

 最后篡改图:

完整代码:

import random
import numpy as np
import cv2
from PIL import Image


def make_copymove(path1, mask_path):
    # 读取图片和mask
    img_1 = cv2.imread(path1)
    mask = cv2.imread(mask_path)

    # 获取图片大小,保证mask和图片大小一致
    h, w, c = img_1.shape
    mask = cv2.resize(mask, (w, h))

    # 因为是copymove,从原mask赋值给另一个mask,调整大小后,粘贴会和原mask大小一致的一个全黑图像。
    # 然后就得到mask2。即mask为原mask,mask1为将mask调整大小后的mask,mask2为和mask大小一致的全黑图像。
    # 将mask1粘贴至mask2的一个位置。得到的mask2为和mask形状一致,但是mask2中的物体大小和位置发生变化。
    mask1 = cv2.resize(mask, (200, 200))
    mask2 = np.zeros_like(mask)
    mask2 = Image.fromarray(cv2.cvtColor(mask2, cv2.COLOR_BGR2RGB))
    mask1 = Image.fromarray(cv2.cvtColor(mask1, cv2.COLOR_BGR2RGB))
    mask2.paste(mask1, (50, 50))
    mask2.show()
    mask2 = np.asarray(mask2)

    # 根据mask,获取要复制的物体image_mask1,然后将image_mask1调整大小,大小和mask1大小一致。
    # 然后再粘贴到一个全黑的大小和原mask大小一致的mask3中。
    # 也就是说,mask2为篡改物体的掩码图,mask3对应位置的篡改的物体。
    image_mask1 = cv2.bitwise_and(img_1, mask)
    image_mask1 = cv2.resize(image_mask1, (200, 200))
    mask3 = np.zeros_like(mask)
    mask3 = Image.fromarray(mask3)
    image_mask1 = Image.fromarray(image_mask1)
    mask3.paste(image_mask1, (50, 50))
    mask3 = np.asarray(mask3)

    # 通过mask2,将原图像的相应位置的像素减掉。
    # 得到的diffImg
    diffImg1 = cv2.subtract(img_1, mask2)

    # 将mask3和diffImg1相加,得到最后的篡改图。
    image_need = cv2.addWeighted(diffImg1, 1, mask3, 1, 0)
    cv2.imshow("image_need", image_need)
    cv2.waitKey(0)
    image_need = Image.fromarray(cv2.cvtColor(image_need, cv2.COLOR_BGR2RGB))

    return image_need


make_copymove("../image/im1.jpg", "../image/mask.jpg")

改进:篡改物体的大小,位置可以随机生成,但是有可能会和原物体重叠,还没想好怎么能。

还有一个问题,篡改位置是由原mask调整大小后,随机粘贴,这时候篡改物体要比原物体小。想要保持物体大小不变,实现不了。想法是将物体裁剪,而不是resize。

后续改好了,在更新……

github:https://github.com/Shanchance/pythonTest

最后版本:

"""
制作copymove数据集。
1.保存真实mask
2.保存篡改mask
3.保存两个mask在一副图像中,不同颜色显示。
4.保存篡改图
"""
import os
import random
import numpy as np
import cv2
from PIL import Image
import matplotlib.pyplot as plt


def object_area(img):
    pictue_size = img.shape
    picture_height = pictue_size[0]
    picture_width = pictue_size[1]
    i = 0
    up = -1
    down = -1
    left = -1
    right = -1

    for a in range(picture_height):
        for b in range(picture_width):
            if img[a, b].all() > 0:
                if up == -1:
                    up = a
                i = i + 1
    r = i / (picture_height * picture_width)
    return r


def make_copymove(path1, mask_path):
    # 读取图片和mask
    try:
        img_1 = cv2.imread(path1)
        mask = cv2.imread(mask_path)

        # 获取图片大小,保证mask和图片大小一致
        h, w, c = img_1.shape
        mask = cv2.resize(mask, (w, h))
        rate = object_area(mask)
        print("rate", rate)
        image = mask
        closed = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

        (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]

        # compute the rotated bounding box of the largest contour
        rect = cv2.minAreaRect(c)
        box = np.int0(cv2.boxPoints(rect))

        Xs = [i[0] for i in box]
        Ys = [i[1] for i in box]
        x1 = min(Xs)
        x2 = max(Xs)
        y1 = min(Ys)
        y2 = max(Ys)
        hight = y2 - y1
        width = x2 - x1
        # print(y1)
        # print(y1 + hight)
        # print(x1)
        # print(x1 + width)
        # cv2.imshow("mask", mask)
        # 因为是copymove,从原mask赋值给另一个mask,调整大小后,粘贴会和原mask大小一致的一个全黑图像。
        # 然后就得到mask2。即mask为原mask,mask1为将mask调整大小后的mask,mask2为和mask大小一致的全黑图像。
        # 将mask1粘贴至mask2的一个位置。得到的mask2为和mask形状一致,但是mask2中的物体大小和位置发生变化
        mask1 = image[y1:y1 + hight, x1:x1 + width]
        # plt.imshow(mask)
        # plt.show()
        # plt.imshow(mask1)
        # plt.show()
        # print(y1 + hight)
        # print(x1 + width)
        mask2 = np.zeros_like(mask)
        # cv2.imshow("mask1", mask1)
        height_paste = random.randint(1, h - hight - 1)
        left = x1
        right = w - x1 - width
        if left < right:
            if right > width:
                width_paste = random.randint(1, (right - width)) + (left + width)
            else:
                if w > h:
                    mask1 = cv2.resize(mask1, (right - 1, hight))
                else:
                    mask1 = cv2.resize(mask1, (width / 2, hight / 2))
                width_paste = right - 1
        else:
            if left > width:
                width_paste = random.randint(1, (left - width - 1))
            else:
                if w > h:
                    mask1 = cv2.resize(mask1, (left - 1, hight))
                else:
                    mask1 = cv2.resize(mask1, (width // 2, hight // 2))
                width_paste = 0
        mask2 = Image.fromarray(cv2.cvtColor(mask2, cv2.COLOR_BGR2RGB))
        mask1 = Image.fromarray(cv2.cvtColor(mask1, cv2.COLOR_BGR2RGB))
        mask2.paste(mask1, (width_paste, height_paste))
        mask2 = np.asarray(mask2)
        # plt.imshow(mask2)
        # plt.show()
        # 根据mask,获取要复制的物体image_mask1,然后将image_mask1调整大小,大小和mask1大小一致。
        # 然后再粘贴到一个全黑的大小和原mask大小一致的mask3中。
        # 也就是说,mask2为篡改物体的掩码图,mask3对应位置的篡改的物体。
        image_mask1 = cv2.bitwise_and(img_1, mask)
        image_mask1 = image_mask1[y1:y1 + hight, x1:x1 + width]
        mask1 = np.asarray(mask1)
        mask1_h, mask1_w, mask1_c = mask1.shape
        image_mask1 = cv2.resize(image_mask1, (mask1_w, mask1_h))
        mask3 = np.zeros_like(mask)
        mask3 = Image.fromarray(mask3)
        image_mask1 = Image.fromarray(image_mask1)
        mask3.paste(image_mask1, (width_paste, height_paste))
        mask3 = np.asarray(mask3)

        # 通过mask2,将原图像的相应位置的像素减掉。
        # 得到的diffImg
        diffImg1 = cv2.subtract(img_1, mask2)

        # 将mask3和diffImg1相加,得到最后的篡改图。
        image_need = cv2.addWeighted(diffImg1, 1, mask3, 1, 0)
        image_need = Image.fromarray(cv2.cvtColor(image_need, cv2.COLOR_BGR2RGB))
        mask_real = Image.fromarray(cv2.cvtColor(mask, cv2.COLOR_BGR2RGB))
        mask_forgery = Image.fromarray(cv2.cvtColor(mask2, cv2.COLOR_BGR2RGB))
        _, mask = cv2.threshold(mask, 90, 255, cv2.THRESH_BINARY)
        mask[np.where((mask == [255, 255, 255]).all(axis=2))] = [0, 0, 255]
        mask_two = cv2.addWeighted(mask, 1, mask2, 1, 0)
        mask_two = Image.fromarray(cv2.cvtColor(mask_two, cv2.COLOR_BGR2RGB))
        return image_need, mask_real, mask_forgery, mask_two
    # 有点小错误,没看出来,不想改了,用个try,异常处理
    except:
        return 0, 0, 0, 0


mask = os.listdir("../coco/use_mask/")
for i in range(len(mask)):
    mask_path = "../coco/use_mask/" + mask[i]
    image_path = "../coco/coco_train_2017/train2017/" + mask[i]
    tam, real_mask, tam_mask, tam_two_mask = make_copymove(image_path, mask_path)
    if tam == 0:
        continue
    tam.save("../coco/copymove/tam/" + mask[i])
    real_mask.save("../coco/copymove/real_mask/" + mask[i])
    tam_mask.save("../coco/copymove/tam_mask/" + mask[i])
    tam_two_mask.save("../coco/copymove/tam_two_mask/" + mask[i])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值