//--------------------------------------------------------- // Compute x-coordinates (LP-based approach) (for graphs) //--------------------------------------------------------- void OptimalHierarchyLayout::computeXCoordinates( const Hierarchy& H, GraphCopyAttributes &AGC) { const GraphCopy &GC = H; const int k = H.size(); // // preprocessing: determine nodes that are considered as virtual // NodeArray<bool> isVirtual(GC); int i; for(i = 0; i < k; ++i) { const Level &L = H[i]; int last = -1; for(int j = 0; j < L.size(); ++j) { node v = L[j]; if(H.isLongEdgeDummy(v) == true) { isVirtual[v] = true; node u = v->firstAdj()->theEdge()->target(); if(u == v) u = v->lastAdj()->theEdge()->target(); if(H.isLongEdgeDummy(u) == true) { int down = H.pos(u); if(last != -1 && last > down) { isVirtual[v] = false; } else { last = down; } } } else isVirtual[v] = false; } } // // determine variables of LP // int nSegments = 0; // number of vertical segments int nRealVertices = 0; // number of real vertices int nEdges = 0; // number of edges not in vertical segments int nBalanced = 0; // number of real vertices with deg > 1 for which // balancing constraints may be applied NodeArray<int> vIndex(GC,-1); // for real node: index of x[v] // for dummy: index of corresponding segment NodeArray<int> bIndex(GC,-1); // (relative) index of b[v] EdgeArray<int> eIndex(GC,-1); // for edge not in vertical segment: // its index Array<int> count(GC.numberOfEdges()); // counts the number of dummy vertices // in corresponding segment that are not at // position 0 for(i = 0; i < k; ++i) { const Level &L = H[i]; for(int j = 0; j < L.size(); ++j) { node v = L[j]; if(isVirtual[v] == true) continue; // we've found a real vertex vIndex[v] = nRealVertices++; if(v->degree() > 1) bIndex[v] = nBalanced++; // consider all outgoing edges edge e; forall_adj_edges(e,v) { node w = e->target(); if(w == v) continue; // we've found an edge not belonging to a vetical segment eIndex[e] = nEdges++; if(isVirtual[w] == false) continue; // we've found a vertical segment count[nSegments] = 0; do { vIndex[w] = nSegments; const int high = H[H.rank(w)].high(); if(high > 0) { if (H.pos(w) == 0 || H.pos(w) == high) ++count[nSegments]; else count[nSegments] += 2; } // next edge / dummy in segment e = e->adjTarget()->cyclicSucc()->theEdge(); w = e->target(); } while(isVirtual[w]); // edge following vertical segment eIndex[e] = nEdges++; ++nSegments; } } }
int main(int argc, char** argv) { // Initialize Google's logging library. google::InitGoogleLogging(argv[0]); google::ParseCommandLineFlags(&argc, &argv, true); if (FLAGS_logging) { FLAGS_logtostderr = 1; } if (FLAGS_input.empty()) { std::cerr << "Input file not specified. Specify via -input.\n"; return 1; } // Determine conversion mode. enum ConvMode { CONV_TEXT, CONV_BINARY, CONV_BITMAP_ID, CONV_BITMAP_COLOR, STRIP }; ConvMode mode = CONV_TEXT; float hier_level = 0; std::string dest_filename; if (FLAGS_text_format) { mode = CONV_TEXT; std::cout << "Converting to text."; } else if (FLAGS_binary_format) { mode = CONV_BINARY; std::cout << "Converting to binary format."; } else if (FLAGS_bitmap_ids >= 0) { mode = CONV_BITMAP_ID; hier_level = FLAGS_bitmap_ids; std::cout << "Converting to id bitmaps for hierarchy level: " << hier_level << "\n"; } else if (FLAGS_bitmap_color >= 0) { mode = CONV_BITMAP_COLOR; hier_level = FLAGS_bitmap_color; std::cout << "Converting to color bitmaps for hierarchy level: " << hier_level << "\n"; } else if (!FLAGS_strip.empty()) { mode = STRIP; dest_filename = FLAGS_strip; } else { std::cout << "Unknown mode specified.\n"; return 1; } std::string filename = FLAGS_input; // Read segmentation file. // Don't need rasterization when we are stripping file. const bool valid_rasterization = !FLAGS_strip.empty(); SegmentationReader segment_reader(filename, valid_rasterization); segment_reader.OpenFileAndReadHeaders(); std::vector<int> segment_headers = segment_reader.GetHeaderFlags(); std::cout << "Segmentation file " << filename << " contains " << segment_reader.NumFrames() << " frames.\n"; SegmentationWriter* writer = nullptr; bool use_vectorization = false; if (mode == STRIP) { writer = new SegmentationWriter(dest_filename); std::vector<int> header_entries; if (!FLAGS_use_rasterization && segment_headers.size() > 0) { header_entries.push_back(use_vectorization = segment_headers[0]); } else { header_entries.push_back(0); } header_entries.push_back(0); // No shape moments. if (!writer->OpenFile(header_entries)) { std::cout << "Could not open destination file.\n"; delete writer; return 1; } LOG(INFO) << "Stripping files with " << (use_vectorization ? "vectorization" : "rasterization"); } Hierarchy hierarchy; const int chunk_size = 100; // By default use chunks of 100 frames. int absolute_level = -1; // Use absolute level if supplied. if (hier_level == 0 || hier_level >= 1) { absolute_level = hier_level; } for (int f = 0; f < segment_reader.NumFrames(); ++f) { segment_reader.SeekToFrame(f); // Read from file. SegmentationDesc segmentation; segment_reader.ReadNextFrame(&segmentation); if (segmentation.hierarchy_size() > 0) { hierarchy.Clear(); hierarchy.MergeFrom(segmentation.hierarchy()); // Convert fractional to constant absolute level. if (absolute_level < 0) { absolute_level = hier_level * (float)hierarchy.size(); LOG(INFO) << "Selecting level " << absolute_level << " of " << hierarchy.size() << std::endl; } } std::string curr_file = FLAGS_output_dir + "/"; if (mode == CONV_TEXT) { curr_file += base::StringPrintf("frame%05d.pbtxt", f); } else if (mode == CONV_BINARY) { curr_file += base::StringPrintf("frame%05d.pb", f); } else { curr_file += base::StringPrintf("frame%05d.png", f); } if (f % 5 == 0) { std::cout << "Writing frame " << f << " of " << segment_reader.NumFrames() << "\n"; } int frame_width = segmentation.frame_width(); int frame_height = segmentation.frame_height(); if (mode == CONV_BINARY) { std::ofstream ofs(curr_file, std::ios_base::out | std::ios_base::binary); segmentation.SerializeToOstream(&ofs); } else if (mode == CONV_TEXT) { std::ofstream ofs(curr_file, std::ios_base::out); ofs << segmentation.DebugString(); } else if (mode == CONV_BITMAP_ID) { cv::Mat id_image(frame_height, frame_width, CV_32S); SegmentationDescToIdImage(absolute_level, segmentation, &hierarchy, &id_image); // Get 4 channel view via evil casting. cv::Mat id_image_view(frame_height, frame_width, CV_8UC4, id_image.ptr<uint8_t>(0)); // Discard most significant 8bit (little endian). vector<cv::Mat> id_channels; cv::split(id_image_view, id_channels); cv::Mat frame_buffer(frame_height, frame_width, CV_8UC3); cv::merge(&id_channels[0], 3, frame_buffer); cv::imwrite(curr_file, frame_buffer); } else if (mode == CONV_BITMAP_COLOR) { cv::Mat frame_buffer(frame_height, frame_width, CV_8UC3); RenderRegionsRandomColor(absolute_level, true, false, segmentation, &hierarchy, &frame_buffer); cv::imwrite(curr_file, frame_buffer); } else if (mode == STRIP) { std::string stripped_data; StripToEssentials(segmentation, use_vectorization, false, // no shape moments. &stripped_data); writer->AddSegmentationDataToChunk(stripped_data, f); if (f > 0 && f % chunk_size == 0) { writer->WriteChunk(); } } } if (mode == STRIP) { writer->WriteTermHeaderAndClose(); delete writer; } segment_reader.CloseFile(); return 0; }