|
|
|
|
@ -39,20 +39,20 @@ struct GunshotClassifier::Impl {
|
|
|
|
|
|
|
|
|
|
// Try simple JSON object format: {"0": "ambient", "1": "threat"}
|
|
|
|
|
if (content.find('{') != std::string::npos) {
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
std::size_t pos = 0;
|
|
|
|
|
while ((pos = content.find('"', pos)) != std::string::npos) {
|
|
|
|
|
size_t key_start = pos + 1;
|
|
|
|
|
size_t key_end = content.find('"', key_start);
|
|
|
|
|
std::size_t key_start = pos + 1;
|
|
|
|
|
std::size_t key_end = content.find('"', key_start);
|
|
|
|
|
if (key_end == std::string::npos) break;
|
|
|
|
|
std::string key = content.substr(key_start, key_end - key_start);
|
|
|
|
|
int idx = -1;
|
|
|
|
|
try { idx = std::stoi(key); } catch (...) {}
|
|
|
|
|
|
|
|
|
|
size_t colon = content.find(':', key_end);
|
|
|
|
|
std::size_t colon = content.find(':', key_end);
|
|
|
|
|
if (colon == std::string::npos) break;
|
|
|
|
|
size_t val_quote = content.find('"', colon);
|
|
|
|
|
std::size_t val_quote = content.find('"', colon);
|
|
|
|
|
if (val_quote == std::string::npos) break;
|
|
|
|
|
size_t val_end = content.find('"', val_quote + 1);
|
|
|
|
|
std::size_t val_end = content.find('"', val_quote + 1);
|
|
|
|
|
if (val_end == std::string::npos) break;
|
|
|
|
|
std::string label = content.substr(val_quote + 1, val_end - val_quote - 1);
|
|
|
|
|
|
|
|
|
|
@ -64,9 +64,9 @@ struct GunshotClassifier::Impl {
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback: "index: label" line format
|
|
|
|
|
size_t line_start = 0;
|
|
|
|
|
std::size_t line_start = 0;
|
|
|
|
|
while (line_start < content.size()) {
|
|
|
|
|
size_t line_end = content.find('\n', line_start);
|
|
|
|
|
std::size_t line_end = content.find('\n', line_start);
|
|
|
|
|
if (line_end == std::string::npos) line_end = content.size();
|
|
|
|
|
std::string line = content.substr(line_start, line_end - line_start);
|
|
|
|
|
line_start = line_end + 1;
|
|
|
|
|
@ -108,7 +108,7 @@ struct GunshotClassifier::Impl {
|
|
|
|
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, nullptr, 0);
|
|
|
|
|
std::wstring wpath;
|
|
|
|
|
if (wlen > 0) {
|
|
|
|
|
wpath.resize(static_cast<size_t>(wlen));
|
|
|
|
|
wpath.resize(static_cast<std::size_t>(wlen));
|
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, &wpath[0], wlen);
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
@ -150,7 +150,7 @@ struct GunshotClassifier::Impl {
|
|
|
|
|
int n_frames = static_cast<int>(mel_spectrogram.cols());
|
|
|
|
|
|
|
|
|
|
// Flatten to std::vector<float> with layout [batch, time_frames, n_mels]
|
|
|
|
|
std::vector<float> input_data(static_cast<size_t>(n_mels) * n_frames);
|
|
|
|
|
std::vector<float> input_data(static_cast<std::size_t>(n_mels) * n_frames);
|
|
|
|
|
for (int t = 0; t < n_frames; ++t) {
|
|
|
|
|
for (int m = 0; m < n_mels; ++m) {
|
|
|
|
|
input_data[t * n_mels + m] = mel_spectrogram(m, t);
|
|
|
|
|
@ -176,27 +176,27 @@ struct GunshotClassifier::Impl {
|
|
|
|
|
// Get output
|
|
|
|
|
float* output_data = output_tensors.front().GetTensorMutableData<float>();
|
|
|
|
|
auto output_shape = output_tensors.front().GetTensorTypeAndShapeInfo().GetShape();
|
|
|
|
|
size_t num_classes = labels.empty() ? static_cast<size_t>(output_shape.back()) : labels.size();
|
|
|
|
|
std::size_t num_classes = labels.empty() ? static_cast<std::size_t>(output_shape.back()) : labels.size();
|
|
|
|
|
if (num_classes == 0) num_classes = 2;
|
|
|
|
|
|
|
|
|
|
// Softmax
|
|
|
|
|
std::vector<float> probs(num_classes);
|
|
|
|
|
float max_val = output_data[0];
|
|
|
|
|
for (size_t i = 1; i < num_classes; ++i) {
|
|
|
|
|
for (std::size_t i = 1; i < num_classes; ++i) {
|
|
|
|
|
if (output_data[i] > max_val) max_val = output_data[i];
|
|
|
|
|
}
|
|
|
|
|
float sum = 0.0f;
|
|
|
|
|
for (size_t i = 0; i < num_classes; ++i) {
|
|
|
|
|
for (std::size_t i = 0; i < num_classes; ++i) {
|
|
|
|
|
probs[i] = std::exp(output_data[i] - max_val);
|
|
|
|
|
sum += probs[i];
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < num_classes; ++i) {
|
|
|
|
|
for (std::size_t i = 0; i < num_classes; ++i) {
|
|
|
|
|
probs[i] /= sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find best
|
|
|
|
|
size_t best_idx = 0;
|
|
|
|
|
for (size_t i = 1; i < num_classes; ++i) {
|
|
|
|
|
std::size_t best_idx = 0;
|
|
|
|
|
for (std::size_t i = 1; i < num_classes; ++i) {
|
|
|
|
|
if (probs[i] > probs[best_idx]) best_idx = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|