// -*- C++ -*-
// $RCSfile: automation.C,v $
// $Revision: 1.31 $
// $Author: langer $
// $Date: 2000/09/06 20:11:24 $
/* This software was produced by NIST, an agency of the U.S. government,
* and by statute is not subject to copyright in the United States.
* Recipients of this software assume all responsibilities associated
* with its operation, modification and maintenance. However, to
* facilitate maintenance we ask that before distributing modifed
* versions of this software, you first contact the authors at
* oof_manager@ctcms.nist.gov.
*/
#include "burn.h"
#include "burner.h"
#include "goof.h"
#include "image.h"
#include <math.h>
#include "menuinterrupt.h"
#include "pixelgroups.h"
#include "random.h"
#include "stencil.h"
#include "vec.h"
void Goof::autoSelect(const Image & theImage,
const CharString &grainGroupName,
const CharString &boundaryGroupName,
const Color &lowerColorBound,
const Color &upperColorBound,
const int localBurn, const int globalBurn,
const int minSize,
const double minAspect, const double maxAspect,
const double maxPerimeter, bool verbose, bool auto_redraw)
{
//automated selection of regions on an image as Group A or B
garcon()->msout << ms_info << "Starting automatic selection..." << endl;
PixelGroup *grain, *boundary; //the two materials
if(!(grain=get_group(grainGroupName)))
grain=add_group(grainGroupName);
if(!(boundary=get_group(boundaryGroupName)))
boundary=add_group(boundaryGroupName);
PixelGroup toBurn;
toBurn.setphysicalsize(height*width); //so the group doesn't have to be
//resized before every addition
//(saves a lot of time)
ArrayIterator iter(theImage);
Cell_coordinate cell;
while(iter(cell)){
if(theImage[cell].query_red()>=lowerColorBound.query_red() &&
theImage[cell].query_red()<=upperColorBound.query_red() &&
theImage[cell].query_blue()>=lowerColorBound.query_blue() &&
theImage[cell].query_blue()<=upperColorBound.query_blue() &&
theImage[cell].query_green()>=lowerColorBound.query_green() &&
theImage[cell].query_green()<=upperColorBound.query_green())
toBurn.append(cell);
}
int initialSize = toBurn.size();
if(verbose)
garcon()->msout << " " << initialSize << " pixels to burn" << endl;
if(toBurn.size()!=0){
Interrupter stop;
Burn burner;
//set burn parameters (Class Goof is a friend to Class Burn)
burner.lcl=localBurn;
burner.glbl=globalBurn;
init_selection(0);
//while there are unslected pixels still left
while((toBurn.size()>0) && !stop()){
//pick random cell coordinate to burn and scale it to toBurn accordingly
double random=rndm();
int index=(int)floor((random*(toBurn.size())));
if(index==toBurn.size())
index--;
burner.igniteNoUndo(theImage, toBurn[index], 0);
(void) current_goof->doDespeckle(5);
double aspect=selected().aspectRatio();
double perimeter=selected().perimeter();
if(verbose)
garcon()->msout << "At " << toBurn[index] << " selected "
<< selected().size() << " pixels that were " ;
if(selected().size()<minSize){
//selection is too small to use aspectRatio or perimeter
//remove the chosen pixel from toBurn group
toBurn.remove(toBurn[index]);
if(verbose)
garcon()->msout << "not enough." << endl;
}
else if(((aspect>minAspect) && (perimeter>maxPerimeter))
|| (aspect>maxAspect)){
//selection is probably part of Group B (boundary)
toBurn.remove(toBurn[index]);
if(verbose)
garcon()->msout << "probably part of Group B." << endl;
if(auto_redraw)
redraw();
}
else{
//selection is part of Group A (grain)
toBurn.remove(selected());
grain->append(selected());
if(verbose)
garcon()->msout << "added to Group A." << endl;
if(auto_redraw)
redraw();
}
if(verbose)
garcon()->msout << "Pixels left to burn: " << toBurn.size()
<< " (" << toBurn.size()*100./initialSize << "%)"
<< endl;
}
grain->weed();
if(verbose)
garcon()->msout << "Total Group A pixels selected before expand: "
<< grain->size() << endl;
expandgroup(*grain, 1);
if(verbose)
garcon()->msout << "Total Group A pixels selected after expand: "
<< grain->size() << endl;
//invert Group A to get Group B
select(*grain);
select_complement();
boundary->append(selected());
unselect_all();
garcon()->msout << "Automated Selection Complete." << endl;
}
else
garcon()->msout << ms_error << "No pixels in color range!" << endl
<< ms_normal;
}
syntax highlighted by Code2HTML, v. 0.9.1