Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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;
        }
    }