| Bsoft 2.0.5 Bernard's software package

balign.cpp
Go to the documentation of this file.
1
9 #include "rwimg.h"
10 #include "ps_marker.h"
11 #include "linked_list.h"
12 #include "options.h"
13 #include "utilities.h"
14 #include "timer.h"
15
16 // Declaration of global variables
17 extern int verbose; // Level of output to the screen
18
19 Transform img_align(Bimage* p1, Bimage* p2, Vector3<long> tile_size,
20 double res_lo, double res_hi, double max_shift, int filter_flag, int refine_flag);
21
22 // Usage assistance
23 const char* use[] = {
24 " ",
25 "Usage: balign [options] input1.img input2.img output.img",
26 "--------------------------------------------------------",
27 "The second input image is aligned to the first, transformed and output.",
28 "(Note: This program is intended to align very large micrograph images).",
29 " ",
30 "Actions:",
31 "-add Add input images after transforming the second.",
32 "-filterextremes Filter micrograph extremes before aligning.",
33 " ",
34 "Parameters:",
35 "-verbose 7 Verbosity of output.",
36 "-datatype u Force writing of a new data type.",
37 "-sampling 1.5,1.5,1.5 Sampling (A/pixel; a single value can be given).",
38 "-tile 1024,1024,5 Size of tiles for correlation (default 512,512,1).",
39 "-resolution 30,500 High and low resolution limits for cross-correlation (default 0.1,1000).",
40 "-maxshift 55 Maximum allowed shift (default 1/4 of tile).",
41 " ",
42 NULL
43 };
44
45 int main(int argc, char* argv[])
46 {
47 // Initialize all settings
48 DataType nudatatype(Unknown_Type); // Conversion to new type
49 Vector3<double> sam; // Units for the three axes (A/pixel)
50 int add(0);
51 Vector3<long> tile_size(512,512,1);
52 double res_hi(0.1);
53 double res_lo(1000);
54 double max_shift(0);
55 int filter_flag(0);
56 int refine_flag(1);
57
58 int optind;
59 Boption* option = get_option_list(use, argc, argv, optind);
60 Boption* curropt;
61 for ( curropt = option; curropt; curropt = curropt->next ) {
62 if ( curropt->tag == "datatype" )
63 nudatatype = curropt->datatype();
64 if ( curropt->tag == "sampling" )
65 sam = curropt->sampling();
66 if ( curropt->tag == "add" )
67 add = 1;
68 if ( curropt->tag == "filterextremes" )
69 filter_flag = 1;
70 if ( curropt->tag == "tile" ) tile_size = curropt->size();
71 if ( curropt->tag == "resolution" ) {
72 if ( curropt->values(res_hi, res_lo) < 1 )
73 cerr << "-resolution: A high resolution limit must be specified." << endl;
74 else if ( res_hi > res_lo )
75 swap(res_hi, res_lo);
76 }
77 if ( curropt->tag == "maxshift" )
78 if ( ( max_shift = curropt->value.real() ) < 1 )
79 cerr << "-maxshift: A maximum shift in pixels must be specified." << endl;
80 }
81 option_kill(option);
82
83 double ti = timer_start();
84
85 // Read the input files
86 int dataflag(0);
87 if ( optind < argc - 1 ) dataflag = 1;
88 Bimage* p1 = read_img(argv[optind++], dataflag, -1);
89 if ( p1 == NULL ) {
90 cerr << "Error: No input file read!" << endl;
91 bexit(-1);
92 }
93
94 Bimage* p2 = read_img(argv[optind++], dataflag, -1);
95 if ( p2 == NULL ) {
96 cerr << "Error: No input file read!" << endl;
97 bexit(-1);
98 }
99
100 if ( sam.volume() ) {
101 p1->sampling(sam);
102 p2->sampling(sam);
103 }
104
105 Transform t = img_align(p1, p2, tile_size, res_lo, res_hi, max_shift, filter_flag, refine_flag);
106
107 p2->transform(t.scale, t.origin, t.trans, Matrix3(t.axis, t.angle), FILL_USER, p2->average());
108
109 Bimage* p = NULL;
110 if ( add ) p = *p1 + *p2;
111 if ( !p ) p = p2;
112
113 // Write an output file if a file name is given
114 if ( argc > optind && strspn(argv[optind],"-") != 1 ) {
115 p->label(get_cmd_line(argc, argv));
116 p->change_type(nudatatype);
117 write_img(argv[optind], p, 0);
118 }
119
120 if ( p != p2 ) delete p;
121 delete p1;
122 delete p2;
123
124 if ( verbose & VERB_TIME )
125 timer_report(ti);
126
127 bexit(0);
128 }
129
145 Transform img_align(Bimage* p1, Bimage* p2, Vector3<long> tile_size,
146 double res_lo, double res_hi, double max_shift, int filter_flag, int refine_flag)
147 {
148 long i, iter, maxiter(5);
149 Vector3<double> shift;
150 Transform t, best_t;
151 best_t.fom = 1e37;
152
153 Vector3<long> start1, common_size, step_size;
154
155 // Find the largest area covering both images
156 common_size = p1->size().min(p2->size());
157 common_size = common_size.max(1);
158
159 // Ensure the tile fits into the images
160 tile_size = tile_size.max(1);
161 tile_size = tile_size.min(common_size);
162 if ( tile_size[0] >= common_size[0] && common_size[0] > 1 ) {
163 tile_size[0] = (int) (0.4*common_size[0]);
164 // start1[0] = (common_size[0] - tile_size[0])/2;
165 }
166 if ( tile_size[1] >= common_size[1] && common_size[1] > 1 ) {
167 tile_size[1] = (int) (0.4*common_size[1]);
168 // start1[1] = (common_size[1] - tile_size[1])/2;
169 }
170 if ( tile_size[2] >= common_size[2] && common_size[2] > 1 ) {
171 tile_size[2] = (int) (0.4*common_size[2]);
172 // start1[2] = (common_size[2] - tile_size[2])/2;
173 }
174
175 if ( max_shift < 1 ) max_shift = tile_size[0]/4;
176
177 Vector3<double> half_tile;
178 half_tile[0] = (tile_size[0] - 1)/2;
179 half_tile[1] = (tile_size[1] - 1)/2;
180 half_tile[2] = (tile_size[2] - 1)/2;
181
182 Bimage* pex1 = NULL;
183 Bimage* pex2 = NULL;
184 Bmarker* set1 = NULL;
185 Bmarker* set2 = NULL;
186 Bmarker* m1 = NULL;
187 Bmarker* m2 = NULL;
188 Bstring fn1(p1->file_name()), fn2(p2->file_name());
189 Bstring filename = fn1.pre_rev('.') + "_" + fn2.pre_rev('.') + ".ps";
190
191 if ( verbose & VERB_LABEL ) {
192 cout << "Aligning images ";
193 if ( refine_flag ) cout << "with ";
194 else cout << "without ";
195 cout << "shift refinement." << endl << endl;
196 }
197
198 if ( common_size[0] > 2*tile_size[0] )
199 start1[0] = (common_size[0]
200 - (int) (tile_size[0]*(common_size[0]/tile_size[0])))/2;
201 if ( common_size[1] > 2*tile_size[1] )
202 start1[1] = (common_size[1]
203 - (int) (tile_size[1]*(common_size[1]/tile_size[1])))/2;
204 if ( common_size[2] > 2*tile_size[2] )
205 start1[2] = (common_size[2]
206 - (int) (tile_size[2]*(common_size[2]/tile_size[2])))/2;
207
208 if ( verbose & VERB_PROCESS ) {
209 cout << "Common size: " << common_size << endl;
210 cout << "Tile size: " << tile_size << endl;
211 cout << "Maximum shift: " << max_shift << endl;
212 cout << "Reference start: " << start1 << endl << endl;
213 }
214
215 if ( res_hi < 0.1 || res_hi > tile_size[0]*p1->sampling()[0] ) res_hi = 4.0*p1->sampling()[0];
216
217 if ( filter_flag ) {
218 p1->filter_extremes();
219 p2->filter_extremes();
220 }
221
222 pex1 = p1->extract_tiles(0, start1, common_size, tile_size, step_size, 0);
223
224 vector<Vector3<long>> tile_start(pex1->images());
225
226 for ( i=0; i<pex1->images(); i++ ) {
227 m1 = (Bmarker *) add_item((char **) &m1, sizeof(Bmarker));
228 m2 = (Bmarker *) add_item((char **) &m2, sizeof(Bmarker));
229 if ( !set1 ) set1 = m1;
230 if ( !set2 ) set2 = m2;
231 m1->sel = m2->sel = 1;
232 m1->fom = m2->fom = 1;
233 m1->loc = pex1->image[i].origin() + half_tile;
234 tile_start[i] = pex1->image[i].origin();
235 }
236
237 for ( iter=0; iter<maxiter && best_t.fom>0.1; iter++ ) {
238 pex2 = p2->extract_tiles(0, tile_start, tile_size);
239 // Determines the shift of the second image onto the first
240 pex1->find_shift(pex2, NULL, res_hi, res_lo, max_shift, 0, refine_flag);
241 for ( i=0, m2=set2; i<pex1->images(); i++, m2=m2->next ) {
242 shift = pex1->image[i].origin() - pex2->image[i].origin();
243 if ( shift[0] > half_tile[0] ) shift[0] -= tile_size[0];
244 if ( shift[1] > half_tile[1] ) shift[1] -= tile_size[1];
245 if ( shift[2] > half_tile[2] ) shift[2] -= tile_size[2];
246 // To get the location in the second image, the shift must be subtracted
247 m2->loc = tile_start[i] + half_tile - shift;
248 }
249 t = markers_find_rottrans(set1, set2, 0.01);
250 // if ( verbose & VERB_PROCESS )
251 cout << "Fit " << iter+1 << ":\t" << p1->file_name() << tab << p2->file_name() << tab
252 << t.trans << tab
253 << t.scale << tab
254 << t.angle*180.0/M_PI << tab << t.fom << endl;
255 if ( best_t.fom > t.fom ) best_t = t;
256 else iter = maxiter;
257 for ( i=0, m1=set1, m2=set2; i<pex1->images(); i++, m1=m1->next, m2=m2->next ) {
258 m2->loc[0] = best_t.scale[0]*(m1->loc[0]*cos(best_t.angle) -
259 m1->loc[1]*sin(best_t.angle)) + t.trans[0] + 0.5;
260 m2->loc[1] = best_t.scale[1]*(m1->loc[0]*sin(best_t.angle) +
261 m1->loc[1]*cos(best_t.angle)) + t.trans[1] + 0.5;
262 m2->loc[2] = best_t.scale[2]*m1->loc[2] + t.trans[2];
263 tile_start[i] = m2->loc - half_tile;
264 }
265 delete pex2;
266 }
267
268 if ( verbose & VERB_RESULT )
269 cout << "Best fit:\t" <<
270 p1->file_name() << tab << p2->file_name() << tab <<
271 best_t.trans << tab <<
272 best_t.scale << tab <<
273 best_t.angle*180.0/M_PI << tab << best_t.fom << endl;
274
275 delete pex1;
276
277 ps_marker_errors(filename, set1, set2, t, p1->size(), 20);
278
279 kill_list((char *) set1, sizeof(Bmarker));
280 kill_list((char *) set2, sizeof(Bmarker));
281
282 return best_t;
283 }
284
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bimage::extract_tiles
Bimage * extract_tiles(long nn, vector< Vector3< long >> &coords, Vector3< long > tile_size)
Extracts a set of tiles at specified positions from an image into a new image.
Definition: Bimage_extract.cpp:335
Bstring::real
double real()
Definition: Bstring.cpp:545
DataType
DataType
Base data type specifier.
Definition: utilities.h:146
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
utilities.h
Header file for general utilities.
Boption::sampling
Vector3< double > sampling()
Definition: options.h:202
Boption::value
Bstring value
Definition: options.h:30
Boption::tag
Bstring tag
Definition: options.h:29
Transform::angle
double angle
Definition: Transform.h:29
kill_list
long kill_list(char *list, unsigned long size)
Frees all the items in a linked list.
Definition: linked_list.cpp:214
Transform::fom
double fom
Definition: Transform.h:32
Bmarker
Definition: marker.h:21
add_item
char * add_item(char **list, unsigned long size)
Adds an item to a linked list.
Definition: linked_list.cpp:26
Matrix3
Definition: Matrix3.h:17
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bimage::file_name
void file_name(string s)
Definition: Bimage.h:230
img_align
Transform img_align(Bimage *p1, Bimage *p2, Vector3< long > tile_size, double res_lo, double res_hi, double max_shift, int filter_flag, int refine_flag)
Aligns the second image to the first.
Definition: balign.cpp:145
get_option_list
Boption * get_option_list(const char *use[], int argc, char *argv[], int &optind)
Parses command line arguments based on a template.
Definition: options.cpp:40
read_img
Bimage * read_img(char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:76
get_cmd_line
string get_cmd_line(int argc, char **argv)
Returns the command line as a string.
Definition: utilities.cpp:36
timer.h
Utilities for timing functions.
Vector3::max
Type max()
Definition: Vector3.h:175
Bimage
General image parameter class.
Definition: Bimage.h:163
Boption::size
Vector3< long > size()
Definition: options.h:163
Bimage::transform
int transform(Vector3< double > scale, Vector3< double > origin, Vector3< double > translate, Matrix3 mat, int fill_type=0, double fill=0)
Transforms an image by translation, rotation, scaling and skewing, in place.
Definition: Bimage_transform.cpp:37
Transform
Definition: Transform.h:24
M_PI
#define M_PI
Definition: utilities.h:59
linked_list.h
Header file for generalized linked list functions.
markers_find_rottrans
Transform markers_find_rottrans(Bmarker *set1, Bmarker *set2, double tolerance)
Finds the rotation and shift between two sets of vectors.
Definition: marker.cpp:416
Boption
A class for a command line input option.
Definition: options.h:26
Bimage::label
void label(string s)
Definition: Bimage.h:235
VERB_TIME
#define VERB_TIME
Definition: utilities.h:110
ps_marker_errors
int ps_marker_errors(Bstring &filename, Bmarker *set1, Bmarker *set2, Transform t, Vector3< int > size, float err_scale)
Output a postscript file that graphs the deviations of points in a Bmarker from their predicted locat...
Definition: ps_marker.cpp:34
ps_marker.h
Header file for postscript tools dealing with Bmarkers.
Transform::scale
Vector3< double > scale
Definition: Transform.h:31
Bmarker::fom
float fom
Definition: marker.h:28
write_img
int write_img(const char *filename, Bimage *p, int compression)
General driver function to write multiple image formats.
Definition: rwimg.cpp:280
Bimage::size
Vector3< long > size() const
Definition: Bimage.h:373
Transform::trans
Vector3< double > trans
Definition: Transform.h:30
FILL_USER
#define FILL_USER
Definition: utilities.h:172
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:127
Bmarker::next
Bmarker * next
Definition: marker.h:22
VERB_RESULT
#define VERB_RESULT
Definition: utilities.h:105
Transform::origin
Vector3< double > origin
Definition: Transform.h:27
Boption::datatype
DataType datatype()
Definition: options.h:93
Bimage::filter_extremes
int filter_extremes()
Filters the extremes out of a micrograph image.
Definition: Bimage_segment.cpp:634
Boption::next
Boption * next
Definition: options.h:28
use
const char * use[]
Definition: balign.cpp:23
Bstring
Definition: Bstring.h:29
Vector3< long >
timer_report
double timer_report(double lasttime)
Reports the time elapsed since a given time.
Definition: timer.cpp:67
Vector3::min
Type min()
Definition: Vector3.h:169
Bmarker::loc
Vector3< float > loc
Definition: marker.h:25
Bimage::find_shift
int find_shift(Bimage *pref, Bimage *pmask, double hires, double lores, double radius, double sigma, int refine_flag)
Calculates a cross-correlation map to find the shift for the pair of images.
Definition: Bimage_correlate.cpp:932
option_kill
int option_kill(Boption *option)
Deallocates a linked list of option structures.
Definition: options.cpp:109
main
int main(int argc, char *argv[])
Definition: balign.cpp:45
Bimage::average
double average(long cc, double xf, double yf, double zf, long nn, double iscale)
Averages in 3D when scaling is less than 1.
Definition: Bimage.cpp:1349
Transform::axis
Vector3< double > axis
Definition: Transform.h:28
Unknown_Type
Definition: utilities.h:147
rwimg.h
Header file for 2D and 3D image I/O.
options.h
Header file for option handlers.
Bimage::images
long images()
Definition: Bimage.h:491
Bstring::pre_rev
Bstring pre_rev(char c)
Definition: Bstring.cpp:413
verbose
int verbose
Vector3::volume
double volume()
Definition: Vector3.h:235
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:106
Boption::values
long values(T1 &v1, T2 &v2)
Definition: options.h:115
bexit
int bexit(int value)
Exit function for cleanup and debugging.
Definition: utilities.cpp:273
timer_start
double timer_start()
Starts timer and prints the time.
Definition: timer.cpp:52
Bmarker::sel
int sel
Definition: marker.h:29
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:188