本文旨在总结博主做项目时总结的基于C++的图片剪切代码,代码难度较低,仅供基础知识的学习巩固。
比如:读取文件1000.txt的内容,每行字符的后面四个数,分别表示图片上裁切矩形的x中心,y中心,width,height。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
//字符串分割
vector split(const string &str, const string &pattern)
{
//const char* convert to char*
char * strc = new char[strlen(str.c_str()) + 1];
strcpy(strc, str.c_str());
vector resultVec;
char* tmpStr = strtok(strc, pattern.c_str());
while (tmpStr != NULL)
{
resultVec.push_back(string(tmpStr));
tmpStr = strtok(NULL, pattern.c_str()); //在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回被分割出片段的指针
}
delete[] strc;
return resultVec;
};
//逐行读取
vector> readTxt(char* file)
{
vector> rect_str;
ifstream infile;
infile.open(file); //将文件流对象与文件连接起来
assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行
string s;
while (getline(infile, s))
{
rect_str.push_back(split(s, " "));
}
infile.close(); //关闭文件输入流
return rect_str;
}
//图片裁切并保存
void ImagePicking(const char* ImageFileName, char* CutFileName, vector> rect)
{
int length = rect.size();
Mat srcImage = imread(ImageFileName);
Mat cutImage;
string num;
int centor_x, centor_y, width, height, point_x, point_y;
for (int i = 0; i < length; i++)
{
int centor_x = stof(rect[i][1]) * 3840; //stof(),字符串转float
int centor_y = stof(rect[i][2]) * 2160;
int width = stof(rect[i][3]) * 3840;
int height = stof(rect[i][4]) * 2160;
int point_x = centor_x - width/2;
int point_y = centor_y - height/2;
num = CutFileName + to_string(i) + ".png";
Rect select = Rect(point_x, point_y, width, height);
//Rect select = Rect(100, 300, 500, 1000);
cutImage = srcImage(select);
imwrite(num, cutImage);
}
}
int main()
{
vector> rect;
//标签路径
char* LabelPath = "E:\\FaceAll\\Project\\PicCut\\tomato_large\\labels\\train\\1000.txt";
//图片路径
char* ImagePath = "E:\\FaceAll\\Project\\PicCut\\tomato_large\\images\\train\\1000.png";
//裁切后的图片保存路径
char* CutPath = "E:\\FaceAll\\Project\\PicCut\\tomato_large\\images\\train\\1000\\";
//将标签文件中的内容读取出来
rect = readTxt(LabelPath);
//根据文件内容裁切图片
ImagePicking(ImagePath, CutPath, rect);
return 0;
}
//字符串分割
vector
Notes:
1. 函数的形参传入引用,形参和实参是一回事,修改形参也会使得实参改变。
2. char * strc = new char[strlen(str.c_str()) + 1];
c_str()函数返回一个指向正规C字符串的指针;
new: 开辟的空间在堆上,而一般声明的变量存放在栈上.
通常来说,当在局部函数中new出一段新的空间,该段空间在局部函数调用结束后仍然能够使用,可以用来向主函数传递参数
3. strcpy(strc, str.c_str());
将str.c_str()指向的字符复制到strc。
4. char* tmpStr = strtok(strc, pattern.c_str());
在第一次调用时,分解字符串 strc 为一组小字符串,pattern.c_str()为分隔符;
在第二次调用时, strc设置为NULL,每次调用成功返回被分割出片段的指针。
5. stof(), 字符串转float, to_string(), int转string.