总结一下关于图片批量处理方法,仅作参考。
批量处理文件夹下所有的图片
以彩色图像灰度化为例.
参考代码
int main(int argc,char** argv){
WIN32_FIND_DATAA FileData;
HANDLE hFind;
hFind = FindFirstFileA((LPCSTR)"Imgs/*.jpg",&FileData);
if (hFind == INVALID_HANDLE_VALUE){
printf ("Invalid File Handle. GetLastError reports %d\n", GetLastError ());
return 0;
}
while (FindNextFileA(hFind, &FileData)){
cout<<FileData.cFileName<<endl;
string name("Imgs/");
name.append(FileData.cFileName);
IplImage* src=cvLoadImage(name.c_str());
if (!src){
cout<<"failed to load image"<<endl; //API
//AfxMessageBox("failed to load image"); //MFC
break;
}
assert(src->nChannels==3);
// 处理
IplImage* srcGray = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src,srcGray,CV_BGR2GRAY);
// 保存
name.append(".srcGray.jpg");
cvSaveImage(name.c_str(),srcGray);
cvReleaseImage(&src);
cvReleaseImage(&srcGray);
}
FindClose(&hFind);
return 0;
}
opencv图片实现格式转换,并使用批处理实现批量转换
#include <stdio.h>
int main( int argc, char** argv ){
IplImage* src;
// -1: the loaded image will be loaded as is (with number of channels depends on the file).
if(argc != 3){
printf("CONV: Image format convertion, support JPG,BMP,TIF,PNG,PPM\n");
printf("Usage: conv srcImage dstImage\n");
return 0;
}
if((strstr(argv[1],".jpg")==NULL&&strstr(argv[1],".bmp")==NULL&&strstr(argv[1],".tif")==NULL
&&strstr(argv[1],".png")==NULL&&strstr(argv[1],".ppm")==NULL&&strstr(argv[1],".JPG")==NULL
&&strstr(argv[1],".BMP")==NULL&& strstr(argv[1],".TIF")==NULL&&strstr(argv[1],".PNG")==NULL
&&strstr(argv[1],".PPM")==NULL)||(strstr(argv[2],".jpg")==NULL&&strstr(argv[2],".bmp")==NULL
&&strstr(argv[2],".tif")==NULL&&strstr(argv[2],".png")==NULL&&strstr(argv[2],".ppm")==NULL)){
printf("WARNING: CONV only support JPG,BMP,TIF,PNG,TGA and PPM\n");
}
else{
if( (src=cvLoadImage(argv[1], -1))!= 0 ) {
cvSaveImage( argv[2], src);
cvReleaseImage(&src);
printf("\n Convert successfully.\n");
}
else{
printf("\n*** Read or write image fails *** \n");
}
}
return 0;
}
bat_run.bat文件
@echo off
for /r .\src %%I in (*.jpg *.png *.bmp) do ImageCovert.exe %%I .\dst\%%~nI.bmp
pause
遍历读取指定文件夹下指定类型的所有文件
#include "stdafx.h"
#include "windows.h"
#include <vector>
#include <string>
#include "iostream"
using namespace std;
typedef std::vector<std::string> file_lists;
static int str_compare(const void *arg1, const void *arg2){
return strcmp((*(std::string*)arg1).c_str(), (*(std::string*)arg2).c_str());
}
file_lists ScanDirectory(const std::string &path, const std::string &extension){
//WIN32_FIND_DATA:Contains information about the file that is found by the
//FindFirstFile, FindFirstFileEx, or FindNextFile function
WIN32_FIND_DATA wfd;WIN32_FIND_DATA wfd;
HANDLE hHandle;
string searchPath, searchFile;
file_lists vFilenames;
int nbFiles = 0;
searchPath = path + "/*" + extension;
//Searches a directory for a file or subdirectory
//with a name that matches a specific name
hHandle = FindFirstFile(searchPath.c_str(), &wfd);
if (INVALID_HANDLE_VALUE == hHandle){
fprintf(stderr, "ERROR(%s, %d): Cannot find (*.%s)files in directory %s/n",
__FILE__, __LINE__, extension.c_str(), path.c_str());
exit(0);
}
do{
//. or ..
if (wfd.cFileName[0] == '.'){
continue;
}
// if exists sub-directory
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
//dwFileAttributes:The file attributes of a file
//FILE_ATTRIBUTE_DIRECTORY:The handle identifies a directory
continue;
}
else{//if file
searchFile = path + "/" + wfd.cFileName;
vFilenames.push_back(searchFile);
nbFiles++;
}
}while (FindNextFile(hHandle, &wfd));
//Call this member function to continue a file search begun
//with a call to CGopherFileFind::FindFile
FindClose(hHandle);
//Closes a file search handle opened by the FindFirstFile, FindFirstFileEx,
//or FindFirstStreamW function
// sort the filenames
qsort((void *)&(vFilenames[0]),(size_t)nbFiles,sizeof(string),str_compare);
//Performs a quick sort
return vFilenames;
}
int _tmain(int argc, _TCHAR* argv[]){
file_lists files = ScanDirectory("..\\TestGroup", ".jpg");
if (files.empty()){
cout<<"no image file find in current directory.."<<endl;
system("pause");
exit(-1);
}
int size = files.size();
cout<<"there are "<<size<<" image files totally...."<<endl;
for (int i=0; i<size; i++){
cout<<files[i].c_str()<<endl;
}
system("pause");
return 0;
}
图片批量归一化处理
#include <cv.h>
#include <highgui.h>
#include <fstream>
#include <string>
#include <vector>
#define LB_TEST
using namespace std;
//read images from the specified directory
void readAllImages(vector<IplImage*>& imgvec)//
CvSeq* readAllImages(){
// Save Filenames to imagelist.txt in the specified directory
system("dir/B .\\new > imagelist.txt");
ifstream infile("imagelist.txt");//
CvMemStorage* mem = cvCreateMemStorage(0);//
CvSeq* imSeq = cvCreateSeq(CV_SEQ_ELTYPE_PTR, sizeof(CvSeq), sizeof(IplImage*), mem);
string filename;
while (getline(infile, filename)) {
filename = "new\\" + filename;
IplImage* image = cvLoadImage(filename.c_str()); //
cvSeqPush(imSeq, &image);
imgvec.push_back(image);
}
infile.close();
// return imSeq;
}
// release images memory
void releaseImages(vector<IplImage*>& imgvec){
for (vector<IplImage*>::iterator it = imgvec.begin(); it != imgvec.end(); ++it) {
cvReleaseImage(&(*it));
}
imgvec.clear();
}
// 需要改写
void imageNorm(vector<IplImage*>& imgvec,CvRect rect, bool roiFlag = false){
if (roiFlag) {
for (vector<IplImage*>::iterator it = imgvec.begin(); it != imgvec.end(); ++it) {
// 添加动态获取ROI区域的函数(待补充)
cvSetImageROI(*it, rect);
// 此处只处理感兴趣区域
cvResetImageROI(*it);
}
}
else {
for (vector<IplImage*>::iterator it = imgvec.begin(); it != imgvec.end(); ++it) {
IplImage* imgTemp = cvCreateImage(cvSize(rect.width, rect.height), IPL_DEPTH_8U, 3);
cvResize(*it, imgTemp);
cvReleaseImage(&(*it));
*it = imgTemp;
}
}
}
int main(int argc, char** argv){
//
CvSeq* test = NULL;
vector<IplImage*> imgvec;
cvNamedWindow("test");
readAllImages(imgvec);
#ifdef LB_TEST
CvRect rect = cvRect(0, 0, 80, 60);
imageNorm(imgvec, rect);
for (vector<IplImage*>::iterator it = imgvec.begin(); it != imgvec.end(); ++it) {
cvShowImage("test", *it);
cvWaitKey(0);
}
#endif//
test = readAllImages();//
cvShowImage("test", (IplImage*)cvGetSeqElem(test, 1));
/*for (int i = 0; i < test->total; i++) { }*/
cvDestroyWindow("test");
releaseImages(imgvec);
return 0;
}
读取文件夹连续图片
char filename[100];
char windowname[100];
IplImage* pScr;
unsigned char *Readfigsmethod1(int num)// 读入num个图片
{
for(int i=1;i<=num;i++)
{
sprintf(filename,"%d.jpg",i);// 将图片以数字命名:例如1.jpg 2.jpg等,放入文件夹下
sprintf(windowname,"window%d.jpg",i);
pScr=cvLoadImage(filename,1);//导入图片
cvNamedWindow(windowname,CV_WINDOW_AUTOSIZE);
cvShowImage(windowname,pScr);//显示图片
//cvWaitKey(0);
}
cvWaitKey(0);
cvReleaseImage(&pScr);//释放图片
cvDestroyAllWindows();//销毁窗口
return 0;
}
注释:连续读取图片主要问题在于filename指向图片目录, sprintf(filename,"%d.jpg",i)的使用可以使得filename可以从1.jpg,2.jpg,一直到num.jpg. filename=i.jpg.
关于Computer Vision更多讨论与交流,敬请关注本博客和新浪微博songzi_tea.