Browse Source

c++03 compiler happy

tags/20200226
nihui 6 years ago
parent
commit
05ab6813f5
4 changed files with 217 additions and 205 deletions
  1. +26
    -35
      tools/CMakeLists.txt
  2. +13
    -9
      tools/quantize/CMakeLists.txt
  3. +14
    -14
      tools/quantize/ncnn2int8.cpp
  4. +164
    -147
      tools/quantize/ncnn2table.cpp

+ 26
- 35
tools/CMakeLists.txt View File

@@ -1,35 +1,26 @@
add_subdirectory(caffe)
add_subdirectory(mxnet)
add_subdirectory(onnx)
find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs)
if(NOT OpenCV_FOUND)
find_package(OpenCV QUIET COMPONENTS core highgui imgproc)
endif()
if(OpenCV_FOUND)
add_subdirectory(quantize)
else()
message(WARNING "OpenCV not found, quantize tools won't be built")
endif()
add_executable(ncnn2mem ncnn2mem.cpp)
target_link_libraries(ncnn2mem PRIVATE ncnn)
if(NCNN_VULKAN)
target_link_libraries(ncnn2mem PRIVATE ${Vulkan_LIBRARY})
endif()
add_executable(ncnnoptimize ncnnoptimize.cpp)
target_link_libraries(ncnnoptimize PRIVATE ncnn)
if(NCNN_VULKAN)
target_link_libraries(ncnnoptimize PRIVATE ${Vulkan_LIBRARY})
endif()
# add all tools to a virtual project group
set_property(TARGET ncnn2mem PROPERTY FOLDER "tools")
set_property(TARGET ncnnoptimize PROPERTY FOLDER "tools")

add_subdirectory(caffe)
add_subdirectory(mxnet)
add_subdirectory(onnx)

add_subdirectory(quantize)

add_executable(ncnn2mem ncnn2mem.cpp)

target_link_libraries(ncnn2mem PRIVATE ncnn)

if(NCNN_VULKAN)
target_link_libraries(ncnn2mem PRIVATE ${Vulkan_LIBRARY})
endif()

add_executable(ncnnoptimize ncnnoptimize.cpp)

target_link_libraries(ncnnoptimize PRIVATE ncnn)

if(NCNN_VULKAN)
target_link_libraries(ncnnoptimize PRIVATE ${Vulkan_LIBRARY})
endif()

# add all tools to a virtual project group
set_property(TARGET ncnn2mem PROPERTY FOLDER "tools")
set_property(TARGET ncnnoptimize PROPERTY FOLDER "tools")

+ 13
- 9
tools/quantize/CMakeLists.txt View File

@@ -1,15 +1,19 @@
find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs)
if(NOT OpenCV_FOUND)
find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc)
find_package(OpenCV QUIET COMPONENTS core highgui imgproc)
endif()

add_executable(ncnn2table ncnn2table.cpp)
target_link_libraries(ncnn2table PRIVATE ncnn ${OpenCV_LIBS})
target_compile_definitions(ncnn2table PRIVATE -DOpenCV_VERSION_MAJOR=${OpenCV_VERSION_MAJOR})
if(OpenCV_FOUND)
add_executable(ncnn2table ncnn2table.cpp)
target_link_libraries(ncnn2table PRIVATE ncnn ${OpenCV_LIBS})
target_compile_definitions(ncnn2table PRIVATE -DOpenCV_VERSION_MAJOR=${OpenCV_VERSION_MAJOR})

add_executable(ncnn2int8 ncnn2int8.cpp)
target_link_libraries(ncnn2int8 PRIVATE ncnn)
add_executable(ncnn2int8 ncnn2int8.cpp)
target_link_libraries(ncnn2int8 PRIVATE ncnn)

# add all ncnn2table and ncnn2int8 tool to a virtual project group
set_property(TARGET ncnn2table PROPERTY FOLDER "tools/optimization")
set_property(TARGET ncnn2int8 PROPERTY FOLDER "tools/optimization")
# add all ncnn2table and ncnn2int8 tool to a virtual project group
set_property(TARGET ncnn2table PROPERTY FOLDER "tools/optimization")
set_property(TARGET ncnn2int8 PROPERTY FOLDER "tools/optimization")
else()
message(WARNING "OpenCV not found, quantize tools won't be built")
endif()

+ 14
- 14
tools/quantize/ncnn2int8.cpp View File

