tabula-extractor 0.6.6-java → 0.7.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AUTHORS.md +1 -0
- data/README.md +27 -11
- data/bin/tabula +61 -19
- data/ext/liblsd-linux32.so +0 -0
- data/ext/liblsd-linux64.so +0 -0
- data/ext/liblsd.dll +0 -0
- data/ext/liblsd.dylib +0 -0
- data/ext/liblsd64.dll +0 -0
- data/ext/lsd.c +137 -137
- data/ext/lsd.h +9 -9
- data/lib/tabula.rb +20 -3
- data/lib/tabula/core_ext.rb +261 -0
- data/lib/tabula/entities.rb +11 -456
- data/lib/tabula/entities/cell.rb +42 -0
- data/lib/tabula/entities/has_cells.rb +244 -0
- data/lib/tabula/entities/line.rb +39 -0
- data/lib/tabula/entities/page.rb +269 -0
- data/lib/tabula/entities/page_area.rb +7 -0
- data/lib/tabula/entities/ruling.rb +300 -0
- data/lib/tabula/entities/spreadsheet.rb +92 -0
- data/lib/tabula/entities/table.rb +81 -0
- data/lib/tabula/entities/text_chunk.rb +114 -0
- data/lib/tabula/entities/text_element.rb +112 -0
- data/lib/tabula/entities/zone_entity.rb +57 -0
- data/lib/tabula/extraction.rb +327 -0
- data/lib/tabula/line_segment_detector.rb +9 -7
- data/lib/tabula/pdf_line_extractor.rb +319 -0
- data/lib/tabula/pdf_render.rb +1 -5
- data/lib/tabula/spreadsheet_extractor.rb +52 -0
- data/lib/tabula/table_extractor.rb +50 -348
- data/lib/tabula/table_guesser.rb +21 -23
- data/lib/tabula/version.rb +1 -1
- data/lib/tabula/writers.rb +5 -6
- data/tabula-extractor.gemspec +1 -0
- data/target/pdfbox-app-2.0.0-SNAPSHOT.jar +0 -0
- data/test/data/47008204D_USA.page4.pdf +0 -0
- data/test/data/560015757GV_China.page1.pdf +0 -0
- data/test/data/GSK_2012_Q4.page437.pdf +0 -0
- data/test/data/S2MNCEbirdisland.pdf +0 -0
- data/test/data/campaign_donors.pdf +0 -0
- data/test/data/frx_2012_disclosure.tsv +88 -0
- data/test/data/no_tables.pdf +0 -0
- data/test/data/puertos1.pdf +0 -0
- data/test/data/spanning_cells.csv +21 -0
- data/test/data/spanning_cells.pdf +0 -0
- data/test/data/strongschools.pdf +0 -0
- data/{vertical_rulings_bug.pdf → test/data/vertical_rulings_bug.pdf} +0 -0
- data/test/data/vietnam3.pdf +0 -0
- data/test/heuristic-test-set/original/560015757GV_China.page1.pdf +0 -0
- data/test/heuristic-test-set/original/S2MNCEbirdisland.pdf +0 -0
- data/test/heuristic-test-set/original/bo_page24.pdf +0 -0
- data/test/heuristic-test-set/original/campaign_donors.pdf +0 -0
- data/test/heuristic-test-set/spreadsheet/47008204D_USA.page4.pdf +0 -0
- data/test/heuristic-test-set/spreadsheet/GSK_2012_Q4.page437.pdf +0 -0
- data/test/heuristic-test-set/spreadsheet/strongschools.pdf +0 -0
- data/test/heuristic-test-set/spreadsheet/tabla_subsidios.pdf +0 -0
- data/test/heuristic.rb +50 -0
- data/test/test_bin_tabula.sh +7 -0
- data/test/tests.rb +476 -63
- metadata +79 -28
- data/lib/geom/point.rb +0 -21
- data/lib/geom/rectangle.rb +0 -101
- data/lib/geom/segment.rb +0 -82
- data/lib/tabula/pdf_dump.rb +0 -132
- data/lib/tabula/whitespace.rb +0 -50
- data/vertical_rulings_bug.rb +0 -29
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa69052647e565cd996f92f1c73e6d00deceea54
|
4
|
+
data.tar.gz: 7d76ccc9b445e9138f65920cd0a401fbee3ababf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d17ad7e967407711d60d9b30e8d231ab9adef313b8ede84e1960e35f24c5374f472a500e7f7148cc485408f796f1d7a67e96393d0fc5331e0f3f88971dad76c4
|
7
|
+
data.tar.gz: 84121390715280e86fb3ff1dd82533863dfabbb0b27582fb0d3bf9ad088f8d05e4c8f7dfbcfd2f621c232accd6145968e263a4e0e081431cf941939974999b20
|
data/AUTHORS.md
CHANGED
data/README.md
CHANGED
@@ -17,25 +17,41 @@ jruby -S gem install tabula-extractor
|
|
17
17
|
## Usage
|
18
18
|
|
19
19
|
```
|
20
|
-
$ tabula --help
|
21
20
|
Tabula helps you extract tables from PDFs
|
22
21
|
|
23
22
|
Usage:
|
24
23
|
tabula [options] <pdf_file>
|
25
24
|
where [options] are:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
Tabula helps you extract tables from PDFs
|
26
|
+
--pages, -p <s>: Comma separated list of ranges. Examples: --pages
|
27
|
+
1-3,5-7 or --pages 3. Default is --pages 1 (default:
|
28
|
+
1)
|
29
|
+
--area, -a <s>: Portion of the page to analyze
|
30
|
+
(top,left,bottom,right). Example: --area
|
31
|
+
269.875,12.75,790.5,561. Default is entire page
|
32
|
+
--columns, -c <s>: X coordinates of column boundaries. Example --columns
|
33
|
+
10.1,20.2,30.3
|
34
|
+
--password, -s <s>: Password to decrypt document. Default is empty
|
35
|
+
(default: )
|
36
|
+
--guess, -g: Guess the portion of the page to analyze per page.
|
37
|
+
--debug, -d: Print detected table areas instead of processing.
|
38
|
+
--format, -f <s>: Output format (CSV,TSV,HTML,JSON) (default: CSV)
|
39
|
+
--outfile, -o <s>: Write output to <file> instead of STDOUT (default: -)
|
40
|
+
--spreadsheet, -r: Force PDF to be extracted using spreadsheet-style
|
41
|
+
extraction (if there are ruling lines separating each
|
42
|
+
cell, as in a PDF of an Excel spreadsheet)
|
43
|
+
--no-spreadsheet, -n: Force PDF not to be extracted using spreadsheet-style
|
44
|
+
extraction (if there are ruling lines separating each
|
45
|
+
cell, as in a PDF of an Excel spreadsheet)
|
46
|
+
--silent, -i: Suppress all stderr output.
|
47
|
+
--version, -v: Print version and exit
|
48
|
+
--help, -h: Show this message
|
34
49
|
```
|
35
50
|
|
36
|
-
|
51
|
+
## Scripting examples
|
52
|
+
|
53
|
+
`tabula-extractor` is a RubyGem that you can use to programmatically extract tabular data, using the Tabula engine, in your scripts or applications. We don't have docs yet, but [the tests](test/tests.rb) are a good source of information.
|
37
54
|
|
38
55
|
## Notes
|
39
56
|
|
40
57
|
`tabula-extractor` uses [LSD: a Line Segment Detector](http://www.ipol.im/pub/art/2012/gjmr-lsd/) by Rafael Grompone von Gioi, Jérémie Jakubowicz, Jean-Michel Morel and Gregory Randall.
|
41
|
-
|
data/bin/tabula
CHANGED
@@ -34,11 +34,20 @@ EOS
|
|
34
34
|
|
35
35
|
opt :pages, 'Comma separated list of ranges. Examples: --pages 1-3,5-7 or --pages 3. Default is --pages 1', :default => '1', :type => String
|
36
36
|
opt :area, 'Portion of the page to analyze (top,left,bottom,right). Example: --area 269.875,12.75,790.5,561. Default is entire page', :type => String, :default => nil
|
37
|
+
opt :columns, 'X coordinates of column boundaries. Example --columns 10.1,20.2,30.3', :default => nil, :type => String
|
37
38
|
opt :password, 'Password to decrypt document. Default is empty', :default => ''
|
38
|
-
opt :guess, 'Guess the portion of the page to analyze per page.
|
39
|
+
opt :guess, 'Guess the portion of the page to analyze per page.'
|
39
40
|
opt :debug, 'Print detected table areas instead of processing.'
|
40
41
|
opt :format, "Output format (#{FORMATS.join(",")})", :default => 'CSV'
|
41
42
|
opt :outfile, 'Write output to <file> instead of STDOUT', :default => '-'
|
43
|
+
opt :spreadsheet, "Force PDF to be extracted using spreadsheet-style extraction (if there are ruling lines separating each cell, as in a PDF of an Excel spreadsheet)"
|
44
|
+
opt :no_spreadsheet, "Force PDF not to be extracted using spreadsheet-style extraction (if there are ruling lines separating each cell, as in a PDF of an Excel spreadsheet)"
|
45
|
+
opt :silent, 'Suppress all stderr output.'
|
46
|
+
end
|
47
|
+
|
48
|
+
if !opts[:columns].nil?
|
49
|
+
c = opts[:columns].split(',')
|
50
|
+
Trollop::die :columns, "is invalid" unless c.all? { |x| x.strip =~ /(\d+\.?\d*)/ }
|
42
51
|
end
|
43
52
|
|
44
53
|
if !opts[:area].nil?
|
@@ -56,31 +65,64 @@ EOS
|
|
56
65
|
return opts, pdf_filename
|
57
66
|
end
|
58
67
|
|
68
|
+
def rulings_from_columns(page, area, vertical_rulings)
|
69
|
+
top = area.nil? ? page.top : area.top
|
70
|
+
vertical_rulings.map do |vr|
|
71
|
+
Tabula::Ruling.new(top, vr, 0, page.height)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def heuristic_to_decide_whether_to_use_spreadsheet_extraction
|
76
|
+
false #TODO
|
77
|
+
end
|
78
|
+
|
59
79
|
def main
|
60
80
|
opts, filename = parse_command_line
|
61
81
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
82
|
+
area_input = opts[:area].nil? ? nil : opts[:area].split(',').map(&:to_f)
|
83
|
+
vertical_rulings = opts[:columns].nil? ? nil : opts[:columns].split(',').map(&:to_f)
|
84
|
+
out = opts[:outfile] == '-' ? $stdout : File.new(opts[:outfile], 'wb')
|
85
|
+
|
86
|
+
use_spreadsheet_extraction = if opts[:spreadsheet]
|
87
|
+
true
|
88
|
+
elsif opts[:no_spreadsheet] || opts[:columns] || opts[:area] || opts[:guess]
|
89
|
+
false
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
extractor = Tabula::Extraction::ObjectExtractor.new(filename, parse_pages_arg(opts[:pages]), opts[:password])
|
94
|
+
extractor.extract.each_with_index do |pdf_page, page_index|
|
95
|
+
|
96
|
+
#do the heuristic here
|
97
|
+
if use_spreadsheet_extraction.nil?
|
98
|
+
use_spreadsheet_extraction = pdf_page.is_tabular?
|
99
|
+
#TODO: tell the user what we're doing, so they can force the other way.
|
100
|
+
STDERR.puts "Using #{use_spreadsheet_extraction ? "spreadsheet": "no_spreadsheet"} extraction method.\n" +
|
101
|
+
"If the output looks wrong, re-run tabula with the #{use_spreadsheet_extraction ? "--no-spreadsheet": "--spreadsheet"} switch." unless opts[:silent]
|
72
102
|
end
|
73
103
|
|
74
|
-
|
75
|
-
if opts[:
|
76
|
-
|
104
|
+
if use_spreadsheet_extraction
|
105
|
+
if opts[:debug]
|
106
|
+
pdf_page.spreadsheets.each do |spreadsheet|
|
107
|
+
STDERR.puts "Page #{pdf_page.number(:one_indexed)}: #{spreadsheet.dims(:top, :left, :bottom, :right)}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
tables = pdf_page.spreadsheets.map(&:rows)
|
111
|
+
else
|
112
|
+
STDERR.puts "Page #{pdf_page.number(:one_indexed)}: #{page_area.to_s}" if opts[:debug]
|
113
|
+
if opts[:guess]
|
114
|
+
page_areas = pdf_page.spreadsheets.map{|rect| pdf_page.get_area(rect.dims(:top, :left, :bottom, :right))}
|
115
|
+
elsif area_input
|
116
|
+
page_areas = [pdf_page.get_area(area_input)]
|
77
117
|
else
|
78
|
-
|
79
|
-
Tabula::Writers.send(opts[:format].to_sym,
|
80
|
-
Tabula.make_table(text),
|
81
|
-
out)
|
118
|
+
page_areas = [pdf_page]
|
82
119
|
end
|
83
|
-
|
120
|
+
tables = page_areas.map{|page_area| page_area.make_table(vertical_rulings.nil? ? {} : { :vertical_rulings => rulings_from_columns(pdf_page, page_area, vertical_rulings) })}
|
121
|
+
end
|
122
|
+
tables.each do |table|
|
123
|
+
Tabula::Writers.send(opts[:format].to_sym,
|
124
|
+
table,
|
125
|
+
out)
|
84
126
|
end
|
85
127
|
end
|
86
128
|
out.close
|
data/ext/liblsd-linux32.so
CHANGED
Binary file
|
data/ext/liblsd-linux64.so
CHANGED
Binary file
|
data/ext/liblsd.dll
CHANGED
Binary file
|
data/ext/liblsd.dylib
CHANGED
Binary file
|
data/ext/liblsd64.dll
CHANGED
Binary file
|
data/ext/lsd.c
CHANGED
@@ -189,9 +189,9 @@ static void error(char * msg)
|
|
189
189
|
should be related to the cumulated rounding error in the chain of
|
190
190
|
computation. Here, as a simplification, a fixed factor is used.
|
191
191
|
*/
|
192
|
-
static int double_equal(
|
192
|
+
static int double_equal(float a, float b)
|
193
193
|
{
|
194
|
-
|
194
|
+
float abs_diff,aa,bb,abs_max;
|
195
195
|
|
196
196
|
/* trivial case */
|
197
197
|
if( a == b ) return TRUE;
|
@@ -215,7 +215,7 @@ static int double_equal(double a, double b)
|
|
215
215
|
/*----------------------------------------------------------------------------*/
|
216
216
|
/** Computes Euclidean distance between point (x1,y1) and point (x2,y2).
|
217
217
|
*/
|
218
|
-
static
|
218
|
+
static float dist(float x1, float y1, float x2, float y2)
|
219
219
|
{
|
220
220
|
return sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
|
221
221
|
}
|
@@ -251,7 +251,7 @@ typedef struct ntuple_list_s
|
|
251
251
|
unsigned int size;
|
252
252
|
unsigned int max_size;
|
253
253
|
unsigned int dim;
|
254
|
-
|
254
|
+
float * values;
|
255
255
|
} * ntuple_list;
|
256
256
|
|
257
257
|
/*----------------------------------------------------------------------------*/
|
@@ -286,7 +286,7 @@ static ntuple_list new_ntuple_list(unsigned int dim)
|
|
286
286
|
n_tuple->dim = dim;
|
287
287
|
|
288
288
|
/* get memory for tuples */
|
289
|
-
n_tuple->values = (
|
289
|
+
n_tuple->values = (float *) malloc( dim*n_tuple->max_size * sizeof(float) );
|
290
290
|
if( n_tuple->values == NULL ) error("not enough memory.");
|
291
291
|
|
292
292
|
return n_tuple;
|
@@ -305,16 +305,16 @@ static void enlarge_ntuple_list(ntuple_list n_tuple)
|
|
305
305
|
n_tuple->max_size *= 2;
|
306
306
|
|
307
307
|
/* realloc memory */
|
308
|
-
n_tuple->values = (
|
309
|
-
n_tuple->dim * n_tuple->max_size * sizeof(
|
308
|
+
n_tuple->values = (float *) realloc( (void *) n_tuple->values,
|
309
|
+
n_tuple->dim * n_tuple->max_size * sizeof(float) );
|
310
310
|
if( n_tuple->values == NULL ) error("not enough memory.");
|
311
311
|
}
|
312
312
|
|
313
313
|
/*----------------------------------------------------------------------------*/
|
314
314
|
/** Add a 7-tuple to an n-tuple list.
|
315
315
|
*/
|
316
|
-
static void add_7tuple( ntuple_list out,
|
317
|
-
|
316
|
+
static void add_7tuple( ntuple_list out, float v1, float v2, float v3,
|
317
|
+
float v4, float v5, float v6, float v7 )
|
318
318
|
{
|
319
319
|
/* check parameters */
|
320
320
|
if( out == NULL ) error("add_7tuple: invalid n-tuple input.");
|
@@ -479,7 +479,7 @@ static image_int new_image_int_ini( unsigned int xsize, unsigned int ysize,
|
|
479
479
|
*/
|
480
480
|
typedef struct image_double_s
|
481
481
|
{
|
482
|
-
|
482
|
+
float * data;
|
483
483
|
unsigned int xsize,ysize;
|
484
484
|
} * image_double;
|
485
485
|
|
@@ -507,7 +507,7 @@ static image_double new_image_double(unsigned int xsize, unsigned int ysize)
|
|
507
507
|
/* get memory */
|
508
508
|
image = (image_double) malloc( sizeof(struct image_double_s) );
|
509
509
|
if( image == NULL ) error("not enough memory.");
|
510
|
-
image->data = (
|
510
|
+
image->data = (float *) calloc( (size_t) (xsize*ysize), sizeof(float) );
|
511
511
|
if( image->data == NULL ) error("not enough memory.");
|
512
512
|
|
513
513
|
/* set image size */
|
@@ -522,7 +522,7 @@ static image_double new_image_double(unsigned int xsize, unsigned int ysize)
|
|
522
522
|
with the data pointed by 'data'.
|
523
523
|
*/
|
524
524
|
static image_double new_image_double_ptr( unsigned int xsize,
|
525
|
-
unsigned int ysize,
|
525
|
+
unsigned int ysize, float * data )
|
526
526
|
{
|
527
527
|
image_double image;
|
528
528
|
|
@@ -556,10 +556,10 @@ static image_double new_image_double_ptr( unsigned int xsize,
|
|
556
556
|
in the middle point between values 'kernel->values[0]'
|
557
557
|
and 'kernel->values[1]'.
|
558
558
|
*/
|
559
|
-
static void gaussian_kernel(ntuple_list kernel,
|
559
|
+
static void gaussian_kernel(ntuple_list kernel, float sigma, float mean)
|
560
560
|
{
|
561
|
-
|
562
|
-
|
561
|
+
float sum = 0.0;
|
562
|
+
float val;
|
563
563
|
unsigned int i;
|
564
564
|
|
565
565
|
/* check parameters */
|
@@ -572,7 +572,7 @@ static void gaussian_kernel(ntuple_list kernel, double sigma, double mean)
|
|
572
572
|
kernel->size = 1;
|
573
573
|
for(i=0;i<kernel->dim;i++)
|
574
574
|
{
|
575
|
-
val = ( (
|
575
|
+
val = ( (float) i - mean ) / sigma;
|
576
576
|
kernel->values[i] = exp( -0.5 * val * val );
|
577
577
|
sum += kernel->values[i];
|
578
578
|
}
|
@@ -619,14 +619,14 @@ static void gaussian_kernel(ntuple_list kernel, double sigma, double mean)
|
|
619
619
|
in the x axis, and then the combined Gaussian kernel and sampling
|
620
620
|
in the y axis.
|
621
621
|
*/
|
622
|
-
static image_double gaussian_sampler( image_double in,
|
623
|
-
|
622
|
+
static image_double gaussian_sampler( image_double in, float scale,
|
623
|
+
float sigma_scale )
|
624
624
|
{
|
625
625
|
image_double aux,out;
|
626
626
|
ntuple_list kernel;
|
627
627
|
unsigned int N,M,h,n,x,y,i;
|
628
628
|
int xc,yc,j,double_x_size,double_y_size;
|
629
|
-
|
629
|
+
float sigma,xx,yy,sum,prec;
|
630
630
|
|
631
631
|
/* check parameters */
|
632
632
|
if( in == NULL || in->data == NULL || in->xsize == 0 || in->ysize == 0 )
|
@@ -636,8 +636,8 @@ static image_double gaussian_sampler( image_double in, double scale,
|
|
636
636
|
error("gaussian_sampler: 'sigma_scale' must be positive.");
|
637
637
|
|
638
638
|
/* compute new image size and get memory for images */
|
639
|
-
if( in->xsize * scale > (
|
640
|
-
in->ysize * scale > (
|
639
|
+
if( in->xsize * scale > (float) UINT_MAX ||
|
640
|
+
in->ysize * scale > (float) UINT_MAX )
|
641
641
|
error("gaussian_sampler: the output image size exceeds the handled size.");
|
642
642
|
N = (unsigned int) ceil( in->xsize * scale );
|
643
643
|
M = (unsigned int) ceil( in->ysize * scale );
|
@@ -671,11 +671,11 @@ static image_double gaussian_sampler( image_double in, double scale,
|
|
671
671
|
xx is the corresponding x-value in the original size image.
|
672
672
|
xc is the integer value, the pixel coordinate of xx.
|
673
673
|
*/
|
674
|
-
xx = (
|
674
|
+
xx = (float) x / scale;
|
675
675
|
/* coordinate (0.0,0.0) is in the center of pixel (0,0),
|
676
676
|
so the pixel with xc=0 get the values of xx from -0.5 to 0.5 */
|
677
677
|
xc = (int) floor( xx + 0.5 );
|
678
|
-
gaussian_kernel( kernel, sigma, (
|
678
|
+
gaussian_kernel( kernel, sigma, (float) h + xx - (float) xc );
|
679
679
|
/* the kernel must be computed for each x because the fine
|
680
680
|
offset xx-xc is different in each case */
|
681
681
|
|
@@ -705,11 +705,11 @@ static image_double gaussian_sampler( image_double in, double scale,
|
|
705
705
|
yy is the corresponding x-value in the original size image.
|
706
706
|
yc is the integer value, the pixel coordinate of xx.
|
707
707
|
*/
|
708
|
-
yy = (
|
708
|
+
yy = (float) y / scale;
|
709
709
|
/* coordinate (0.0,0.0) is in the center of pixel (0,0),
|
710
710
|
so the pixel with yc=0 get the values of yy from -0.5 to 0.5 */
|
711
711
|
yc = (int) floor( yy + 0.5 );
|
712
|
-
gaussian_kernel( kernel, sigma, (
|
712
|
+
gaussian_kernel( kernel, sigma, (float) h + yy - (float) yc );
|
713
713
|
/* the kernel must be computed for each y because the fine
|
714
714
|
offset yy-yc is different in each case */
|
715
715
|
|
@@ -760,13 +760,13 @@ static image_double gaussian_sampler( image_double in, double scale,
|
|
760
760
|
- a pointer 'mem_p' to the memory used by 'list_p' to be able to
|
761
761
|
free the memory when it is not used anymore.
|
762
762
|
*/
|
763
|
-
static image_double ll_angle( image_double in,
|
763
|
+
static image_double ll_angle( image_double in, float threshold,
|
764
764
|
struct coorlist ** list_p, void ** mem_p,
|
765
765
|
image_double * modgrad, unsigned int n_bins )
|
766
766
|
{
|
767
767
|
image_double g;
|
768
768
|
unsigned int n,p,x,y,adr,i;
|
769
|
-
|
769
|
+
float com1,com2,gx,gy,norm,norm2;
|
770
770
|
/* the rest of the variables are used for pseudo-ordering
|
771
771
|
the gradient magnitude values */
|
772
772
|
int list_count = 0;
|
@@ -775,7 +775,7 @@ static image_double ll_angle( image_double in, double threshold,
|
|
775
775
|
struct coorlist ** range_l_e; /* array of pointers to end of bin list */
|
776
776
|
struct coorlist * start;
|
777
777
|
struct coorlist * end;
|
778
|
-
|
778
|
+
float max_grad = 0.0;
|
779
779
|
|
780
780
|
/* check parameters */
|
781
781
|
if( in == NULL || in->data == NULL || in->xsize == 0 || in->ysize == 0 )
|
@@ -858,7 +858,7 @@ static image_double ll_angle( image_double in, double threshold,
|
|
858
858
|
norm = (*modgrad)->data[y*p+x];
|
859
859
|
|
860
860
|
/* store the point in the right bin according to its norm */
|
861
|
-
i = (unsigned int) (norm * (
|
861
|
+
i = (unsigned int) (norm * (float) n_bins / max_grad);
|
862
862
|
if( i >= n_bins ) i = n_bins-1;
|
863
863
|
if( range_l_e[i] == NULL )
|
864
864
|
range_l_s[i] = range_l_e[i] = list+list_count++;
|
@@ -902,10 +902,10 @@ static image_double ll_angle( image_double in, double threshold,
|
|
902
902
|
/*----------------------------------------------------------------------------*/
|
903
903
|
/** Is point (x,y) aligned to angle theta, up to precision 'prec'?
|
904
904
|
*/
|
905
|
-
static int isaligned( int x, int y, image_double angles,
|
906
|
-
|
905
|
+
static int isaligned( int x, int y, image_double angles, float theta,
|
906
|
+
float prec )
|
907
907
|
{
|
908
|
-
|
908
|
+
float a;
|
909
909
|
|
910
910
|
/* check parameters */
|
911
911
|
if( angles == NULL || angles->data == NULL )
|
@@ -940,7 +940,7 @@ static int isaligned( int x, int y, image_double angles, double theta,
|
|
940
940
|
/*----------------------------------------------------------------------------*/
|
941
941
|
/** Absolute value angle difference.
|
942
942
|
*/
|
943
|
-
static double angle_diff(
|
943
|
+
static double angle_diff(float a, float b)
|
944
944
|
{
|
945
945
|
a -= b;
|
946
946
|
while( a <= -M_PI ) a += M_2__PI;
|
@@ -952,7 +952,7 @@ static double angle_diff(double a, double b)
|
|
952
952
|
/*----------------------------------------------------------------------------*/
|
953
953
|
/** Signed angle difference.
|
954
954
|
*/
|
955
|
-
static double angle_diff_signed(
|
955
|
+
static double angle_diff_signed(float a, float b)
|
956
956
|
{
|
957
957
|
a -= b;
|
958
958
|
while( a <= -M_PI ) a += M_2__PI;
|
@@ -989,19 +989,19 @@ static double angle_diff_signed(double a, double b)
|
|
989
989
|
q5 = 83.8676043424,
|
990
990
|
q6 = 2.50662827511.
|
991
991
|
*/
|
992
|
-
static double log_gamma_lanczos(
|
992
|
+
static double log_gamma_lanczos(float x)
|
993
993
|
{
|
994
|
-
static
|
994
|
+
static float q[7] = { 75122.6331530, 80916.6278952, 36308.2951477,
|
995
995
|
8687.24529705, 1168.92649479, 83.8676043424,
|
996
996
|
2.50662827511 };
|
997
|
-
|
998
|
-
|
997
|
+
float a = (x+0.5) * log(x+5.5) - (x+5.5);
|
998
|
+
float b = 0.0;
|
999
999
|
int n;
|
1000
1000
|
|
1001
1001
|
for(n=0;n<7;n++)
|
1002
1002
|
{
|
1003
|
-
a -= log( x + (
|
1004
|
-
b += q[n] * pow( x, (
|
1003
|
+
a -= log( x + (float) n );
|
1004
|
+
b += q[n] * pow( x, (float) n );
|
1005
1005
|
}
|
1006
1006
|
return a + log(b);
|
1007
1007
|
}
|
@@ -1023,7 +1023,7 @@ static double log_gamma_lanczos(double x)
|
|
1023
1023
|
@f]
|
1024
1024
|
This formula is a good approximation when x > 15.
|
1025
1025
|
*/
|
1026
|
-
static double log_gamma_windschitl(
|
1026
|
+
static double log_gamma_windschitl(float x)
|
1027
1027
|
{
|
1028
1028
|
return 0.918938533204673 + (x-0.5)*log(x) - x
|
1029
1029
|
+ 0.5*x*log( x*sinh(1/x) + 1/(810.0*pow(x,6.0)) );
|
@@ -1083,11 +1083,11 @@ static double log_gamma_windschitl(double x)
|
|
1083
1083
|
of the terms are neglected based on a bound to the error obtained
|
1084
1084
|
(an error of 10% in the result is accepted).
|
1085
1085
|
*/
|
1086
|
-
static double nfa(int n, int k,
|
1086
|
+
static double nfa(int n, int k, float p, float logNT)
|
1087
1087
|
{
|
1088
|
-
static
|
1089
|
-
|
1090
|
-
|
1088
|
+
static float inv[TABSIZE]; /* table to keep computed inverse values */
|
1089
|
+
float tolerance = 0.1; /* an error of 10% in the result is accepted */
|
1090
|
+
float log1term,term,bin_term,mult_term,bin_tail,err,p_term;
|
1091
1091
|
int i;
|
1092
1092
|
|
1093
1093
|
/* check parameters */
|
@@ -1096,7 +1096,7 @@ static double nfa(int n, int k, double p, double logNT)
|
|
1096
1096
|
|
1097
1097
|
/* trivial cases */
|
1098
1098
|
if( n==0 || k==0 ) return -logNT;
|
1099
|
-
if( n==k ) return -logNT - (
|
1099
|
+
if( n==k ) return -logNT - (float) n * log10(p);
|
1100
1100
|
|
1101
1101
|
/* probability term */
|
1102
1102
|
p_term = p / (1.0-p);
|
@@ -1109,15 +1109,15 @@ static double nfa(int n, int k, double p, double logNT)
|
|
1109
1109
|
bincoef(n,k) = gamma(n+1) / ( gamma(k+1) * gamma(n-k+1) ).
|
1110
1110
|
We use this to compute the first term. Actually the log of it.
|
1111
1111
|
*/
|
1112
|
-
log1term = log_gamma( (
|
1113
|
-
- log_gamma( (
|
1114
|
-
+ (
|
1112
|
+
log1term = log_gamma( (float) n + 1.0 ) - log_gamma( (float) k + 1.0 )
|
1113
|
+
- log_gamma( (float) (n-k) + 1.0 )
|
1114
|
+
+ (float) k * log(p) + (float) (n-k) * log(1.0-p);
|
1115
1115
|
term = exp(log1term);
|
1116
1116
|
|
1117
1117
|
/* in some cases no more computations are needed */
|
1118
1118
|
if( double_equal(term,0.0) ) /* the first term is almost zero */
|
1119
1119
|
{
|
1120
|
-
if( (
|
1120
|
+
if( (float) k > (float) n * p ) /* at begin or end of the tail? */
|
1121
1121
|
return -log1term / M_LN10 - logNT; /* end: use just the first term */
|
1122
1122
|
else
|
1123
1123
|
return -logNT; /* begin: the tail is roughly 1 */
|
@@ -1140,9 +1140,9 @@ static double nfa(int n, int k, double p, double logNT)
|
|
1140
1140
|
because divisions are expensive.
|
1141
1141
|
p/(1-p) is computed only once and stored in 'p_term'.
|
1142
1142
|
*/
|
1143
|
-
bin_term = (
|
1144
|
-
( inv[i]!=0.0 ? inv[i] : ( inv[i] = 1.0 / (
|
1145
|
-
1.0 / (
|
1143
|
+
bin_term = (float) (n-i+1) * ( i<TABSIZE ?
|
1144
|
+
( inv[i]!=0.0 ? inv[i] : ( inv[i] = 1.0 / (float) i ) ) :
|
1145
|
+
1.0 / (float) i );
|
1146
1146
|
|
1147
1147
|
mult_term = bin_term * p_term;
|
1148
1148
|
term *= mult_term;
|
@@ -1153,7 +1153,7 @@ static double nfa(int n, int k, double p, double logNT)
|
|
1153
1153
|
Then, the error on the binomial tail when truncated at
|
1154
1154
|
the i term can be bounded by a geometric series of form
|
1155
1155
|
term_i * sum mult_term_i^j. */
|
1156
|
-
err = term * ( ( 1.0 - pow( mult_term, (
|
1156
|
+
err = term * ( ( 1.0 - pow( mult_term, (float) (n-i+1) ) ) /
|
1157
1157
|
(1.0-mult_term) - 1.0 );
|
1158
1158
|
|
1159
1159
|
/* One wants an error at most of tolerance*final_result, or:
|
@@ -1180,13 +1180,13 @@ static double nfa(int n, int k, double p, double logNT)
|
|
1180
1180
|
*/
|
1181
1181
|
struct rect
|
1182
1182
|
{
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1183
|
+
float x1,y1,x2,y2; /* first and second point of the line segment */
|
1184
|
+
float width; /* rectangle width */
|
1185
|
+
float x,y; /* center of the rectangle */
|
1186
|
+
float theta; /* angle */
|
1187
|
+
float dx,dy; /* (dx,dy) is vector oriented as the line segment */
|
1188
|
+
float prec; /* tolerance angle */
|
1189
|
+
float p; /* probability of a point with angle within 'prec' */
|
1190
1190
|
};
|
1191
1191
|
|
1192
1192
|
/*----------------------------------------------------------------------------*/
|
@@ -1270,9 +1270,9 @@ static void rect_copy(struct rect * in, struct rect * out)
|
|
1270
1270
|
*/
|
1271
1271
|
typedef struct
|
1272
1272
|
{
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1273
|
+
float vx[4]; /* rectangle's corner X coordinates in circular order */
|
1274
|
+
float vy[4]; /* rectangle's corner Y coordinates in circular order */
|
1275
|
+
float ys,ye; /* start and end Y values of current 'column' */
|
1276
1276
|
int x,y; /* coordinates of currently explored pixel */
|
1277
1277
|
} rect_iter;
|
1278
1278
|
|
@@ -1286,7 +1286,7 @@ typedef struct
|
|
1286
1286
|
- x1 <= x
|
1287
1287
|
- x <= x2
|
1288
1288
|
*/
|
1289
|
-
static double inter_low(
|
1289
|
+
static double inter_low(float x, float x1, float y1, float x2, float y2)
|
1290
1290
|
{
|
1291
1291
|
/* check parameters */
|
1292
1292
|
if( x1 > x2 || x < x1 || x > x2 )
|
@@ -1308,7 +1308,7 @@ static double inter_low(double x, double x1, double y1, double x2, double y2)
|
|
1308
1308
|
- x1 <= x
|
1309
1309
|
- x <= x2
|
1310
1310
|
*/
|
1311
|
-
static double inter_hi(
|
1311
|
+
static double inter_hi(float x, float x1, float y1, float x2, float y2)
|
1312
1312
|
{
|
1313
1313
|
/* check parameters */
|
1314
1314
|
if( x1 > x2 || x < x1 || x > x2 )
|
@@ -1342,7 +1342,7 @@ static int ri_end(rect_iter * i)
|
|
1342
1342
|
/* if the current x value is larger than the largest
|
1343
1343
|
x value in the rectangle (vx[2]), we know the full
|
1344
1344
|
exploration of the rectangle is finished. */
|
1345
|
-
return (
|
1345
|
+
return (float)(i->x) > i->vx[2];
|
1346
1346
|
}
|
1347
1347
|
|
1348
1348
|
/*----------------------------------------------------------------------------*/
|
@@ -1362,7 +1362,7 @@ static void ri_inc(rect_iter * i)
|
|
1362
1362
|
/* if the end of the current 'column' is reached,
|
1363
1363
|
and it is not the end of exploration,
|
1364
1364
|
advance to the next 'column' */
|
1365
|
-
while( (
|
1365
|
+
while( (float) (i->y) > i->ye && !ri_end(i) )
|
1366
1366
|
{
|
1367
1367
|
/* increase x, next 'column' */
|
1368
1368
|
i->x++;
|
@@ -1385,10 +1385,10 @@ static void ri_inc(rect_iter * i)
|
|
1385
1385
|
or last 'columns') then we pick the lower value of the side
|
1386
1386
|
by using 'inter_low'.
|
1387
1387
|
*/
|
1388
|
-
if( (
|
1389
|
-
i->ys = inter_low((
|
1388
|
+
if( (float) i->x < i->vx[3] )
|
1389
|
+
i->ys = inter_low((float)i->x,i->vx[0],i->vy[0],i->vx[3],i->vy[3]);
|
1390
1390
|
else
|
1391
|
-
i->ys = inter_low((
|
1391
|
+
i->ys = inter_low((float)i->x,i->vx[3],i->vy[3],i->vx[2],i->vy[2]);
|
1392
1392
|
|
1393
1393
|
/* update upper y limit (end) for the new 'column'.
|
1394
1394
|
|
@@ -1405,10 +1405,10 @@ static void ri_inc(rect_iter * i)
|
|
1405
1405
|
or last 'columns') then we pick the lower value of the side
|
1406
1406
|
by using 'inter_low'.
|
1407
1407
|
*/
|
1408
|
-
if( (
|
1409
|
-
i->ye = inter_hi((
|
1408
|
+
if( (float)i->x < i->vx[1] )
|
1409
|
+
i->ye = inter_hi((float)i->x,i->vx[0],i->vy[0],i->vx[1],i->vy[1]);
|
1410
1410
|
else
|
1411
|
-
i->ye = inter_hi((
|
1411
|
+
i->ye = inter_hi((float)i->x,i->vx[1],i->vy[1],i->vx[2],i->vy[2]);
|
1412
1412
|
|
1413
1413
|
/* new y */
|
1414
1414
|
i->y = (int) ceil(i->ys);
|
@@ -1422,7 +1422,7 @@ static void ri_inc(rect_iter * i)
|
|
1422
1422
|
*/
|
1423
1423
|
static rect_iter * ri_ini(struct rect * r)
|
1424
1424
|
{
|
1425
|
-
|
1425
|
+
float vx[4],vy[4];
|
1426
1426
|
int n,offset;
|
1427
1427
|
rect_iter * i;
|
1428
1428
|
|
@@ -1491,7 +1491,7 @@ static rect_iter * ri_ini(struct rect * r)
|
|
1491
1491
|
/*----------------------------------------------------------------------------*/
|
1492
1492
|
/** Compute a rectangle's NFA value.
|
1493
1493
|
*/
|
1494
|
-
static
|
1494
|
+
static float rect_nfa(struct rect * rec, image_double angles, float logNT)
|
1495
1495
|
{
|
1496
1496
|
rect_iter * i;
|
1497
1497
|
int pts = 0;
|
@@ -1577,13 +1577,13 @@ static double rect_nfa(struct rect * rec, image_double angles, double logNT)
|
|
1577
1577
|
When |Ixx| > |Iyy| we use the first, otherwise the second (just to
|
1578
1578
|
get better numeric precision).
|
1579
1579
|
*/
|
1580
|
-
static
|
1581
|
-
image_double modgrad,
|
1580
|
+
static float get_theta( struct point * reg, int reg_size, float x, float y,
|
1581
|
+
image_double modgrad, float reg_angle, float prec )
|
1582
1582
|
{
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1583
|
+
float lambda,theta,weight;
|
1584
|
+
float Ixx = 0.0;
|
1585
|
+
float Iyy = 0.0;
|
1586
|
+
float Ixy = 0.0;
|
1587
1587
|
int i;
|
1588
1588
|
|
1589
1589
|
/* check parameters */
|
@@ -1597,9 +1597,9 @@ static double get_theta( struct point * reg, int reg_size, double x, double y,
|
|
1597
1597
|
for(i=0; i<reg_size; i++)
|
1598
1598
|
{
|
1599
1599
|
weight = modgrad->data[ reg[i].x + reg[i].y * modgrad->xsize ];
|
1600
|
-
Ixx += ( (
|
1601
|
-
Iyy += ( (
|
1602
|
-
Ixy -= ( (
|
1600
|
+
Ixx += ( (float) reg[i].y - y ) * ( (float) reg[i].y - y ) * weight;
|
1601
|
+
Iyy += ( (float) reg[i].x - x ) * ( (float) reg[i].x - x ) * weight;
|
1602
|
+
Ixy -= ( (float) reg[i].x - x ) * ( (float) reg[i].y - y ) * weight;
|
1603
1603
|
}
|
1604
1604
|
if( double_equal(Ixx,0.0) && double_equal(Iyy,0.0) && double_equal(Ixy,0.0) )
|
1605
1605
|
error("get_theta: null inertia matrix.");
|
@@ -1621,10 +1621,10 @@ static double get_theta( struct point * reg, int reg_size, double x, double y,
|
|
1621
1621
|
/** Computes a rectangle that covers a region of points.
|
1622
1622
|
*/
|
1623
1623
|
static void region2rect( struct point * reg, int reg_size,
|
1624
|
-
image_double modgrad,
|
1625
|
-
|
1624
|
+
image_double modgrad, float reg_angle,
|
1625
|
+
float prec, float p, struct rect * rec )
|
1626
1626
|
{
|
1627
|
-
|
1627
|
+
float x,y,dx,dy,l,w,theta,weight,sum,l_min,l_max,w_min,w_max;
|
1628
1628
|
int i;
|
1629
1629
|
|
1630
1630
|
/* check parameters */
|
@@ -1648,8 +1648,8 @@ static void region2rect( struct point * reg, int reg_size,
|
|
1648
1648
|
for(i=0; i<reg_size; i++)
|
1649
1649
|
{
|
1650
1650
|
weight = modgrad->data[ reg[i].x + reg[i].y * modgrad->xsize ];
|
1651
|
-
x += (
|
1652
|
-
y += (
|
1651
|
+
x += (float) reg[i].x * weight;
|
1652
|
+
y += (float) reg[i].y * weight;
|
1653
1653
|
sum += weight;
|
1654
1654
|
}
|
1655
1655
|
if( sum <= 0.0 ) error("region2rect: weights sum equal to zero.");
|
@@ -1676,8 +1676,8 @@ static void region2rect( struct point * reg, int reg_size,
|
|
1676
1676
|
l_min = l_max = w_min = w_max = 0.0;
|
1677
1677
|
for(i=0; i<reg_size; i++)
|
1678
1678
|
{
|
1679
|
-
l = ( (
|
1680
|
-
w = -( (
|
1679
|
+
l = ( (float) reg[i].x - x) * dx + ( (float) reg[i].y - y) * dy;
|
1680
|
+
w = -( (float) reg[i].x - x) * dy + ( (float) reg[i].y - y) * dx;
|
1681
1681
|
|
1682
1682
|
if( l > l_max ) l_max = l;
|
1683
1683
|
if( l < l_min ) l_min = l;
|
@@ -1714,10 +1714,10 @@ static void region2rect( struct point * reg, int reg_size,
|
|
1714
1714
|
tolerance 'prec', starting at point (x,y).
|
1715
1715
|
*/
|
1716
1716
|
static void region_grow( int x, int y, image_double angles, struct point * reg,
|
1717
|
-
int * reg_size,
|
1718
|
-
|
1717
|
+
int * reg_size, float * reg_angle, image_char used,
|
1718
|
+
float prec )
|
1719
1719
|
{
|
1720
|
-
|
1720
|
+
float sumdx,sumdy;
|
1721
1721
|
int xx,yy,i;
|
1722
1722
|
|
1723
1723
|
/* check parameters */
|
@@ -1765,13 +1765,13 @@ static void region_grow( int x, int y, image_double angles, struct point * reg,
|
|
1765
1765
|
/** Try some rectangles variations to improve NFA value. Only if the
|
1766
1766
|
rectangle is not meaningful (i.e., log_nfa <= log_eps).
|
1767
1767
|
*/
|
1768
|
-
static
|
1769
|
-
|
1768
|
+
static float rect_improve( struct rect * rec, image_double angles,
|
1769
|
+
float logNT, float log_eps )
|
1770
1770
|
{
|
1771
1771
|
struct rect r;
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1772
|
+
float log_nfa,log_nfa_new;
|
1773
|
+
float delta = 0.5;
|
1774
|
+
float delta_2 = delta / 2.0;
|
1775
1775
|
int n;
|
1776
1776
|
|
1777
1777
|
log_nfa = rect_nfa(rec,angles,logNT);
|
@@ -1879,12 +1879,12 @@ static double rect_improve( struct rect * rec, image_double angles,
|
|
1879
1879
|
density of region points or to discard the region if too small.
|
1880
1880
|
*/
|
1881
1881
|
static int reduce_region_radius( struct point * reg, int * reg_size,
|
1882
|
-
image_double modgrad,
|
1883
|
-
|
1882
|
+
image_double modgrad, float reg_angle,
|
1883
|
+
float prec, float p, struct rect * rec,
|
1884
1884
|
image_char used, image_double angles,
|
1885
|
-
|
1885
|
+
float density_th )
|
1886
1886
|
{
|
1887
|
-
|
1887
|
+
float density,rad1,rad2,rad,xc,yc;
|
1888
1888
|
int i;
|
1889
1889
|
|
1890
1890
|
/* check parameters */
|
@@ -1899,15 +1899,15 @@ static int reduce_region_radius( struct point * reg, int * reg_size,
|
|
1899
1899
|
error("reduce_region_radius: invalid image 'angles'.");
|
1900
1900
|
|
1901
1901
|
/* compute region points density */
|
1902
|
-
density = (
|
1902
|
+
density = (float) *reg_size /
|
1903
1903
|
( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
|
1904
1904
|
|
1905
1905
|
/* if the density criterion is satisfied there is nothing to do */
|
1906
1906
|
if( density >= density_th ) return TRUE;
|
1907
1907
|
|
1908
1908
|
/* compute region's radius */
|
1909
|
-
xc = (
|
1910
|
-
yc = (
|
1909
|
+
xc = (float) reg[0].x;
|
1910
|
+
yc = (float) reg[0].y;
|
1911
1911
|
rad1 = dist( xc, yc, rec->x1, rec->y1 );
|
1912
1912
|
rad2 = dist( xc, yc, rec->x2, rec->y2 );
|
1913
1913
|
rad = rad1 > rad2 ? rad1 : rad2;
|
@@ -1919,7 +1919,7 @@ static int reduce_region_radius( struct point * reg, int * reg_size,
|
|
1919
1919
|
|
1920
1920
|
/* remove points from the region and update 'used' map */
|
1921
1921
|
for(i=0; i<*reg_size; i++)
|
1922
|
-
if( dist( xc, yc, (
|
1922
|
+
if( dist( xc, yc, (float) reg[i].x, (float) reg[i].y ) > rad )
|
1923
1923
|
{
|
1924
1924
|
/* point not kept, mark it as NOTUSED */
|
1925
1925
|
used->data[ reg[i].x + reg[i].y * used->xsize ] = NOTUSED;
|
@@ -1938,7 +1938,7 @@ static int reduce_region_radius( struct point * reg, int * reg_size,
|
|
1938
1938
|
region2rect(reg,*reg_size,modgrad,reg_angle,prec,p,rec);
|
1939
1939
|
|
1940
1940
|
/* re-compute region points density */
|
1941
|
-
density = (
|
1941
|
+
density = (float) *reg_size /
|
1942
1942
|
( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
|
1943
1943
|
}
|
1944
1944
|
|
@@ -1957,10 +1957,10 @@ static int reduce_region_radius( struct point * reg, int * reg_size,
|
|
1957
1957
|
'reduce_region_radius' is called to try to satisfy this condition.
|
1958
1958
|
*/
|
1959
1959
|
static int refine( struct point * reg, int * reg_size, image_double modgrad,
|
1960
|
-
|
1961
|
-
image_char used, image_double angles,
|
1960
|
+
float reg_angle, float prec, float p, struct rect * rec,
|
1961
|
+
image_char used, image_double angles, float density_th )
|
1962
1962
|
{
|
1963
|
-
|
1963
|
+
float angle,ang_d,mean_angle,tau,density,xc,yc,ang_c,sum,s_sum;
|
1964
1964
|
int i,n;
|
1965
1965
|
|
1966
1966
|
/* check parameters */
|
@@ -1974,7 +1974,7 @@ static int refine( struct point * reg, int * reg_size, image_double modgrad,
|
|
1974
1974
|
error("refine: invalid image 'angles'.");
|
1975
1975
|
|
1976
1976
|
/* compute region points density */
|
1977
|
-
density = (
|
1977
|
+
density = (float) *reg_size /
|
1978
1978
|
( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
|
1979
1979
|
|
1980
1980
|
/* if the density criterion is satisfied there is nothing to do */
|
@@ -1983,15 +1983,15 @@ static int refine( struct point * reg, int * reg_size, image_double modgrad,
|
|
1983
1983
|
/*------ First try: reduce angle tolerance ------*/
|
1984
1984
|
|
1985
1985
|
/* compute the new mean angle and tolerance */
|
1986
|
-
xc = (
|
1987
|
-
yc = (
|
1986
|
+
xc = (float) reg[0].x;
|
1987
|
+
yc = (float) reg[0].y;
|
1988
1988
|
ang_c = angles->data[ reg[0].x + reg[0].y * angles->xsize ];
|
1989
1989
|
sum = s_sum = 0.0;
|
1990
1990
|
n = 0;
|
1991
1991
|
for(i=0; i<*reg_size; i++)
|
1992
1992
|
{
|
1993
1993
|
used->data[ reg[i].x + reg[i].y * used->xsize ] = NOTUSED;
|
1994
|
-
if( dist( xc, yc, (
|
1994
|
+
if( dist( xc, yc, (float) reg[i].x, (float) reg[i].y ) < rec->width )
|
1995
1995
|
{
|
1996
1996
|
angle = angles->data[ reg[i].x + reg[i].y * angles->xsize ];
|
1997
1997
|
ang_d = angle_diff_signed(angle,ang_c);
|
@@ -2000,8 +2000,8 @@ static int refine( struct point * reg, int * reg_size, image_double modgrad,
|
|
2000
2000
|
++n;
|
2001
2001
|
}
|
2002
2002
|
}
|
2003
|
-
mean_angle = sum / (
|
2004
|
-
tau = 2.0 * sqrt( (s_sum - 2.0 * mean_angle * sum) / (
|
2003
|
+
mean_angle = sum / (float) n;
|
2004
|
+
tau = 2.0 * sqrt( (s_sum - 2.0 * mean_angle * sum) / (float) n
|
2005
2005
|
+ mean_angle*mean_angle ); /* 2 * standard deviation */
|
2006
2006
|
|
2007
2007
|
/* find a new region from the same starting point and new angle tolerance */
|
@@ -2014,7 +2014,7 @@ static int refine( struct point * reg, int * reg_size, image_double modgrad,
|
|
2014
2014
|
region2rect(reg,*reg_size,modgrad,reg_angle,prec,p,rec);
|
2015
2015
|
|
2016
2016
|
/* re-compute region points density */
|
2017
|
-
density = (
|
2017
|
+
density = (float) *reg_size /
|
2018
2018
|
( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
|
2019
2019
|
|
2020
2020
|
/*------ Second try: reduce region radius ------*/
|
@@ -2034,16 +2034,16 @@ static int refine( struct point * reg, int * reg_size, image_double modgrad,
|
|
2034
2034
|
/*----------------------------------------------------------------------------*/
|
2035
2035
|
/** LSD full interface.
|
2036
2036
|
*/
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2037
|
+
float * LineSegmentDetection( int * n_out,
|
2038
|
+
float * img, int X, int Y,
|
2039
|
+
float scale, float sigma_scale, float quant,
|
2040
|
+
float ang_th, float log_eps, float density_th,
|
2041
2041
|
int n_bins,
|
2042
2042
|
int ** reg_img, int * reg_x, int * reg_y )
|
2043
2043
|
{
|
2044
2044
|
image_double image;
|
2045
2045
|
ntuple_list out = new_ntuple_list(7);
|
2046
|
-
|
2046
|
+
float * return_value;
|
2047
2047
|
image_double scaled_image,angles,modgrad;
|
2048
2048
|
image_char used;
|
2049
2049
|
image_int region = NULL;
|
@@ -2053,7 +2053,7 @@ double * LineSegmentDetection( int * n_out,
|
|
2053
2053
|
struct point * reg;
|
2054
2054
|
int reg_size,min_reg_size,i;
|
2055
2055
|
unsigned int xsize,ysize;
|
2056
|
-
|
2056
|
+
float rho,reg_angle,prec,p,log_nfa,logNT;
|
2057
2057
|
int ls_count = 0; /* line segments are numbered 1,2,3,... */
|
2058
2058
|
|
2059
2059
|
|
@@ -2103,7 +2103,7 @@ double * LineSegmentDetection( int * n_out,
|
|
2103
2103
|
whose logarithm value is
|
2104
2104
|
log10(11) + 5/2 * (log10(X) + log10(Y)).
|
2105
2105
|
*/
|
2106
|
-
logNT = 5.0 * ( log10( (
|
2106
|
+
logNT = 5.0 * ( log10( (float) xsize ) + log10( (float) ysize ) ) / 2.0
|
2107
2107
|
+ log10(11.0);
|
2108
2108
|
min_reg_size = (int) (-logNT/log10(p)); /* minimal number of points in region
|
2109
2109
|
that can give a meaningful event */
|
@@ -2221,18 +2221,18 @@ double * LineSegmentDetection( int * n_out,
|
|
2221
2221
|
/*----------------------------------------------------------------------------*/
|
2222
2222
|
/** LSD Simple Interface with Scale and Region output.
|
2223
2223
|
*/
|
2224
|
-
|
2225
|
-
|
2224
|
+
float * lsd_scale_region( int * n_out,
|
2225
|
+
float * img, int X, int Y, float scale,
|
2226
2226
|
int ** reg_img, int * reg_x, int * reg_y )
|
2227
2227
|
{
|
2228
2228
|
/* LSD parameters */
|
2229
|
-
|
2229
|
+
float sigma_scale = 0.6; /* Sigma for Gaussian filter is computed as
|
2230
2230
|
sigma = sigma_scale/scale. */
|
2231
|
-
|
2231
|
+
float quant = 2.0; /* Bound to the quantization error on the
|
2232
2232
|
gradient norm. */
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2233
|
+
float ang_th = 22.5; /* Gradient angle tolerance in degrees. */
|
2234
|
+
float log_eps = 0.0; /* Detection threshold: -log10(NFA) > log_eps */
|
2235
|
+
float density_th = 0.7; /* Minimal density of region points in rectangle. */
|
2236
2236
|
int n_bins = 1024; /* Number of bins in pseudo-ordering of gradient
|
2237
2237
|
modulus. */
|
2238
2238
|
|
@@ -2244,7 +2244,7 @@ double * lsd_scale_region( int * n_out,
|
|
2244
2244
|
/*----------------------------------------------------------------------------*/
|
2245
2245
|
/** LSD Simple Interface with Scale.
|
2246
2246
|
*/
|
2247
|
-
|
2247
|
+
float * lsd_scale(int * n_out, float * img, int X, int Y, float scale)
|
2248
2248
|
{
|
2249
2249
|
return lsd_scale_region(n_out,img,X,Y,scale,NULL,NULL,NULL);
|
2250
2250
|
}
|
@@ -2252,10 +2252,10 @@ double * lsd_scale(int * n_out, double * img, int X, int Y, double scale)
|
|
2252
2252
|
/*----------------------------------------------------------------------------*/
|
2253
2253
|
/** LSD Simple Interface.
|
2254
2254
|
*/
|
2255
|
-
|
2255
|
+
float * lsd(int * n_out, float * img, int X, int Y)
|
2256
2256
|
{
|
2257
2257
|
/* LSD parameters */
|
2258
|
-
|
2258
|
+
float scale = 0.8; /* Scale the image by Gaussian filter to 'scale'. */
|
2259
2259
|
|
2260
2260
|
return lsd_scale(n_out,img,X,Y,scale);
|
2261
2261
|
|
@@ -2265,6 +2265,6 @@ double * lsd(int * n_out, double * img, int X, int Y)
|
|
2265
2265
|
|
2266
2266
|
/***** added by manuel aristaran ****/
|
2267
2267
|
|
2268
|
-
void free_values(
|
2268
|
+
void free_values(float * p) {
|
2269
2269
|
free((void *) p);
|
2270
2270
|
}
|