make gpr update
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
// Автономный пример: C++ без Python. Грузит S21 снапшота из .npy,
|
||||
// строит A-сканы и 3D SAR-объём апертуры, печатает максимум |acc/cnt|.
|
||||
//
|
||||
// Использование:
|
||||
// standalone_bp <preprocessed_dir> <center_snapshot_name>
|
||||
// где preprocessed_dir содержит папки снапшотов с i{rx}_o{tx}_s21.npy и _freq.npy.
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <dirent.h>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gpr/ascan.hpp"
|
||||
#include "gpr/config.hpp"
|
||||
#include "gpr/geometry.hpp"
|
||||
#include "gpr/sar3d.hpp"
|
||||
|
||||
using namespace gpr;
|
||||
|
||||
// --- минимальный загрузчик numpy .npy (v1.0, 1-D complex128 или float64) ---
|
||||
struct NpyArray { std::vector<double> f64; std::vector<c128> c128v; bool is_complex = false; };
|
||||
|
||||
static NpyArray load_npy(const std::string& path) {
|
||||
std::ifstream in(path, std::ios::binary);
|
||||
if (!in) throw std::runtime_error("не открыть " + path);
|
||||
char magic[6]; in.read(magic, 6);
|
||||
uint8_t ver[2]; in.read((char*)ver, 2);
|
||||
uint16_t hlen; in.read((char*)&hlen, 2);
|
||||
std::string hdr(hlen, '\0'); in.read(&hdr[0], hlen);
|
||||
auto sp = hdr.find("'shape':");
|
||||
auto lp = hdr.find('(', sp), rp = hdr.find(')', sp);
|
||||
long n = std::stol(hdr.substr(lp + 1, rp - lp - 1));
|
||||
NpyArray a;
|
||||
auto has = [&](const char* s) { return hdr.find(s) != std::string::npos; };
|
||||
if (has("c8")) { // complex64 → c128
|
||||
a.is_complex = true; a.c128v.resize(n);
|
||||
std::vector<std::complex<float>> tmp(n);
|
||||
in.read((char*)tmp.data(), n * sizeof(std::complex<float>));
|
||||
for (long i = 0; i < n; ++i) a.c128v[i] = c128(tmp[i].real(), tmp[i].imag());
|
||||
} else if (has("c16")) { // complex128
|
||||
a.is_complex = true; a.c128v.resize(n);
|
||||
in.read((char*)a.c128v.data(), n * sizeof(c128));
|
||||
} else if (has("f4")) { // float32 → double
|
||||
a.f64.resize(n);
|
||||
std::vector<float> tmp(n); in.read((char*)tmp.data(), n * sizeof(float));
|
||||
for (long i = 0; i < n; ++i) a.f64[i] = tmp[i];
|
||||
} else { // float64
|
||||
a.f64.resize(n); in.read((char*)a.f64.data(), n * sizeof(double));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 3) { printf("usage: %s <preprocessed_dir> <center_snapshot>\n", argv[0]); return 1; }
|
||||
std::string root = argv[1], center = argv[2];
|
||||
|
||||
GeometryConfig geom; geom.finalize();
|
||||
BPConfig bp; MotionConfig mot; SARConfig sar;
|
||||
auto pairs = geom.pair_keys();
|
||||
auto tx = geom.output_idx, rx = geom.input_idx;
|
||||
std::sort(tx.begin(), tx.end()); std::sort(rx.begin(), rx.end());
|
||||
|
||||
// список снапшотов, выбор апертуры вокруг center
|
||||
std::vector<std::string> snaps;
|
||||
if (DIR* d = opendir(root.c_str())) {
|
||||
for (dirent* e; (e = readdir(d));) {
|
||||
std::string n = e->d_name;
|
||||
if (!n.empty() && isdigit(n[0])) snaps.push_back(n);
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
std::sort(snaps.begin(), snaps.end());
|
||||
int ci = -1; for (int i = 0; i < (int)snaps.size(); ++i) if (snaps[i] == center) ci = i;
|
||||
if (ci < 0) { printf("центр %s не найден\n", center.c_str()); return 1; }
|
||||
int lo = std::max(0, ci - sar.frame_radius), hi = std::min((int)snaps.size(), ci + sar.frame_radius + 1);
|
||||
std::vector<std::string> aperture(snaps.begin() + lo, snaps.begin() + hi);
|
||||
printf("апертура: %d кадров вокруг %s\n", (int)aperture.size(), center.c_str());
|
||||
|
||||
auto load_snapshot = [&](const std::string& snap,
|
||||
std::map<PairKey, std::vector<c128>>& s21,
|
||||
std::map<PairKey, std::vector<double>>& freq) {
|
||||
for (int p = 0; p < (int)pairs.size(); ++p) {
|
||||
int i_tx = pairs[p].first, i_rx = pairs[p].second;
|
||||
int phys_tx = tx[i_tx], phys_rx = rx[i_rx];
|
||||
char fn[512];
|
||||
snprintf(fn, sizeof(fn), "%s/%s/i%d_o%d_s21.npy", root.c_str(), snap.c_str(), phys_rx, phys_tx);
|
||||
s21[{i_tx, i_rx}] = load_npy(fn).c128v;
|
||||
snprintf(fn, sizeof(fn), "%s/%s/i%d_o%d_freq.npy", root.c_str(), snap.c_str(), phys_rx, phys_tx);
|
||||
freq[{i_tx, i_rx}] = load_npy(fn).f64;
|
||||
}
|
||||
};
|
||||
|
||||
auto ts = compute_pair_timestamps(mot, geom);
|
||||
SarEngine engine(geom, bp, mot, sar);
|
||||
|
||||
// держим AScanSet живыми
|
||||
std::vector<std::shared_ptr<AScanSet>> keep;
|
||||
std::vector<ApertureFrame> frames;
|
||||
std::vector<double> frame_times;
|
||||
for (auto& snap : aperture) {
|
||||
// время из суффикса _nsNNNN
|
||||
auto pos = snap.rfind("_ns");
|
||||
double t = (pos != std::string::npos) ? std::stod(snap.substr(pos + 3)) * 1e-9 : 0.0;
|
||||
frame_times.push_back(t);
|
||||
}
|
||||
double t_ref = frame_times[ci - lo];
|
||||
auto offs = frame_offsets(frame_times, t_ref, mot);
|
||||
auto wts = frame_weights(offs, sar.edge_frame_weight);
|
||||
|
||||
for (int f = 0; f < (int)aperture.size(); ++f) {
|
||||
std::map<PairKey, std::vector<c128>> s21;
|
||||
std::map<PairKey, std::vector<double>> freq;
|
||||
load_snapshot(aperture[f], s21, freq);
|
||||
auto a = std::make_shared<AScanSet>(
|
||||
preprocess_snapshot(s21, freq, nullptr, mot, geom, bp, ts, true));
|
||||
keep.push_back(a);
|
||||
frames.push_back(ApertureFrame{a.get(), offs[f], wts[f]});
|
||||
}
|
||||
|
||||
// центр сетки: под центральным снапшотом на глубине 5.6 м (сцена)
|
||||
auto center_scene = point_to_scene(0.0, 0.0, 5.6, mot, sar);
|
||||
Grid grid = build_grid_scene(center_scene, sar);
|
||||
printf("сетка %dx%dx%d, счёт объёма...\n", grid.NX(), grid.NY(), grid.NZ());
|
||||
|
||||
VolumeRaw vol = engine.aperture_volume(frames, grid);
|
||||
|
||||
// финализация: |acc/cnt|, максимум
|
||||
double vmax = 0; size_t amax = 0;
|
||||
for (size_t i = 0; i < vol.acc.size(); ++i) {
|
||||
double v = std::abs(vol.acc[i]) / (vol.cnt[i] + 1e-12);
|
||||
if (v > vmax) { vmax = v; amax = i; }
|
||||
}
|
||||
int NX = vol.NX, NZ = vol.NZ;
|
||||
int ix = amax % NX, iz = (amax / NX) % NZ, iy = amax / ((size_t)NX * NZ);
|
||||
printf("МАКСИМУМ объёма: |acc/cnt|=%.4e в вокселе (ix=%d,iy=%d,iz=%d)\n", vmax, ix, iy, iz);
|
||||
printf(" X=%.1f см, Y=%.1f см, Z=%.1f см\n",
|
||||
grid.x[ix] * 100, grid.y[iy] * 100, grid.z[iz] * 100);
|
||||
printf("OK: автономный C++ путь отработал без Python.\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user