1 // This is brl/bpro/core/vil_pro/processes/vil_binary_edge_detection_process.cxx
2 #include <iostream>
3 #include <algorithm>
4 #include <bprb/bprb_func_process.h>
5 //:
6 // \file
7 // Process to return edge pixels of a binary image using vil_blob
8
9 #include "vil/vil_image_view.h"
10 #include <vil/algo/vil_structuring_element.h>
11 #include <vil/algo/vil_blob.h>
12 #include <vil/algo/vil_binary_closing.h>
13 #include "vil/vil_save.h"
14 #ifdef _MSC_VER
15 # include "vcl_msvc_warnings.h"
16 #endif
17
18 namespace vil_binary_edge_detection_process_globals
19 {
20 unsigned n_inputs_ = 4;
21 unsigned n_outputs_ = 1;
22 }
23
24 //: constructor
vil_binary_edge_detection_process_cons(bprb_func_process & pro)25 bool vil_binary_edge_detection_process_cons(bprb_func_process& pro)
26 {
27 using namespace vil_binary_edge_detection_process_globals;
28 // process takes 3 inputs
29 std::vector<std::string> input_types(n_inputs_);
30 input_types[0] = "vil_image_view_base_sptr"; // input image
31 input_types[1] = "unsigned"; // max size of the blob in pixels
32 input_types[2] = "unsigned"; // min size of the blob in pixels
33 input_types[3] = "unsigned"; // threshold id to transfer from byte image to boolean image
34 // process takes 1 output
35 std::vector<std::string> output_types(n_outputs_);
36 output_types[0] = "vil_image_view_base_sptr"; // edge image
37
38 return pro.set_input_types(input_types) && pro.set_output_types(output_types);
39 }
40
41 //: execute the process
vil_binary_edge_detection_process(bprb_func_process & pro)42 bool vil_binary_edge_detection_process(bprb_func_process& pro)
43 {
44 // sanity check
45 if (!pro.verify_inputs())
46 return false;
47 // get input
48 unsigned in_i = 0;
49 vil_image_view_base_sptr img_ptr = pro.get_input<vil_image_view_base_sptr>(in_i++);
50 auto max_size = pro.get_input<unsigned>(in_i++);
51 auto min_size = pro.get_input<unsigned>(in_i++);
52 auto threshold = pro.get_input<unsigned>(in_i++);
53 auto thres_id = (unsigned char)threshold;
54
55 auto* view = dynamic_cast<vil_image_view<bool>*>(img_ptr.ptr());
56 if (!view) {
57 vil_image_view<bool> temp(img_ptr->ni(), img_ptr->nj(), img_ptr->nplanes());
58 temp.fill(false);
59 auto* view_temp = dynamic_cast<vil_image_view<vxl_byte>*>(img_ptr.ptr());
60 if (!view_temp) {
61 std::cerr << pro.name() << " input image pixel " << img_ptr->pixel_format() << " is not supported!\n";
62 return false;
63 }
64 // transfer byte image
65 for (unsigned i = 0; i < img_ptr->ni(); i++)
66 for (unsigned j = 0; j < img_ptr->nj(); j++)
67 for (unsigned k = 0; k < img_ptr->nplanes(); k++)
68 if ( (*view_temp)(i,j,k) == thres_id)
69 temp(i,j,k) = true;
70 view = new vil_image_view<bool>(temp);
71 }
72
73 // Closing the holes or gaps
74 vil_structuring_element selem;
75 selem.set_to_disk(1.0);
76 vil_image_view<bool> view_closed(view->ni(),view->nj());
77 vil_binary_closing(*view,view_closed,selem);
78
79 // Find the blob
80 vil_image_view<unsigned> blob_labels;
81 vil_image_view<unsigned> edge_labels;
82 std::vector<vil_blob_pixel_list> edge_pixel_list;
83 vil_blob_labels(*view, vil_blob_8_conn, blob_labels);
84 vil_blob_labels_to_edge_labels(blob_labels, vil_blob_8_conn, edge_labels);
85 vil_blob_labels_to_pixel_lists(edge_labels, edge_pixel_list);
86
87 // remove the edges that do not satisfy the desired size
88 std::vector<unsigned> valid_edge_labels;
89 for (auto & vit : edge_pixel_list) {
90 if ( vit.size() > max_size || vit.size() < min_size )
91 continue;
92 unsigned label = edge_labels(vit.begin()->first, vit.begin()->second);
93 valid_edge_labels.push_back(label);
94 }
95
96
97 vil_image_view<vxl_byte> view_blobs(view->ni(),view->nj());
98 view_blobs.fill(0);
99 for (unsigned i = 0; i < edge_labels.ni(); i++)
100 for (unsigned j = 0; j < edge_labels.nj(); j++)
101 for (unsigned k = 0; k < edge_labels.nplanes(); k++)
102 if ( std::find(valid_edge_labels.begin(), valid_edge_labels.end(), edge_labels(i,j,k)) != valid_edge_labels.end())
103 view_blobs(i,j,k) = 255;
104
105 // output
106 pro.set_output_val<vil_image_view_base_sptr>(0, new vil_image_view<vxl_byte>(view_blobs));
107
108 return true;
109 }
110