C++ 并行地从文件中读取图像
我有这个函数从数据集中读取负片图像(大约122000) 无效加载图像(常量字符串和目录名,向量C++ 并行地从文件中读取图像,c++,image,opencv,parallel-processing,C++,Image,Opencv,Parallel Processing,我有这个函数从数据集中读取负片图像(大约122000) 无效加载图像(常量字符串和目录名,向量和img lst,bool showImages=false) { 向量文件; glob(dirname,files); 对于(size_t i=0;i
class parReader
{
public:
parReader(std::string dirname, std::vector< cv::Mat > & lst);
private:
size_t filesIdx;
HANDLE hFilesMux,hImgListMux;
std::vector<cv::String> files;
std::vector<cv::Mat> img_lst;
static void readImgs(parReader *nm);
const char *getNext();
void push_back(cv::Mat &img);
};
parReader::parReader(std::string dirname, std::vector<cv::Mat> & lst) :img_lst(lst), filesIdx(0),hFilesMux(NULL),hImgListMux(NULL)
{
hFilesMux = CreateMutex(NULL, 0, NULL);
hImgListMux = CreateMutex(NULL, 0, NULL);
cv::glob(dirname, files);
std::thread pr1(readImgs, this);
std::thread pr2(readImgs, this);
std::thread pr3(readImgs, this);
std::thread pr4(readImgs, this);
pr1.join();
pr2.join();
pr3.join();
pr4.join();
CloseHandle(hFilesMux);
CloseHandle(hImgListMux);
}
const char *parReader::getNext()
{
const char *res = NULL;
WaitForSingleObject(hFilesMux, INFINITE);
if (filesIdx < files.size())
res = files[filesIdx++].c_str();
ReleaseMutex(hFilesMux);
return res;
}
void parReader::push_back(cv::Mat &img)
{
WaitForSingleObject(hImgListMux, INFINITE);
img_lst.push_back(img);
ReleaseMutex(hImgListMux);
}
void parReader::readImgs(parReader *nm)
{
while (true)
{
const char *fn = nm->getNext();
if (fn == NULL) break;
cv::Mat img = cv::imread(fn);
if (img.empty()) // treci peste daca este imagine invalida
{
std::cout << fn << " is invalid!" << std::endl;
continue;
}
nm->push_back(img);
}
}
int main()
{
std::vector<cv::Mat> imgList;
parReader mgr("*.png",imgList);
}
类读取器
{
公众:
parReader(std::string dirname,std::vector&lst);
私人:
大小\u t文件IDX;
处理Hflesmux、hImgListMux;
std::矢量文件;
std::向量img_lst;
静态空隙读数(帕雷德尔*纳米);
常量char*getNext();
无效推回(cv::Mat和img);
};
parReader::parReader(std::string dirname,std::vector&lst):img_lst(lst),filesIdx(0),hFilesMux(NULL),hImgListMux(NULL)
{
hFilesMux=CreateMutex(NULL,0,NULL);
hImgListMux=CreateMutex(NULL,0,NULL);
cv::glob(目录名、文件);
std::线程pr1(readImgs,this);
std::线程pr2(readImgs,this);
std::线程pr3(readImgs,this);
std::线程pr4(readImgs,this);
pr1.join();
pr2.join();
pr3.join();
pr4.join();
闭合手柄(hFilesMux);
闭柄(hImgListMux);
}
常量char*parReader::getNext()
{
const char*res=NULL;
WaitForSingleObject(HFilesMax,无限);
if(filesIdxgetNext();
如果(fn==NULL)中断;
cv::Mat img=cv::imread(fn);
if(img.empty())//treci peste daca este imagine invalida
{
你可以试试这个
class parReader
{
public:
parReader(std::string dirname, std::vector< cv::Mat > & lst);
private:
size_t filesIdx;
HANDLE hFilesMux,hImgListMux;
std::vector<cv::String> files;
std::vector<cv::Mat> img_lst;
static void readImgs(parReader *nm);
const char *getNext();
void push_back(cv::Mat &img);
};
parReader::parReader(std::string dirname, std::vector<cv::Mat> & lst) :img_lst(lst), filesIdx(0),hFilesMux(NULL),hImgListMux(NULL)
{
hFilesMux = CreateMutex(NULL, 0, NULL);
hImgListMux = CreateMutex(NULL, 0, NULL);
cv::glob(dirname, files);
std::thread pr1(readImgs, this);
std::thread pr2(readImgs, this);
std::thread pr3(readImgs, this);
std::thread pr4(readImgs, this);
pr1.join();
pr2.join();
pr3.join();
pr4.join();
CloseHandle(hFilesMux);
CloseHandle(hImgListMux);
}
const char *parReader::getNext()
{
const char *res = NULL;
WaitForSingleObject(hFilesMux, INFINITE);
if (filesIdx < files.size())
res = files[filesIdx++].c_str();
ReleaseMutex(hFilesMux);
return res;
}
void parReader::push_back(cv::Mat &img)
{
WaitForSingleObject(hImgListMux, INFINITE);
img_lst.push_back(img);
ReleaseMutex(hImgListMux);
}
void parReader::readImgs(parReader *nm)
{
while (true)
{
const char *fn = nm->getNext();
if (fn == NULL) break;
cv::Mat img = cv::imread(fn);
if (img.empty()) // treci peste daca este imagine invalida
{
std::cout << fn << " is invalid!" << std::endl;
continue;
}
nm->push_back(img);
}
}
int main()
{
std::vector<cv::Mat> imgList;
parReader mgr("*.png",imgList);
}
类读取器
{
公众:
parReader(std::string dirname,std::vector&lst);
私人:
大小\u t文件IDX;
处理Hflesmux、hImgListMux;
std::矢量文件;
std::向量img_lst;
静态空隙读数(帕雷德尔*纳米);
常量char*getNext();
无效推回(cv::Mat和img);
};
parReader::parReader(std::string dirname,std::vector&lst):img_lst(lst),filesIdx(0),hFilesMux(NULL),hImgListMux(NULL)
{
hFilesMux=CreateMutex(NULL,0,NULL);
hImgListMux=CreateMutex(NULL,0,NULL);
cv::glob(目录名、文件);
std::线程pr1(readImgs,this);
std::线程pr2(readImgs,this);
std::线程pr3(readImgs,this);
std::线程pr4(readImgs,this);
pr1.join();
pr2.join();
pr3.join();
pr4.join();
闭合手柄(hFilesMux);
闭柄(hImgListMux);
}
常量char*parReader::getNext()
{
const char*res=NULL;
WaitForSingleObject(HFilesMax,无限);
if(filesIdxgetNext();
如果(fn==NULL)中断;
cv::Mat img=cv::imread(fn);
if(img.empty())//treci peste daca este imagine invalida
{
std::cout我稍微更改了您的代码,以使用OpenMP并行加载-实际更改最小-我只是在for
循环之前放置一个OpenMPpragma
,并序列化访问图像向量,因为向量不是线程安全的
#include <iostream>
#include <vector>
#include <mutex>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void load_images(int start,int end){
vector<Mat>img_lst;
mutex mtx;
#pragma omp parallel for
for(size_t i=start;i<=end;i++){
char filename[16];
sprintf(filename,"%d.jpg",i);
Mat img = imread(filename);
if (img.empty()){
cerr << "ERROR: Failed to load " << filename << endl;
}
mtx.lock();
img_lst.push_back(img);
mtx.unlock();
}
mtx.lock();
cout << "INFO: Loaded " << img_lst.size() << endl;
mtx.unlock();
}
int
main(int argc,char*argv[])
{
load_images(1,122000);
}
加载122000个图像的时间根据下表中我使用的线程数而变化:
Threads Time (s)
================
1 44
2 23
4 12.4
8 8.8
然后,我决定,如果你经常这么做,你可能会想提前付出一点代价来进一步提高时间。因此,与其用CPU密集型代码来解压JPEG,不如将图像转换一次,转换为更简单的读取格式,例如。因此,我将所有JPEG图像转换为pNM使用GNU并行,然后加载PNM图像:
这看起来像:
seq 122000 | parallel convert {}.jpg {}.pnm
代码是:
...
...
#pragma omp parallel for
for(size_t i=start;i<=end;i++){
char filename[16];
sprintf(filename,"%d.pnm",i); <--- ONLY LINE CHANGED
Mat img = imread(filename);
...
...
要使用OpenMP进行编译,请使用:
g++ -fopenmp =O3 -march native ...
我稍微修改了您的代码,以使用OpenMP并行加载-实际更改最小-我只是在for
循环之前放置了一个OpenMPpragma
,并序列化了对图像向量的访问,因为向量不是线程安全的
#include <iostream>
#include <vector>
#include <mutex>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void load_images(int start,int end){
vector<Mat>img_lst;
mutex mtx;
#pragma omp parallel for
for(size_t i=start;i<=end;i++){
char filename[16];
sprintf(filename,"%d.jpg",i);
Mat img = imread(filename);
if (img.empty()){
cerr << "ERROR: Failed to load " << filename << endl;
}
mtx.lock();
img_lst.push_back(img);
mtx.unlock();
}
mtx.lock();
cout << "INFO: Loaded " << img_lst.size() << endl;
mtx.unlock();
}
int
main(int argc,char*argv[])
{
load_images(1,122000);
}
加载122000个图像的时间根据下表中我使用的线程数而变化:
Threads Time (s)
================
1 44
2 23
4 12.4
8 8.8
然后,我决定,如果你经常这么做,你可能会想提前付出一点代价来进一步提高时间。因此,与其用CPU密集型代码来解压JPEG,不如将图像转换一次,转换为更简单的读取格式,例如。因此,我将所有JPEG图像转换为pNM使用GNU并行,然后加载PNM图像:
这看起来像:
seq 122000 | parallel convert {}.jpg {}.pnm
代码是:
...
...
#pragma omp parallel for
for(size_t i=start;i<=end;i++){
char filename[16];
sprintf(filename,"%d.pnm",i); <--- ONLY LINE CHANGED
Mat img = imread(filename);
...
...
要使用OpenMP进行编译,请使用:
g++ -fopenmp =O3 -march native ...
CUDA无法进行文件I/O,因此不可能不使用CUDAgood来了解,谢谢:)图像的尺寸以像素为单位是多少?以kB为单位是多少?你到底打算如何处理122000个图像,一次全部存储在内存中?你的磁盘速度是否很快,文件是否分布在多个文件系统和驱动器上?你使用的是什么操作系统?安装了多少RAMed?我在试着训练Hog,20kb*122000,96x120我想你可以试着并行启动4个线程看看是否有帮助…CUDA不能做文件I/O,所以不可能不用CUDAgood知道谢谢:)图像的像素尺寸是多少?以kB为单位?耳朵上是什么