初衷
项目需要,需要做样本类别训练,即将每类样本分放在不同的文件夹,通过网络训练后得到模型,检测数据输出为所属类别;
先前深度学习输出为类别和位置,需要遍历全局图像,比较耗时。
问题
分类别训练时,需要搜集大量样本并进行裁剪,这是一个很费时间和感情的事情;
恰好在深度学习时,通过labelimage等工具得到样本数据,如下图所示:
可否通过这些数据,将样本裁剪出来呢?
于是乎,写了个脚本,并且实现了。
代码实现
#include<fstream>
#include<map>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
#include<sstream> //istringstream 必须包含这个头文件
#include<opencv2/opencv.hpp>
int main()
{
//图片所在文件夹
string path = "D:\\python_objectdetection\\models-master\\models-master\\research\\object_detection\\images_Iray\\test\\";
//CSV文件所在路径,即生成tfrecord前的原始数据
ifstream fin("D:\\python_objectdetection\\models-master\\models-master\\research\\object_detection\\data\\Iray\\test.csv"); //打开文件流操作
string imgpath = "";
//输出图片保存位置
string cutpath = "D:\\train_by_CNN\\images_iray\\";
//读图计数
int count = 0;
string line;
//记录行数,第一行不操作
int lines = 0;
vector<string>classes;
while (getline(fin, line)) //整行读取,换行符“\n”区分,遇到文件尾标志eof终止读取
{
lines++;
istringstream stream_in(line); //将整行字符串line读入到字符串流istringstream中
vector<string> fields; //声明一个字符串向量
string field;
while (getline(stream_in, field, ',')) //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
{
fields.push_back(field); //将刚刚读取的字符串添加到向量fields中
}
if (lines == 1)
continue;
imgpath = path + fields[0];
cv::Mat image = cv::imread(imgpath);
int xmin = std::stoi(fields[4]);
int ymin = std::stoi(fields[5]);
int xmax = std::stoi(fields[6]);
int ymax = std::stoi(fields[7]);
cv::Rect roi = cv::Rect(xmin, ymin, abs(xmax - xmin), abs(ymax - ymin));
cv::Mat image_cut = image(roi);
//我这边有两类,所以新建了两个文件夹
if (fields[3] == "car")
{
count++;
cutpath = cutpath + "1//" + "car_" + to_string(count) + ".jpg";
cv::imwrite(cutpath, image_cut);
cutpath = "D:\\train_by_CNN\\images_iray\\";
}
if (fields[3] == "boat")
{
count++;
cutpath = cutpath + "2//" + "boat_" + to_string(count) + ".jpg";
cv::imwrite(cutpath, image_cut);
cutpath = "D:\\train_by_CNN\\images_iray\\";
}
image.release();
image_cut.release();
}
fin.close();
}
裁剪后效果这样,文件夹名就1、2、3区分类别,在tf那边有相应代码生成record格式。
代码如下:
import os
import tensorflow as tf
from PIL import Image
import sys
def creat_tf(imgpath):
cwd = os.getcwd()
classes = os.listdir(cwd + imgpath)
# 此处定义tfrecords文件存放
#存放record格式数据的位置
writer = tf.python_io.TFRecordWriter("images_iray/train.tfrecords")
for index, name in enumerate(classes):
class_path = cwd + imgpath + name + "/"
print(class_path)
if os.path.isdir(class_path):
for img_name in os.listdir(class_path):
img_path = class_path + img_name
img = Image.open(img_path)
img = img.resize((224, 224))
img_raw = img.tobytes()
example = tf.train.Example(features=tf.train.Features(feature={
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[int(name)])),
'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
}))
writer.write(example.SerializeToString())
print(img_name)
writer.close()
if __name__ == '__main__':
#裁剪图像所在文件夹,是那个1、2文件夹上层路径
imgpath = '/images_iray/'
creat_tf(imgpath)