Stat() 函数 returns 值为 -1,因此无法访问文件属性。我该如何纠正这个问题?
Stat() function returns value -1 and thus, file attributes cannot be accessed. How do I correct this?
此代码是使用OpenCV进行人脸识别的训练代码。它裁剪和均衡图像以仅包含脸部。
唯一发生的错误是 stat() 函数 returns 值为 -1 并且未访问 D:\Project\Original 下的文件。
The output of the following is:
-1 Cannot access Folder1
请帮助我理解为什么会这样。当使用 OpenCV 2.4.9
在 CodeBlocks 16.01 上编译相同代码(稍作更改)时,不会发生此错误
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <string>
#include <string.h>
#include <fstream>
#include <string.h>
#include <direct.h>
#include <dirent.h>
#include <opencv/cv.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
using namespace std;
using namespace cv;
char* IMG_SEP = "_";
int MAX_IMAGE_NAME_SIZE = 100;
int IM_HEIGHT = 200;
int IM_WIDTH = 200;
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
vector<string> fileNames;
vector<string> outputLabel;
vector<string> outputPath;
char* srcDirName = "D:/Project/Original";
char* dstDirName = "D:/Project/Cropped";
char* CSV_PATH = "D:/Project/Cropped/myCSV.csv";
void getFileNames(char* path) {
DIR *dir;
struct stat info;
struct dirent *ent;
if ((dir = opendir(path)) != NULL) {
while ((ent = readdir(dir)) != NULL) {
if ((!strcmp(ent->d_name, ".") == 0) && (!strcmp(ent->d_name, "..") == 0)) {
char* temp = (char*)malloc(256);
sprintf_s(temp, 100, "%s%s", path, ent->d_name);
// THIS IS WHERE THE DEBUGGER GOES. STAT RETURNS -1
if (stat(temp, &info) != 0) {
cout << stat(temp, &info) << " ";
cout << "Cannot access " << ent->d_name << "\n";
}
if (info.st_mode & S_IFREG) {
string temp1 = ent->d_name;
temp1 = temp1.substr(0, temp1.rfind(IMG_SEP));
temp1 = dstDirName + temp1;
_mkdir(temp1.c_str());
fileNames.push_back(temp);
}
else if (info.st_mode & S_IFDIR) {
char* temp1 = (char*)malloc(256);
sprintf_s(temp1, 100, "%s/%s", dstDirName, ent->d_name);
_mkdir(temp1);
strcat_s(temp, sizeof temp, "/");
getFileNames(temp);
}
}
}
closedir(dir);
}
else {
cout << "Could not open the required image directory";
}
}
void printVector(vector<string> images) {
for (int i = 0; i < images.size(); i++) {
cout << images[i] << "\n";
}
}
void initializeDetector() {
if (!face_cascade.load(face_cascade_name)) {
cout << "Error while loading the face detection cascade classifier";
}
if (!eyes_cascade.load(eyes_cascade_name)) {
cout << "Error while loading the eye detection cascade classifier";
}
}
void detectAndStore(Mat image, String imageName) {
vector<Rect> faces;
vector<Rect> eyes;
Mat frame_grey;
cvtColor(image, frame_grey, CV_BGR2GRAY);
equalizeHist(frame_grey, frame_grey);
face_cascade.detectMultiScale(frame_grey, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//if(faces.size() == 1){
for (size_t i = 0; i < faces.size(); i++) {
Mat faceROI = frame_grey(faces[i]);
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
if (eyes.size() < 1) {
continue;
}
resize(faceROI, faceROI, Size(IM_WIDTH, IM_HEIGHT), 1.0, 1.0, INTER_CUBIC);
String fileName = imageName;
int posBeg = fileName.rfind('/') + 1;
String label = fileName.substr(posBeg, MAX_IMAGE_NAME_SIZE);
int posEnd = label.rfind('.');
String labelNameWithNum = label.substr(0, posEnd);
cout << "Cropping and storing " << labelNameWithNum << "\n";
int pos = labelNameWithNum.rfind(IMG_SEP);
String labelNameWithoutNum = labelNameWithNum.substr(0, pos);
String destination = dstDirName + labelNameWithoutNum + "/" + label;
outputPath.push_back(destination);
outputLabel.push_back(labelNameWithoutNum);
equalizeHist(faceROI, faceROI);
imwrite(destination, faceROI);
break;
}
}
void processImages() {
initializeDetector();
for (int i = 0; i < fileNames.size(); i++) {
Mat image = imread(fileNames[i], CV_LOAD_IMAGE_COLOR);
detectAndStore(image, fileNames[i]);
}
}
void createCSV() {
ofstream myFile;
myFile.open(CSV_PATH, ios_base::out);
for (int i = 0; i < outputPath.size(); i++) {
myFile << outputPath[i] << ";" << outputLabel[i] << "\n";
}
myFile.close();
}
int main() {
getFileNames(srcDirName);
processImages();
createCSV();
return 0;
}
sprintf_s(temp, 100, "%s%s", path, ent->d_name);
->
sprintf_s(temp, 100, "%s/%s", path, ent->d_name);
(加斜杠)
这是通过检查 "temp" 在失败统计点处进行的简单调试。
由于 dirent 没有随 MSVC 一起提供,也许它是您粘贴的 dirent.h 中的错误..但您稍后使用 ent->d_name 执行了 %s/%s,并且 "path" 来自您的硬编码常量,所以我认为您在从 "code blocks"
移植时犯了一个错误
由于您使用的是 OpenCV 3.1,因此可以使用 glob。这避免了像您这样的复杂代码及其错误。
您的 getFileNames
基本上减少为:
vector<cv::String> fileNames; // This must be a cv::String now
...
void getFileNames(std::string path)
{
cv::glob(path,fileNames,false);
}
您可以看到 glob
用于许多其他答案,例如here.
此代码是使用OpenCV进行人脸识别的训练代码。它裁剪和均衡图像以仅包含脸部。 唯一发生的错误是 stat() 函数 returns 值为 -1 并且未访问 D:\Project\Original 下的文件。
The output of the following is:
-1 Cannot access Folder1
请帮助我理解为什么会这样。当使用 OpenCV 2.4.9
在 CodeBlocks 16.01 上编译相同代码(稍作更改)时,不会发生此错误#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <string>
#include <string.h>
#include <fstream>
#include <string.h>
#include <direct.h>
#include <dirent.h>
#include <opencv/cv.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
using namespace std;
using namespace cv;
char* IMG_SEP = "_";
int MAX_IMAGE_NAME_SIZE = 100;
int IM_HEIGHT = 200;
int IM_WIDTH = 200;
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
vector<string> fileNames;
vector<string> outputLabel;
vector<string> outputPath;
char* srcDirName = "D:/Project/Original";
char* dstDirName = "D:/Project/Cropped";
char* CSV_PATH = "D:/Project/Cropped/myCSV.csv";
void getFileNames(char* path) {
DIR *dir;
struct stat info;
struct dirent *ent;
if ((dir = opendir(path)) != NULL) {
while ((ent = readdir(dir)) != NULL) {
if ((!strcmp(ent->d_name, ".") == 0) && (!strcmp(ent->d_name, "..") == 0)) {
char* temp = (char*)malloc(256);
sprintf_s(temp, 100, "%s%s", path, ent->d_name);
// THIS IS WHERE THE DEBUGGER GOES. STAT RETURNS -1
if (stat(temp, &info) != 0) {
cout << stat(temp, &info) << " ";
cout << "Cannot access " << ent->d_name << "\n";
}
if (info.st_mode & S_IFREG) {
string temp1 = ent->d_name;
temp1 = temp1.substr(0, temp1.rfind(IMG_SEP));
temp1 = dstDirName + temp1;
_mkdir(temp1.c_str());
fileNames.push_back(temp);
}
else if (info.st_mode & S_IFDIR) {
char* temp1 = (char*)malloc(256);
sprintf_s(temp1, 100, "%s/%s", dstDirName, ent->d_name);
_mkdir(temp1);
strcat_s(temp, sizeof temp, "/");
getFileNames(temp);
}
}
}
closedir(dir);
}
else {
cout << "Could not open the required image directory";
}
}
void printVector(vector<string> images) {
for (int i = 0; i < images.size(); i++) {
cout << images[i] << "\n";
}
}
void initializeDetector() {
if (!face_cascade.load(face_cascade_name)) {
cout << "Error while loading the face detection cascade classifier";
}
if (!eyes_cascade.load(eyes_cascade_name)) {
cout << "Error while loading the eye detection cascade classifier";
}
}
void detectAndStore(Mat image, String imageName) {
vector<Rect> faces;
vector<Rect> eyes;
Mat frame_grey;
cvtColor(image, frame_grey, CV_BGR2GRAY);
equalizeHist(frame_grey, frame_grey);
face_cascade.detectMultiScale(frame_grey, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//if(faces.size() == 1){
for (size_t i = 0; i < faces.size(); i++) {
Mat faceROI = frame_grey(faces[i]);
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
if (eyes.size() < 1) {
continue;
}
resize(faceROI, faceROI, Size(IM_WIDTH, IM_HEIGHT), 1.0, 1.0, INTER_CUBIC);
String fileName = imageName;
int posBeg = fileName.rfind('/') + 1;
String label = fileName.substr(posBeg, MAX_IMAGE_NAME_SIZE);
int posEnd = label.rfind('.');
String labelNameWithNum = label.substr(0, posEnd);
cout << "Cropping and storing " << labelNameWithNum << "\n";
int pos = labelNameWithNum.rfind(IMG_SEP);
String labelNameWithoutNum = labelNameWithNum.substr(0, pos);
String destination = dstDirName + labelNameWithoutNum + "/" + label;
outputPath.push_back(destination);
outputLabel.push_back(labelNameWithoutNum);
equalizeHist(faceROI, faceROI);
imwrite(destination, faceROI);
break;
}
}
void processImages() {
initializeDetector();
for (int i = 0; i < fileNames.size(); i++) {
Mat image = imread(fileNames[i], CV_LOAD_IMAGE_COLOR);
detectAndStore(image, fileNames[i]);
}
}
void createCSV() {
ofstream myFile;
myFile.open(CSV_PATH, ios_base::out);
for (int i = 0; i < outputPath.size(); i++) {
myFile << outputPath[i] << ";" << outputLabel[i] << "\n";
}
myFile.close();
}
int main() {
getFileNames(srcDirName);
processImages();
createCSV();
return 0;
}
sprintf_s(temp, 100, "%s%s", path, ent->d_name);
->
sprintf_s(temp, 100, "%s/%s", path, ent->d_name);
(加斜杠)
这是通过检查 "temp" 在失败统计点处进行的简单调试。
由于 dirent 没有随 MSVC 一起提供,也许它是您粘贴的 dirent.h 中的错误..但您稍后使用 ent->d_name 执行了 %s/%s,并且 "path" 来自您的硬编码常量,所以我认为您在从 "code blocks"
移植时犯了一个错误由于您使用的是 OpenCV 3.1,因此可以使用 glob。这避免了像您这样的复杂代码及其错误。
您的 getFileNames
基本上减少为:
vector<cv::String> fileNames; // This must be a cv::String now
...
void getFileNames(std::string path)
{
cv::glob(path,fileNames,false);
}
您可以看到 glob
用于许多其他答案,例如here.