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.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +3 -1
- data/.rspec +3 -0
- data/.rubocop.yml +110 -0
- data/.rubocop_todo.yml +383 -0
- data/.tool-versions +2 -0
- data/Gemfile +12 -1
- data/Gemfile.lock +138 -0
- data/Guardfile +10 -0
- data/README.md +20 -0
- data/Rakefile +18 -0
- data/bin/percept +8 -1
- data/lib/ext/rmagick_pixel.rb +19 -0
- data/lib/percept/checkbox_collection.rb +19 -0
- data/lib/percept/checkbox_detector.rb +19 -0
- data/lib/percept/checkbox_field.rb +24 -0
- data/lib/percept/color_utils.rb +17 -0
- data/lib/percept/config.rb +35 -0
- data/lib/percept/field.rb +74 -0
- data/lib/percept/field_collection.rb +29 -0
- data/lib/percept/field_detector.rb +56 -0
- data/lib/percept/image.rb +60 -0
- data/lib/percept/line.rb +116 -4
- data/lib/percept/line_collection.rb +88 -0
- data/lib/percept/line_detector.rb +102 -0
- data/lib/percept/line_filter.rb +95 -0
- data/lib/percept/pixel.rb +28 -0
- data/lib/percept/pixel_utils.rb +73 -0
- data/lib/percept/rmagick_image.rb +49 -0
- data/lib/percept/runner.rb +15 -96
- data/lib/percept/utils.rb +15 -0
- data/lib/percept/version.rb +3 -1
- data/lib/percept.rb +40 -1
- data/percept.gemspec +6 -7
- data/spec/fixtures/black_lines.png +0 -0
- data/spec/fixtures/bottom_line.png +0 -0
- data/spec/fixtures/bumpy_no_line.png +0 -0
- data/spec/fixtures/corners.png +0 -0
- data/spec/fixtures/divots.png +0 -0
- data/spec/fixtures/field_next_to_text.png +0 -0
- data/spec/fixtures/gray_cell_bottom.png +0 -0
- data/spec/fixtures/gray_image_section.png +0 -0
- data/spec/fixtures/grey_lines.png +0 -0
- data/spec/fixtures/high_line.png +0 -0
- data/spec/fixtures/large_checkbox.png +0 -0
- data/spec/fixtures/large_checkboxes.png +0 -0
- data/spec/fixtures/light_gray.png +0 -0
- data/spec/fixtures/low_line.png +0 -0
- data/spec/fixtures/low_lines.png +0 -0
- data/spec/fixtures/mid_lines.png +0 -0
- data/spec/fixtures/more_corners.png +0 -0
- data/spec/fixtures/more_text_on_line.png +0 -0
- data/spec/fixtures/nub_both_sides.png +0 -0
- data/spec/fixtures/nub_bottom_left.png +0 -0
- data/spec/fixtures/nub_top_right.png +0 -0
- data/spec/fixtures/nubs.png +0 -0
- data/spec/fixtures/slanted_left.png +0 -0
- data/spec/fixtures/slanted_right.png +0 -0
- data/spec/fixtures/small_checkbox.png +0 -0
- data/spec/fixtures/text_no_line.png +0 -0
- data/spec/fixtures/text_no_line_2.png +0 -0
- data/spec/fixtures/text_on_line.png +0 -0
- data/spec/fixtures/thick_line.png +0 -0
- data/spec/fixtures/thin_field.png +0 -0
- data/spec/percept/checkbox_field/height_spec.rb +15 -0
- data/spec/percept/checkbox_field/width_spec.rb +15 -0
- data/spec/percept/field/contains_spec.rb +50 -0
- data/spec/percept/field_detector/detect_field_spec.rb +90 -0
- data/spec/percept/field_detector/detect_fields_spec.rb +42 -0
- data/spec/percept/fields_collection/shovel_spec.rb +53 -0
- data/spec/percept/line/approxequals_spec.rb +60 -0
- data/spec/percept/line/initialize_spec.rb +29 -0
- data/spec/percept/line/length_spec.rb +22 -0
- data/spec/percept/line/merge_bang_spec.rb +58 -0
- data/spec/percept/line/pixels_spec.rb +15 -0
- data/spec/percept/line/split_spec.rb +28 -0
- data/spec/percept/line/to_s_spec.rb +13 -0
- data/spec/percept/line_collection/merge_line_spec.rb +50 -0
- data/spec/percept/line_collection/remove_unwanted_lines_bang_spec.rb +17 -0
- data/spec/percept/line_collection/split_spec.rb +20 -0
- data/spec/percept/line_collection/to_s_spec.rb +11 -0
- data/spec/percept/line_detector/detect_lines_spec.rb +93 -0
- data/spec/percept/line_detector/scaled_color_spec.rb +14 -0
- data/spec/percept/line_filter/filter_line_predicate_spec.rb +29 -0
- data/spec/percept/line_filter/left_bottom_corner_predicate_spec.rb +49 -0
- data/spec/percept/line_filter/left_top_corner_predicate_spec.rb +50 -0
- data/spec/percept/line_filter/right_bottom_corner_predicate_spec.rb +49 -0
- data/spec/percept/line_filter/right_top_corner_predicate_spec.rb +49 -0
- data/spec/percept/line_filter/table_bottom_predicate_spec.rb +48 -0
- data/spec/percept/line_filter/table_top_predicate_spec.rb +48 -0
- data/spec/percept/pixel/blackish_predicate_spec.rb +36 -0
- data/spec/percept/rmagick_image/interface_spec.rb +11 -0
- data/spec/percept/runner/color_fields_spec.rb +28 -0
- data/spec/percept/runner/color_lines_spec.rb +27 -0
- data/spec/shared_examples/image_interface_shared_examples.rb +162 -0
- data/spec/spec_helper.rb +52 -0
- data/tddium.yml +12 -0
- data/test_images/funky_image.png +0 -0
- data/test_images/interaction_test.png +0 -0
- data/test_images/jagged_lines.png +0 -0
- data/test_images/permission.png +0 -0
- data/test_images/rough.png +0 -0
- data/test_images/slanted.png +0 -0
- data/test_images/time_sheet.png +0 -0
- data/test_images/travel_reimbursement.png +0 -0
- data/test_images/warehouse_form.png +0 -0
- metadata +171 -34
- data/new_permission.png +0 -0
- data/permission.png +0 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
class LineCollection
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_accessor :lines
|
8
|
+
|
9
|
+
def initialize(lines = [])
|
10
|
+
self.lines = lines
|
11
|
+
end
|
12
|
+
|
13
|
+
def <<(new_line)
|
14
|
+
merge_line(new_line) || lines << new_line
|
15
|
+
end
|
16
|
+
|
17
|
+
def merge!(other)
|
18
|
+
other.lines.each do |line|
|
19
|
+
self << line
|
20
|
+
end
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def split
|
25
|
+
collection = self.class.new
|
26
|
+
lines.each do |line|
|
27
|
+
collection.merge!(line.split)
|
28
|
+
end
|
29
|
+
collection
|
30
|
+
end
|
31
|
+
|
32
|
+
def merge_line(new_line)
|
33
|
+
old_line = lines.detect { |line| line =~ new_line }
|
34
|
+
|
35
|
+
return unless old_line
|
36
|
+
|
37
|
+
old_line.merge!(new_line)
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
def size
|
42
|
+
lines.size
|
43
|
+
end
|
44
|
+
alias length size
|
45
|
+
|
46
|
+
def each
|
47
|
+
lines.each { |line| yield(line) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def first
|
51
|
+
lines.first
|
52
|
+
end
|
53
|
+
|
54
|
+
def last
|
55
|
+
lines.last
|
56
|
+
end
|
57
|
+
|
58
|
+
def [](index)
|
59
|
+
lines[index]
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
lines.map(&:to_s).to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
def empty?
|
67
|
+
lines.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
def remove_unwanted_lines!
|
71
|
+
lines.delete_if { |line| line_filter.filter_line?(line) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def remove_short_lines!
|
75
|
+
lines.delete_if(&:short?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def filtered
|
79
|
+
self.class.new(lines.select { |line| !line_filter.filter_line?(line) })
|
80
|
+
end
|
81
|
+
|
82
|
+
def line_filter
|
83
|
+
LineFilter.new
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
class LineDetector
|
4
|
+
|
5
|
+
include Percept::Utils
|
6
|
+
|
7
|
+
attr_accessor :image
|
8
|
+
|
9
|
+
def find_lines(row, row_number)
|
10
|
+
start_index = nil
|
11
|
+
lines = LineCollection.new
|
12
|
+
|
13
|
+
row.each_with_index do |pixel, index|
|
14
|
+
if pixel.blackish?
|
15
|
+
start_index ||= index
|
16
|
+
elsif divot?(row, index)
|
17
|
+
next
|
18
|
+
elsif start_index
|
19
|
+
if index - start_index > slope_length
|
20
|
+
lines << Line.new(
|
21
|
+
start_x: start_index,
|
22
|
+
end_x: index,
|
23
|
+
start_y: row_number,
|
24
|
+
row: row,
|
25
|
+
image: image,
|
26
|
+
)
|
27
|
+
end
|
28
|
+
start_index = nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
lines
|
32
|
+
end
|
33
|
+
|
34
|
+
def detect_lines(image)
|
35
|
+
self.image = image
|
36
|
+
lines = detect_lines_in_rows
|
37
|
+
if lines.empty?
|
38
|
+
Percept.config.maximize_color_tolerance!
|
39
|
+
@columns = nil
|
40
|
+
lines = detect_lines_in_rows
|
41
|
+
end
|
42
|
+
lines.remove_short_lines!
|
43
|
+
lines
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def detect_lines_in_rows
|
49
|
+
lines = LineCollection.new
|
50
|
+
row_numbers.each do |row_number|
|
51
|
+
row = image.retrieve_row(row_number)
|
52
|
+
lines.merge!(find_lines(row, row_number))
|
53
|
+
end
|
54
|
+
lines
|
55
|
+
end
|
56
|
+
|
57
|
+
def row_numbers
|
58
|
+
row_numbers = []
|
59
|
+
0.upto(image.row_count - 1).each do |row_number|
|
60
|
+
0.upto(columns.size - 2) do |index|
|
61
|
+
left_pixel = columns[index][row_number]
|
62
|
+
right_pixel = columns[index + 1][row_number]
|
63
|
+
|
64
|
+
if left_pixel.blackish? && right_pixel.blackish?
|
65
|
+
row_numbers << row_number
|
66
|
+
break
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
row_numbers
|
71
|
+
end
|
72
|
+
|
73
|
+
def columns
|
74
|
+
@columns ||= collect_columns
|
75
|
+
end
|
76
|
+
|
77
|
+
def collect_columns
|
78
|
+
0.step(image.column_count - 1, line_length / 2).map do |column_number|
|
79
|
+
image.magick_column(column_number)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def line_length
|
84
|
+
Percept.config.line_length
|
85
|
+
end
|
86
|
+
|
87
|
+
def slope_length
|
88
|
+
1.0 / slope
|
89
|
+
end
|
90
|
+
|
91
|
+
def slope
|
92
|
+
1.0 / 20.0
|
93
|
+
end
|
94
|
+
|
95
|
+
def divot?(row, index)
|
96
|
+
row[index + 2] && row[index + 2].blackish? ||
|
97
|
+
row[index + 1] && row[index + 1].blackish?
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
class LineFilter
|
4
|
+
|
5
|
+
def filter_line?(line)
|
6
|
+
table_top?(line) || top_of_letters?(line) || too_thick?(line)
|
7
|
+
end
|
8
|
+
|
9
|
+
def too_thick?(line)
|
10
|
+
line.height > Percept.config.max_line_height
|
11
|
+
end
|
12
|
+
|
13
|
+
def top_of_letters?(line)
|
14
|
+
blackish_bottom_pixels(line).length.to_f / line.length > 0.20
|
15
|
+
end
|
16
|
+
|
17
|
+
def blackish_bottom_pixels(line)
|
18
|
+
bottom_pixels(line).select(&:blackish?)
|
19
|
+
end
|
20
|
+
|
21
|
+
def bottom_pixels(line)
|
22
|
+
line.columns_for(line.start_x..line.end_x, line.end_y + 1).flatten
|
23
|
+
end
|
24
|
+
|
25
|
+
def left_top_corner?(line)
|
26
|
+
bottom_left_blackish?(line) && !top_left_blackish?(line)
|
27
|
+
end
|
28
|
+
|
29
|
+
def right_top_corner?(line)
|
30
|
+
bottom_right_blackish?(line) && !top_right_blackish?(line)
|
31
|
+
end
|
32
|
+
|
33
|
+
def left_bottom_corner?(line)
|
34
|
+
top_left_blackish?(line) && !bottom_left_blackish?(line)
|
35
|
+
end
|
36
|
+
|
37
|
+
def right_bottom_corner?(line)
|
38
|
+
top_right_blackish?(line) && !bottom_right_blackish?(line)
|
39
|
+
end
|
40
|
+
|
41
|
+
def top_left_blackish?(line)
|
42
|
+
top_left_columns(line).any? { |column| column.all?(&:blackish?) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def bottom_left_blackish?(line)
|
46
|
+
bottom_left_columns(line).any? { |column| column.all?(&:blackish?) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def top_right_blackish?(line)
|
50
|
+
top_right_columns(line).any? { |column| column.all?(&:blackish?) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def bottom_right_blackish?(line)
|
54
|
+
bottom_right_columns(line).any? { |column| column.all?(&:blackish?) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def bottom_left_columns(line)
|
58
|
+
line.columns_for(line.start_x..(line.start_x + 5), line.end_y)
|
59
|
+
end
|
60
|
+
|
61
|
+
def top_left_columns(line)
|
62
|
+
line.columns_for(line.start_x..(line.start_x + 5), line.start_y - 2)
|
63
|
+
end
|
64
|
+
|
65
|
+
def bottom_right_columns(line)
|
66
|
+
line.columns_for((line.end_x - 5)..line.end_x, line.end_y)
|
67
|
+
end
|
68
|
+
|
69
|
+
def top_right_columns(line)
|
70
|
+
line.columns_for((line.end_x - 5)..line.end_x, line.start_y - 2)
|
71
|
+
end
|
72
|
+
|
73
|
+
def table_top?(line)
|
74
|
+
left_top_corner?(line) && right_top_corner?(line)
|
75
|
+
end
|
76
|
+
|
77
|
+
def table_bottom?(line)
|
78
|
+
bottom_corners?(line) && !divided?(line)
|
79
|
+
end
|
80
|
+
|
81
|
+
def bottom_corners?(line)
|
82
|
+
left_bottom_corner?(line) && right_bottom_corner?(line)
|
83
|
+
end
|
84
|
+
|
85
|
+
def divided?(line)
|
86
|
+
line.split.length > 1
|
87
|
+
end
|
88
|
+
|
89
|
+
def table_border?(line)
|
90
|
+
table_top?(line) || table_bottom?(line)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
class Pixel
|
4
|
+
|
5
|
+
extend Forwardable
|
6
|
+
include Percept::Utils
|
7
|
+
include Percept::PixelUtils
|
8
|
+
|
9
|
+
attr_accessor :selected, :red, :green, :blue
|
10
|
+
|
11
|
+
def initialize(values, selected: false)
|
12
|
+
self.red = values.fetch(:red)
|
13
|
+
self.green = values.fetch(:green)
|
14
|
+
self.blue = values.fetch(:blue)
|
15
|
+
self.selected = selected == true
|
16
|
+
end
|
17
|
+
|
18
|
+
def scale_down(color_value)
|
19
|
+
color_value
|
20
|
+
end
|
21
|
+
|
22
|
+
def scale_up(color_value)
|
23
|
+
color_value
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
module PixelUtils
|
4
|
+
|
5
|
+
attr_accessor :selected
|
6
|
+
|
7
|
+
def scaled_colors
|
8
|
+
[scaled_red, scaled_green, scaled_blue]
|
9
|
+
end
|
10
|
+
|
11
|
+
def blackish?
|
12
|
+
scaled_colors.all? { |color| color <= color_tolerance }
|
13
|
+
end
|
14
|
+
|
15
|
+
def selected?
|
16
|
+
selected
|
17
|
+
end
|
18
|
+
|
19
|
+
def select!
|
20
|
+
self.selected = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def deselect!
|
24
|
+
self.selected = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
symbol.colorize(foreground_color).colorize(background: background_color)
|
29
|
+
end
|
30
|
+
|
31
|
+
def symbol
|
32
|
+
selected? ? '╺╸' : ' '
|
33
|
+
end
|
34
|
+
|
35
|
+
def foreground_color
|
36
|
+
blackish? ? :white : :black
|
37
|
+
end
|
38
|
+
|
39
|
+
def background_color
|
40
|
+
blackish? ? :black : :white
|
41
|
+
end
|
42
|
+
|
43
|
+
def color_tolerance
|
44
|
+
Percept.config.color_tolerance
|
45
|
+
end
|
46
|
+
|
47
|
+
def scaled_red
|
48
|
+
scale_down(red)
|
49
|
+
end
|
50
|
+
|
51
|
+
def scaled_green
|
52
|
+
scale_down(green)
|
53
|
+
end
|
54
|
+
|
55
|
+
def scaled_blue
|
56
|
+
scale_down(blue)
|
57
|
+
end
|
58
|
+
|
59
|
+
def scaled_red=(new_red)
|
60
|
+
self.red = scale_up(new_red)
|
61
|
+
end
|
62
|
+
|
63
|
+
def scaled_green=(new_green)
|
64
|
+
self.green = scale_up(new_green)
|
65
|
+
end
|
66
|
+
|
67
|
+
def scaled_blue=(new_blue)
|
68
|
+
self.blue = scale_up(new_blue)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
class RMagickImage < Image
|
4
|
+
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_writer :source
|
8
|
+
|
9
|
+
def_delegators :source, :columns, :rows, :store_pixels
|
10
|
+
|
11
|
+
def initialize(file_path)
|
12
|
+
self.file_path = file_path
|
13
|
+
end
|
14
|
+
|
15
|
+
def source
|
16
|
+
@source ||= Magick::Image.read(file_path).first
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(path)
|
20
|
+
dirname = File.dirname(path)
|
21
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
22
|
+
source.write(path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def magick_rows
|
26
|
+
@magick_rows ||= Array.new(row_count) do |row_number|
|
27
|
+
source.get_pixels(0, row_number, column_count, 1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def pixels
|
32
|
+
magick_rows.flatten
|
33
|
+
end
|
34
|
+
|
35
|
+
def retrieve_pixels(x, y, columns, rows)
|
36
|
+
source.get_pixels(x, y, columns, rows)
|
37
|
+
end
|
38
|
+
|
39
|
+
def row_count
|
40
|
+
rows
|
41
|
+
end
|
42
|
+
|
43
|
+
def column_count
|
44
|
+
columns
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/percept/runner.rb
CHANGED
@@ -1,114 +1,33 @@
|
|
1
1
|
module Percept
|
2
2
|
|
3
3
|
class Runner
|
4
|
-
def scaled_color(value)
|
5
|
-
(value * 256) - 1
|
6
|
-
end
|
7
|
-
|
8
|
-
LINE_LENGTH = 50
|
9
4
|
|
10
|
-
|
11
|
-
scaled_color(150)
|
12
|
-
end
|
13
|
-
#def black?(pixel)
|
14
|
-
# [pixel.red, pixel.green, pixel.blue].all? { |color| color == 0 }
|
15
|
-
#end
|
16
|
-
#
|
17
|
-
def blackish?(pixel)
|
18
|
-
[pixel.red, pixel.green, pixel.blue].all? { |color| color <= tolerance }
|
19
|
-
end
|
20
|
-
out_pixels = []
|
5
|
+
include Percept::Utils
|
21
6
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
7
|
+
def color_lines(file_path)
|
8
|
+
image = Percept.config.image_class.new(file_path)
|
9
|
+
lines = image.lines
|
10
|
+
lines = lines.split
|
11
|
+
lines.remove_unwanted_lines!
|
26
12
|
|
27
|
-
|
28
|
-
|
29
|
-
# continue
|
30
|
-
elsif blackish?(pixel) && !start_index
|
31
|
-
start_index = index
|
32
|
-
elsif start_index
|
33
|
-
if index - start_index > LINE_LENGTH
|
34
|
-
line_indices += (start_index...index).to_a
|
35
|
-
end
|
36
|
-
start_index = nil
|
37
|
-
end
|
13
|
+
lines.each do |line|
|
14
|
+
line.color!(255, 0, 0)
|
38
15
|
end
|
39
16
|
|
40
|
-
|
41
|
-
pixel = row[index]
|
42
|
-
pixel.red = scaled_color(256)
|
43
|
-
end
|
44
|
-
row
|
17
|
+
image.write(Percept.config.output_path)
|
45
18
|
end
|
46
19
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
20
|
+
def color_fields(file_path)
|
21
|
+
image = Percept.config.image_class.new(file_path)
|
22
|
+
fields = image.fields
|
50
23
|
|
51
|
-
|
52
|
-
|
53
|
-
start_index ||= index
|
54
|
-
elsif start_index
|
55
|
-
if index - start_index > LINE_LENGTH
|
56
|
-
lines << Line.new(:start_x => start_index, :end_x => index, :row => row, :start_y => row_number)
|
57
|
-
end
|
58
|
-
start_index = nil
|
59
|
-
end
|
24
|
+
fields.each do |field|
|
25
|
+
field.color!(255, 0, 0)
|
60
26
|
end
|
61
|
-
lines
|
62
|
-
end
|
63
27
|
|
64
|
-
|
65
|
-
column_count = image.columns
|
66
|
-
row_count = image.rows
|
67
|
-
row_count.times do |row_number|
|
68
|
-
row = image.get_pixels(0, row_number, column_count, 1)
|
69
|
-
yield(row, row_number)
|
70
|
-
end
|
28
|
+
image.write(Percept.config.output_path)
|
71
29
|
end
|
72
30
|
|
73
|
-
def run
|
74
|
-
images = Magick::ImageList.new('./permission.png')
|
75
|
-
image = images.first
|
76
|
-
#new_image = Magick::Image.new
|
77
|
-
|
78
|
-
rows = image.rows
|
79
|
-
columns = image.columns
|
80
|
-
|
81
|
-
lines = []
|
82
|
-
output_pixels = []
|
83
|
-
each_row(image) do |row, index|
|
84
|
-
output_pixels += row
|
85
|
-
if index % 50 == 0
|
86
|
-
puts "working on row: #{index} of #{rows}"
|
87
|
-
end
|
88
|
-
lines += find_lines(row, index)
|
89
|
-
#out_pixels += highlight_lines!(row)
|
90
|
-
#row.each do |pixel|
|
91
|
-
# pixel.red = scaled_color(256) if blackish?(pixel)
|
92
|
-
# out_pixels << pixel
|
93
|
-
#end
|
94
|
-
end
|
95
|
-
|
96
|
-
line_count = lines.count
|
97
|
-
lines.each_with_index do |line, index|
|
98
|
-
puts "coloring line #{index} of #{line_count}"
|
99
|
-
line.pixels.each do |pixel|
|
100
|
-
pixel.red = scaled_color(256)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
#image.each_pixel do |pixel, column, row|
|
105
|
-
# pixel.red = 60000 if blackish?(pixel)
|
106
|
-
# out_pixels << pixel
|
107
|
-
#end
|
108
|
-
|
109
|
-
image = image.store_pixels(0, 0, columns, rows, output_pixels)
|
110
|
-
image.write('new_permission.png')
|
111
|
-
end
|
112
31
|
end
|
113
32
|
|
114
33
|
end
|
data/lib/percept/version.rb
CHANGED
data/lib/percept.rb
CHANGED
@@ -1,4 +1,43 @@
|
|
1
|
-
|
1
|
+
module Percept
|
2
|
+
|
3
|
+
def self.config
|
4
|
+
@config ||= Config.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.configure
|
8
|
+
yield config if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.reset
|
12
|
+
@config = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def config
|
16
|
+
Percept.config
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rmagick'
|
22
|
+
require 'forwardable'
|
23
|
+
|
24
|
+
require_relative 'percept/utils'
|
25
|
+
require_relative 'percept/color_utils'
|
26
|
+
require_relative 'percept/config'
|
27
|
+
require_relative 'percept/checkbox_field'
|
28
|
+
require_relative 'percept/checkbox_collection'
|
29
|
+
require_relative 'percept/checkbox_detector'
|
30
|
+
require_relative 'percept/field'
|
31
|
+
require_relative 'percept/field_collection'
|
32
|
+
require_relative 'percept/field_detector'
|
33
|
+
require_relative 'percept/pixel_utils'
|
34
|
+
require_relative 'ext/rmagick_pixel'
|
35
|
+
require_relative 'percept/pixel'
|
2
36
|
require_relative 'percept/line'
|
37
|
+
require_relative 'percept/line_collection'
|
38
|
+
require_relative 'percept/line_filter'
|
39
|
+
require_relative 'percept/line_detector'
|
40
|
+
require_relative 'percept/image'
|
41
|
+
require_relative 'percept/rmagick_image'
|
3
42
|
require_relative 'percept/runner'
|
4
43
|
require_relative 'percept/version'
|
data/percept.gemspec
CHANGED
@@ -1,23 +1,22 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
|
3
|
+
require_relative 'lib/percept/version'
|
4
|
+
require 'English'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'percept'
|
8
8
|
spec.version = Percept::VERSION
|
9
9
|
spec.authors = ['Robert Fletcher']
|
10
10
|
spec.email = ['lobatifricha@gmail.com']
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
11
|
+
spec.description = 'Detect lines in an image'
|
12
|
+
spec.summary = 'Blackish lines for now...'
|
13
13
|
spec.homepage = ''
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split(
|
16
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(spec)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.
|
22
|
-
spec.add_development_dependency 'rake'
|
21
|
+
spec.add_runtime_dependency 'rmagick', '~> 6.1.1'
|
23
22
|
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|