1 //This is brl/bpro/core/vil_pro/processes/vil_nitf_remove_margin_process.cxx
2 #include <iostream>
3 #include <cmath>
4 #include <bprb/bprb_func_process.h>
5 //:
6 // \file
7 //
8 //  a process to remove margin existed in satellite imagery, assuming the margin is a rectangular region and have zero pixel value in all the bands
9 //
10 
11 #include "vil/vil_image_resource.h"
12 #include "vil/vil_image_resource_sptr.h"
13 #include "vil/vil_new.h"
14 #include "vil/vil_image_view.h"
15 #include "vil/vil_blocked_image_resource.h"
16 #include "vil/vil_blocked_image_resource_sptr.h"
17 #include "vil/vil_crop.h"
18 #ifdef _MSC_VER
19 #  include "vcl_msvc_warnings.h"
20 #endif
21 #include "vil/vil_save.h"
22 #include "vil/vil_plane.h"
23 
24 //: set the input and output type
vil_nitf_remove_margin_process_cons(bprb_func_process & pro)25 bool vil_nitf_remove_margin_process_cons(bprb_func_process& pro)
26 {
27   // process takes one input
28   std::vector<std::string> input_types_(1);
29   input_types_[0]  = "vil_image_resource_sptr";
30   // process has one output
31   std::vector<std::string> output_types_(4);
32   output_types_[0] = "unsigned";  // top left valid image position vi
33   output_types_[1] = "unsigned";  // top left valid image position vj
34   output_types_[2] = "unsigned";  // valid image size vni
35   output_types_[3] = "unsigned";  // valid image size vnj
36   return pro.set_input_types(input_types_) && pro.set_output_types(output_types_);
37 }
38 
39 //: execute the process
vil_nitf_remove_margin_process(bprb_func_process & pro)40 bool vil_nitf_remove_margin_process(bprb_func_process& pro)
41 {
42   // sanity check
43   if (!pro.verify_inputs()) {
44     std::cerr << pro.name() << ": Invalid inputs!\n";
45     return false;
46   }
47   // get input
48   unsigned in_i = 0;
49   vil_image_resource_sptr img_res_sptr = pro.get_input<vil_image_resource_sptr>(in_i);
50   if (!img_res_sptr) {
51     std::cerr << pro.name() << ": problem with the inut image resource handle!\n";
52     return false;
53   }
54   if (img_res_sptr->pixel_format() != VIL_PIXEL_FORMAT_UINT_16) {
55     std::cerr << pro.name() << ": unsupported pixel format -- " << img_res_sptr->pixel_format() << "!\n";
56     return false;
57   }
58 
59   unsigned int ni = img_res_sptr->ni();
60   unsigned int nj = img_res_sptr->nj();
61 
62   unsigned int vi = 0, vj = 0, vni = 0, vnj = 0;
63 
64   // create blocked image resource for IO speed up
65   vil_blocked_image_resource_sptr bir = blocked_image_resource(img_res_sptr);
66 
67   // start by trimming from top left corner
68   bool found = false;
69   unsigned sub_i0, sub_j0, sub_size_i, sub_size_j;
70   sub_i0 = 0;
71   sub_j0 = 0;
72   sub_size_i = std::floor(ni / 10.0);
73   sub_size_j = std::floor(nj / 10.0);
74   for (unsigned sub_idx_i = 1; (sub_idx_i <= 10 && !found);  sub_idx_i++)
75     for (unsigned sub_idx_j = 1; (sub_idx_j <= 10 && !found);  sub_idx_j++)
76     {
77       unsigned sni = sub_idx_i * sub_size_i;
78       if (sub_size_i == 10)  sni = ni;
79       unsigned snj = sub_idx_j * sub_size_j;
80       if (sub_size_j == 10)  snj = nj;
81       if (sni == 0 || snj == 0)
82         continue;
83       // get the block view from blocked image resource
84       vil_image_view_base_sptr roi = bir->get_copy_view(sub_i0, sni, sub_j0, snj);
85       if (!roi) {
86         std::cerr << pro.name() << " can not crop from image with size " << ni << 'x' << nj << " at position (" << sub_i0 << ',' << sub_j0
87                  << ") of size (" << sni << ',' << snj << ")!\n";
88         return false;
89       }
90       // check pixels inside roi
91       vil_image_view<vxl_uint_16> img(roi);
92       for (unsigned p = 0; (p < img.nplanes() && !found); p++)
93         for (unsigned i = 0; (i < img.ni() && !found); i++)
94           for (unsigned j = 0; (j < img.nj() && !found); j++)
95             if (img(i,j,p) != 0) {
96               found = true;
97               vi = sub_i0 + i; vj = sub_j0 + j;
98             }
99     }
100   if (!found) {
101     std::cerr << pro.name() << ": entire image is invalid!\n";
102     return false;
103   }
104 
105   // trimming from the bottom right
106   found = false;
107   unsigned int bottom_i = ni, bottom_j = nj;
108   for (int sub_idx_i = 10; (sub_idx_i >= 0 && !found); sub_idx_i--) {
109     for (int sub_idx_j = 10; (sub_idx_j >= 0 && !found); sub_idx_j--)
110     {
111       sub_i0 = sub_idx_i * sub_size_i;
112       sub_j0 = sub_idx_j * sub_size_j;
113       unsigned sni = ni - sub_i0, snj = nj - sub_j0;
114       if (sni == 0 || snj == 0)
115         continue;
116       // get the block view from blocked image resource
117       vil_image_view_base_sptr roi = bir->get_copy_view(sub_i0, sni, sub_j0, snj);
118       if (!roi) {
119         std::cerr << pro.name() << " can not crop from image with size " << ni << 'x' << nj << " at position (" << sub_i0 << ',' << sub_j0
120                  << ") of size (" << sni << ',' << snj << ")!\n";
121         return false;
122       }
123       // check pixels inside roi
124       vil_image_view<vxl_uint_16> img(roi);
125       for (unsigned p = 0; (p < img.nplanes() && !found); p++)
126         for (int i = (int)(img.ni()-1); (i >= 0 && !found); i--)
127           for (int j = (int)(img.nj()-1); (j >= 0 && !found); j--)
128             if (img(i,j,p) != 0) {
129               found = true;
130               bottom_i = sub_i0+i;  bottom_j = sub_j0+j;
131 #if 0
132               // save the image for debugging purpose
133               std::cout << "image has valid pixel: sub_i0: " << sub_i0 << ", sub_j0: " << sub_j0 << ", sni: " << sni << ", snj: " << snj << std::endl;
134               std::cout << " valid pixel is caught at pixel (" << i << ',' << j << ',' << p << ")" << std::endl;
135               std::string out_folder = "d:/work/Dropbox/pyscripts/expt_scripts/src/11jul10003056-m1bs-500081228070_01_p001/";
136               std::string band_c_file = out_folder + "coastal.tif";
137               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 0)), band_c_file.c_str());
138               std::string band_b_file = out_folder + "blue.tif";
139               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 1)), band_b_file.c_str());
140               std::string band_g_file = out_folder + "green.tif";
141               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 2)), band_g_file.c_str());
142               std::string band_y_file = out_folder + "yellow.tif";
143               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 3)), band_y_file.c_str());
144               std::string band_r_file = out_folder + "red.tif";
145               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 4)), band_r_file.c_str());
146               std::string band_re_file = out_folder + "red_edge.tif";
147               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 5)), band_re_file.c_str());
148               std::string band_nir1_file = out_folder + "nir1.tif";
149               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 6)), band_nir1_file.c_str());
150               std::string band_nir2_file = out_folder + "nir2.tif";
151               vil_save(vil_image_view<vxl_uint_16>(vil_plane(img, 7)), band_nir2_file.c_str());
152 #endif
153             }
154     }
155   }
156   if (!found) {
157     std::cerr << pro.name() << ": entire image is invalid!\n";
158     return false;
159   }
160 
161   // calculate image size
162   vni = bottom_i - vi;
163   vnj = bottom_j - vj;
164 
165   // truncate 50 pixels on each boundary
166   unsigned margin = 50;
167   vi += margin;
168   vj += margin;
169   if (vni > margin)  vni -= margin;
170   if (vnj > margin)  vnj -= margin;
171 
172   unsigned out_i = 0;
173   pro.set_output_val<unsigned>(out_i++,  vi);
174   pro.set_output_val<unsigned>(out_i++,  vj);
175   pro.set_output_val<unsigned>(out_i++, vni);
176   pro.set_output_val<unsigned>(out_i++, vnj);
177 
178   return true;
179 }
180