图像增强标注代码C++(旋转、平移、翻转)(已有新方法,链接如下)
已封装类
最近在做项目时需要用到labelme进行数据集标注,大量图像以及增强图像的标注十分费时,因此想到利用代码对标注好的原始图像进行处理来扩充数据集。
使用说明
注意:暂时仅用于只有一个类别标签的txt文件(后续有需求会进行更改),确保txt文件的命名格式为6位数字,从000001.txt到999999.txt为止,序号可以不连续
使用前需要更改:
一:folder地址和读取txt、写入txt的地址
二:图片大小、平移距离、旋转角度(逆时针)、旋转中心(归一化坐标)等参数
旋转
constexpr auto PI = 3.141592654;
const auto ang = 90;//逆时针旋转角度
int h = 1236;
int w = 1626;//原始图片大小
double x = 0.5;
double y = 0.5;//旋转中心的归一化坐标
Point2d rotate(Point2d a, Point2d a0, double angle) {
a = Point2d(a.x * h, a.y * w);
a0 = Point2d(a0.x * h, a0.y * w);
Point2d b;
b.x = (a.x - a0.x) * cos(angle * PI / 180) - (a.y - a0.y) * sin(angle * PI / 180) + a0.x;
b.y = (a.x - a0.x) * sin(angle * PI / 180) + (a.y - a0.y) * cos(angle * PI / 180) + a0.y;
b = Point2d(b.x / h, b.y / w);
return b;
}
平移
int t_h = -100;
int t_w = -100;//平移距离
Point2d translation(Point2d a, int th, int tw) {
a = Point2d(a.x * h, a.y * w);
Point2d b;
b = Point2d(a.x + th, a.y + tw);
b = Point2d(b.x / h, b.y / w);
return b;
}
翻转
Point2d horizontal(Point2d a) {//水平翻转
Point2d b;
b = Point2d(a.x, 1 - a.y);
return b;
}
Point2d vertical(Point2d a) {//垂直翻转
Point2d b;
b = Point2d(1 - a.x, a.y);
return b;
}
完整代码(以旋转为例)
#include <opencv2/opencv.hpp>
#include <fstream>
#include <sstream>
using namespace std;
using namespace cv;
constexpr auto PI = 3.141592654;
const auto ang = 90;//逆时针旋转角度; 需要更改
int h = 1236;
int w = 1626;//图片大小
double x = 0.5;
double y = 0.5;//旋转中心的归一化坐标
//旋转:点a以a0为圆心逆时针旋转angle度(角度制)到点b
Point2d rotate(Point2d a, Point2d a0, double angle) {
a = Point2d(a.x * h, a.y * w);
a0 = Point2d(a0.x * h, a0.y * w);
Point2d b;
b.x = (a.x - a0.x) * cos(angle * PI / 180) - (a.y - a0.y) * sin(angle * PI / 180) + a0.x;
b.y = (a.x - a0.x) * sin(angle * PI / 180) + (a.y - a0.y) * cos(angle * PI / 180) + a0.y;
b = Point2d(b.x / h, b.y / w);
return b;
}
//double转string
string dou2str(double num) {
stringstream ss;
string str;
ss << num;
ss >> str;
return str;
}
//坐标变换
void Transform(string &strx, string &stry) {
double Tx = atof(strx.c_str());
double Ty = atof(stry.c_str());
Point2d point = Point2d(Tx, Ty);
Point2d T_point = rotate(point, Point2d(x, y), ang);
Tx = T_point.x;
Ty = T_point.y;
strx = dou2str(Tx);
stry = dou2str(Ty);
}
int main()
{
cv::String folder = "./txt/*.txt";//需要转换的txt文件总数
std::vector<cv::String> imagePathList;
cv::glob(folder, imagePathList, false);
int index = 1;
for (auto fileName : imagePathList) {
bool ispoint = false;//跳过第一个表示类别的“0”
bool space_y = false;//下一个空格是否是x坐标前的空格
bool space_x = false;//下一个空格是否是y坐标前的空格
char intxtName[50];
char outtxtName[50];
if (index < 10) {//按名字读取txt文件(需要优化)
sprintf_s(intxtName, "./txt/00000%d.txt", index);
sprintf_s(outtxtName, "./D%dtxt/00000%d.txt", ang, index);
}
if (index >= 10 && index < 100) {
sprintf_s(intxtName, "./txt/0000%d.txt", index);
sprintf_s(outtxtName, "./D%dtxt/0000%d.txt", ang, index);
}
if (index >= 100 && index < 1000) {
sprintf_s(intxtName, "./txt/000%d.txt", index);
sprintf_s(outtxtName, "./D%dtxt/000%d.txt", ang, index);
}
if (index >= 1000 && index < 10000) {
sprintf_s(intxtName, "./txt/00%d.txt", index);
sprintf_s(outtxtName, "./D%dtxt/00%d.txt", ang, index);
}
if (index >= 10000 && index < 100000) {
sprintf_s(intxtName, "./txt/0%d.txt", index);
sprintf_s(outtxtName, "./D%dtxt/0%d.txt", ang, index);
}
if (index >= 100000 && index < 1000000) {
sprintf_s(intxtName, "./txt/%d.txt", index);
sprintf_s(outtxtName, "./D%dtxt/%d.txt", ang, index);
}
ifstream fIn(intxtName);
ofstream fOut(outtxtName);
if (!fIn) {
index++;
cout << "Open input file faild." << endl;
continue;
}
if (!fOut) cout << "Open output file faild." << endl;
fIn >> noskipws;//读取所有字符(包括空格和回车)
string str = "";
string strx = "";
string stry = "";
while (!fIn.eof())
{
char c;
fIn >> c;
if (ispoint) {
if (c != ' ') {
str = str + c;
}
else if (space_y) {
strx = str;
str = "";
space_y = false;
space_x = true;
}
else if (space_x) {
stry = str;
str = "";
space_y = true;
space_x = false;
}
if (strx != "" && stry != "") {//在检测到x坐标前的空格时有strx!=""&& stry!=""
Transform(strx, stry);
fOut << " " << stry << " " << strx;
strx = "";
stry = "";
}
}
else {
ispoint = true;
space_y = true;
fOut << c;
}
}
strx = str;
Transform(strx, stry);//最后一个y坐标后没有空格,在循环外进行最后一个坐标的旋转
fOut << " " << stry << " " << strx;
strx = "";
stry = "";
fIn.close();
fOut.close();
index++;
}
return 0;
}