一、代码需求
目标检测中常常需要大量不同类别的数据集,目前常用的yolo系列算法有时候面对大量的数据分类效果可能不是很好,但检测框却是准确的,我们分析原因可能是图片背景不够干净影响分类的结果,此时可能需要对图片进行裁剪处理进行第二次训练。
二、任务可用文件
(1)通过yolo算法获取到的检测框位置列表.txt文件:bird_imgs.txt
(2)检测框位置对应图片名称+图片所在文件夹名称的路径列表.txt文件:boxes.txt
三、任务需求
(1)因为boxes文件中的坐标位置信息(x,y,w,h)为归一化后的比例系数,所以需要先还原成图片的真实位置
(2)截取图片后需要以原文件夹名称及原图片名称保存到一个新的文件夹中
四、代码思路
(1)同时读取两个txt文件保证裁剪操作一一对应
(2)获取原图像真实长宽,用真实长宽乘以位置比例系数得到真实坐标信息
(3)利用(2)中得到的真实坐标信息进行裁剪操作
(4)因为路径.txt文件中的信息为[/文件夹/图片.jpg]所以需要同时从该文件中获取[/文件夹]字符串,并以此创建新的文件保存路径
代码实现如下:
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/stat.h>
int main()
{
// 读取图片路径列表文件
std::ifstream imageListFile("/home/路径/bird_imgs.txt");
if (!imageListFile.is_open())
{
std::cout << "Error opening image list file!" << std::endl;
return -1;
}
// 读取截取位置列表文件
std::ifstream coordinatesListFile("/home/路径/boxes.txt");
if (!coordinatesListFile.is_open())
{
std::cout << "Error opening coordinates list file!" << std::endl;
return -1;
}
std::string imagePath, coordinatesPath;//定义路径和相对位置两个变量
while (std::getline(imageListFile, imagePath))//按顺序读取图片路径列表中的一行
{
// 循环处理每张图片
std::string imagePath_final = "/home/路径/" + imagePath;
// 读取原始图片
cv::Mat originalImage = cv::imread(imagePath_final);
// 获取图片的长宽
int imageWidth = originalImage.cols;
int imageHeight = originalImage.rows;
// 读取截取框坐标,并调整为相对于图片长宽的比例
float x_ratio, y_ratio, w_ratio, h_ratio;
coordinatesListFile >> x_ratio >> y_ratio >> w_ratio >> h_ratio;//获取相对位置信息并同时赋值
//输出赋值结果检查是否赋值正确,可注释掉
std::cout << x_ratio << std::endl;
std::cout << y_ratio << std::endl;
std::cout << w_ratio << std::endl;
std::cout << h_ratio << std::endl;
// 计算截取框的绝对坐标
int x = static_cast<int>(x_ratio * imageWidth);
int y = static_cast<int>(y_ratio * imageHeight);
int w = static_cast<int>(w_ratio * imageWidth);
int h = static_cast<int>(h_ratio * imageHeight);
// 利用位置信息裁剪图像
cv::Rect roi(x - 0.5 * w, y - 0.5 * h, w, h);
cv::Mat croppedImage = originalImage(roi);
// 显示原始图像和裁剪后的图像,用于测试时检查图像裁剪效果,实际运行注释掉
cv::imshow("Original Image", originalImage);
cv::imshow("Cropped Image", croppedImage);
cv::waitKey(0);
cv::destroyAllWindows();
// 查找分隔符的位置
size_t pos = imagePath.find('/');
if (pos != std::string::npos)
{
// 提取两个子字符串
std::string folder = imagePath.substr(0, pos);//提取前一个字符串并赋值给folder变量
std::string image = imagePath.substr(pos + 1);
// 保存裁剪后的图像
std::string folderpath = "/home/路径/New Image/" + folder + "/";
mkdir(folderpath.c_str(),0777);//创建新的保存文件夹
cv::imwrite(folderpath + image , croppedImage);
}
}
imageListFile.close();
coordinatesListFile.close();
return 0;
}
ps:可以在调试代码时通过“std::cout<<XX<<std::endl”输出变量值或者获取到的文本信息以检查代码逻辑以及是否正确运行