diff options
Diffstat (limited to 'meowpp.test')
-rw-r--r-- | meowpp.test/GNUmakefile.targets | 7 | ||||
-rw-r--r-- | meowpp.test/inc/features__.h | 2 | ||||
-rw-r--r-- | meowpp.test/inc/match.h | 71 | ||||
-rw-r--r-- | meowpp.test/src/autostitch.cpp | 2 | ||||
-rw-r--r-- | meowpp.test/src/features.cpp | 2 | ||||
-rw-r--r-- | meowpp.test/src/features_Harris.cpp | 9 | ||||
-rw-r--r-- | meowpp.test/src/match.cpp | 547 | ||||
-rw-r--r-- | meowpp.test/src/match_MatchAll.cpp | 66 | ||||
-rw-r--r-- | meowpp.test/src/match_MatchChk.cpp | 102 | ||||
-rw-r--r-- | meowpp.test/src/match_MatchOne.cpp | 207 | ||||
-rw-r--r-- | meowpp.test/src/match_MatchOne.h | 45 |
11 files changed, 814 insertions, 246 deletions
diff --git a/meowpp.test/GNUmakefile.targets b/meowpp.test/GNUmakefile.targets index 056bfa5..b4f866a 100644 --- a/meowpp.test/GNUmakefile.targets +++ b/meowpp.test/GNUmakefile.targets @@ -34,3 +34,10 @@ $(BIN)/features: $(OBJ)/features.o $(features_OBJS) @echo Target: $@... @$(CXX) $^ $(CXXFLAGS) `pkg-config --cflags --libs $(features_LIBS) 2>/dev/null` -o $@ +TARGETS := $(TARGETS) $(BIN)/match +match_OBJS := $(OBJ)/match_MatchAll.o $(OBJ)/match_MatchChk.o $(OBJ)/match_MatchOne.o +match_LIBS := opencv +$(BIN)/match: $(OBJ)/match.o $(match_OBJS) + @echo Target: $@... + @$(CXX) $^ $(CXXFLAGS) `pkg-config --cflags --libs $(match_LIBS) 2>/dev/null` -o $@ + diff --git a/meowpp.test/inc/features__.h b/meowpp.test/inc/features__.h index ab484ae..c8c94c1 100644 --- a/meowpp.test/inc/features__.h +++ b/meowpp.test/inc/features__.h @@ -9,7 +9,7 @@ #include <vector> -typedef std::vector<meow::FeaturePoint<double, double> > FeaturePoints; +typedef std::vector<meow::FeaturePoint<double, double, meow::Vector2D<double> > > FeaturePoints; class FeaturePointsDetectors: public meow::ObjBase { public: diff --git a/meowpp.test/inc/match.h b/meowpp.test/inc/match.h index d05e8e8..f0dfa1c 100644 --- a/meowpp.test/inc/match.h +++ b/meowpp.test/inc/match.h @@ -1,47 +1,72 @@ -#ifndef aligement_H__ -#define aligement_H__ +#ifndef match_H__ +#define match_H__ +#include "meowpp/gra/FeaturePoint.h" +#include "meowpp/utility.h" #include "meowpp/geo/Vectors.h" +#include "meowpp/Usage.h" +typedef meow::FeaturePoint<double, double, meow::Vector2D<double> > FP; +typedef std::pair<size_t, size_t> Pair; + +class MatchAll: public meow::ObjBase { +public: + virtual ~MatchAll() { } + virtual std::vector<meow::PairToPair<size_t> > match(std::vector<std::vector<FP> > const& fpss) const = 0; + virtual std::string description() const = 0; + virtual meow::Usage usage( ) const = 0; + virtual bool usage(meow::Usage const& usg) = 0; +}; + +int const kMatchAll_ID = 456; + +////////////////////////////////////////////////////////////////////// struct MatchInfo { + bool ok; + meow::Vector2D<double> x_axis; meow::Vector2D<double> y_axis; - double x_offset, y_offset; + double x_offset; + double y_offset; meow::Vector2D<double> depth; - - std::vector<std::pair<Vector2D<double>, Vector2D<double> > > pairs; + + std::vector<Pair> pairs; }; -class MatchAlls: public meow::ObjBase { +class MatchOne: public meow::ObjBase { public: - virtual ~MatchAlls() { } - virtual std::vector<PairToPair<size_t> > match( - std::vector<std::vector<FeaturePoint<double, double> > > > const& fpss) = 0; + virtual ~MatchOne() { } + virtual MatchInfo match(std::vector<meow::Vector2D<double> > const& fps1, + std::vector<meow::Vector2D<double> > const& fps2, + std::vector<Pair > const& pairs, + size_t width, size_t height) const = 0; virtual std::string description() const = 0; virtual meow::Usage usage( ) const = 0; virtual bool usage(meow::Usage const& usg) = 0; + virtual int minNumber() const = 0; }; -int const kMatchAllsID = 456; +int const kMatchOne_ID = 123; -class TryAndChecks: public meow::ObjBase { +////////////////////////////////////////////////////////////////////// + +class MatchChk: public meow::ObjBase { public: - virtual TryAndChecks() { } - virtual MatchInfo run(std::vector<meow::Vector2D<double> > const& fps1, - size_t w1, - size_t h1, - std::vector<meow::Vector2D<double> > const& fps2, - size_t w2, - size_t h2, - std::vector<std::pair<size_t,size_t> >const& pairs) = 0; + virtual ~MatchChk() { } + virtual bool check(std::vector<meow::Vector2D<double> > const& fps1, + size_t w1, + size_t h1, + std::vector<meow::Vector2D<double> > const& fps2, + size_t w2, + size_t h2, + std::vector<Pair > const& pairs, + MatchInfo const& info) = 0; virtual std::string description() const = 0; virtual meow::Usage usage( ) const = 0; virtual bool usage(meow::Usage const& usg) = 0; - virtual int minNumber() const = 0; }; -int const kTryAndChecksID = 123; - +int const kMatchChk_ID = 1234; -#endif // aligement_H__ +#endif // match_H__ diff --git a/meowpp.test/src/autostitch.cpp b/meowpp.test/src/autostitch.cpp index e6b473b..8472a74 100644 --- a/meowpp.test/src/autostitch.cpp +++ b/meowpp.test/src/autostitch.cpp @@ -390,7 +390,7 @@ bool pair_output(){ output_bitmap.push_back(input_bitmap[i]); for(ssize_t x = 0, X = input_bitmap[i].width(); x < X; x++) { for(ssize_t y = 0, Y = input_bitmap[i].height(); y < Y; y++) { - Vector2D<double> to(chk.to(Vector2D<double>(x, y))); + Vector2D<double> to(chk.to(Vector2D<double>(1.0 * x, 1.0 * y))); ssize_t x2 = to.x(), y2 = to.y(); if (0 <= x2 && x2 < (ssize_t)input_bitmap[j].width() && 0 <= y2 && y2 < (ssize_t)input_bitmap[j].height()) { diff --git a/meowpp.test/src/features.cpp b/meowpp.test/src/features.cpp index 6972fa3..b3c2ff6 100644 --- a/meowpp.test/src/features.cpp +++ b/meowpp.test/src/features.cpp @@ -72,7 +72,7 @@ FeaturePointsDetectors* detector; struct Job { int id; std::string file_name; - std::vector<FeaturePoint<double, double> > fps; + std::vector<FeaturePoint<double, double, Vector2D<double> > > fps; Bitmap<RGBf_Space> bmp; }; diff --git a/meowpp.test/src/features_Harris.cpp b/meowpp.test/src/features_Harris.cpp index eeb2f2d..3f74145 100644 --- a/meowpp.test/src/features_Harris.cpp +++ b/meowpp.test/src/features_Harris.cpp @@ -9,7 +9,7 @@ using namespace meow; class Harris: public FeaturePointsDetectors { private: - FeaturePointsDetector_Harris<RGBf_Space> detector_; + FeaturePointsDetector_Harris<RGBf_Space, FeaturePoint<double, double, Vector2D<double> > > detector_; public: std::string description() const { return "Harris-Corner-Detect"; @@ -33,6 +33,11 @@ class Harris: public FeaturePointsDetectors { "<floating point>", stringPrintf("%.10f", detector_.paramW()), false); + ret.optionAdd("harris-a", + "angle", + "<floating point>", + stringPrintf("%d", (int)detector_.paramA()), + false); ret.optionAdd("harris-n", "Specify the sigma of the gaussian blur to de-noise", "<floating point>", @@ -64,6 +69,7 @@ class Harris: public FeaturePointsDetectors { double L = atof(usg.optionValue("harris-l", 0).c_str()); double G = atof(usg.optionValue("harris-g", 0).c_str()); size_t B = atoi(usg.optionValue("harris-b", 0).c_str()); + size_t A = atoi(usg.optionValue("harris-a", 0).c_str()); detector_.paramK(K); detector_.paramR(R); detector_.paramW(W); @@ -71,6 +77,7 @@ class Harris: public FeaturePointsDetectors { detector_.paramL(L); detector_.paramG(G); detector_.paramB(B); + detector_.paramA(A); return true; } 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) { } - - - diff --git a/meowpp.test/src/match_MatchAll.cpp b/meowpp.test/src/match_MatchAll.cpp new file mode 100644 index 0000000..062c1e5 --- /dev/null +++ b/meowpp.test/src/match_MatchAll.cpp @@ -0,0 +1,66 @@ +#include "match.h" + +#include "meowpp/gra/FeaturePointsMatch_K_Match.h" +#include "meowpp/Usage.h" +#include "meowpp/oo/ObjSelector.h" + +#include <string> +#include <vector> + +using namespace meow; +using namespace std; + + +class MatchAll_K_Match: public MatchAll { +private: + FeaturePointsMatch_K_Match<double, double, FeaturePoint<double, double, Vector2D<double> > > match_; +public: + vector<PairToPair<size_t> > match(std::vector<std::vector<FP> > const& fpss) const { + int des = 0; + bool ok = false; + for (size_t i = 0; !ok && i < fpss.size(); ++i) + for (size_t j = 0; !ok && j < fpss[i].size(); ++j) { + des = fpss[0][0].description().dimension(); + ok = true; + } + /* + vector<PairToPair<size_t> > normal = match_.match(des, fpss); + ((MatchAll_K_Match*)this)->match_.paramK(match_.paramK() * 2); + vector<PairToPair<size_t> > large = match_.match(des, fpss); + for (size_t i = 0, I = normal.size(); i < I; ++i) { + bool found = false; + for (size_t j = 0, J = large.size(); j < J && !found; ++j) { + if (normal[i] == large[j]) { + found = true; + } + } + if (!found) { + printf("!!!!!!!!!!!!\n"); + } + } + // */ + return match_.match(des, fpss); + } + string description() const { + return string("k nearest match"); + } + Usage usage() const { + Usage tmp; + tmp.optionAdd("kmatch-k", + "...", + "number", + stringPrintf("%d", match_.paramK()), + false); + return tmp; + } + bool usage(Usage const& usg) { + int k = atoi(usg.optionValue("kmatch-k", 0).c_str()); + match_.paramK(k); + return true; + } + ObjBase* create() const { + return new MatchAll_K_Match; + } +}; + +static ObjSelector<kMatchAll_ID> __("kmatch", new MatchAll_K_Match, true); diff --git a/meowpp.test/src/match_MatchChk.cpp b/meowpp.test/src/match_MatchChk.cpp new file mode 100644 index 0000000..6b8239c --- /dev/null +++ b/meowpp.test/src/match_MatchChk.cpp @@ -0,0 +1,102 @@ +#include "match.h" +#include "meowpp/oo/ObjSelector.h" + +using namespace meow; +using namespace std; + + +class MatchChk_Prob: public MatchChk { +private: + double p1_, p0_, pmin_; +public: + MatchChk_Prob(): p1_(0.7), p0_(0.01), pmin_(0.97) { + } + bool check(vector<Vector2D<double> > const& fps1, + size_t w1, + size_t h1, + vector<Vector2D<double> > const& fps2, + size_t w2, + size_t h2, + vector<Pair > const& pairs, + MatchInfo const& info) { + double m_ni = log(p1_ * (1 - p0_)) - log(p0_ * (1 - p1_)); + double c = log(pmin_) - log(1 - pmin_); + double m_nf = log(1 - p0_) - log(1 - p1_); + // ni * ?? > c + nf * ?? + double ni = info.pairs.size(); + double nf = 0; + for (size_t i = 0; i < fps1.size(); ++i) { + Vector2D<double> v( + (fps1[i].dot(info.x_axis) + info.x_offset) / (fps1[i].dot(info.depth) + 1), + (fps1[i].dot(info.y_axis) + info.y_offset) / (fps1[i].dot(info.depth) + 1) + ); + if (0 <= v.x() && v.x() < w2 && 0 <= v.y() && v.y() < h2) { + ++nf; + } + } + //printf("nf = %f, ni = %f\n", nf, ni); + return (ni * m_ni > c + nf * m_nf); + } + string description() const { + return string("prob module"); + } + Usage usage() const { + Usage tmp; + tmp.optionAdd("prob-p1", + "p1", + "floating number", + stringPrintf("%.3f", p1_), + false); + tmp.optionAdd("prob-p0", + "p0", + "floating number", + stringPrintf("%.3f", p0_), + false); + tmp.optionAdd("prob-pmin", + "pmin", + "floating number", + stringPrintf("%.3f", pmin_), + false); + return tmp; + } + bool usage(Usage const& usg) { + p1_ = inRange(0.00001, 0.99999, atof(usg.optionValue("prob-p1" , 0).c_str())); + p0_ = inRange(0.00001, 0.99999, atof(usg.optionValue("prob-p0" , 0).c_str())); + pmin_ = inRange(0.00001, 0.99999, atof(usg.optionValue("prob-pmin", 0).c_str())); + return true; + } + ObjBase* create() const { + return new MatchChk_Prob(); + } +}; + +static ObjSelector<kMatchChk_ID> __("prob-module", new MatchChk_Prob, true); + +class MatchChk_Nothing: public MatchChk { +private: +public: + bool check(vector<Vector2D<double> > const& fps1, + size_t w1, + size_t h1, + vector<Vector2D<double> > const& fps2, + size_t w2, + size_t h2, + vector<Pair > const& pairs, + MatchInfo const& info) { + return true; + } + string description() const { + return string("always true"); + } + Usage usage() const { + return Usage(""); + } + bool usage(Usage const& usg) { + return true; + } + ObjBase* create() const { + return new MatchChk_Nothing(); + } +}; + +static ObjSelector<kMatchChk_ID> ___("nothing", new MatchChk_Nothing, true); diff --git a/meowpp.test/src/match_MatchOne.cpp b/meowpp.test/src/match_MatchOne.cpp new file mode 100644 index 0000000..1ce7bf3 --- /dev/null +++ b/meowpp.test/src/match_MatchOne.cpp @@ -0,0 +1,207 @@ +#include "match.h" +#include <cmath> +#include <algorithm> +#include "meowpp/oo/ObjSelector.h" +#include <vector> +#include "meowpp/math/methods.h" +#include <utility> + +using namespace meow; +using namespace std; + +inline Vector<double> calc8(vector<pair<Vector2D<double>, Vector2D<double> > > const& p) { + Matrix<double> m(p.size() * 2, 8, 0.0), b(8, 1, 0.0); + for (size_t i = 0; i < p.size(); ++i) { + m.entry(i * 2 + 0, 0, p[i].first.x()); + m.entry(i * 2 + 0, 1, p[i].first.y()); + m.entry(i * 2 + 0, 2, 1); + m.entry(i * 2 + 0, 6, -p[i].first.x() * p[i].second.x()); + m.entry(i * 2 + 0, 7, -p[i].first.y() * p[i].second.x()); + m.entry(i * 2 + 1, 3, p[i].first.x()); + m.entry(i * 2 + 1, 4, p[i].first.y()); + m.entry(i * 2 + 1, 5, 1); + m.entry(i * 2 + 1, 6, -p[i].first.x() * p[i].second.y()); + m.entry(i * 2 + 1, 7, -p[i].first.y() * p[i].second.y()); + b.entry(i * 2 + 0, 0, p[i].second.x()); + b.entry(i * 2 + 1, 0, p[i].second.y()); + } + if (p.size() == 4) { + /* + Vector<double> x = m.inverse() * b; + if (x.dimension() == 8) { + bool ok = true; + printf("size = %d\n", (int)x.dimension()); + for (size_t i = 0; i < p.size(); ++i) { + double a = x(0) * p[i].first.x() + x(1) * p[i].first.y() + x(2) - x(6) * p[i].first.x() * p[i].second.x() - x(7) * p[i].first.y() * p[i].second.x() - p[i].second.x(); + double b = x(3) * p[i].first.x() + x(4) * p[i].first.y() + x(5) - x(6) * p[i].first.x() * p[i].second.y() - x(7) * p[i].first.y() * p[i].second.y() - p[i].second.y(); + printf("ab = %f, %f\n", a, b); + if (fabs(a) > 10 || fabs(b) > 10) ok = false; + } + if (!ok) { + for (size_t i = 0; i < p.size(); ++i) { + printf("<%10.3f, %10.3f> ---> <%10.3f, %10.3f>\n", p[i].first.x(), p[i].first.y(), p[i].second.x(), p[i].second.y()); + } + getchar(); + } + } + // */ + return Vector<double>(m.inverse() * b); + } + else { + return Vector<double>((m.transpose() * m).inverse() * m.transpose() * b); + } +} + +inline vector<Pair> goodPair(vector<Vector2D<double> > const& from, + vector<Vector2D<double> > const& to, + vector<Pair> const& pairs, + Vector<double> const& v, + double t) { + vector<Pair> ret; + for (size_t i = 0; i < pairs.size(); ++i) { + Vector2D<double> v1 = from[pairs[i].first ]; + Vector2D<double> v2 = to [pairs[i].second]; + Vector2D<double> v12( + (v1.x() * v(0) + v1.y() * v(1) + v(2)) / (v1.x() * v(6) + v1.y() * v(7) + 1), + (v1.x() * v(3) + v1.y() * v(4) + v(5)) / (v1.x() * v(6) + v1.y() * v(7) + 1) + ); + if ((v12 - v2).length() <= t) { + ret.push_back(pairs[i]); + } + } + return ret; +} + + +class MatchOne_RANSAC: public MatchOne { +private: + double P_, p0_, t_; + double rat_, ang_; + + class Controller { + vector<Vector2D<double> > v1_; + vector<Vector2D<double> > v2_; + double t_, rat_, ang_; + double x_max_, y_max_; + bool check(Vector<double> const& v) const { + Vector2D<double> vx((double)v(0), v(1)); + Vector2D<double> vy((double)v(3), v(4)); + Vector2D<double> d ((double)v(6), v(7)); + double l1 = vx.length() * rat_, l2 = vx.length() / rat_; + if (vy.length() < min(l1, l2) ) return false; + if ( max(l1, l2) < vy.length()) return false; + double ang = acos(vx.dot(vy) / vx.length() / vy.length()); + if (ang < PI * 0.5 - ang_ || PI * 0.5 + ang_ < ang) return false; + if (d.x() * 0 + d.y() * 0 + 1 <= 0) return false; + if (d.x() * x_max_ + d.y() * 0 + 1 <= 0) return false; + if (d.x() * 0 + d.y() * y_max_ + 1 <= 0) return false; + if (d.x() * x_max_ + d.y() * y_max_ + 1 <= 0) return false; + return true; + } + public: + Controller(vector<Vector2D<double> > const& fps1, + vector<Vector2D<double> > const& fps2, + double threshold, + double rat, double ang, double xmax, double ymax): + v1_(fps1), v2_(fps2), t_(threshold), rat_(rat), ang_(fabs(ang)), x_max_(xmax), y_max_(ymax) { + } + double operator()(vector<Pair> const& p, vector<Pair> const& pairs) const { + vector<pair<Vector2D<double>, Vector2D<double> > > ps; + for (size_t i = 0; i < p.size(); ++i) + for (size_t j = 0; j < p.size(); ++j) + if (i != j && (v1_[p[i].first ] == v1_[p[j].first ] || + v2_[p[i].second] == v2_[p[j].second])) + return -1.0; + for (size_t i = 0; i < p.size(); ++i) { + ps.push_back(pair<Vector2D<double>, Vector2D<double> >(v1_[p[i].first], v2_[p[i].second])); + } + Vector<double> v = calc8(ps); + if (v.valid() == false || check(v) == false) return -1; + return 0.1 + (double)goodPair(v1_, v2_, pairs, v, t_).size(); + } + }; +public: + MatchOne_RANSAC(): P_(0.99), p0_(0.05), t_(5), rat_(0.8), ang_(PI / 2 / 8) { + } + MatchInfo match(vector<Vector2D<double> > const& fps1, + vector<Vector2D<double> > const& fps2, + vector<Pair> const& pairs, + size_t width, size_t height) const { + MatchInfo ret; + if ((int)pairs.size() < minNumber()) { + ret.ok = false; + } + else { + ret.pairs = ransac(pairs, Controller(fps1, fps2, t_, rat_, ang_, width, height), minNumber(), p0_, P_); + if ((int)ret.pairs.size() < minNumber()) { + ret.ok = false; + } + else { + vector<pair<Vector2D<double>, Vector2D<double> > > ps; + for (size_t i = 0; i <ret.pairs.size(); ++i) { + ps.push_back(pair<Vector2D<double>, Vector2D<double> >(fps1[ret.pairs[i].first], fps2[ret.pairs[i].second])); + } + Vector<double> v = calc8(ps); + ret.ok = true; + ret.pairs = goodPair(fps1, fps2, pairs, v, t_); + ret.x_axis.x(v(0)); + ret.x_axis.y(v(1)); + ret.x_offset = v(2); + ret.y_axis.x(v(3)); + ret.y_axis.y(v(4)); + ret.y_offset = v(5); + ret.depth.x(v(6)); + ret.depth.y(v(7)); + } + } + return ret; + } + string description() const { + return string("ransac with eight parameter"); + } + Usage usage() const { + Usage tmp; + tmp.optionAdd("ransac-P", + "prob what I want", + "floating number", + stringPrintf("%.2f", P_), + false); + tmp.optionAdd("ransac-p0", + "prob each time", + "floating number", + stringPrintf("%.2f", p0_), + false); + tmp.optionAdd("ransac-t", + "threshold t", + "floating number", + stringPrintf("%.2f", t_), + false); + tmp.optionAdd("ransac-ratio", + "ratio", + "floating number", + stringPrintf("%.2f", rat_), + false); + tmp.optionAdd("ransac-angle", + "angle", + "floating number", + stringPrintf("%.2f", ang_), + false); + return tmp; + } + bool usage(Usage const& usg) { + P_ = inRange(0.00001, 0.99999, atof(usg.optionValue("ransac-P" , 0).c_str())); + p0_ = inRange(0.00001, 0.99999, atof(usg.optionValue("ransac-p0", 0).c_str())); + t_ = inRange(0.00001, 0.99999, atof(usg.optionValue("ransac-t" , 0).c_str())); + rat_ = inRange(0.00001, 0.99999, atof(usg.optionValue("ransac-ratio", 0).c_str())); + ang_ = inRange(0.00001, 0.99999, atof(usg.optionValue("ransac-angle", 0).c_str())); + return true; + } + int minNumber() const { + return 4; + } + ObjBase* create() const { + return new MatchOne_RANSAC; + } +}; + +static ObjSelector<kMatchOne_ID> __("ransac8", new MatchOne_RANSAC, true); diff --git a/meowpp.test/src/match_MatchOne.h b/meowpp.test/src/match_MatchOne.h new file mode 100644 index 0000000..9613fa5 --- /dev/null +++ b/meowpp.test/src/match_MatchOne.h @@ -0,0 +1,45 @@ +#include "match.h" +#include "oo/ObjSelector.h" + +using namespace meow; +using namespace std; + + +class MatchOne_RANSAC: public MatchOne { +private: + double P_, p0_; +public: + MatchOne_RANSAC(): P_(0.99), p0_(0.05) { + } + MatchInfo match(std::vector<meow::Vector2D<double> > const& fps1, + std::vector<meow::Vector2D<double> > const& fps2, + std::vector<std::pair<size_t, size_t> > const& pairs) { + vector<Pair> p = + } + string description() const { + return string("ransac with eight parameter"); + } + Usage usage() const { + Usage tmp; + tmp.optionAdd("ransac-P", + "prob what I want", + "floating number", + stringPrintf("%.2f", P_), + false); + tmp.optionAdd("ransac-p0", + "prob each time", + "floating number", + stringPrintf("%.2f", p0_), + false); + } + bool usage(Usage const& usg) { + P_ = inRange(0.00001, 0.99999, atof(tmp.optionValue("ransac-P" , 0).c_str())); + p0_ = inRange(0.00001, 0.99999, atof(tmp.optionValue("ransac-p0", 0).c_str())); + return true; + } + int minNumber() const { + return 4; + } +}; + +static ObjSelector<kMatchOne_ID> __("ransac8", new MatchOne_RANSAC, true); |