/// <summary> /// This looks at the transition from state pair /// (f1,f2) -> (t1,t2), withthe given cost. /// </summary> public void Relax(int f1, int f2, // input state pair int t1, int t2, // output state pair float cost, // transition cost int arc_id1, // (unused) int arc_id2, // (unused) int input, // input label int intermediate, // (unused) int output, // output label float base_cost, // cost of the path so far int trail_index) { //logger.format("relaxing %d %d -> %d %d (bcost %f, cost %f)", f1, f2, t1, t2, base_cost, cost); if (!nbest.AddReplacingId(t1 * fst2.nStates() + t2, all_costs.Length(), -base_cost - cost)) { return; } //logger.format("nbest changed"); //nbest.log(logger); if (input > 0) { // The candidate for the next beam is stored in all_XX arrays. // (can we store it in the stree instead?) all_inputs.Push(input); all_targets1.Push(t1); all_targets2.Push(t2); all_outputs.Push(output); all_costs.Push(cost); parent_trails.Push(trail_index); } else { // Beam control hack // ----------------- // if a node is important (changes nbest) AND its input is 0, // then it's added to the CURRENT beam. //logger.format("pushing control point from trail %d to %d, %d", //trail_index, t1, t2); int new_node = stree.Add(beam[trail_index], t1, t2, input, output, (float)cost); beam.Push(new_node); beamcost.Push(base_cost + cost); // This is a stub entry indicating that the node should not // be added to the next generation beam. all_inputs.Push(0); all_targets1.Push(-1); all_targets2.Push(-1); all_outputs.Push(0); all_costs.Push(0); parent_trails.Push(-1); } }
public void BestPath(Intarray v1, Intarray v2, Intarray inputs, Intarray outputs, Floatarray costs) { stree.Clear(); beam.Resize(1); beamcost.Resize(1); beam[0] = stree.Add(-1, fst1.GetStart(), fst2.GetStart(), 0, 0, 0); beamcost[0] = 0; best_so_far = 0; best_cost_so_far = fst1.GetAcceptCost(fst1.GetStart()) + fst2.GetAcceptCost(fst1.GetStart()); while (beam.Length() > 0) { Radiate(); } stree.Get(v1, v2, inputs, outputs, costs, best_so_far); costs.Push(fst1.GetAcceptCost(stree.v1[best_so_far]) + fst2.GetAcceptCost(stree.v2[best_so_far])); //logger("costs", costs); }
public void Get(Intarray r_vertices1, Intarray r_vertices2, Intarray r_inputs, Intarray r_outputs, Floatarray r_costs, int id) { Intarray t_v1 = new Intarray(); // vertices Intarray t_v2 = new Intarray(); // vertices Intarray t_i = new Intarray(); // inputs Intarray t_o = new Intarray(); // outputs Floatarray t_c = new Floatarray(); // costs int current = id; while (current != -1) { t_v1.Push(v1[current]); t_v2.Push(v2[current]); t_i.Push(inputs[current]); t_o.Push(outputs[current]); t_c.Push(costs[current]); current = parents[current]; } NarrayUtil.Reverse(r_vertices1, t_v1); NarrayUtil.Reverse(r_vertices2, t_v2); NarrayUtil.Reverse(r_inputs, t_i); NarrayUtil.Reverse(r_outputs, t_o); NarrayUtil.Reverse(r_costs, t_c); }
/// <summary> /// Randomly sample an FST, assuming any input. /// </summary> /// <param name="result">The array of output symbols, excluding epsilons.</param> /// <param name="fst">The FST.</param> /// <param name="max">The maximum length of the result.</param> /// <returns>total cost</returns> public static double fst_sample(Intarray result, IGenericFst fst, int max = 1000) { double total_cost = 0; int current = fst.GetStart(); for (int counter = 0; counter < max; counter++) { Intarray inputs = new Intarray(); Intarray outputs = new Intarray(); Intarray targets = new Intarray(); Floatarray costs = new Floatarray(); fst.Arcs(inputs, targets, outputs, costs, current); // now we need to deal with the costs uniformly, so: costs.Push(fst.GetAcceptCost(current)); int choice = sample_by_costs(costs); if (choice == costs.Length() - 1) { break; } result.Push(outputs[choice]); total_cost += costs[choice]; current = targets[choice]; } return(total_cost + fst.GetAcceptCost(current)); }
public static void line_segmentation_sort_x(Intarray segmentation) { if (NarrayUtil.Max(segmentation) > 100000) { throw new Exception("line_segmentation_merge_small_components: to many segments"); } Narray <Rect> bboxes = new Narray <Rect>(); ImgLabels.bounding_boxes(ref bboxes, segmentation); Floatarray x0s = new Floatarray(); unchecked { x0s.Push((float)-999999); } for (int i = 1; i < bboxes.Length(); i++) { if (bboxes[i].Empty()) { x0s.Push(999999); } else { x0s.Push(bboxes[i].x0); } } // dprint(x0s,1000); printf("\n"); Narray <int> permutation = new Intarray(); Narray <int> rpermutation = new Intarray(); NarrayUtil.Quicksort(permutation, x0s); rpermutation.Resize(permutation.Length()); for (int i = 0; i < permutation.Length(); i++) { rpermutation[permutation[i]] = i; } // dprint(rpermutation,1000); printf("\n"); for (int i = 0; i < segmentation.Length1d(); i++) { if (segmentation.At1d(i) == 0) { continue; } segmentation.Put1d(i, rpermutation[segmentation.At1d(i)]); } }
public List<List<float>> SpaceCosts(List<Candidate> candidates, Bytearray image) { /* Given a list of character recognition candidates and their classifications, and an image of the corresponding text line, compute a list of pairs of costs for putting/not putting a space after each of the candidate characters. The basic idea behind this simple algorithm is to try larger and larger horizontal closing operations until most of the components start having a "wide" aspect ratio; that's when characters have merged into words. The remaining whitespace should be spaces. This is just a simple stopgap measure; it will be replaced with trainable space modeling. */ int w = image.Dim(0); int h = image.Dim(1); Bytearray closed = new Bytearray(); int r; for (r = 0; r < maxrange; r++) { if (r > 0) { closed.Copy(image); Morph.binary_close_circle(closed, r); } else closed.Copy(image); Intarray labeled = new Intarray(); labeled.Copy(closed); ImgLabels.label_components(ref labeled); Narray<Rect> rects = new Narray<Rect>(); ImgLabels.bounding_boxes(ref rects, labeled); Floatarray aspects = new Floatarray(); for (int i = 0; i < rects.Length(); i++) { Rect rect = rects[i]; float aspect = rect.Aspect(); aspects.Push(aspect); } float maspect = NarrayUtil.Median(aspects); if (maspect >= this.aspect_threshold) break; } // close with a little bit of extra space closed.Copy(image); Morph.binary_close_circle(closed, r+1); // compute the remaining aps //Morph.binary_dilate_circle(); // every character box that ends near a cap gets a space appended return null; }
/// <summary> /// The main loop iteration. /// </summary> public void Radiate() { Clear(); //logger("beam", beam); //logger("beamcost", beamcost); int control_beam_start = beam.Length(); for (int i = 0; i < control_beam_start; i++) { TryAccept(i); } // in this loop, traversal may add "control nodes" to the beam for (int i = 0; i < beam.Length(); i++) { Traverse(stree.v1[beam[i]], stree.v2[beam[i]], beamcost[i], i); } // try accepts from control beam nodes // (they're not going to the next beam) for (int i = control_beam_start; i < beam.Length(); i++) { TryAccept(i); } Intarray new_beam = new Intarray(); Floatarray new_beamcost = new Floatarray(); for (int i = 0; i < nbest.Length(); i++) { int k = nbest.Tag(i); if (parent_trails[k] < 0) // skip the control beam nodes { continue; } new_beam.Push(stree.Add(beam[parent_trails[k]], all_targets1[k], all_targets2[k], all_inputs[k], all_outputs[k], all_costs[k])); new_beamcost.Push(beamcost[parent_trails[k]] + all_costs[k]); //logger.format("to new beam: trail index %d, stree %d, target %d,%d", //k, new_beam[new_beam.length() - 1], all_targets1[k], all_targets2[k]); } //move(beam, new_beam); beam.Move(new_beam); //move(beamcost, new_beamcost); beamcost.Move(new_beamcost); }
public void Copy(Floatarray v, float eps = 1e-11f) { Clear(); int n = v.Length(); for (int i = 0; i < n; i++) { float value = v.At1d(i); if (Math.Abs(value) >= eps) { _keys.Push(i); _values.Push(value); } } _len = v.Length(); _keys.Resize(_len); for (int i = 0; i < _len; i++) { _keys.Put1d(i, i); } _values.Copy(v); }
// writing public override int NewState() { accept_costs.Push(1e38f); m_targets.Push(); m_inputs.Push(); m_outputs.Push(); m_costs.Push(); int i = accept_costs.Length() - 1; CorrectTargetsNull(i); CorrectOutputsNull(i); CorrectInputsNull(i); CorrectCostsNull(i); return(i); }
public int Add(int parent, int vertex1, int vertex2, int input, int output, float cost) { int n = parents.Length(); //logger.format("stree: [%d]: parent %d, v1 %d, v2 %d, cost %f", // n, parent, vertex1, vertex2, cost); parents.Push(parent); v1.Push(vertex1); v2.Push(vertex2); inputs.Push(input); outputs.Push(output); costs.Push(cost); return(n); }
public virtual void Extract(Floatarray outa, Floatarray ina) { outa.Clear(); Narray<Floatarray> items = new Narray<Floatarray>(); Extract(items, ina); //int num = 0; for (int i = 0; i < items.Length(); i++) { Floatarray a = items[i]; outa.ReserveTo(outa.Length() + a.Length()); // optimization for (int j = 0; j < a.Length(); j++) { outa.Push(a.At1d(j)); //outa[num++] = a.At1d(j); } } }
public virtual void Extract(Floatarray outa, Floatarray ina) { outa.Clear(); Narray <Floatarray> items = new Narray <Floatarray>(); Extract(items, ina); //int num = 0; for (int i = 0; i < items.Length(); i++) { Floatarray a = items[i]; outa.ReserveTo(outa.Length() + a.Length()); // optimization for (int j = 0; j < a.Length(); j++) { outa.Push(a.At1d(j)); //outa[num++] = a.At1d(j); } } }
/// <summary> /// Push the node in the heap if it's not already there, otherwise promote. /// </summary> /// <returns> /// True if the heap was changed, false if the item was already /// in the heap and with a better cost. /// </returns> public bool Push(int node, float cost) { int i = heapback[node]; if (i != -1) { if (cost < costs[i]) { costs[i] = cost; heapify_up(i); return(true); } return(false); } else { heap.Push(node); costs.Push(cost); heapback[node] = heap.Length() - 1; heapify_up(heap.Length() - 1); return(true); } }
public override void Arcs(Intarray ids, Intarray targets, Intarray outputs, Floatarray costs, int node) { int n1 = node / l2.nStates(); int n2 = node % l2.nStates(); Intarray ids1 = new Intarray(); Intarray ids2 = new Intarray(); Intarray t1 = new Intarray(); Intarray t2 = new Intarray(); Intarray o1 = new Intarray(); Intarray o2 = new Intarray(); Floatarray c1 = new Floatarray(); Floatarray c2 = new Floatarray(); l1.Arcs(ids1, t1, o1, c1, n1); l2.Arcs(ids2, t2, o2, c2, n2); // sort & permute Intarray p1 = new Intarray(); Intarray p2 = new Intarray(); NarrayUtil.Quicksort(p1, o1); NarrayUtil.Permute(ids1, p1); NarrayUtil.Permute(t1, p1); NarrayUtil.Permute(o1, p1); NarrayUtil.Permute(c1, p1); NarrayUtil.Quicksort(p2, ids2); NarrayUtil.Permute(ids2, p2); NarrayUtil.Permute(t2, p2); NarrayUtil.Permute(o2, p2); NarrayUtil.Permute(c2, p2); int k1, k2; // l1 epsilon moves for (k1 = 0; k1 < o1.Length() && o1.At1d(k1) == 0; k1++) { ids.Push(ids1.At1d(k1)); targets.Push(Combine(t1.At1d(k1), n2)); outputs.Push(0); costs.Push(c1.At1d(k1)); } // l2 epsilon moves for (k2 = 0; k2 < o2.Length() && ids2.At1d(k2) == 0; k2++) { ids.Push(0); targets.Push(Combine(n1, t2.At1d(k2))); outputs.Push(o2.At1d(k2)); costs.Push(c2.At1d(k2)); } // non-epsilon moves while (k1 < o1.Length() && k2 < ids2.Length()) { while (k1 < o1.Length() && o1.At1d(k1) < ids2.At1d(k2)) { k1++; } if (k1 >= o1.Length()) { break; } while (k2 < ids2.Length() && o1.At1d(k1) > ids2.At1d(k2)) { k2++; } while (k1 < o1.Length() && k2 < ids2.Length() && o1.At1d(k1) == ids2.At1d(k2)) { for (int j = k2; j < ids2.Length() && o1.At1d(k1) == ids2.At1d(j); j++) { ids.Push(ids1.At1d(k1)); targets.Push(Combine(t1.At1d(k1), t2.At1d(j))); outputs.Push(o2.At1d(j)); costs.Push(c1.At1d(k1) + c2.At1d(j)); } k1++; } } }
public List <List <float> > SpaceCosts(List <Candidate> candidates, Bytearray image) { /* * Given a list of character recognition candidates and their * classifications, and an image of the corresponding text line, * compute a list of pairs of costs for putting/not putting a space * after each of the candidate characters. * * The basic idea behind this simple algorithm is to try larger * and larger horizontal closing operations until most of the components * start having a "wide" aspect ratio; that's when characters have merged * into words. The remaining whitespace should be spaces. * * This is just a simple stopgap measure; it will be replaced with * trainable space modeling. */ int w = image.Dim(0); int h = image.Dim(1); Bytearray closed = new Bytearray(); int r; for (r = 0; r < maxrange; r++) { if (r > 0) { closed.Copy(image); Morph.binary_close_circle(closed, r); } else { closed.Copy(image); } Intarray labeled = new Intarray(); labeled.Copy(closed); ImgLabels.label_components(ref labeled); Narray <Rect> rects = new Narray <Rect>(); ImgLabels.bounding_boxes(ref rects, labeled); Floatarray aspects = new Floatarray(); for (int i = 0; i < rects.Length(); i++) { Rect rect = rects[i]; float aspect = rect.Aspect(); aspects.Push(aspect); } float maspect = NarrayUtil.Median(aspects); if (maspect >= this.aspect_threshold) { break; } } // close with a little bit of extra space closed.Copy(image); Morph.binary_close_circle(closed, r + 1); // compute the remaining aps //Morph.binary_dilate_circle(); // every character box that ends near a cap gets a space appended return(null); }
public override void Arcs(Intarray ids, Intarray targets, Intarray outputs, Floatarray costs, int node) { int n1 = node / l2.nStates(); int n2 = node % l2.nStates(); Intarray ids1 = new Intarray(); Intarray ids2 = new Intarray(); Intarray t1 = new Intarray(); Intarray t2 = new Intarray(); Intarray o1 = new Intarray(); Intarray o2 = new Intarray(); Floatarray c1 = new Floatarray(); Floatarray c2 = new Floatarray(); l1.Arcs(ids1, t1, o1, c1, n1); l2.Arcs(ids2, t2, o2, c2, n2); // sort & permute Intarray p1 = new Intarray(); Intarray p2 = new Intarray(); NarrayUtil.Quicksort(p1, o1); NarrayUtil.Permute(ids1, p1); NarrayUtil.Permute(t1, p1); NarrayUtil.Permute(o1, p1); NarrayUtil.Permute(c1, p1); NarrayUtil.Quicksort(p2, ids2); NarrayUtil.Permute(ids2, p2); NarrayUtil.Permute(t2, p2); NarrayUtil.Permute(o2, p2); NarrayUtil.Permute(c2, p2); int k1, k2; // l1 epsilon moves for (k1 = 0; k1 < o1.Length() && o1.At1d(k1) == 0; k1++) { ids.Push(ids1.At1d(k1)); targets.Push(Combine(t1.At1d(k1), n2)); outputs.Push(0); costs.Push(c1.At1d(k1)); } // l2 epsilon moves for (k2 = 0; k2 < o2.Length() && ids2.At1d(k2) == 0; k2++) { ids.Push(0); targets.Push(Combine(n1, t2.At1d(k2))); outputs.Push(o2.At1d(k2)); costs.Push(c2.At1d(k2)); } // non-epsilon moves while (k1 < o1.Length() && k2 < ids2.Length()) { while (k1 < o1.Length() && o1.At1d(k1) < ids2.At1d(k2)) k1++; if (k1 >= o1.Length()) break; while (k2 < ids2.Length() && o1.At1d(k1) > ids2.At1d(k2)) k2++; while (k1 < o1.Length() && k2 < ids2.Length() && o1.At1d(k1) == ids2.At1d(k2)) { for (int j = k2; j < ids2.Length() && o1.At1d(k1) == ids2.At1d(j); j++) { ids.Push(ids1.At1d(k1)); targets.Push(Combine(t1.At1d(k1), t2.At1d(j))); outputs.Push(o2.At1d(j)); costs.Push(c1.At1d(k1) + c2.At1d(j)); } k1++; } } }
public void BestPath(Intarray v1, Intarray v2, Intarray inputs, Intarray outputs, Floatarray costs) { stree.Clear(); beam.Resize(1); beamcost.Resize(1); beam[0] = stree.Add(-1, fst1.GetStart(), fst2.GetStart(), 0, 0, 0); beamcost[0] = 0; best_so_far = 0; best_cost_so_far = fst1.GetAcceptCost(fst1.GetStart()) + fst2.GetAcceptCost(fst1.GetStart()); while (beam.Length() > 0) Radiate(); stree.Get(v1, v2, inputs, outputs, costs, best_so_far); costs.Push(fst1.GetAcceptCost(stree.v1[best_so_far]) + fst2.GetAcceptCost(stree.v2[best_so_far])); //logger("costs", costs); }
/// <summary> /// The main loop iteration. /// </summary> public void Radiate() { Clear(); //logger("beam", beam); //logger("beamcost", beamcost); int control_beam_start = beam.Length(); for (int i = 0; i < control_beam_start; i++) TryAccept(i); // in this loop, traversal may add "control nodes" to the beam for (int i = 0; i < beam.Length(); i++) { Traverse(stree.v1[beam[i]], stree.v2[beam[i]], beamcost[i], i); } // try accepts from control beam nodes // (they're not going to the next beam) for (int i = control_beam_start; i < beam.Length(); i++) TryAccept(i); Intarray new_beam = new Intarray(); Floatarray new_beamcost = new Floatarray(); for (int i = 0; i < nbest.Length(); i++) { int k = nbest.Tag(i); if (parent_trails[k] < 0) // skip the control beam nodes continue; new_beam.Push(stree.Add(beam[parent_trails[k]], all_targets1[k], all_targets2[k], all_inputs[k], all_outputs[k], all_costs[k])); new_beamcost.Push(beamcost[parent_trails[k]] + all_costs[k]); //logger.format("to new beam: trail index %d, stree %d, target %d,%d", //k, new_beam[new_beam.length() - 1], all_targets1[k], all_targets2[k]); } //move(beam, new_beam); beam.Move(new_beam); //move(beamcost, new_beamcost); beamcost.Move(new_beamcost); }
/// <summary> /// Randomly sample an FST, assuming any input. /// </summary> /// <param name="result">The array of output symbols, excluding epsilons.</param> /// <param name="fst">The FST.</param> /// <param name="max">The maximum length of the result.</param> /// <returns>total cost</returns> public static double fst_sample(Intarray result, IGenericFst fst, int max=1000) { double total_cost = 0; int current = fst.GetStart(); for (int counter = 0; counter < max; counter++) { Intarray inputs = new Intarray(); Intarray outputs = new Intarray(); Intarray targets = new Intarray(); Floatarray costs = new Floatarray(); fst.Arcs(inputs, targets, outputs, costs, current); // now we need to deal with the costs uniformly, so: costs.Push(fst.GetAcceptCost(current)); int choice = sample_by_costs(costs); if (choice == costs.Length() - 1) break; result.Push(outputs[choice]); total_cost += costs[choice]; current = targets[choice]; } return total_cost + fst.GetAcceptCost(current); }