diff options
Diffstat (limited to 'meowpp.test/src/match.cpp')
-rw-r--r-- | meowpp.test/src/match.cpp | 547 |
1 files changed, 328 insertions, 219 deletions
diff --git a/meowpp.test/src/match.cpp b/meowpp.test/src/match.cpp index c69b958..8fec09b 100644 --- a/meowpp.test/src/match.cpp +++ b/meowpp.test/src/match.cpp @@ -1,35 +1,103 @@ #include <cstdio> +#include <string> +#include <cstdlib> -#include "match.h" +struct Job; -#include "meowpp/Usage.h" -#include "meowpp/colors/RGB_Space.h" -#include "meowpp/geo/Vectors.h" -#include "meowpp/gra/Bitmap.h" -#include "meowpp/oo/ObjBase.h" -#include "meowpp/oo/ObjSelector.h" +void init ( ); +void setup(int argc, char** argv); +void end ( ); -#include <opencv/cv.h> -#include <opencv/highgui.h> +Job* get(size_t counter); -extern "C"{ -#include <sys/types.h> -#include <dirent.h> +void input (Job* job); +void handle(Job* job); +void output(Job* job); +void clear (Job* job); + +void info0 (Job* job); +void info1 (Job* job); +void info2 (Job* job); + +int main(int argc, char** argv) { + Job* now; + try { + init(); + setup(argc, argv); + for (size_t counter = 0; (now = get(counter)) != NULL; clear(now), ++counter) { + try { + input (now); info0(now); + handle(now); info1(now); + output(now); info2(now); + } + catch (std::string reason) { + throw reason.c_str(); + } + catch (char const* reason) { + printf("fail '%s', ignore.\n\n", reason); + continue; + } + printf("\n"); + } + end(); + } + catch (int num) { + return num; + } + return 0; } +/////////////////////////////////////////////////////////// + +#include "test_utility.h" +#include "match.h" + +#include "meowpp/utility.h" +#include "meowpp/Usage.h" +#include "meowpp/oo/ObjSelector.h" +#include "meowpp/gra/IdentityPoints.h" + #include <vector> #include <algorithm> #include <string> +#include <cstdio> using namespace meow; +/////////////////////////////////////////////////////////// + Usage usg("match"); -std::vector<bool> fg; +MatchAll* match_all; +MatchOne* match_one; +MatchChk* match_chk; + +struct Job { + struct Picture { + std::string fname; + size_t width; + size_t height; + std::vector<FP> features; + std::vector<Vector2D<double> > fvs; + IdentityPoints<int, double, Vector2D<double> > fps; + Picture(): fps(2) { + } + }; + std::vector<Picture> pictures; + std::vector<std::vector<std::vector<Pair> > > pairs; + std::vector<std::vector<MatchInfo> > matches; +}; + +std::vector<Job> jobs; + std::vector<std::string> names; -std::vector<std::vector<FeaturePoint<double, double> > > fps; -int setup(int argc, char** argv) { +std::string out_pre; + + +/////////////////////////////////////////////////////////// + +void init() { usg.optionAdd("h" , "Display this help document"); usg.optionAdd("help", "Display this help document"); usg.optionAdd("i", @@ -38,264 +106,305 @@ int setup(int argc, char** argv) { "pathname", "", false); + usg.optionAdd("r", + "recur"); usg.optionAdd("o", - "Output images with denoting aligement points", + "Output images with denoting matches", "filename", "", false); - usg.optionAdd("f", - "Output text file name (prefix)", - "filename", - "output", - false); + usg.optionAdd("a", + "Specify which feature match algorithm to use", + "name", + "", + true); usg.optionAdd("m", - "Specify which match algorithm to use", + "Specify which match detect algorithm to use", "name", "", true); usg.optionAdd("c", - "Specify which check algorithm to use", + "Specify which match match_chk algorithm to use", "name", "", true); - std::vector<std::string> nlist; - nlist = (ObjSelector<kMatchAllsID>::names()); - for (size_t i = 0, I = nlist.size(); i < I; ++i) { - MatchAlls const* m; - m = (MatchAlls const*)ObjSelector<kMatchAllsID>::get(nlist[i]); - usg.optionValueAcceptAdd("m", nlist[i], m->description()); - usg.import(m->usage()); + std::vector<std::string> algo_list; + algo_list = ObjSelector<kMatchAll_ID>::names(); + for (size_t i = 0, I = algo_list.size(); i < I; ++i) { + MatchAll const* f = (MatchAll const*)ObjSelector<kMatchAll_ID>::get(algo_list[i]); + usg.optionValueAcceptAdd("a", algo_list[i], f->description()); + if (usg.import(f->usage()) == false) + throw -1; + } + algo_list = ObjSelector<kMatchOne_ID>::names(); + for (size_t i = 0, I = algo_list.size(); i < I; ++i) { + MatchOne const* f = (MatchOne const*)ObjSelector<kMatchOne_ID>::get(algo_list[i]); + usg.optionValueAcceptAdd("m", algo_list[i], f->description()); + if (usg.import(f->usage()) == false) + throw -1; } - nlist = ObjSelector<kMatchAllsID>::names(); - for (size_t i = 0, I = nlist.size(); i < I; ++i) { - TryAndChecks const* m; - m = (TryAndChecks const*)ObjSelector<kTryAndChecks>::get(nlist[i]); - usg.optionValueAcceptAdd("c", nlist[i], m->description()); - usg.import(m->usage()); + algo_list = ObjSelector<kMatchChk_ID>::names(); + for (size_t i = 0, I = algo_list.size(); i < I; ++i) { + MatchChk const* f = (MatchChk const*)ObjSelector<kMatchChk_ID>::get(algo_list[i]); + usg.optionValueAcceptAdd("c", algo_list[i], f->description()); + if (usg.import(f->usage()) == false) + throw -1; } +} + +void setup(int argc, char** argv) { std::string err; bool ret = usg.arguments(argc, argv, &err); if (usg.hasOptionSetup("h") || usg.hasOptionSetup("help")) { fprintf(stderr, "%s\n", usg.usage().c_str()); - return 0; + throw 0; } if (ret == false) { fprintf(stderr, "%s\n", err.c_str()); - return -1; + throw -2; } - return 1; -} -int getName() { - if (usg.hasOptionSetup("i") == false) { - names = usg.procArgs(); + match_all = (MatchAll*)ObjSelector<kMatchAll_ID>::create(usg.optionValue("a", 0)); + match_one = (MatchOne*)ObjSelector<kMatchOne_ID>::create(usg.optionValue("m", 0)); + match_chk = (MatchChk*)ObjSelector<kMatchChk_ID>::create(usg.optionValue("c", 0)); + if (match_all->usage(usg) == false) throw -3; + if (match_one->usage(usg) == false) throw -4; + if (match_chk->usage(usg) == false) throw -5; + + if (usg.hasOptionSetup("i")) { + names = cgetFiles(usg.optionValue("i", 0).c_str(), usg.hasOptionSetup("r"), + 4, ".jpg", ".jpeg", ".JPG", ".JPEG"); } else { - std::string base = usg.optionValue("i", 0); - if (base.length() == 0 || base[base.length() - 1] != '/') { - base += "/"; - } - DIR* dir = opendir(base.c_str()); - if (!dir) { - fprintf(stderr, "can't open dir '%s'\n", base.c_str()); - return -1; - } - for (dirent* ent; (ent = readdir(dir)) != NULL; ) { - if (!cstringEndWith(ent->d_name, 4, ".jpeg", ".jpg", ".JPG", ".JPEG")) { - continue; - } - names.push_back(base + std::string(ent->d_name) + ".txt"); - } + names = usg.procArgs(); } - fg.resize(names.size(), true); - return 1; + std::sort(names.begin(), names.end(), filenameCompare); + out_pre = usg.optionValue("o", 0); +} + +void end() { + delete match_all; + delete match_one; + delete match_chk; } -int readIn() { - std::vector<std::string> nn(names); - names.clear(); - for (int i = 0, I = nn.size(); i < I; ++i) { - messagePrintf(1, "read '%s'", nn[i].c_str()); - FILE* f = fopen(nn[i].c_str(), "r"); +/////////////////////////////////////////////////////////// + +Job* get(size_t counter) { + if (counter >= 1) return NULL; + Job* job = new Job; + for (size_t i = 0, I = names.size(); i < I; ++i) { + Job::Picture pic; + pic.fname = names[i]; + job->pictures.push_back(pic); + } + return job; +} + +/////////////////////////////////////////////////////////// + +void input(Job* job) { + for (int i = 0, I = job->pictures.size(); i < I; ++i) { + bool ok = true; + std::string fname = job->pictures[i].fname + ".fps"; + FILE* f = fopen(fname.c_str(), "r"); if (f == NULL) { - messagePrintf(-1, "cannot open, ignore"); - continue; + printf("cannot open %s, ignore\n", fname.c_str()); + ok = false; } - std::vector<FeaturePoint<double, double> > tmp; - bool succ = true; - int N = 0, M; - if (fscanf(f, "%d %d", &N, &M) < 1) succ = false; - if (succ) { - tmp.resize(N); - for (size_t i = 0; i < N; ++i) { - if (tmp[i].read(f, false, 0) == false) { - succ = false; - break; - } - if ((int)tmp[i].description().diemnsion() != M) { - succ = false; - break; - } + else { + size_t N; + if (fscanf(f, "%lu %lu %lu", &(job->pictures[i].width), &(job->pictures[i].height), &N) < 3) + ok = false; + for (size_t j = 0; ok && j < N; ++j) { + FeaturePoint<double, double, Vector2D<double> > fp; + if (fp.read(f, false, 0) == false) + ok = false; + job->pictures[i].features.push_back(fp); } + fclose(f); } - fclose(f); - if (succ) { - names.push_back(nn[i]); - fps .push_back(tmp); - messagePrintf(-1, "ok"); - } - else { - messagePrintf(-1, "file format error"); + if (!ok) { + if (i != I - 1) + std::swap(job->pictures[i], job->pictures[I - 1]); + --I; + --i; + printf("format error '%s'\n", fname.c_str()); } + else + printf("loaded %s\n", fname.c_str()); + } + job->pairs .resize(job->pictures.size()); + job->matches.resize(job->pictures.size()); + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) { + job->pairs [i].resize(job->pictures.size()); + job->matches[i].resize(job->pictures.size()); } - return fps.size(); } -int match() { - MatchAlls* algo = ObjSelector<kMatchAllsID>::create(usg.optionValeu("m", 0)); - if (algo->usage(usg) == false) { - delete algo; - messagePrintf(0, "usage error"); - return -1; +void handle(Job* job) { + // match all + printf("match all\n"); + std::vector<std::vector<FP> > fpss(job->pictures.size()); + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) + fpss[i] = job->pictures[i].features; + std::vector<PairToPair<size_t> > pps = match_all->match(fpss); + for (size_t i = 0, I = pps.size(); i < I; ++i) { + job->pairs[pps[i].from.first][pps[i].to.first].push_back(Pair(pps[i].from.second, pps[i].to.second)); } - std::vector<PairToPair<size_t> > p = algo->match(fps); - for (size_t i = 0, I = p.size(); i < I; ++i) { - std::pair<size_t, size_t> pr(p[i].from.second, p[i].to.second); - pairs[p[i].from.first][p[i].to.first].push_back(pr); + printf("pairs: \n"); + for (size_t i = 0, I = job->pairs.size(); i < I; ++i, printf("\n")) { + for (size_t j = 0; j < I; ++j) { + printf("%3d ", (int)job->pairs[i][j].size()); + } } - delete algo; - return 1; -} -int check() { - TryAndChecks*chk=ObjSelector<kTryAndChecksID>::create(usg.optionValue("c",0)); - for (size_t i = 0, I = names.size(); i < I; ++i) { + // match one + printf("match one\n"); + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) + for (size_t j = 0, J = job->pictures[i].features.size(); j < J; ++j) + job->pictures[i].fvs.push_back(job->pictures[i].features[j].position()); + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) for (size_t j = 0; j < I; ++j) { - match[i][j].pairs.clear(); - if (i != j && pairs[i][j].size() >= chk->minNumber()) { - match[i][j] = chk->run(fps[i], width[i], height[i], - fps[j], width[j], height[j], - pairs[i][j]); + if (i == j) + continue; + job->matches[i][j] = match_one->match(job->pictures[i].fvs, + job->pictures[j].fvs, + job->pairs[i][j], + job->pictures[i].width, + job->pictures[i].height); + if (job->matches[i][j].ok) { + printf("ok for %3lu -- %3lu (%3d)\n", i, j, (int)job->matches[i][j].pairs.size()); } } - } - delete chk; - return 1; -} - -Bitmap<RGBf_Space> readOne(std::string name) { - Bitmap<RGBf_Space> ret; - messagePrintf(1, "Loading image..."); - cv::Mat img = cv::imread(name, CV_LOAD_IMAGE_COLOR); - if (img.data) { - size_t height = img.size().height; - size_t width = img.size().width ; - ret.size(height, width, RGBf_Space(0)); - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; ++x) { - Vector3D<int> v; - for (size_t i = 0; i < 3; ++i) - v.scalar(i, img.at<cv::Vec3b>(y, x)[2 - i]); - RGBf_Space p; - colorTransformate(RGBi_Space(v), &p); - ret.pixel(y, x, p); + + // match_chk + printf("match check\n"); + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) + for (size_t j = 0; j < I; ++j) { + if (i == j || job->matches[i][j].ok == false) + continue; + job->matches[i][j].ok = match_chk->check(job->pictures[i].fvs, + job->pictures[i].width, + job->pictures[i].height, + job->pictures[j].fvs, + job->pictures[j].width, + job->pictures[j].height, + job->pairs[i][j], + job->matches[i][j]); + if (job->matches[i][j].ok == true) { + printf("accept %lu %lu (%lu)\n", i, j, job->matches[i][j].pairs.size()); + } + } + + // 整理 + int ct = 0; + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) + for (size_t j = 0; j < I; ++j) { + if (i == j || job->matches[i][j].ok == false) + continue; + for (size_t k = 0; k < job->matches[i][j].pairs.size(); ++k) { + job->pictures[i].fps.pointAdd(ct, job->pictures[i].fvs[job->matches[i][j].pairs[k].first ]); + job->pictures[j].fps.pointAdd(ct, job->pictures[j].fvs[job->matches[i][j].pairs[k].second]); + ct++; } } - } - messagePrintf(-1, (ret.size() > 0 ? "ok" : "fail")); - return ret; } -int writeBmpOne(std::string name, Bitmap<RGBf_Space> const& bmp) { - size_t height = bmp.height(); - size_t width = bmp.width (); - messagePrintf(1, "write to image '%s' (%lu x %lu)", - name.c_str(), height, width); - cv::Mat img(height, width, CV_8UC3); - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - RGBi_Space tmp; - colorTransformate(bmp.pixel(y, x), &tmp); - for (size_t i = 0; i < 3; ++i) - img.at<cv::Vec3b>(y, x)[i] = tmp.rgb(2 - i); - } +void output(Job *job) { + printf("output...\n"); + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) { + FILE* f = fopen((job->pictures[i].fname + ".fp2ds").c_str(), "w"); + job->pictures[i].fps.write(f, false, 0); + fclose(f); } - if (imwrite(name, img) == false) { - messagePrintf(-1, "fail"); - return -1; + if (out_pre.size() > 0) { + printf("output pictures\n"); + int ct = 0; + for (size_t i = 0, I = job->pictures.size(); i < I; ++i) + for (size_t j = 0; j < I; ++j) { + if (i == j || job->matches[i][j].ok == false) continue; + Bitmap<RGBf_Space> bmp1, bmp2; + if (readBitmap(job->pictures[i].fname, &bmp1) == false) continue; + if (readBitmap(job->pictures[j].fname, &bmp2) == false) continue; + Bitmap<RGBf_Space> out(bmp2); + Bitmap<double> sum(bmp2.height(), bmp2.width(), 1.0); + Matrix<double> m(3, 3, 0.0); + m.entry(0, 0, job->matches[i][j].x_axis.scalar(0)); + m.entry(0, 1, job->matches[i][j].x_axis.scalar(1)); + m.entry(0, 2, job->matches[i][j].x_offset); + m.entry(1, 0, job->matches[i][j].y_axis.scalar(0)); + m.entry(1, 1, job->matches[i][j].y_axis.scalar(1)); + m.entry(1, 2, job->matches[i][j].y_offset); + m.entry(2, 0, job->matches[i][j].depth(0)); + m.entry(2, 1, job->matches[i][j].depth(1)); + m.entry(2, 2, 1); + m.inversed(); + for (size_t y = 0, Y = bmp1.height(); y < Y; ++y) + for (size_t x = 0, X = bmp1.width(); x < X; ++x) { + RGBf_Space tmp(bmp1.pixel(y, x)); + tmp.b(0); + tmp.r(0); + bmp1.pixel(y, x, tmp); + } + for (size_t y = 0, Y = bmp2.height(); y < Y; ++y) + for (size_t x = 0, X = bmp2.width(); x < X; ++x) { + Vector3D<double> v2(x, y, 1.0), v1(m * v2.matrix()); + int x1 = v1(0) / v1(2); + int y1 = v1(1) / v1(2); + if (x1 < 0 || (int)bmp1.width() <= x1 || y1 < 0 || (int)bmp1.height() <= y1) continue; + sum.pixel(y, x, sum.pixel(y, x) + 1); + out.pixel(y, x, out.pixel(y, x) + bmp1.pixel(y1, x1)); + } + for (size_t y = 0, Y = out.height(); y < Y; ++y) + for (size_t x = 0, X = out.width(); x < X; ++x) + out.pixel(y, x, out.pixel(y, x) / sum.pixel(y, x)); + int w = std::min(out.height() , out.width()) / 32; + for (size_t k = 0, K = job->matches[i][j].pairs.size(); k < K; ++k) { + int id_j = job->matches[i][j].pairs[k].second; + int x0 = job->pictures[j].fvs[id_j].x(); + int y0 = job->pictures[j].fvs[id_j].y(); + for (int d = -w; d <= w; ++d) { + if (0 <= x0 + d && x0 + d < (int)out.width ()) out.pixel(y0, x0 + d, RGBf_Space(Vector3D<double>(1.0, 0.0, 0.0))); + if (0 <= y0 + d && y0 + d < (int)out.height()) out.pixel(y0 + d, x0, RGBf_Space(Vector3D<double>(1.0, 0.0, 0.0))); + } + } + for (size_t k = 0, K = job->pictures[i].fvs.size(); k < K; ++k) { + Vector2D<double> v_tr( + (job->pictures[i].fvs[k].dot(job->matches[i][j].x_axis) + job->matches[i][j].x_offset) / (job->pictures[i].fvs[k].dot(job->matches[i][j].depth) + 1), + (job->pictures[i].fvs[k].dot(job->matches[i][j].y_axis) + job->matches[i][j].y_offset) / (job->pictures[i].fvs[k].dot(job->matches[i][j].depth) + 1) + ); + if (v_tr.x() < 0 || out.width () <= v_tr.x()) continue; + if (v_tr.y() < 0 || out.height() <= v_tr.y()) continue; + for (size_t l = 0, L = job->pairs[i][j].size(); l < L; ++l) { + if (job->pairs[i][j][l].first == k) { + Vector2D<double> v2(job->pictures[j].fvs[job->pairs[i][j][l].second]); + Vector2D<double> delta(v2 - v_tr); + for (int z = 0, Z = delta.length(); z <= Z; ++z) { + Vector2D<double> v(v_tr + delta * (double)z / (double)Z); + if (v.x() < 0 || out.width () <= v.x()) continue; + if (v.y() < 0 || out.height() <= v.y()) continue; + out.pixel(v.y(), v.x(), RGBf_Space(Vector3D<double>(0.0, 0.0, 1.0 * (Z - z) / Z))); + } + } + } + } + writeBitmap(stringPrintf("%s%d.jpg", out_pre.c_str(), ct), out); + printf("write to bmp '%s%d.jpg'\n", out_pre.c_str(), ct); + ct++; + } } - messagePrintf(-1, "ok"); - return 1; } -int writeBmp(size_t id) { - if (usg.hasOptionSetup("o") == false) - return 1; - std::string name2; - name2 = stringPrintf("%s%lu.jpg", usg.optionValue("o", 0).c_str(), id); - messagePrintf(1, "Write img file to '%s'", name2.c_str()); - Bitmap<RGBf_Space> bmp(readOne(names[id])); - bool succ; - if ((succ = (bmp.size() > 0))) { - int wh = std::min(bmp.height(), bmp.width()) / 32; - for (size_t j = 0, J = fps[id].size(); j < J; ++j) { - int x0 = fps[id][j].position()(0); - int y0 = fps[id][j].position()(1); - for (int dx = -wh; dx <= wh; ++dx) - if (0 <= x0 + dx && x0 + dx < (int)bmp.width()) - bmp.pixel(y0, x0 + dx, RGBf_Space(Vector3D<double>(1.0, 0.0, 0.0))); - for (int dy = -wh; dy <= wh; ++dy) - if (0 <= y0 + dy && y0 + dy < (int)bmp.height()) - bmp.pixel(y0 + dy, x0, RGBf_Space(Vector3D<double>(1.0, 0.0, 0.0))); - } - succ = (writeBmpOne(name2, bmp) > 0); - } - messagePrintf(-1, succ ? "ok" : "fail"); - return 1; +void clear(Job *job) { + delete job; } -int writeOne(FILE* f, size_t i) { - if (fprintf(f, "%d\n", (int)fps[i].size()) < 1) return -1; - for (size_t j = 0, J = fps[i].size(); j < J; ++j) { - if (fps[i][j].write(f, false, 0) == false) return -1; - } - return 1; +void info0(Job* job) { } -int writeText() { - for(size_t i = 0, I = fps.size(); i < I; ++i) { - if (!fg[i]) continue; - std::string name2; - if (usg.hasOptionSetup("f")) { name2 = usg.optionValue("f", i); } - else { name2 = names[i] + ".txt"; } - messagePrintf(1, "Write text file to '%s'", name2.c_str()); - FILE* f = fopen(name2.c_str(), "w"); - if (f == NULL) { - messagePrintf(-1, "fail to open file!, ignore"); - continue; - } - if (writeOne(f, i) < 0) { - messagePrintf(-1, "write fail"); - fclose(f); - continue; - } - fclose(f); - messagePrintf(-1, "ok"); - } - return 1; +void info1(Job* job) { } -int main(int argc, char** argv) { - int ret; - if ((ret = setup(argc, argv)) <= 0) return ret; - if ((ret = getName()) <= 0) return ret; - if ((ret = readIn()) <= 0) return ret; - if ((ret = match()) <= 0) return ret; - if ((ret = check()) <= 0) return ret; - if ((ret = writeText()) <= 0) return ret; - if ((ret = writeBmp()) <= 0) return ret; - return 0; +void info2(Job* job) { } - - - |