int main(){ while (1) { char* word; word = malloc(200); scanf("%s", word); add_to_hash(word); free(word); if (should_stop()){ break; } } sort_all(); print_all(); return 0; }
void HehFeatureGen::Compute(const ImageRGB<byte>& imagergb, const ImageF& image, const MatI& seg) { // General notes: // We must always be careful to deal with normalized image // coordinates, which range from 0 to 1 in both dimensions. This // includes pixel locations, vanishing point locations, and line // intersections. // Any homogeneous vector can represent a point at infinity, which // will manifest as an INF if we Project() it. This is fine so // long as we keep track of which coordinates might potentially be // INF and only do sensible things with them -- e.g. no sqrt(), // atan2(), division between two variables that can both be INF, // etc. const int w = image.GetWidth(); const int h = image.GetHeight(); const int image_size = w*h; // Run the filter bank // TODO: implement LM filters. Here we just use 12 Gabor filters. vector<shared_ptr<ImageF> > responses; FilterBank filterbank(1); // *** should be 3 scales MakeGaborFilters(4, &filterbank.filters); filterbank.Run(image, &responses); // // Find lines and compute vanishing points // vpts.Compute(image); const int num_lines = vpts.lines.segments.size(); const int num_vpts = vpts.vanpts.size(); // // Pre-process the line segments // // Whether each pair of lines is nearly parallel MatI is_nearly_parallel(num_lines, num_lines); // Whether the intersection of each pair is right of center MatI isct_is_right(num_lines, num_lines); // Whether the intersection of each pair is below center MatI isct_is_bottom(num_lines, num_lines); // Histogram bin index for intersection of each pair, or -1 if outside MatI isct_bin(num_lines, num_lines); // Compute line intersections for (int i = 0; i < num_lines; i++) { const LineSegment& segi = *vpts.lines.segments[i]; is_nearly_parallel[i][i] = 0; for (int j = 1; j < num_lines; j++) { const LineSegment& segj = *vpts.lines.segments[j]; // Parallel ? float dtheta = segi.theta - segj.theta; dtheta = min(dtheta, M_PI-dtheta); is_nearly_parallel[i][j] = (dtheta <= kParallelThresh ? 1 : 0); if (is_nearly_parallel[i][j]) { // Intersection position relative to center Vec3 isct = Cross3D(segi.line, segj.line); isct[0] /= w; // can be +/- INF isct[1] /= h; // can be +/- INF const float eucl_x = Project(isct)[0]; const float eucl_y = Project(isct)[1]; isct_is_right[i][j] = eucl_x > 0.5; isct_is_bottom[i][j] = eucl_y > 0.5; // Compute distance from centre // don't take sqrt(radius_sqr) because radius_sqr can be INF const float radius_sqr = eucl_x*eucl_x + eucl_y*eucl_y; int rad_bin = -1; if (radius_sqr > kFarRadius*kFarRadius) { rad_bin = 1; } else if (radius_sqr > kNearRadius*kNearRadius) { rad_bin = 0; } // Compute orientation from centre if (rad_bin == -1) { isct_bin[i][j] = -1; } else { // Must do atan2 with homogeneous coords. It will stay sane in // the case of points-at-infinity float phi = atan2(isct[1] - 0.5*isct[2], isct[0] - 0.5*isct[2]); int phi_bin = static_cast<int>(phi*M_PI/kNumOrientBins)%kNumOrientBins; int bin = rad_bin * kNumOrientBins + phi_bin; isct_bin[i][j] = bin; } } is_nearly_parallel[j][i] = is_nearly_parallel[i][j]; isct_is_right[j][i] = isct_is_right[i][j]; isct_is_bottom[j][i] = isct_is_bottom[i][j]; isct_bin[j][i] = isct_bin[i][j]; } } // // Pre-process vanishing points // enum VanPointCla { kVptNone, kVptHoriz, kVptVert }; const float h_vpt_min = 0.5-kHorizVptThresh; const float h_vpt_max = 0.5+kHorizVptThresh; const float v_vpt_low = 0.5-kVertVptThresh; const float v_vpt_high = 0.5+kVertVptThresh; int num_hvpts = 0; float sum_hvpts_y = 0; vector<VectorFixed<2,float> > norm_vpts; // can contain INF VecI vanpt_cla(vpts.vanpts.size(), kVptNone); COUNTED_FOREACH(int i, const VecD& vpt, vpts.vanpts) { const float eucl_x = Project(vpt)[0] / w; // can be +/-INF const float eucl_y = Project(vpt)[1] / h; // can be +/-INF // Classify vanishing point as horizontal, vertical, or none norm_vpts.push_back(MakeVector<2,float>(eucl_x, eucl_y)); if (eucl_y > h_vpt_min && eucl_y < h_vpt_max) { vanpt_cla[i] = kVptHoriz; sum_hvpts_y += eucl_y; num_hvpts++; } else if (eucl_y < v_vpt_low || eucl_y > v_vpt_high) { vanpt_cla[i] = kVptVert; } } // Assume horizon is horizontal with Y coord equal to average of the // "horizontal" vanishing points float horizon_y = 0.5; if (num_hvpts > 0) { horizon_y = sum_hvpts_y / num_hvpts; } // Print vanpt clas DREPORT(vanpt_cla); // Initialize features int num_segments = seg.MaxValue()+1; features.resize(num_segments); for (int i = 0; i < features.size(); i++) { features[i].seen = VecI(num_lines, 0); } // // Compute sums over the image // for (int r = 0; r < h; r++) { const PixelRGB<byte>* imrgbrow = imagergb[r]; const PixelF* imrow = image[r]; const int* segrow = seg[r]; const int* linerow = vpts.lines.segment_map[r]; for (int c = 0; c < w; c++) { HehFeature& ftr = features[segrow[c]]; // Shape ftr.xs.push_back(1.0*c/w); ftr.ys.push_back(1.0*r/h); // Color PixelHSV<byte> hsv; const PixelRGB<byte>& rgb = imrgbrow[c]; ImageConversions::RGB2HSV(rgb.r, rgb.g, rgb.b, hsv.h, hsv.s, hsv.v); ftr.r_mean += rgb.r; ftr.g_mean += rgb.g; ftr.b_mean += rgb.b; ftr.h_mean += hsv.h; ftr.s_mean += hsv.s; ftr.v_mean += hsv.v; const int hbin = static_cast<int>(kNumHueBins * hsv.h / 256); const int sbin = static_cast<int>(kNumSatBins * hsv.s / 256); ftr.hue_hist[hbin]++; ftr.sat_hist[sbin]++; // Texture ImageRef pyrpos(c, r); int maxi; float maxv = -INFINITY; for (int i = 0; i < responses.size(); i++) { if (i > 0 && responses[i]->GetWidth() < responses[i-1]->GetWidth()) { pyrpos /= 2; } const float v = (*responses[i])[pyrpos].y; ftr.filter_means[i] += v; if (v > maxv) { maxv = v; maxi = i; } } ftr.filter_max_hist[maxi]++; // Lines const int line = linerow[c]; if (line != -1) { if (!ftr.seen[line]) { ftr.seen[line] = 1; ftr.lines.push_back(line); } ftr.num_line_pix++; const int line_cla = vanpt_cla[vpts.owners[line]]; if (line_cla == kVptVert) { ftr.pct_vert_vpt++; ftr.pct_vert_vpt_pix++; } else if (line_cla == kVptHoriz) { ftr.pct_horiz_vpt_pix++; } } } } // // Normalize over each segment // for (int i = 0; i < features.size(); i++) { HehFeature& ftr = features[i]; float size = ftr.xs.size(); // Shape ftr.area = size/image_size; sort_all(ftr.xs); sort_all(ftr.ys); ftr.x_mean = accumulate_all(ftr.xs, 0.0) / size; ftr.x_10pct = ftr.xs[size/10]; ftr.x_90pct = ftr.xs[size*9/10]; ftr.y_mean = accumulate_all(ftr.ys, 0.0) / size; ftr.y_10pct = ftr.ys[size/10]; ftr.y_90pct = ftr.ys[size*9/10]; ftr.y_mean_wrt_horizon = ftr.y_mean - horizon_y; ftr.y_10pct_wrt_horizon = ftr.y_10pct - horizon_y; ftr.y_90pct_wrt_horizon = ftr.y_90pct - horizon_y; // Color ftr.r_mean /= size; ftr.g_mean /= size; ftr.b_mean /= size; ftr.h_mean /= size; ftr.s_mean /= size; ftr.v_mean /= size; ftr.hue_hist /= size; ftr.sat_hist /= size; // Texture ftr.filter_means /= size; ftr.filter_max_hist /= size; // Lines int num_nearly_parallel = 0; BOOST_FOREACH(int i, ftr.lines) { BOOST_FOREACH(int j, ftr.lines) { if (i == j) continue; if (is_nearly_parallel[i][j]) { num_nearly_parallel++; ftr.pct_parallel_lines++; if (isct_is_right[i][j]) { ftr.pct_isct_right++; } if (isct_is_bottom[i][j]) { ftr.pct_isct_bottom++; } if (isct_bin[i][j] != -1) { ftr.isct_hist[isct_bin[i][j]]++; } } } } const int num_line_pairs = ftr.lines.size() * (ftr.lines.size()-1); const float sqrt_area = sqrt(size); // don't use normalized area! ftr.pct_line_pix = ftr.num_line_pix / sqrt_area; if (num_line_pairs > 0) { ftr.pct_parallel_lines /= num_line_pairs; } if (num_nearly_parallel > 0) { ftr.isct_hist /= num_nearly_parallel; ftr.isct_hist_entropy = GetEntropy(ftr.isct_hist); ftr.pct_isct_right /= num_nearly_parallel; ftr.pct_isct_bottom /= num_nearly_parallel; } // Vanishing points bool has_horiz_vpt = false; bool has_vert_vpt = false; float horiz_vpt_x; float vert_vpt_y; for (int i = 0; i < ftr.lines.size(); i++) { const int owner_vpt = vpts.owners[ftr.lines[i]]; if (vanpt_cla[owner_vpt] == kVptHoriz) { horiz_vpt_x = Project(norm_vpts[owner_vpt])[0]; // can be +/- INF has_horiz_vpt = true; } if (vanpt_cla[owner_vpt] == kVptHoriz) { vert_vpt_y = Project(norm_vpts[owner_vpt])[1]; // can be +/- INF has_vert_vpt = true; } } ftr.pct_vert_vpt_pix /= sqrt_area; ftr.pct_horiz_vpt_pix /= sqrt_area; if (ftr.num_line_pix > 0) { ftr.pct_vert_vpt /= ftr.num_line_pix; } if (has_horiz_vpt) { ftr.x_mean_wrt_hvpt = ftr.x_mean - horiz_vpt_x; // can be +/- INF ftr.x_10pct_wrt_hvpt = ftr.x_10pct - horiz_vpt_x; // can be +/- INF ftr.x_90pct_wrt_hvpt = ftr.x_90pct - horiz_vpt_x; // can be +/- INF } else { ftr.x_mean_wrt_hvpt = 0; ftr.x_10pct_wrt_hvpt = 0; ftr.x_90pct_wrt_hvpt = 0; } if (has_vert_vpt) { ftr.y_mean_wrt_vert_vpt = ftr.y_mean - vert_vpt_y; } else { ftr.y_mean_wrt_vert_vpt = 0; } } }
void ManhattanGroundTruth::ProcessWalls(const proto::FloorPlan& fp, const PosedCamera& pc) { // Initialize nocclusions = 0; nwalls = 0; // First strip out the NaN vertices vector<Vec2> verts; for (int i = 0; i < fp.vertices_size(); i++) { Vec2 v = asToon(fp.vertices(i)); if (!isnan(v[0]) && !isnan(v[1])) { verts.push_back(v); } } // Compute rectifier in retina coords Mat3 ret_vrect = GetVerticalRectifierInRetina(pc); Mat3 ret_vrect_inv = LU<3>(ret_vrect).get_inverse(); Bounds2D<> ret_vrect_bounds = Bounds2D<>::ComputeBoundingBox (pc.retina_bounds().GetPolygon().Transform(ret_vrect)); Interval xbounds(ret_vrect_bounds.left(), ret_vrect_bounds.right()); // Note that the floorplan vertices do _not_ wrap around Vec3 focal_line = makeVector(0, -1, 1e-6); vector<Vec3> lines; vector<Interval> intervals; for (int i = 0; i < verts.size()-1; i++) { Vec3 a_cam = ret_vrect * (pc.pose() * concat(verts[i], 0.0)); Vec3 b_cam = ret_vrect * (pc.pose() * concat(verts[i+1], 0.0)); Vec3 a_flat = makeVector(a_cam[0], a_cam[2], 1.0); // y no longer matters, and now homog Vec3 b_flat = makeVector(b_cam[0], b_cam[2], 1.0); // y no longer matters, and now homog bool nonempty = ClipAgainstLine(a_flat, b_flat, focal_line, -1); if (nonempty) { // project() must come after clipping Vec2 a0 = project(a_flat); Vec2 b0 = project(b_flat); intervals.push_back(Interval(a0[0]/a0[1], b0[0]/b0[1])); lines.push_back(a_flat ^ b_flat); } } // Compare polygons MatI interval_comp(verts.size()-1, verts.size()-1); for (int i = 0; i < intervals.size(); i++) { for (int j = 0; j < intervals.size(); j++) { if (i==j) continue; Interval isct = Intersect(intervals[i], intervals[j]); if (isct.empty()) { interval_comp[i][j] = i>j ? 1 : -1; } else { double m = (isct.hi + isct.lo) / 2.; double zi = -lines[i][2] / (lines[i][0]*m + lines[i][1]); double zj = -lines[j][2] / (lines[j][0]*m + lines[j][1]); interval_comp[i][j] = zi > zj ? 1 : -1; } } } // Generate tokens vector<Token> tokens; for (int i = 0; i < intervals.size(); i++) { tokens.push_back(Token(intervals[i].lo, i, true)); tokens.push_back(Token(intervals[i].hi, i, false)); } // Add tokens for left and right image bounds tokens.push_back(Token(xbounds.lo, -1, true)); tokens.push_back(Token(xbounds.hi, -1, false)); sort_all(tokens); // Walk from left to right vector<Vec2> xs; int prev = -1; bool inbounds = false; bool done = false; VecI active(intervals.size(), 0); TableComp comp(interval_comp); priority_queue<int,vector<int>,TableComp> heap(comp); for (int i = 0; !done; i++) { // Process next token bool bound_token = tokens[i].index == -1; if (bound_token && tokens[i].activate) { inbounds = true; } else if (bound_token && !tokens[i].activate) { done = true; } else if (tokens[i].activate) { active[tokens[i].index] = true; heap.push(tokens[i].index); } else { active[tokens[i].index] = false; while (!heap.empty() && !active[heap.top()]) { // okay for heap to be temporarily empty heap.pop(); } } double xcur = tokens[i].x; if ((tokens[i+1].x-xcur) > 1e-8) { int cur = heap.empty() ? -1 : heap.top(); // Count walls if (inbounds && (cur != prev || bound_token)) { if (!done) { nwalls++; if (!bound_token && RingDist<int>(prev, cur, intervals.size()) > 1) { nocclusions++; } } // Reconstruct vertices vector<int> to_add; if (!xs.empty()) { to_add.push_back(prev); } if (!done) { to_add.push_back(cur); } // Compute vertices BOOST_FOREACH(int j, to_add) { const Vec3& line = lines[j]; const Interval& intv = intervals[j]; Vec2 pflat = project(line ^ makeVector(-1, xcur, 0)); Vec3 pcam = makeVector(pflat[0], 0, pflat[1]); Vec3 pworld = pc.pose_inverse() * (ret_vrect_inv * pcam); xs.push_back(pworld.slice<0,2>()); } } prev = cur; } }