2019-08-07 16:44:09 +08:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Helper.cpp
|
|
|
|
|
// MNN
|
|
|
|
|
//
|
|
|
|
|
// Created by MNN on 2019/08/05.
|
|
|
|
|
// Copyright © 2018, Alibaba Group Holding Limited
|
|
|
|
|
//
|
|
|
|
|
#include "Helper.hpp"
|
2019-09-01 19:25:26 +08:00
|
|
|
#if defined(_MSC_VER)
|
|
|
|
|
#include <Windows.h>
|
|
|
|
|
#undef min
|
|
|
|
|
#undef max
|
|
|
|
|
#else
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#endif
|
2019-08-07 16:44:09 +08:00
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
|
|
|
#include "stb_image.h"
|
|
|
|
|
|
2020-03-22 20:16:29 +08:00
|
|
|
std::set<std::string> Helper::gNeedFeatureOp = {"Convolution", "ConvolutionDepthwise", "Eltwise", "Pooling"};
|
2019-08-07 16:44:09 +08:00
|
|
|
|
|
|
|
|
std::set<MNN::OpType> Helper::INT8SUPPORTED_OPS = {
|
2019-08-22 20:13:46 +08:00
|
|
|
MNN::OpType_ConvInt8, MNN::OpType_DepthwiseConvInt8, MNN::OpType_PoolInt8, MNN::OpType_EltwiseInt8,
|
2019-08-07 16:44:09 +08:00
|
|
|
// MNN::OpType_Int8ToFloat,
|
|
|
|
|
// MNN::OpType_FloatToInt8,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::set<std::string> Helper::featureQuantizeMethod = {"KL", "ADMM"};
|
2019-08-22 20:13:46 +08:00
|
|
|
std::set<std::string> Helper::weightQuantizeMethod = {"MAX_ABS", "ADMM"};
|
2019-08-07 16:44:09 +08:00
|
|
|
|
2019-09-01 19:25:26 +08:00
|
|
|
#if !defined(_MSC_VER)
|
2019-08-07 16:44:09 +08:00
|
|
|
bool Helper::fileExist(const std::string& file) {
|
|
|
|
|
struct stat buffer;
|
|
|
|
|
return stat(file.c_str(), &buffer) == 0;
|
|
|
|
|
}
|
2019-09-01 19:25:26 +08:00
|
|
|
#endif
|
2019-08-07 16:44:09 +08:00
|
|
|
|
2019-08-23 12:51:23 +08:00
|
|
|
void Helper::readImages(std::vector<std::string>& images, const std::string& filePath, int* usedImageNum) {
|
2019-08-07 16:44:09 +08:00
|
|
|
int count = 0;
|
2019-09-01 19:25:26 +08:00
|
|
|
#if defined(_MSC_VER)
|
|
|
|
|
WIN32_FIND_DATA ffd;
|
|
|
|
|
HANDLE hFind = INVALID_HANDLE_VALUE;
|
|
|
|
|
hFind = FindFirstFile(filePath.c_str(), &ffd);
|
|
|
|
|
if (INVALID_HANDLE_VALUE == hFind) {
|
|
|
|
|
std::cout << "open " << filePath << " failed: " << strerror(errno) << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
do {
|
|
|
|
|
const std::string fileName = filePath + "\\" + ffd.cFileName;
|
|
|
|
|
if(INVALID_FILE_ATTRIBUTES != GetFileAttributes(fileName.c_str()) && GetLastError() != ERROR_FILE_NOT_FOUND) {
|
|
|
|
|
if (*usedImageNum == 0) {
|
|
|
|
|
// use all images in the folder
|
|
|
|
|
images.push_back(fileName);
|
|
|
|
|
count++;
|
|
|
|
|
} else if (count < *usedImageNum) {
|
|
|
|
|
// use usedImageNum images
|
|
|
|
|
images.push_back(fileName);
|
|
|
|
|
count++;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (FindNextFile(hFind, &ffd) != 0);
|
|
|
|
|
FindClose(hFind);
|
|
|
|
|
#else
|
|
|
|
|
DIR* root = opendir(filePath.c_str());
|
2019-08-07 16:44:09 +08:00
|
|
|
if (root == NULL) {
|
|
|
|
|
MNN_ERROR("open %s failed!\n", filePath.c_str());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
struct dirent* ent = readdir(root);
|
|
|
|
|
while (ent != NULL) {
|
|
|
|
|
if (ent->d_name[0] != '.') {
|
|
|
|
|
const std::string fileName = filePath + "/" + ent->d_name;
|
|
|
|
|
if (fileExist(fileName)) {
|
|
|
|
|
// std::cout << "==> " << fileName << std::endl;
|
|
|
|
|
// DLOG(INFO) << fileName;
|
2019-08-23 12:51:23 +08:00
|
|
|
if (*usedImageNum == 0) {
|
2019-08-07 16:44:09 +08:00
|
|
|
// use all images in the folder
|
|
|
|
|
images.push_back(fileName);
|
|
|
|
|
count++;
|
2019-08-23 12:51:23 +08:00
|
|
|
} else if (count < *usedImageNum) {
|
2019-08-07 16:44:09 +08:00
|
|
|
// use usedImageNum images
|
|
|
|
|
images.push_back(fileName);
|
|
|
|
|
count++;
|
2019-08-22 20:13:46 +08:00
|
|
|
} else {
|
2019-08-07 16:44:09 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ent = readdir(root);
|
|
|
|
|
}
|
2019-09-01 19:25:26 +08:00
|
|
|
#endif
|
2019-08-23 12:51:23 +08:00
|
|
|
if (*usedImageNum == 0) {
|
|
|
|
|
*usedImageNum = count;
|
|
|
|
|
}
|
2019-08-07 16:44:09 +08:00
|
|
|
DLOG(INFO) << "used image num: " << images.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Helper::preprocessInput(MNN::CV::ImageProcess* pretreat, int targetWidth, int targetHeight,
|
2019-08-22 20:13:46 +08:00
|
|
|
const std::string& inputImageFileName, MNN::Tensor* input) {
|
2019-08-07 16:44:09 +08:00
|
|
|
int originalWidth, originalHeight, comp;
|
|
|
|
|
auto bitmap32bits = stbi_load(inputImageFileName.c_str(), &originalWidth, &originalHeight, &comp, 4);
|
|
|
|
|
|
|
|
|
|
DCHECK(bitmap32bits != nullptr) << "input image error!";
|
|
|
|
|
MNN::CV::Matrix trans;
|
|
|
|
|
// choose resize or crop
|
|
|
|
|
// resize method
|
|
|
|
|
trans.setScale((float)(originalWidth - 1) / (float)(targetWidth - 1),
|
|
|
|
|
(float)(originalHeight - 1) / (float)(targetHeight - 1));
|
|
|
|
|
// crop method
|
|
|
|
|
// trans.setTranslate(16.0f, 16.0f);
|
2019-12-31 10:36:59 +08:00
|
|
|
pretreat->setMatrix(trans);
|
2019-08-07 16:44:09 +08:00
|
|
|
pretreat->convert(bitmap32bits, originalWidth, originalHeight, 0, input);
|
|
|
|
|
|
|
|
|
|
stbi_image_free(bitmap32bits);
|
2019-08-22 20:13:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Helper::invertData(float* dst, const float* src, int size) {
|
|
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
|
if (src[i] == .0f) {
|
|
|
|
|
dst[i] = 0.0f;
|
|
|
|
|
} else {
|
|
|
|
|
dst[i] = 1.0 / src[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|