基于C++的图片指定区域剪切

本文旨在总结博主做项目时总结的基于C++的图片剪切代码,代码难度较低,仅供基础知识的学习巩固。

比如:读取文件1000.txt的内容,每行字符的后面四个数,分别表示图片上裁切矩形的x中心,y中心,width,height。

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include<vector>
#include<fstream>
#include <cassert>
#include <string>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;


//字符串分割
vector<string> 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<string> 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<vector<string>> readTxt(char* file)
{
	vector<vector<string>> 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<vector<string>> 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<vector<string>> 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<string> split(const string &str, const string &pattern){......}

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.

         

          

猜你喜欢

转载自blog.csdn.net/weixin_38584764/article/details/124040082