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