tabula-extractor 0.6.6-java → 0.7.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|