@@ -95,10 +95,10 @@ static bool read_int8scale_table(const char* filepath, std::map<std::string, std
std::vector<float> scales;

std::vector<char>line(102400);
char *pch = nullptr;
char *pch = NULL;
size_t len = 0;

while (nullptr != std::fgets(line.data(), static_cast<int>(line.size()), fp))
while (NULL != std::fgets(line.data(), static_cast<int>(line.size()), fp))
{
float scale = 1.f;
char key[256];
@@ -106,10 +106,10 @@ static bool read_int8scale_table(const char* filepath, std::map<std::string, std

pch = strtok(line.data(), " ");

if (pch == nullptr) break;
if (pch == NULL) break;

bool is_key = true;
while (pch != nullptr)
while (pch != NULL)
{
if (is_key)
{
@@ -125,7 +125,7 @@ static bool read_int8scale_table(const char* filepath, std::map<std::string, std
scales.push_back(scale);
}

pch = strtok(nullptr, " ");
pch = strtok(NULL, " ");
}

// XYZ_param_N pattern
@@ -179,14 +179,14 @@ int NetQuantize::quantize_convolution()
continue;

// find convolution layer
auto iter_data = blob_int8scale_table.find(layers[i]->name);
std::map<std::string, std::vector<float> >::iterator iter_data = blob_int8scale_table.find(layers[i]->name);
if (iter_data == blob_int8scale_table.end())
continue;

char key[256];
sprintf(key, "%s_param_0", layers[i]->name.c_str());

auto iter = weight_int8scale_table.find(key);
std::map<std::string, std::vector<float> >::iterator iter = weight_int8scale_table.find(key);
if (iter == weight_int8scale_table.end())
{
fprintf(stderr, "this layer need to be quantized, but no scale param!\n");
@@ -194,7 +194,7 @@ int NetQuantize::quantize_convolution()
}

// Convolution - quantize weight from fp32 to int8
auto convolution = (ncnn::Convolution*)layers[i];
ncnn::Convolution* convolution = (ncnn::Convolution*)layers[i];

std::vector<float> weight_data_int8_scales = iter->second;

@@ -246,14 +246,14 @@ int NetQuantize::quantize_convolutiondepthwise()
continue;

// find convolutiondepthwise layer
auto iter_data = blob_int8scale_table.find(layers[i]->name);
std::map<std::string, std::vector<float> >::iterator iter_data = blob_int8scale_table.find(layers[i]->name);
if (iter_data == blob_int8scale_table.end())
continue;

char key[256];
sprintf(key, "%s_param_0", layers[i]->name.c_str());

auto iter = weight_int8scale_table.find(key);
std::map<std::string, std::vector<float> >::iterator iter = weight_int8scale_table.find(key);
if (iter == weight_int8scale_table.end())
{
fprintf(stderr, "this layer need to be quantized, but no scale param!\n");
@@ -261,7 +261,7 @@ int NetQuantize::quantize_convolutiondepthwise()
}

// Convolution - quantize weight from fp32 to int8
auto convdw = (ncnn::ConvolutionDepthWise*)layers[i];
ncnn::ConvolutionDepthWise* convdw = (ncnn::ConvolutionDepthWise*)layers[i];

std::vector<float> weight_data_int8_scales = iter->second;

@@ -313,14 +313,14 @@ int NetQuantize::quantize_innerproduct()
continue;

// find InnerProduct layer
auto iter_data = blob_int8scale_table.find(layers[i]->name);
std::map<std::string, std::vector<float> >::iterator iter_data = blob_int8scale_table.find(layers[i]->name);
if (iter_data == blob_int8scale_table.end())
continue;

char key[256];
sprintf(key, "%s_param_0", layers[i]->name.c_str());

auto iter = weight_int8scale_table.find(key);
std::map<std::string, std::vector<float> >::iterator iter = weight_int8scale_table.find(key);
if (iter == weight_int8scale_table.end())
{
fprintf(stderr, "this layer need to be quantized, but no scale param!\n");
@@ -328,7 +328,7 @@ int NetQuantize::quantize_innerproduct()
}

// InnerProduct - quantize weight from fp32 to int8
auto fc = (ncnn::InnerProduct*)layers[i];
ncnn::InnerProduct* fc = (ncnn::InnerProduct*)layers[i];

std::vector<float> weight_data_int8_scales = iter->second;



+ 164
- 147
tools/quantize/ncnn2table.cpp View File

@@ -53,9 +53,10 @@ int parse_images_dir(const std::string& base_path, std::vector<std::string>& fil

cv::glob(base_path_str, image_list, true);

for (auto& image_path : image_list)
for (size_t i = 0; i < image_list.size(); i++)
{
file_path.emplace_back(image_path);
const cv::String& image_path = image_list[i];
file_path.push_back(image_path);
}

return 0;
@@ -78,12 +79,15 @@ public:

int QuantNet::get_input_names()
{
for (auto layer : layers)
for (size_t i = 0; i < layers.size(); i++)
{
const ncnn::Layer* layer = layers[i];

if (layer->type == "Input")
{
for (int blob_index : layer->tops)
for (size_t j = 0; j < layer->tops.size(); j++)
{
int blob_index = layer->tops[j];
std::string name = blobs[blob_index].name;
input_names.push_back(name);
}
@@ -97,7 +101,7 @@ int QuantNet::get_conv_names()
{
for (size_t i = 0; i < layers.size(); i++)
{
const auto layer = layers[i];
const ncnn::Layer* layer = layers[i];

if (layer->type == "Convolution" || layer->type == "ConvolutionDepthWise" || layer->type == "InnerProduct")
{
@@ -112,12 +116,14 @@ int QuantNet::get_conv_names()
int QuantNet::get_conv_bottom_blob_names()
{
// find conv bottom name or index
for (auto layer : layers)
for (size_t i = 0; i < layers.size(); i++)
{
const ncnn::Layer* layer = layers[i];

if (layer->type == "Convolution" || layer->type == "ConvolutionDepthWise" || layer->type == "InnerProduct")
{
auto name = layer->name;
const auto bottom_blob_name = blobs[layer->bottoms[0]].name;
const std::string& name = layer->name;
const std::string& bottom_blob_name = blobs[layer->bottoms[0]].name;
conv_bottom_blob_names[name] = bottom_blob_name;
}
}
@@ -127,29 +133,33 @@ int QuantNet::get_conv_bottom_blob_names()

int QuantNet::get_conv_weight_blob_scales()
{
for (auto layer : layers)
for (size_t i = 0; i < layers.size(); i++)
{
const ncnn::Layer* layer = layers[i];

if (layer->type == "Convolution")
{
const ncnn::Convolution* convolution = static_cast<const ncnn::Convolution*>(layer);

std::string name = layer->name;
const int weight_data_size_output = static_cast<ncnn::Convolution*>(layer)->weight_data_size / static_cast<ncnn::Convolution*>(layer)->num_output;
const int weight_data_size_output = convolution->weight_data_size / convolution->num_output;
std::vector<float> scales;

// int8 winograd F43 needs weight data to use 6bit quantization
bool quant_6bit = false;
int kernel_w = static_cast<ncnn::Convolution*>(layer)->kernel_w;
int kernel_h = static_cast<ncnn::Convolution*>(layer)->kernel_h;
int dilation_w = static_cast<ncnn::Convolution*>(layer)->dilation_w;
int dilation_h = static_cast<ncnn::Convolution*>(layer)->dilation_h;
int stride_w = static_cast<ncnn::Convolution*>(layer)->stride_w;
int stride_h = static_cast<ncnn::Convolution*>(layer)->stride_h;
int kernel_w = convolution->kernel_w;
int kernel_h = convolution->kernel_h;
int dilation_w = convolution->dilation_w;
int dilation_h = convolution->dilation_h;
int stride_w = convolution->stride_w;
int stride_h = convolution->stride_h;

if (kernel_w == 3 && kernel_h == 3 && dilation_w == 1 && dilation_h == 1 && stride_w == 1 && stride_h == 1)
quant_6bit = true;

for (int n = 0; n < static_cast<ncnn::Convolution*>(layer)->num_output; n++)
for (int n = 0; n < convolution->num_output; n++)
{
const ncnn::Mat weight_data_n = static_cast<ncnn::Convolution*>(layer)->weight_data.range(weight_data_size_output * n, weight_data_size_output);
const ncnn::Mat weight_data_n = convolution->weight_data.range(weight_data_size_output * n, weight_data_size_output);
const float *data_n = weight_data_n;
float max_value = std::numeric_limits<float>::min();

@@ -173,13 +183,15 @@ int QuantNet::get_conv_weight_blob_scales()

if (layer->type == "ConvolutionDepthWise")
{
const ncnn::ConvolutionDepthWise* convolutiondepthwise = static_cast<const ncnn::ConvolutionDepthWise*>(layer);

std::string name = layer->name;
const int weight_data_size_output = static_cast<ncnn::ConvolutionDepthWise*>(layer)->weight_data_size / static_cast<ncnn::ConvolutionDepthWise*>(layer)->group;
const int weight_data_size_output = convolutiondepthwise->weight_data_size / convolutiondepthwise->group;
std::vector<float> scales;

for (int n = 0; n < static_cast<ncnn::ConvolutionDepthWise*>(layer)->group; n++)
for (int n = 0; n < convolutiondepthwise->group; n++)
{
const ncnn::Mat weight_data_n = static_cast<ncnn::ConvolutionDepthWise*>(layer)->weight_data.range(weight_data_size_output * n, weight_data_size_output);
const ncnn::Mat weight_data_n = convolutiondepthwise->weight_data.range(weight_data_size_output * n, weight_data_size_output);
const float *data_n = weight_data_n;
float max_value = std::numeric_limits<float>::min();

@@ -196,13 +208,15 @@ int QuantNet::get_conv_weight_blob_scales()

if (layer->type == "InnerProduct")
{
const ncnn::InnerProduct* innerproduct = static_cast<const ncnn::InnerProduct*>(layer);

std::string name = layer->name;
const int weight_data_size_output = static_cast<ncnn::InnerProduct*>(layer)->weight_data_size / static_cast<ncnn::InnerProduct*>(layer)->num_output;
const int weight_data_size_output = innerproduct->weight_data_size / innerproduct->num_output;
std::vector<float> scales;

for (int n = 0; n < static_cast<ncnn::InnerProduct*>(layer)->num_output; n++)
for (int n = 0; n < innerproduct->num_output; n++)
{
const ncnn::Mat weight_data_n = static_cast<ncnn::InnerProduct*>(layer)->weight_data.range(weight_data_size_output * n, weight_data_size_output);
const ncnn::Mat weight_data_n = innerproduct->weight_data.range(weight_data_size_output * n, weight_data_size_output);
const float *data_n = weight_data_n;
float max_value = std::numeric_limits<float>::min();

@@ -288,9 +302,9 @@ int QuantizeData::initial_histogram_interval()

int QuantizeData::initial_histogram_value()
{
for (float& i : histogram)
for (size_t i = 0; i < histogram.size(); i++)
{
i = 0.00001f;
histogram[i] = 0.00001f;
}

return 0;
@@ -298,7 +312,7 @@ int QuantizeData::initial_histogram_value()

int QuantizeData::normalize_histogram()
{
const auto length = histogram.size();
const size_t length = histogram.size();
float sum = 0;

for (size_t i = 0; i < length; i++)
@@ -334,7 +348,7 @@ int QuantizeData::update_histogram(ncnn::Mat data)

float QuantizeData::compute_kl_divergence(const std::vector<float> &dist_a, const std::vector<float> &dist_b) const
{
const auto length = dist_a.size();
const size_t length = dist_a.size();
assert(dist_b.size() == length);
float result = 0;

@@ -381,26 +395,26 @@ int QuantizeData::threshold_distribution(const std::vector<float> &distribution,
// get P
fill(quantize_distribution.begin(), quantize_distribution.end(), 0.0f);

const auto num_per_bin = static_cast<float>(threshold) / static_cast<float>(target_bin);
const float num_per_bin = static_cast<float>(threshold) / static_cast<float>(target_bin);

for (int i = 0; i < target_bin; i++)
{
const auto start = static_cast<float>(i) * num_per_bin;
const auto end = start + num_per_bin;
const float start = static_cast<float>(i) * num_per_bin;
const float end = start + num_per_bin;

const auto left_upper = static_cast<int>(ceil(start));
const int left_upper = static_cast<int>(ceil(start));
if (static_cast<float>(left_upper) > start)
{
const auto left_scale = static_cast<float>(left_upper) - start;
const float left_scale = static_cast<float>(left_upper) - start;
quantize_distribution[i] += left_scale * distribution[left_upper - 1];
}

const auto right_lower = static_cast<int>(floor(end));
const int right_lower = static_cast<int>(floor(end));

if (static_cast<float>(right_lower) < end)
{

const auto right_scale = end - static_cast<float>(right_lower);
const float right_scale = end - static_cast<float>(right_lower);
quantize_distribution[i] += right_scale * distribution[right_lower];
}

@@ -415,8 +429,8 @@ int QuantizeData::threshold_distribution(const std::vector<float> &distribution,

for (int i = 0; i < target_bin; i++)
{
const auto start = static_cast<float>(i) * num_per_bin;
const auto end = start + num_per_bin;
const float start = static_cast<float>(i) * num_per_bin;
const float end = start + num_per_bin;

float count = 0;

@@ -450,7 +464,7 @@ int QuantizeData::threshold_distribution(const std::vector<float> &distribution,
}
}

const auto expand_value = quantize_distribution[i] / count;
const float expand_value = quantize_distribution[i] / count;

if (static_cast<float>(left_upper) > start)
{
@@ -509,7 +523,7 @@ struct PreParam

static int post_training_quantize(const std::vector<std::string>& image_list, const std::string& param_path, const std::string& bin_path, const std::string& table_path, struct PreParam& per_param)
{
auto size = image_list.size();
size_t size = image_list.size();

QuantNet net;
net.opt = g_default_option;
@@ -557,9 +571,9 @@ static int post_training_quantize(const std::vector<std::string>& image_list, co
std::vector<float> weight_scale_n = net.weight_scales[layer_name];

fprintf(fp, "%s_param_0 ", layer_name.c_str());
for (float j : weight_scale_n)
for (size_t j = 0 ; j < weight_scale_n.size(); j++)
{
fprintf(fp, "%f ", j);
fprintf(fp, "%f ", weight_scale_n[j]);
}
fprintf(fp, "\n");
}
@@ -613,11 +627,11 @@ static int post_training_quantize(const std::vector<std::string>& image_list, co
ncnn::Mat out;
ex.extract(blob_name.c_str(), out);

for (auto& quantize_data : quantize_datas)
for (size_t k = 0; k < quantize_datas.size(); k++)
{
if (quantize_data.name == layer_name)
if (quantize_datas[k].name == layer_name)
{
quantize_data.initial_blob_max(out);
quantize_datas[k].initial_blob_max(out);
break;
}
}
@@ -630,13 +644,13 @@ static int post_training_quantize(const std::vector<std::string>& image_list, co
{
std::string layer_name = net.conv_names[i];

for (auto& quantize_data : quantize_datas)
for (size_t k = 0; k < quantize_datas.size(); k++)
{
if (quantize_data.name == layer_name)
if (quantize_datas[k].name == layer_name)
{
quantize_data.initial_histogram_interval();
quantize_datas[k].initial_histogram_interval();

fprintf(stderr, "%-20s : max = %-15f interval = %-10f\n", quantize_data.name.c_str(), quantize_data.max_value, quantize_data.histogram_interval);
fprintf(stderr, "%-20s : max = %-15f interval = %-10f\n", quantize_datas[k].name.c_str(), quantize_datas[k].max_value, quantize_datas[k].histogram_interval);
break;
}
}
@@ -667,19 +681,19 @@ static int post_training_quantize(const std::vector<std::string>& image_list, co
ncnn::Extractor ex = net.create_extractor();
ex.input(net.input_names[0].c_str(), in);

for (size_t k = 0; k < net.conv_names.size(); k++)
for (size_t j = 0; j < net.conv_names.size(); j++)
{
std::string layer_name = net.conv_names[k];
std::string layer_name = net.conv_names[j];
std::string blob_name = net.conv_bottom_blob_names[layer_name];

ncnn::Mat out;
ex.extract(blob_name.c_str(), out);

for (auto& quantize_data : quantize_datas)
for (size_t k = 0; k < quantize_datas.size(); k++)
{
if (quantize_data.name == layer_name)
if (quantize_datas[k].name == layer_name)
{
quantize_data.update_histogram(out);
quantize_datas[k].update_histogram(out);
break;
}
}
@@ -694,18 +708,18 @@ static int post_training_quantize(const std::vector<std::string>& image_list, co
std::string blob_name = net.conv_bottom_blob_names[layer_name];
fprintf(stderr, "%-20s ", layer_name.c_str());

for (auto& quantize_data : quantize_datas)
for (size_t k = 0; k < quantize_datas.size(); k++)
{
if (quantize_data.name == layer_name)
if (quantize_datas[k].name == layer_name)
{
quantize_data.get_data_blob_scale();
quantize_datas[k].get_data_blob_scale();
fprintf(stderr, "bin : %-8d threshold : %-15f interval : %-10f scale : %-10f\n",
quantize_data.threshold_bin,
quantize_data.threshold,
quantize_data.histogram_interval,
quantize_data.scale);
quantize_datas[k].threshold_bin,
quantize_datas[k].threshold,
quantize_datas[k].histogram_interval,
quantize_datas[k].scale);

fprintf(fp, "%s %f\n", layer_name.c_str(), quantize_data.scale);
fprintf(fp, "%s %f\n", layer_name.c_str(), quantize_datas[k].scale);

break;
}
@@ -724,24 +738,84 @@ void showUsage()
std::cout << "example: ./ncnn2table --param=squeezenet-fp32.param --bin=squeezenet-fp32.bin --images=images/ --output=squeezenet.table --mean=104,117,123 --norm=1,1,1 --size=227,227 --swapRB --thread=2" << std::endl;
}

int main(int argc, char** argv)
static int find_all_value_in_string(const std::string& values_string, std::vector<float>& value)
{
std::cout << "--- ncnn post training quantization tool --- " << __TIME__ << " " << __DATE__ << std::endl;
std::vector<int> masks_pos;

const cv::CommandLineParser parser(argc, argv,
for (size_t i = 0; i < values_string.size(); i++)
{
if (',' == values_string[i])
{
masks_pos.push_back(static_cast<int>(i));
}
}

// check
if (masks_pos.empty())
{
fprintf(stderr, "ERROR: Cannot find any ',' in string, please check.\n");
return -1;
}

if (2 != masks_pos.size())
{
fprintf(stderr, "ERROR: Char ',' in fist of string, please check.\n");
return -1;
}

if (masks_pos.front() == 0)
{
fprintf(stderr, "ERROR: Char ',' in fist of string, please check.\n");
return -1;
}

if (masks_pos.back() == 0)
{
fprintf(stderr, "ERROR: Char ',' in last of string, please check.\n");
return -1;
}

for (size_t i = 0; i < masks_pos.size(); i++)
{
if (i > 0)
{
if (!(masks_pos[i] - masks_pos[i - 1] > 1))
{
fprintf(stderr, "ERROR: Neighbouring char ',' was found.\n");
return -1;
}
}
}

const cv::String ch0_val_str = values_string.substr(0, masks_pos[0]);
const cv::String ch1_val_str = values_string.substr(masks_pos[0] + 1, masks_pos[1] - masks_pos[0] - 1);
const cv::String ch2_val_str = values_string.substr(masks_pos[1] + 1, values_string.size() - masks_pos[1] - 1);

"{help h usage ? | | print this message }"
"{param p | | path to ncnn.param file }"
"{bin b | | path to ncnn.bin file }"
"{images i | | path to calibration images }"
"{output o | | path to output calibration table file }"
"{mean m | | value of mean }"
"{norm n | | value of normalize(scale value,default is 1 }"
"{size s | | the size of input image(using the resize the original image,default is w=224,h=224) }"
"{swapRB c | | flag which indicates that swap first and last channels in 3-channel image is necessary }"
"{thread t | 4 | count of processing threads }"
});
value.push_back(static_cast<float>(std::atof(std::string(ch0_val_str).c_str())));
value.push_back(static_cast<float>(std::atof(std::string(ch1_val_str).c_str())));
value.push_back(static_cast<float>(std::atof(std::string(ch2_val_str).c_str())));

return 0;
}

int main(int argc, char** argv)
{
std::cout << "--- ncnn post training quantization tool --- " << __TIME__ << " " << __DATE__ << std::endl;

const char* key_map =
"{help h usage ? | | print this message }"
"{param p | | path to ncnn.param file }"
"{bin b | | path to ncnn.bin file }"
"{images i | | path to calibration images }"
"{output o | | path to output calibration table file }"
"{mean m | | value of mean }"
"{norm n | | value of normalize(scale value,default is 1 }"
"{size s | | the size of input image(using the resize the original image,default is w=224,h=224) }"
"{swapRB c | | flag which indicates that swap first and last channels in 3-channel image is necessary }"
"{thread t | 4 | count of processing threads }"
;

const cv::CommandLineParser parser(argc, argv, key_map);

if (parser.has("help"))
{
@@ -770,82 +844,25 @@ int main(int argc, char** argv)
return 0;
}

const auto num_threads = parser.get<int>("thread");

struct PreParam pre_param {
{104.f, 117.f, 103.f},
{ 1.f, 1.f, 1.f },
224,
224,
false
};

const auto find_all_value_in_string = [](const std::string& values_string, std::vector<float>& value)
{
std::vector<int> masks_pos;

for (size_t i = 0; i < values_string.size(); i++)
{
if (',' == values_string[i])
{
masks_pos.push_back(static_cast<int>(i));
}
}

// check
if (masks_pos.empty())
{
fprintf(stderr, "ERROR: Cannot find any ',' in string, please check.\n");
return -1;
}

if (2 != masks_pos.size())
{
fprintf(stderr, "ERROR: Char ',' in fist of string, please check.\n");
return -1;
}

if (masks_pos.front() == 0)
{
fprintf(stderr, "ERROR: Char ',' in fist of string, please check.\n");
return -1;
}

if (masks_pos.back() == 0)
{
fprintf(stderr, "ERROR: Char ',' in last of string, please check.\n");
return -1;
}
const int num_threads = parser.get<int>("thread");

for (size_t i = 0; i < masks_pos.size(); i++)
{
if (i > 0)
{
if (!(masks_pos[i] - masks_pos[i - 1] > 1))
{
fprintf(stderr, "ERROR: Neighbouring char ',' was found.\n");
return -1;
}
}
}

const cv::String ch0_val_str = values_string.substr(0, masks_pos[0]);
const cv::String ch1_val_str = values_string.substr(masks_pos[0] + 1, masks_pos[1] - masks_pos[0] - 1);
const cv::String ch2_val_str = values_string.substr(masks_pos[1] + 1, values_string.size() - masks_pos[1] - 1);

value.emplace_back(static_cast<float>(std::atof(std::string(ch0_val_str).c_str())));
value.emplace_back(static_cast<float>(std::atof(std::string(ch1_val_str).c_str())));
value.emplace_back(static_cast<float>(std::atof(std::string(ch2_val_str).c_str())));

return 0;
};
struct PreParam pre_param;
pre_param.mean[0] = 104.f;
pre_param.mean[1] = 117.f;
pre_param.mean[2] = 103.f;
pre_param.norm[0] = 1.f;
pre_param.norm[1] = 1.f;
pre_param.norm[2] = 1.f;
pre_param.width = 224;
pre_param.height = 224;
pre_param.swapRB = false;

if (parser.has("mean"))
{
const std::string mean_str = parser.get<std::string>("mean");

std::vector<float> mean_values;
const auto ret = find_all_value_in_string(mean_str, mean_values);
const int ret = find_all_value_in_string(mean_str, mean_values);
if (0 != ret && 3 != mean_values.size())
{
fprintf(stderr, "ERROR: Searching mean value from --mean was failed.\n");
@@ -863,7 +880,7 @@ int main(int argc, char** argv)
const std::string norm_str = parser.get<std::string>("norm");

std::vector<float> norm_values;
const auto ret = find_all_value_in_string(norm_str, norm_values);
const int ret = find_all_value_in_string(norm_str, norm_values);
if (0 != ret && 3 != norm_values.size())
{
fprintf(stderr, "ERROR: Searching mean value from --mean was failed, please check --mean param.\n");
@@ -880,7 +897,7 @@ int main(int argc, char** argv)
{
cv::String size_str = parser.get<std::string>("size");

auto sep_pos = size_str.find_first_of(',');
size_t sep_pos = size_str.find_first_of(',');

if (cv::String::npos != sep_pos && sep_pos < size_str.size())
{
@@ -934,7 +951,7 @@ int main(int argc, char** argv)
parse_images_dir(image_folder_path, image_file_path_list);

// get the calibration table file, and save it.
const auto ret = post_training_quantize(image_file_path_list, ncnn_param_file_path, ncnn_bin_file_path, saved_table_file_path, pre_param);
const int ret = post_training_quantize(image_file_path_list, ncnn_param_file_path, ncnn_bin_file_path, saved_table_file_path, pre_param);
if (!ret)
{
fprintf(stderr, "\nNCNN Int8 Calibration table create success, best wish for your INT8 inference has a low accuracy loss...\\(^0^)/...233...\n");


Loading…
Cancel
Save