percept 0.0.1 → 3.0.0

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.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +34 -0
  3. data/.gitignore +3 -1
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +110 -0
  6. data/.rubocop_todo.yml +383 -0
  7. data/.tool-versions +2 -0
  8. data/Gemfile +12 -1
  9. data/Gemfile.lock +138 -0
  10. data/Guardfile +10 -0
  11. data/README.md +20 -0
  12. data/Rakefile +18 -0
  13. data/bin/percept +8 -1
  14. data/lib/ext/rmagick_pixel.rb +19 -0
  15. data/lib/percept/checkbox_collection.rb +19 -0
  16. data/lib/percept/checkbox_detector.rb +19 -0
  17. data/lib/percept/checkbox_field.rb +24 -0
  18. data/lib/percept/color_utils.rb +17 -0
  19. data/lib/percept/config.rb +35 -0
  20. data/lib/percept/field.rb +74 -0
  21. data/lib/percept/field_collection.rb +29 -0
  22. data/lib/percept/field_detector.rb +56 -0
  23. data/lib/percept/image.rb +60 -0
  24. data/lib/percept/line.rb +116 -4
  25. data/lib/percept/line_collection.rb +88 -0
  26. data/lib/percept/line_detector.rb +102 -0
  27. data/lib/percept/line_filter.rb +95 -0
  28. data/lib/percept/pixel.rb +28 -0
  29. data/lib/percept/pixel_utils.rb +73 -0
  30. data/lib/percept/rmagick_image.rb +49 -0
  31. data/lib/percept/runner.rb +15 -96
  32. data/lib/percept/utils.rb +15 -0
  33. data/lib/percept/version.rb +3 -1
  34. data/lib/percept.rb +40 -1
  35. data/percept.gemspec +6 -7
  36. data/spec/fixtures/black_lines.png +0 -0
  37. data/spec/fixtures/bottom_line.png +0 -0
  38. data/spec/fixtures/bumpy_no_line.png +0 -0
  39. data/spec/fixtures/corners.png +0 -0
  40. data/spec/fixtures/divots.png +0 -0
  41. data/spec/fixtures/field_next_to_text.png +0 -0
  42. data/spec/fixtures/gray_cell_bottom.png +0 -0
  43. data/spec/fixtures/gray_image_section.png +0 -0
  44. data/spec/fixtures/grey_lines.png +0 -0
  45. data/spec/fixtures/high_line.png +0 -0
  46. data/spec/fixtures/large_checkbox.png +0 -0
  47. data/spec/fixtures/large_checkboxes.png +0 -0
  48. data/spec/fixtures/light_gray.png +0 -0
  49. data/spec/fixtures/low_line.png +0 -0
  50. data/spec/fixtures/low_lines.png +0 -0
  51. data/spec/fixtures/mid_lines.png +0 -0
  52. data/spec/fixtures/more_corners.png +0 -0
  53. data/spec/fixtures/more_text_on_line.png +0 -0
  54. data/spec/fixtures/nub_both_sides.png +0 -0
  55. data/spec/fixtures/nub_bottom_left.png +0 -0
  56. data/spec/fixtures/nub_top_right.png +0 -0
  57. data/spec/fixtures/nubs.png +0 -0
  58. data/spec/fixtures/slanted_left.png +0 -0
  59. data/spec/fixtures/slanted_right.png +0 -0
  60. data/spec/fixtures/small_checkbox.png +0 -0
  61. data/spec/fixtures/text_no_line.png +0 -0
  62. data/spec/fixtures/text_no_line_2.png +0 -0
  63. data/spec/fixtures/text_on_line.png +0 -0
  64. data/spec/fixtures/thick_line.png +0 -0
  65. data/spec/fixtures/thin_field.png +0 -0
  66. data/spec/percept/checkbox_field/height_spec.rb +15 -0
  67. data/spec/percept/checkbox_field/width_spec.rb +15 -0
  68. data/spec/percept/field/contains_spec.rb +50 -0
  69. data/spec/percept/field_detector/detect_field_spec.rb +90 -0
  70. data/spec/percept/field_detector/detect_fields_spec.rb +42 -0
  71. data/spec/percept/fields_collection/shovel_spec.rb +53 -0
  72. data/spec/percept/line/approxequals_spec.rb +60 -0
  73. data/spec/percept/line/initialize_spec.rb +29 -0
  74. data/spec/percept/line/length_spec.rb +22 -0
  75. data/spec/percept/line/merge_bang_spec.rb +58 -0
  76. data/spec/percept/line/pixels_spec.rb +15 -0
  77. data/spec/percept/line/split_spec.rb +28 -0
  78. data/spec/percept/line/to_s_spec.rb +13 -0
  79. data/spec/percept/line_collection/merge_line_spec.rb +50 -0
  80. data/spec/percept/line_collection/remove_unwanted_lines_bang_spec.rb +17 -0
  81. data/spec/percept/line_collection/split_spec.rb +20 -0
  82. data/spec/percept/line_collection/to_s_spec.rb +11 -0
  83. data/spec/percept/line_detector/detect_lines_spec.rb +93 -0
  84. data/spec/percept/line_detector/scaled_color_spec.rb +14 -0
  85. data/spec/percept/line_filter/filter_line_predicate_spec.rb +29 -0
  86. data/spec/percept/line_filter/left_bottom_corner_predicate_spec.rb +49 -0
  87. data/spec/percept/line_filter/left_top_corner_predicate_spec.rb +50 -0
  88. data/spec/percept/line_filter/right_bottom_corner_predicate_spec.rb +49 -0
  89. data/spec/percept/line_filter/right_top_corner_predicate_spec.rb +49 -0
  90. data/spec/percept/line_filter/table_bottom_predicate_spec.rb +48 -0
  91. data/spec/percept/line_filter/table_top_predicate_spec.rb +48 -0
  92. data/spec/percept/pixel/blackish_predicate_spec.rb +36 -0
  93. data/spec/percept/rmagick_image/interface_spec.rb +11 -0
  94. data/spec/percept/runner/color_fields_spec.rb +28 -0
  95. data/spec/percept/runner/color_lines_spec.rb +27 -0
  96. data/spec/shared_examples/image_interface_shared_examples.rb +162 -0
  97. data/spec/spec_helper.rb +52 -0
  98. data/tddium.yml +12 -0
  99. data/test_images/funky_image.png +0 -0
  100. data/test_images/interaction_test.png +0 -0
  101. data/test_images/jagged_lines.png +0 -0
  102. data/test_images/permission.png +0 -0
  103. data/test_images/rough.png +0 -0
  104. data/test_images/slanted.png +0 -0
  105. data/test_images/time_sheet.png +0 -0
  106. data/test_images/travel_reimbursement.png +0 -0
  107. data/test_images/warehouse_form.png +0 -0
  108. metadata +171 -34
  109. data/new_permission.png +0 -0
  110. data/permission.png +0 -0
