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