[VS]批量读取文件夹,自动改图片名字

本文介绍如何使用C++和Python批量重命名文件夹内图像,并将其转换为统一格式。同时提供一种方法来检查图像及其对应标签是否匹配,确保数据集完整无遗漏。
// Getfile.cpp : 重命名文件夹内的所有图像并写入txt,同时也可通过重写图像修改格式
//配用Opencv2.4.10

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include<io.h>  
#include <opencv2\opencv.hpp>
#define IMGNUM 20000 //图片所在文件夹中图片的最大数量  
char img_files[IMGNUM][1000];

using namespace cv;
int getFiles(char *path)
{
	int num_of_img = 0;
	long   hFile = 0;
	struct _finddata_t fileinfo;
	char p[700] = { 0 };
	strcpy(p, path);
	strcat(p, "\\*");
	if ((hFile = _findfirst(p, &fileinfo)) != -1)
	{
		do
		{
			if ((fileinfo.attrib & _A_SUBDIR))
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					continue;
			}
			else
			{
				strcpy(img_files[num_of_img], path);
				strcat(img_files[num_of_img], "\\");
				strcat(img_files[num_of_img++], fileinfo.name);
			}
		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
	return num_of_img;
}
int main()
{
	char path[] = "SrcImage";								//source image
	char dstpath[] = "DstImage";							//destination image
	int num = getFiles(path);
	int i;
	char order[1000];
	FILE *fp = fopen("train.txt", "w");
	for (i = 0; i < num; ++i)
	{
		printf("%s\n", img_files[i]);
		IplImage *pSrc = cvLoadImage(img_files[i]);
		sprintf(order, "DstImage\\%06d.jpg", i);
		fprintf(fp, "%06d\n", i);
		cvSaveImage(order, pSrc);
		printf("Saving %s!\n", order);
		cvReleaseImage(&pSrc);
	}
	fclose(fp);
	return 0;

}

2.python版本,批量修改名字

# -*- coding:utf8 -*-
__author__ = "lingjun"
# E-mail: lingjum.qian@zying.com.cn

import os

############################################################
# 批量重命名
############################################################
def rename(input_path):
    for f1 in os.listdir(input_path):
        target_path=os.path.join(input_path, f1)
        #print(f1)

        for (path, dirs, files) in os.walk(target_path):
            for filename in files:
                #print(filename)
                no_suffix_name=(filename.split('.')[0]).split("_")[0:5]
                print(no_suffix_name)

                #if suffix_name=='png':
                new_name = f1 + '_' + filename

                os.rename(path + "/" + filename, path + "/" + new_name)
                print(new_name)
############################################################
# 批量去除带有特点字符的文件名,重命名
############################################################
def re_name(path):

    for root, dirs, files in os.walk(path):
        for name in files:  # 遍历所有文件
            pos = name.find("_label")  # 把文件带有_label的字符删除
            if (pos == -1):
                continue
            newname = name[0:pos] + ".png"
            os.rename(os.path.join(root, name), os.path.join(root, newname))
            print(newname)


if __name__=='__main__':
    in_path = "F:/image/mask"
    re_name(in_path)

参考文献:https://blog.youkuaiyun.com/liuyudong_/article/details/80319592

3.修改好了,那看看两个对应的图片,是否有遗漏的

(例如深度学习分割里面,image and label)

# -*- coding: utf-8 -*-
__author__ = "lingjun"
# E-mail: lingjum.qian@zying.com.cn
# 微信公众号:小白CV
import os

def file_name(file_dir):
    label_list = []
    image_list = []
    for root, dirs, files in os.walk(file_dir):
        for filename in files:
            file_name=filename.split(".")[0]

            if file_name.split("_")[-1] == 'label':
                label_list.append(file_name)
            else:
                image_list.append(file_name+"_label")

    diff = set(image_list).difference(set(label_list))  # 差集,在a中但不在b中的元素
    print(len(diff))
    for name in diff:
        print("在a中但不在b中的元素", name + ".jpg")

    diff2 = set(label_list).difference(set(image_list))  # 差集,在b中但不在a中的元素
    print(len(diff2))
    for name in diff2:
        print("在b中但不在a中", name + ".jpg")
    return label_list,image_list

    # 其中os.path.splitext()函数将路径拆分为文件名+扩展名

if __name__ == '__main__':
    #所有文件都放在这一个文件夹image里面
    path1 = r'F:\image'
    file_name(path1)

 

<think>好的,我现在需要帮助用户解决如何使用C++和OpenCV批量读取文件夹中的所有图片的问题。用户已经提供了一些之前的回答和引用内容,我需要综合这些信息来给出一个全面且准确的解决方案。 首先,用户之前的问题是关于批量保存图片并按数字序号命名,而现在的问题是批量读取图片。之前的回答中已经提到了使用cv::glob函数来获取文件路径列表,这可能在这里同样适用。引用中的几个例子也展示了不同的方法,比如使用cv::glob或者cv::utils::fs::glob,还有一些类封装的方法。 我需要确认OpenCV版本的问题,因为引用中提到在OpenCV3.X之后,contrib模块需要自己编译,但cv::glob是自带的函数。因此,在回答时需要说明不同版本的方法,确保用户知道如何根据他们的版本来选择正确的函数。 用户可能的需求不仅仅是读取图片,还可能包括如何处理读取过程中的错误,比如文件不存在或无法读取的情况。同时,用户可能希望代码结构清晰,比如使用类来封装读取功能,如引用中的Ve类。 另外,用户可能关心跨平台的问题,比如路径分隔符的处理,是否需要使用正斜杠或反斜杠,这在之前的回答中也提到了统一使用正斜杠以避免问题。此外,是否需要递归遍历子文件夹,引用中的glob函数有一个参数可以控制是否递归,需要说明这一点。 还有,用户可能想知道如何显示图片或者进行进一步的处理,但根据当前问题,重点应放在读取上。不过,引用中的示例代码有的包含显示图片的部分,可能需要提及,但保持回答的专注性。 需要检查引用中的代码是否存在潜在问题,例如在读取图片时是否检查了图像是否为空,避免程序崩溃。比如引用1中的代码在读取后直接emplace_back,但没有检查是否成功读取,这可能导致问题,所以应该在回答中加入错误处理的建议。 另外,用户可能对性能有要求,比如一次性读取所有图片到内存中是否可行,如果图片很多,可能会占用大量内存,但根据问题描述,用户可能只是需要基本的读取方法,因此可以建议在循环中逐个处理,而不是全部加载到内存。 总结步骤应该是:获取文件路径列表,遍历每个路径,读取图片,检查是否有效,然后处理或存储。需要提供两种方法,一种是使用cv::glob,另一种是使用cv::utils::fs::glob(如果有的话),并说明版本差异。 最后,确保代码示例正确,包括必要的头文件和命名空间,路径处理的注意事项,以及错误检查的部分,比如检查文件列表是否为空,处理无法读取图片文件。</think>#### 基于OpenCV的C++批量读取图片方法 以下是两种常用方法实现文件夹图片批量读取,涵盖不同OpenCV版本和代码封装方式: --- ### 方法一:使用`cv::glob`(OpenCV 3.0+通用) **核心步骤:** 1. **路径配置**:使用通配符定义文件匹配模式(如`*.jpg`) 2. **路径获取**:`cv::glob`函数扫描目录生成路径列表 3. **循环读取**:遍历路径列表并加载图像数据 ```cpp #include <opencv2/opencv.hpp> #include <vector> #include <iostream> int main() { // 配置输入路径(注意斜杠方向) std::string inputPattern = "D:/dataset/images/*.png"; // 获取所有匹配文件路径 std::vector<cv::String> imagePaths; cv::glob(inputPattern, imagePaths); // 错误检查 if(imagePaths.empty()) { std::cerr << "错误:未找到匹配图片" << std::endl; return -1; } // 批量读取 std::vector<cv::Mat> images; for(const auto& path : imagePaths) { cv::Mat img = cv::imread(path, cv::IMREAD_COLOR); // 以彩色模式读取 if(!img.empty()) { images.push_back(img); std::cout << "成功读取: " << path << std::endl; } else { std::cerr << "读取失败: " << path << std::endl; } } return 0; } ``` --- ### 方法二:使用`cv::utils::fs::glob`(OpenCV 4.5+推荐) **版本优势**: - 更严格的路径检查 - 支持递归遍历子目录(通过`recursive=true`参数) - 明确的文件存在性验证 ```cpp #include <opencv2/opencv.hpp> #include <opencv2/core/utils/filesystem.hpp> #include <vector> #include <iostream> int main() { std::string imgDir = "../input_images"; // 检查目录存在性 if(!cv::utils::fs::exists(imgDir)) { std::cerr << "错误:目录不存在" << std::endl; return -1; } // 获取所有JPG文件路径 std::vector<cv::String> imgPaths; cv::utils::fs::glob(imgDir, "*.jpg", imgPaths); // 批量读取(带异常处理) try { std::vector<cv::Mat> imageData; for(const auto& path : imgPaths) { cv::Mat img = cv::imread(path); if(img.empty()) throw std::runtime_error("图像加载失败: " + path); imageData.push_back(img.clone()); // 深拷贝避免内存冲突 } std::cout << "成功读取" << imageData.size() << "张图片" << std::endl; } catch(const std::exception& e) { std::cerr << "异常: " << e.what() << std::endl; } return 0; } ``` --- ### 关键差异对比表 | 特性 | `cv::glob` | `cv::utils::fs::glob` | |--------------------|-----------------------------|-------------------------------| | OpenCV版本要求 | ≥3.0 | ≥4.5(需编译contrib模块) | | 路径检查 | 无自动检查 | 支持`exists()`目录存在性验证 | | 递归遍历 | 需设置`bool recursive`参数 | 同左 | | 通配符灵活性 | 支持`*`和`?` | 同左 | | 跨平台兼容性 | 高 | 高 | --- ### 最佳实践建议 1. **路径规范**:统一使用正斜杠`/`,避免Windows反斜杠转义问题 ```cpp std::string path = "C:/dataset/2023/images/*.jpg"; // 正确 // std::string path = "C:\dataset\images"; // 错误(转义符问题) ``` 2. **内存优化**:大尺寸图像建议逐张处理而非全加载 ```cpp for(const auto& path : imagePaths) { cv::Mat img = cv::imread(path); processImage(img); // 立即处理单张 } ``` 3. **异常处理**:通过`try-catch`捕获读取异常 ```cpp try { cv::Mat img = cv::imread("invalid_path.jpg"); if(img.empty()) throw std::runtime_error("文件损坏或路径错误"); } catch(...) { // 处理异常 } ``` 4. **扩展名过滤**:多格式支持时使用通配符组合 ```cpp cv::glob("input/*.{jpg,png,bmp}", imagePaths); // 读取JPG/PNG/BMP ``` --- ### 常见问题解决 **Q1: 为什么`cv::glob`返回空列表?** - 检查路径权限(确保程序有访问权限) - 验证通配符是否正确(如`*.jpg`匹配扩展名严格区分大小写) - 使用绝对路径替代相对路径 **Q2: 如何实现子目录递归遍历?** 设置`recursive`参数为`true`: ```cpp cv::glob("dataset/**/*.png", imagePaths, true); // **表示递归所有子目录 ``` **Q3: 读取后图像数据为何异常?** - 检查`cv::imread`的第二个参数(如`cv::IMREAD_GRAYSCALE`指定灰度模式) - 验证文件是否损坏(用图片查看器手动打开测试) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钱多多先森

你的鼓励,是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值