DGtalTools 2.1.0
Loading...
Searching...
No Matches
img2freeman.cpp
1
24#include "DGtal/io/colormaps/GrayscaleColorMap.h"
25#include "DGtal/io/readers/GenericReader.h"
26#include "DGtal/images/ImageContainerBySTLVector.h"
27#include "DGtal/images/ImageSelector.h"
28#include "DGtal/geometry/curves/FreemanChain.h"
29#include "DGtal/geometry/helpers/ContourHelper.h"
30#include "DGtal/topology/helpers/Surfaces.h"
31
32#include "CLI11.hpp"
33
34#include <vector>
35#include <string>
36#include <climits>
37
38
39using namespace DGtal;
101typedef ImageSelector < Z2i::Domain, unsigned char>::Type Image;
102
103
104std::vector<unsigned int> getHistoFromImage(const Image &image){
105 const Image::Domain &imgDom = image.domain();
106 std::vector<unsigned int> vectHisto(UCHAR_MAX);
107 for(Image::Domain::ConstIterator it=imgDom.begin(); it!= imgDom.end(); ++it){
108 vectHisto[image(*it)]++;
109 }
110 return vectHisto;
111}
112
113unsigned int
114getOtsuThreshold(const Image &image){
115 std::vector<unsigned int> histo = getHistoFromImage(image);
116 unsigned int imageSize = image.domain().size();
117 unsigned int sumA = 0;
118 unsigned int sumB = imageSize;
119 unsigned int muA=0;
120 unsigned int muB=0;
121 unsigned int sumMuAll= 0;
122 for( unsigned int t=0; t< histo.size();t++){
123 sumMuAll+=histo[t]*t;
124 }
125
126 unsigned int thresholdRes=0;
127 double valMax=0.0;
128 for( unsigned int t=0; t< histo.size(); t++){
129 sumA+=histo[t];
130 if(sumA==0)
131 continue;
132 sumB=imageSize-sumA;
133 if(sumB==0){
134 break;
135 }
136
137 muA+=histo[t]*t;
138 muB=sumMuAll-muA;
139 double muAr=muA/(double)sumA;
140 double muBr=muB/(double)sumB;
141 double sigma= (double)sumA*(double)sumB*(muAr-muBr)*(muAr-muBr);
142 if(valMax<=sigma){
143 valMax=sigma;
144 thresholdRes=t;
145 }
146 }
147 return thresholdRes;
148}
149
150struct CompContours{
151 bool operator()(std::vector<Z2i::Point> a, std::vector<Z2i::Point> b ){
152 return a.size() > b.size();
153 }
154};
155
156
157void saveAllContoursAsFc( std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels,
158 unsigned int minSize, bool sort=false){
159 CompContours comp;
160 if(sort){
161 std::sort(vectContoursBdryPointels.begin(), vectContoursBdryPointels.end(), comp);
162 }
163 for(unsigned int k=0; k<vectContoursBdryPointels.size(); k++){
164 if(vectContoursBdryPointels.at(k).size()>minSize){
165 FreemanChain<Z2i::Integer> fc (vectContoursBdryPointels.at(k));
166 std::cout << fc.x0 << " " << fc.y0 << " " << fc.chain << std::endl;
167
168 }
169 }
170}
171
172
173void saveSelContoursAsFC(std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels,
174 unsigned int minSize, Z2i::Point refPoint, double selectDistanceMax,
175 bool sort=false){
176 CompContours comp;
177 if(sort){
178 std::sort(vectContoursBdryPointels.begin(), vectContoursBdryPointels.end(), comp);
179 }
180
181 for(unsigned int k=0; k<vectContoursBdryPointels.size(); k++){
182 if(vectContoursBdryPointels.at(k).size()>minSize){
183 Z2i::RealPoint ptMean = ContourHelper::getBarycenter(vectContoursBdryPointels.at(k));
184 unsigned int distance = (unsigned int)ceil(sqrt((ptMean[0]-refPoint[0])*(ptMean[0]-refPoint[0])+
185 (ptMean[1]-refPoint[1])*(ptMean[1]-refPoint[1])));
186 if(distance<=selectDistanceMax){
187 FreemanChain<Z2i::Integer> fc (vectContoursBdryPointels.at(k));
188 std::cout << fc.x0 << " " << fc.y0 << " " << fc.chain << std::endl;
189 }
190 }
191 }
192}
193
194
195
196
197int main( int argc, char** argv )
198{
199 // parse command line using CLI ----------------------------------------------
200 CLI::App app;
201 std::string inputFileName;
202 std::string outputFileName {"result.fc"};
203
204 double minThreshold {128};
205 double maxThreshold {255};
206 unsigned int minSize {0};
207 bool select {false};
208 bool sortCnt {false};
209
210 Z2i::Point selectCenter;
211 unsigned int selectDistanceMax = 0;
212 std::vector<int> cntConstraints;
213 std::vector<int> vectRangeMin, vectRangeMax, vectRange;
214
215 app.description("Extract FreemanChains from thresholded image.\n Basic example: \t img2freeman [options] --input <imageName> -min 128 -max 255 > contours.fc \n Note that if you don't specify any threshold a threshold threshold max is automatically defined from the Otsu algorithm with min=0. ");
216 app.add_option("-i,--input,1", inputFileName, "input image file name (any 2D image format accepted by DGtal::GenericReader)." )
217 ->required()
218 ->check(CLI::ExistingFile);
219 app.add_option("-m,--min", minThreshold, "min image threshold value (default 128)");
220 app.add_option("-M,--max", maxThreshold, "max image threshold value (default 255)");
221 app.add_flag("--sort", sortCnt,"to sort the resulting freemanchain by decreasing size." );
222 app.add_option("-s,--minSize", minSize,"minSize of the extracted freeman chain (default 0)" );
223 app.add_option("contourSelect",cntConstraints,"Select contour according reference point and maximal distance: ex. --contourSelect X Y distanceMax" )
224 -> expected(3);
225 app.add_option("-r,--thresholdRangeMin",vectRangeMin, "use a range interval as threshold (from min) : --thresholdRangeMin min increment max : for each possible i, it define a digital sets [min, min+((i+1)*increment)] such that min+((i+1)*increment)< max and extract their boundary." )
226 -> expected(3);
227 app.add_option("-R,--thresholdRangeMax",vectRangeMax, "use a range interval as threshold (from max) : --thresholdRangeMax min increment max : for each possible i, it define a digital sets [ max-((i)*increment), max] such that max-((i)*increment)>min and extract their boundary." )
228 -> expected(3);
229
230
231 app.get_formatter()->column_width(40);
232 CLI11_PARSE(app, argc, argv);
233 // END parse command line using CLI ----------------------------------------------
234
235
236 bool thresholdRange=vectRangeMax.size()==3 || vectRangeMin.size()==3;
237 typedef functors::IntervalThresholder<Image::Value> Binarizer;
238 Image image = GenericReader<Image>::import( inputFileName );
239
240
241 if(cntConstraints.size()==3){
242 select=true;
243 selectCenter[0]= cntConstraints.at(0);
244 selectCenter[1]= cntConstraints.at(1);
245 selectDistanceMax= (unsigned int) cntConstraints.at(2);
246 }
247
248 int min, max, increment;
249 if(! thresholdRange){
250 min=(int)minThreshold;
251 max= (int)maxThreshold;
252 increment = (int)(maxThreshold - minThreshold);
253 if(minThreshold == 128 && maxThreshold == 255) {
254 min=0;
255 trace.info() << "Min/Max threshold values not specified, set min to 0 and computing max with the otsu algorithm...";
256 max = getOtsuThreshold(image);
257 trace.info() << "[done] (max= " << max << ") "<< std::endl;
258 }
259
260 }else{
261 vectRange = (vectRangeMin.size()==3) ? vectRangeMin : vectRangeMax;
262 min=vectRange.at(0);
263 increment=vectRange.at(1);
264 max = vectRange.at(2);
265 minThreshold=min;
266 maxThreshold=max;
267 }
268
269
270 Z2i::KSpace ks;
271 if(! ks.init( image.domain().lowerBound(),
272 image.domain().upperBound(), true )){
273 trace.error() << "Problem in KSpace initialisation"<< std::endl;
274 }
275
276
277 if (!thresholdRange){
278 Binarizer b(min, max);
279 functors::PointFunctorPredicate<Image,Binarizer> predicate(image, b);
280 trace.info() << "DGtal contour extraction from thresholds ["<< min << "," << max << "]" ;
281 SurfelAdjacency<2> sAdj( true );
282 std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels;
283 Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels,
284 ks, predicate, sAdj );
285 if(select){
286 saveSelContoursAsFC(vectContoursBdryPointels, minSize, selectCenter, selectDistanceMax, sortCnt);
287 }else{
288 saveAllContoursAsFc(vectContoursBdryPointels, minSize, sortCnt);
289 }
290 }else{
291 for(int i=0; minThreshold+i*increment< maxThreshold; i++){
292 if(vectRangeMin.size()==3){
293 min = (int)(minThreshold+(i)*increment);
294 }
295 if(vectRangeMax.size()==3){
296 max = (int)(maxThreshold-(i)*increment);
297 }
298 Binarizer b(min, max);
299 functors::PointFunctorPredicate<Image,Binarizer> predicate(image, b);
300
301 trace.info() << "DGtal contour extraction from thresholds ["<< min << "," << max << "]" ;
302 SurfelAdjacency<2> sAdj( true );
303 std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels;
304 Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels,
305 ks, predicate, sAdj );
306 if(select){
307 saveSelContoursAsFC(vectContoursBdryPointels, minSize,
308 selectCenter, selectDistanceMax, sortCnt);
309 }else{
310 saveAllContoursAsFc(vectContoursBdryPointels,
311 minSize, sortCnt);
312 }
313 trace.info() << " [done]" << std::endl;
314 }
315 }
316}
317
Definition ATu0v1.h:57