@@ -0,0 +1,93 @@
1
+ describe Percept::LineDetector, '#detect_lines' do
2
+
3
+ let(:line_detector) { Percept::LineDetector.new }
4
+
5
+ before(:each) do
6
+ Percept.config.line_length = 30
7
+ end
8
+
9
+ it 'returns a collection of lines with the appropriate coordinates' do
10
+ image = image_class.new(File.join(fixture_path, 'low_line.png'))
11
+ lines = line_detector.detect_lines(image)
12
+ expect(lines.size).to eq 1
13
+ line = lines.first
14
+ expect(line.length).to eq 32
15
+ expect(line.start_y).to eq 14
16
+ expect(line.end_y).to eq 15
17
+ expect(line.start_x).to eq 4
18
+ expect(line.end_x).to eq 36
19
+ end
20
+
21
+ it 'detects lines with divots' do
22
+ image = image_class.new(File.join(fixture_path, 'divots.png'))
23
+ lines = line_detector.detect_lines(image)
24
+ expect(lines.size).to eq 1
25
+ line = lines.first
26
+ expect(line.length).to eq 32
27
+ expect(line.start_y).to eq 11
28
+ expect(line.end_y).to eq 14
29
+ expect(line.start_x).to eq 4
30
+ expect(line.end_x).to eq 36
31
+ end
32
+
33
+ it 'detects lines with nubs' do
34
+ image = image_class.new(File.join(fixture_path, 'nubs.png'))
35
+ lines = line_detector.detect_lines(image)
36
+ expect(lines.size).to eq 1
37
+ line = lines.first
38
+ expect(line.length).to eq 32
39
+ expect(line.start_y).to eq 12
40
+ expect(line.end_y).to eq 14
41
+ expect(line.start_x).to eq 4
42
+ expect(line.end_x).to eq 36
43
+ end
44
+
45
+ it 'detects lines that are sloped to the left' do
46
+ image = image_class.new(File.join(fixture_path, 'slanted_left.png'))
47
+ lines = line_detector.detect_lines(image)
48
+ expect(lines.size).to eq 1
49
+ line = lines.first
50
+ expect(line.length).to eq 91
51
+ expect(line.start_y).to eq 21
52
+ expect(line.end_y).to eq 23
53
+ expect(line.start_x).to eq 5
54
+ expect(line.end_x).to eq 96
55
+ end
56
+
57
+ it 'detects lines that are sloped to the right' do
58
+ image = image_class.new(File.join(fixture_path, 'slanted_right.png'))
59
+ lines = line_detector.detect_lines(image)
60
+ expect(lines.size).to eq 1
61
+ line = lines.first
62
+ expect(line.length).to eq 91
63
+ expect(line.start_y).to eq 21
64
+ expect(line.end_y).to eq 23
65
+ expect(line.start_x).to eq 5
66
+ expect(line.end_x).to eq 96
67
+ end
68
+
69
+ it 'detects lines in images with gray filler' do
70
+ image = image_class.new(File.join(fixture_path, 'gray_image_section.png'))
71
+ lines = line_detector.detect_lines(image)
72
+ expect(lines.size).to eq 2
73
+ line = lines.first
74
+ expect(line.length).to eq 180
75
+ expect(line.start_y).to eq 16
76
+ expect(line.end_y).to eq 19
77
+ expect(line.start_x).to eq 20
78
+ expect(line.end_x).to eq 200
79
+ line = lines.last
80
+ expect(line.length).to eq 180
81
+ expect(line.start_y).to eq 68
82
+ expect(line.end_y).to eq 72
83
+ expect(line.start_x).to eq 20
84
+ expect(line.end_x).to eq 200
85
+ end
86
+
87
+ it 'it detects lines in a lighter gray image' do
88
+ image = image_class.new(File.join(fixture_path, 'light_gray.png'))
89
+ lines = line_detector.detect_lines(image)
90
+ expect(lines.size).to eq 1
91
+ end
92
+
93
+ end
@@ -0,0 +1,14 @@
1
+ describe Percept::LineDetector, '#scaled_color' do
2
+
3
+ let(:detector) { Percept::LineDetector.new }
4
+
5
+ before(:each) do
6
+ Percept.config.color_tolerance = 150
7
+ end
8
+
9
+ it 'multiplies the value by 256' do
10
+ expect(detector.scaled_color(1)).to eq 255
11
+ expect(detector.scaled_color(256)).to eq 65_535
12
+ end
13
+
14
+ end
@@ -0,0 +1,29 @@
1
+ describe Percept::LineFilter, '#filter_line?' do
2
+
3
+ let(:filter) { Percept::LineFilter.new }
4
+
5
+ context 'when a line is the tops of letters' do
6
+ it 'returns true' do
7
+ image = image_class.new(File.join(fixture_path, 'text_no_line.png'))
8
+ line = image.lines.first
9
+ expect(filter.filter_line?(line)).to be true
10
+ end
11
+ end
12
+
13
+ context 'when a line is the bottom of a table cell' do
14
+ it 'returns false' do
15
+ image = image_class.new(File.join(fixture_path, 'gray_cell_bottom.png'))
16
+ line = image.lines.first
17
+ expect(filter.filter_line?(line)).to be false
18
+ end
19
+ end
20
+
21
+ context 'when a line is too thick' do
22
+ it 'returns true' do
23
+ image = image_class.new(File.join(fixture_path, 'bumpy_no_line.png'))
24
+ line = image.lines.first
25
+ expect(filter.filter_line?(line)).to be true
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,49 @@
1
+ describe Percept::LineFilter, '#left_bottom_corner?' do
2
+
3
+ let(:corners_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image_1) { image_class.new(corners_path) }
5
+ let(:lines_1) { image_1.lines }
6
+
7
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
8
+ let(:image_2) { image_class.new(more_corners_path) }
9
+ let(:lines_2) { image_2.lines }
10
+
11
+ let(:filter) { Percept::LineFilter.new }
12
+
13
+ before(:each) do
14
+ Percept.config.line_length = 30
15
+ end
16
+
17
+ context 'when the line is the left bottom corner of a box' do
18
+ it 'returns true' do
19
+ expect(filter.left_bottom_corner?(lines_1[5])).to eq true
20
+ expect(filter.left_bottom_corner?(lines_1[6])).to eq true
21
+ expect(filter.left_bottom_corner?(lines_1[8])).to eq true
22
+
23
+ expect(filter.left_bottom_corner?(lines_2[8])).to eq true
24
+ end
25
+ end
26
+
27
+ context 'when the line is not the left bottom corner of a box' do
28
+ it 'returns false' do
29
+ expect(filter.left_bottom_corner?(lines_1[0])).to eq false
30
+ expect(filter.left_bottom_corner?(lines_1[1])).to eq false
31
+ expect(filter.left_bottom_corner?(lines_1[2])).to eq false
32
+ expect(filter.left_bottom_corner?(lines_1[3])).to eq false
33
+ expect(filter.left_bottom_corner?(lines_1[4])).to eq false
34
+ expect(filter.left_bottom_corner?(lines_1[7])).to eq false
35
+ expect(filter.left_bottom_corner?(lines_1[9])).to eq false
36
+
37
+ expect(filter.left_bottom_corner?(lines_2[0])).to eq false
38
+ expect(filter.left_bottom_corner?(lines_2[1])).to eq false
39
+ expect(filter.left_bottom_corner?(lines_2[2])).to eq false
40
+ expect(filter.left_bottom_corner?(lines_2[3])).to eq false
41
+ expect(filter.left_bottom_corner?(lines_2[4])).to eq false
42
+ expect(filter.left_bottom_corner?(lines_2[5])).to eq false
43
+ expect(filter.left_bottom_corner?(lines_2[6])).to eq false
44
+ expect(filter.left_bottom_corner?(lines_2[7])).to eq false
45
+ expect(filter.left_bottom_corner?(lines_2[9])).to eq false
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,50 @@
1
+ describe Percept::LineFilter, '#left_top_corner?' do
2
+
3
+ let(:corners_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image_1) { image_class.new(corners_path) }
5
+ let(:lines_1) { image_1.lines }
6
+
7
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
8
+ let(:image_2) { image_class.new(more_corners_path) }
9
+ let(:lines_2) { image_2.lines }
10
+
11
+ let(:filter) { Percept::LineFilter.new }
12
+
13
+ before(:each) do
14
+ Percept.config.line_length = 30
15
+ end
16
+
17
+ context 'when the line is the left top corner of a box' do
18
+ it 'returns true' do
19
+ expect(lines_1.size).to eq 10
20
+ expect(filter.left_top_corner?(lines_1[2])).to eq true
21
+ expect(filter.left_top_corner?(lines_1[2])).to eq true
22
+ expect(filter.left_top_corner?(lines_1[3])).to eq true
23
+ end
24
+ end
25
+
26
+ context 'when the line is not the left top corner of a box' do
27
+ it 'returns false' do
28
+ expect(filter.left_top_corner?(lines_1[0])).to eq false
29
+ expect(filter.left_top_corner?(lines_1[1])).to eq false
30
+ expect(filter.left_top_corner?(lines_1[4])).to eq false
31
+ expect(filter.left_top_corner?(lines_1[5])).to eq false
32
+ expect(filter.left_top_corner?(lines_1[6])).to eq false
33
+ expect(filter.left_top_corner?(lines_1[7])).to eq false
34
+ expect(filter.left_top_corner?(lines_1[8])).to eq false
35
+ expect(filter.left_top_corner?(lines_1[9])).to eq false
36
+
37
+ expect(filter.left_top_corner?(lines_2[0])).to eq false
38
+ expect(filter.left_top_corner?(lines_2[1])).to eq false
39
+ expect(filter.left_top_corner?(lines_2[2])).to eq false
40
+ expect(filter.left_top_corner?(lines_2[3])).to eq false
41
+ expect(filter.left_top_corner?(lines_2[4])).to eq false
42
+ expect(filter.left_top_corner?(lines_2[5])).to eq false
43
+ expect(filter.left_top_corner?(lines_2[6])).to eq false
44
+ expect(filter.left_top_corner?(lines_2[7])).to eq false
45
+ expect(filter.left_top_corner?(lines_2[8])).to eq false
46
+ expect(filter.left_top_corner?(lines_2[9])).to eq false
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,49 @@
1
+ describe Percept::LineFilter, '#right_bottom_corner?' do
2
+
3
+ let(:corners_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image_1) { image_class.new(corners_path) }
5
+ let(:lines_1) { image_1.lines }
6
+
7
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
8
+ let(:image_2) { image_class.new(more_corners_path) }
9
+ let(:lines_2) { image_2.lines }
10
+
11
+ let(:filter) { Percept::LineFilter.new }
12
+
13
+ before(:each) do
14
+ Percept.config.line_length = 30
15
+ end
16
+
17
+ context 'when the line is the right bottom corner of a box' do
18
+ it 'returns true' do
19
+ expect(filter.right_bottom_corner?(lines_1[4])).to eq true
20
+ expect(filter.right_bottom_corner?(lines_1[6])).to eq true
21
+ expect(filter.right_bottom_corner?(lines_1[7])).to eq true
22
+
23
+ expect(filter.right_bottom_corner?(lines_2[9])).to eq true
24
+ end
25
+ end
26
+
27
+ context 'when the line is not the right bottom corner of a box' do
28
+ it 'returns false' do
29
+ expect(filter.right_bottom_corner?(lines_1[0])).to eq false
30
+ expect(filter.right_bottom_corner?(lines_1[1])).to eq false
31
+ expect(filter.right_bottom_corner?(lines_1[2])).to eq false
32
+ expect(filter.right_bottom_corner?(lines_1[3])).to eq false
33
+ expect(filter.right_bottom_corner?(lines_1[5])).to eq false
34
+ expect(filter.right_bottom_corner?(lines_1[8])).to eq false
35
+ expect(filter.right_bottom_corner?(lines_1[9])).to eq false
36
+
37
+ expect(filter.right_bottom_corner?(lines_2[0])).to eq false
38
+ expect(filter.right_bottom_corner?(lines_2[1])).to eq false
39
+ expect(filter.right_bottom_corner?(lines_2[2])).to eq false
40
+ expect(filter.right_bottom_corner?(lines_2[3])).to eq false
41
+ expect(filter.right_bottom_corner?(lines_2[4])).to eq false
42
+ expect(filter.right_bottom_corner?(lines_2[5])).to eq false
43
+ expect(filter.right_bottom_corner?(lines_2[6])).to eq false
44
+ expect(filter.right_bottom_corner?(lines_2[7])).to eq false
45
+ expect(filter.right_bottom_corner?(lines_2[8])).to eq false
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,49 @@
1
+ describe Percept::LineFilter, '#right_top_corner?' do
2
+
3
+ let(:corners_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image_1) { image_class.new(corners_path) }
5
+ let(:lines_1) { image_1.lines }
6
+
7
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
8
+ let(:image_2) { image_class.new(more_corners_path) }
9
+ let(:lines_2) { image_2.lines }
10
+
11
+ let(:filter) { Percept::LineFilter.new }
12
+
13
+ before(:each) do
14
+ Percept.config.line_length = 30
15
+ end
16
+
17
+ context 'when the line is the right top corner of a box' do
18
+ it 'returns true' do
19
+ expect(lines_1.size).to eq 10
20
+ expect(filter.right_top_corner?(lines_1[1])).to eq true
21
+ expect(filter.right_top_corner?(lines_1[3])).to eq true
22
+ end
23
+ end
24
+
25
+ context 'when the line is not the right top corner of a box' do
26
+ it 'returns false' do
27
+ expect(filter.right_top_corner?(lines_1[0])).to eq false
28
+ expect(filter.right_top_corner?(lines_1[2])).to eq false
29
+ expect(filter.right_top_corner?(lines_1[4])).to eq false
30
+ expect(filter.right_top_corner?(lines_1[5])).to eq false
31
+ expect(filter.right_top_corner?(lines_1[6])).to eq false
32
+ expect(filter.right_top_corner?(lines_1[7])).to eq false
33
+ expect(filter.right_top_corner?(lines_1[8])).to eq false
34
+ expect(filter.right_top_corner?(lines_1[9])).to eq false
35
+
36
+ expect(filter.right_top_corner?(lines_2[0])).to eq false
37
+ expect(filter.right_top_corner?(lines_2[1])).to eq false
38
+ expect(filter.right_top_corner?(lines_2[2])).to eq false
39
+ expect(filter.right_top_corner?(lines_2[3])).to eq false
40
+ expect(filter.right_top_corner?(lines_2[4])).to eq false
41
+ expect(filter.right_top_corner?(lines_2[5])).to eq false
42
+ expect(filter.right_top_corner?(lines_2[6])).to eq false
43
+ expect(filter.right_top_corner?(lines_2[7])).to eq false
44
+ expect(filter.right_top_corner?(lines_2[8])).to eq false
45
+ expect(filter.right_top_corner?(lines_2[9])).to eq false
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,48 @@
1
+ describe Percept::LineFilter, '#table_bottom?' do
2
+
3
+ let(:corners_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image_1) { image_class.new(corners_path) }
5
+ let(:lines_1) { image_1.lines }
6
+
7
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
8
+ let(:image_2) { image_class.new(more_corners_path) }
9
+ let(:lines_2) { image_2.lines }
10
+
11
+ let(:filter) { Percept::LineFilter.new }
12
+
13
+ before(:each) do
14
+ Percept.config.line_length = 30
15
+ end
16
+
17
+ context 'when the line has both left and right bottom corners' do
18
+ it 'returns true' do
19
+ expect(filter.table_bottom?(lines_1[6])).to eq true
20
+ end
21
+ end
22
+
23
+ context 'when the line does not have left and right bottom corners' do
24
+ it 'returns false' do
25
+ expect(filter.table_bottom?(lines_1[0])).to eq false
26
+ expect(filter.table_bottom?(lines_1[1])).to eq false
27
+ expect(filter.table_bottom?(lines_1[2])).to eq false
28
+ expect(filter.table_bottom?(lines_1[3])).to eq false
29
+ expect(filter.table_bottom?(lines_1[4])).to eq false
30
+ expect(filter.table_bottom?(lines_1[5])).to eq false
31
+ expect(filter.table_bottom?(lines_1[7])).to eq false
32
+ expect(filter.table_bottom?(lines_1[8])).to eq false
33
+ expect(filter.table_bottom?(lines_1[9])).to eq false
34
+
35
+ expect(filter.table_bottom?(lines_2[0])).to eq false
36
+ expect(filter.table_bottom?(lines_2[1])).to eq false
37
+ expect(filter.table_bottom?(lines_2[2])).to eq false
38
+ expect(filter.table_bottom?(lines_2[3])).to eq false
39
+ expect(filter.table_bottom?(lines_2[4])).to eq false
40
+ expect(filter.table_bottom?(lines_2[5])).to eq false
41
+ expect(filter.table_bottom?(lines_2[6])).to eq false
42
+ expect(filter.table_bottom?(lines_2[7])).to eq false
43
+ expect(filter.table_bottom?(lines_2[8])).to eq false
44
+ expect(filter.table_bottom?(lines_2[9])).to eq false
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,48 @@
1
+ describe Percept::LineFilter, '#table_top?' do
2
+
3
+ let(:corners_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image_1) { image_class.new(corners_path) }
5
+ let(:lines_1) { image_1.lines }
6
+
7
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
8
+ let(:image_2) { image_class.new(more_corners_path) }
9
+ let(:lines_2) { image_2.lines }
10
+
11
+ let(:filter) { Percept::LineFilter.new }
12
+
13
+ before(:each) do
14
+ Percept.config.line_length = 30
15
+ end
16
+
17
+ context 'when the line has both left and right top corners' do
18
+ it 'returns true' do
19
+ expect(filter.table_top?(lines_1[3])).to eq true
20
+ end
21
+ end
22
+
23
+ context 'when the line does not have left and right top corners' do
24
+ it 'returns false' do
25
+ expect(filter.table_top?(lines_1[0])).to eq false
26
+ expect(filter.table_top?(lines_1[1])).to eq false
27
+ expect(filter.table_top?(lines_1[2])).to eq false
28
+ expect(filter.table_top?(lines_1[4])).to eq false
29
+ expect(filter.table_top?(lines_1[5])).to eq false
30
+ expect(filter.table_top?(lines_1[6])).to eq false
31
+ expect(filter.table_top?(lines_1[7])).to eq false
32
+ expect(filter.table_top?(lines_1[8])).to eq false
33
+ expect(filter.table_top?(lines_1[9])).to eq false
34
+
35
+ expect(filter.table_top?(lines_2[0])).to eq false
36
+ expect(filter.table_top?(lines_2[1])).to eq false
37
+ expect(filter.table_top?(lines_2[2])).to eq false
38
+ expect(filter.table_top?(lines_2[3])).to eq false
39
+ expect(filter.table_top?(lines_2[4])).to eq false
40
+ expect(filter.table_top?(lines_2[5])).to eq false
41
+ expect(filter.table_top?(lines_2[6])).to eq false
42
+ expect(filter.table_top?(lines_2[7])).to eq false
43
+ expect(filter.table_top?(lines_2[8])).to eq false
44
+ expect(filter.table_top?(lines_2[9])).to eq false
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,36 @@
1
+ describe Percept::Pixel, '#blackish?' do
2
+
3
+ let(:pixel) { Percept::Pixel.new({ red: 10, green: 10, blue: 10 }) }
4
+
5
+ before(:each) do
6
+ Percept.config.color_tolerance = 150
7
+ end
8
+
9
+ context 'if the given object has all colors below the tolerance' do
10
+ it 'returns true' do
11
+ expect(pixel.blackish?).to eq true
12
+ end
13
+ end
14
+
15
+ context 'if red is greater than the tolerance' do
16
+ it 'returns false' do
17
+ expect(pixel).to receive(:red).and_return(45_000)
18
+ expect(pixel.blackish?).to eq false
19
+ end
20
+ end
21
+
22
+ context 'if blue is greater than the tolerance' do
23
+ it 'returns false' do
24
+ expect(pixel).to receive(:blue).and_return(45_000)
25
+ expect(pixel.blackish?).to eq false
26
+ end
27
+ end
28
+
29
+ context 'if green is greater than the tolerance' do
30
+ it 'returns false' do
31
+ expect(pixel).to receive(:green).and_return(45_000)
32
+ expect(pixel.blackish?).to eq false
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,11 @@
1
+ describe Percept::RMagickImage do
2
+
3
+ it_behaves_like 'image interface' do
4
+ let(:image) { Percept::RMagickImage.new(image_path) }
5
+
6
+ before(:each) do
7
+ Percept.config.image_class = Percept::RMagickImage
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,28 @@
1
+ describe Percept::Runner, '#color_fields' do
2
+
3
+ let(:image_path) { File.join(fixture_path, 'black_lines.png') }
4
+ let(:runner) { Percept::Runner.new }
5
+ let(:image) { image_class.new(image_path) }
6
+
7
+ before(:each) do
8
+ Percept.config.line_length = 30
9
+ Percept.config.min_field_height = 10
10
+ end
11
+
12
+ def red?(pixel)
13
+ pixel.red > 0 && pixel.blue == 0 && pixel.green == 0
14
+ end
15
+
16
+ it 'colors a red box above the lines' do
17
+ black_pixels = image.pixels.select(&:blackish?)
18
+ runner.color_fields(image_path)
19
+ line = image.lines.first
20
+ field = Percept::FieldDetector.new.detect_field(line, image)
21
+ output_image = image_class.new(output_path)
22
+ output_black_pixels = output_image.pixels.select(&:blackish?)
23
+ expect(output_black_pixels.length).to eq black_pixels.length
24
+ output_red_pixels = output_image.pixels.select { |p| red?(p) }
25
+ expect(output_red_pixels.length).to eq field.pixels.length
26
+ end
27
+
28
+ end
@@ -0,0 +1,27 @@
1
+ describe Percept::Runner, '#color_lines' do
2
+
3
+ let(:image_path) { File.join(fixture_path, 'black_lines.png') }
4
+ let(:runner) { Percept::Runner.new }
5
+ let(:image) { image_class.new(image_path) }
6
+
7
+ before(:each) do
8
+ Percept.config.line_length = 30
9
+ Percept.config.color_tolerance = 150
10
+ end
11
+
12
+ def red?(pixel)
13
+ pixel.red > 0 && pixel.blue == 0 && pixel.green == 0
14
+ end
15
+
16
+ it 'colors lines red that are greater than or equal to the line length' do
17
+ black_pixels = image.pixels.select(&:blackish?)
18
+ runner.color_lines(image_path)
19
+ output_image = image_class.new(output_path)
20
+ output_black_pixels = output_image.pixels.select(&:blackish?)
21
+ output_red_pixels = output_image.pixels.select { |p| red?(p) }
22
+ expect(output_red_pixels.length).to eq 77
23
+ expected_length = black_pixels.length - output_red_pixels.length
24
+ expect(output_black_pixels.length).to eq expected_length
25
+ end
26
+
27
+ end