前言
- 基于mask_rcnn网络图像篡改检测,对在网上阅读了许多相关内容发现都不利于小白复现mask_rcnn,因此记录一下自己实现的过程。
- 神经网络的训练最好基于gpu, 楼主条件不允许所以直接拿自己电脑刚了。初次训练了10来个小时,效果还不错(心疼我的小风扇嘤嘤嘤)。
- 第一次写博客,所以排版及表达可能不是特别严谨,万各位包容以及提出指正,谢谢~
准备工具
- macos系统
- anaconda——用于装Keras,tensorflow等机器学习必要的包
- pycharm开发工具
- labelme标注工具——用于制作train的数据集,打上自己想要的标签
下载地址:https://github.com/wkentaro/labelme
使用参考:https://blog.youkuaiyun.com/shwan_ma/article/details/77823281 - mask-rcnn源码下载地址:https://github.com/matterport/Mask_RCNN 。在mask-rcnn根目录下建立logs文件夹,用于保存训练模型的历史信息
- 所使用的图片集:coverage图片集和comofod图片集——这两个图片集都是经过copymove篡改后的图片,但是由于他们所提供的标注的信息我不会使用,所以我就自己使用labelme做了标注。所以其实在这种情况下,无论我们要使用mask-rcnn进行何种检测,都可以参考楼主的过程,因为此时只有标注分类不同。
- 原模型下载:用的是coco的模型,一般来讲有一个初始模型算法会收敛的更快一点,所以使用了mask_rcnn_coco.h5。要楼主模型的可私信,只针对copymove图像篡改检测的。mask_rcnn_coco.h5下载地址: https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5.
将用于训练的原模型置于指定路径下。(由于我的代码找原模型是在根目录下找,所以将模型置于根目录下)
数据集制作
图片准备
- 将coverage和comofod图片集中的图片合到一个文件夹下,并使所有图片都文件名为递增序列如1.png、2.png。
- 最先开始跑代码的时候出现错误:
Exception: Image size must be dividable by 2 at least 6 times to avoid fractions when downscaling and upscaling.
马上查看了一下图片的大小,果然很多图片的个位数都是奇数。然后将代码中有关图片大小设置为512*512(这里可以由读者自行更改),并将准备的图片集进行resize一下,使用python代码进行resize。代码内容如下:
//resize.py
from PIL import Image
import os.path
import glob
def convertjpg(jpgfile,outdir,width=512,height=512):
img=Image.open(jpgfile)
try:
new_img=img.resize((width,height),Image.BILINEAR)
new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))
except Exception as e:
print(e)
for jpgfile in glob.glob("/Users/empty/Desktop/dataset/*.png"): //对路径下适配‘*.png’的所有图片进行转换大小
convertjpg(jpgfile,"/Users/empty/Desktop/dataset")
图片标注处理
- 在终端下输入conda activate labelme,系统将会启动labelme程序,而后输入labelme打开图形化界面,而后如何使用labelme进行标注可以参考这篇文章:https://blog.youkuaiyun.com/shwan_ma/article/details/77823281
- 参考完上篇文章使用labelme对resize后的图片进行标注,生成文件名.json数据对所有的json数据进行处理生成文件名_json文件。此时对json数据的处理过程是使用shell脚本进行批量化处理的,由于必须使用labelme_json_to_dataset,所以要进入到labelme应用程序(在终端下输入:conda activate labelme 进入labelme)。脚本代码如下:
// task.bash
#!/bin/bash
for((i=1;i<301;i++))//这里是文件名从小到大,如果训练集有500张图片就到500
do
s=${
i}
labelme_json_to_dataset ${
s}.json
done
- 此时对所有的文件名.json文件都会生成文件名_json文件夹,如下图所示:
打开1_json文件夹,我们可看到如下文件:
如上图所示,img.png为原图,label.png为生成掩膜的图片。
生成最后数据集
- 为了为代码提供正确的数据,我们将数据集设置为4个文件:
a)json文件夹下存储所有的标注后的json数据
b)labelme_json文件夹下存储所有的文件名_json文件夹
c)pic文件夹下存储所有的原图
d)cv2_mask文件夹下存储所有的掩码标注图片,即上文中所说的文件名_json下的label.png图片。由于labelme生成的掩码标签 label.png为16位图,opencv默认处理8位图,所以需要将所有的掩码标签图由16位转8位,这里使用python实现,并将生成后的8位图直接保存到cv2_mask文件夹下。代码如下:
//img_16to8.py
def img_16to8():
from PIL import Image
import numpy as np
import shutil
import os
src_dir = r'/Users/empty/Desktop/dataset/labelme_json'
dest_dir = r'/Users/empty/Desktop/dataset/cv2_mask'
for child_dir in os.listdir(src_dir):
new_name = child_dir.split('_')[0] + '.png'
old_mask = os.path.join(os.path.join(src_dir, child_dir), 'label.png')
img = Image.open(old_mask)
img = Image.fromarray(np.uint8(np.array(img)))
new_mask = os.path.join(dest_dir, new_name)
img.save(new_mask)
img_16to8()
代码运行成功后cv2_mask文件夹内容如下所示,此时所有的图片都是黑乎乎的,这是正常现象不用担心。
2. 完成所有文件夹创建并将内容归位后,数据集的制作就完成啦!
代码修改
代码准备
- 在samples目录下建立文件夹copymove(或者你自己取的文件名),并在copymove文件目录下建立新的文件train.py和test.py
train.py代码解析
- train.py对训练数据集进行训练并生成模型,代码内容如下:
# -*- coding: utf-8 -*-
import os
import sys
import random
import math
import re
import time
import numpy as np
import cv2
import matplotlib
import matplotlib.pyplot as plt
import tensorflow as tf
from mrcnn.config import Config
#import utils
from mrcnn import model as modellib,utils
from mrcnn import visualize