imatcher 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ad15eab2eb3ec4656cafb23117199966625e18d
4
- data.tar.gz: 3d15c721ce46ed7cbca79a0d9d4e310972ebcfc2
3
+ metadata.gz: cdc4ac5a873087643b65c5d5b196cb389c64bf96
4
+ data.tar.gz: 2c2641e6e1421b5627731cdcc9e912b289539dc2
5
5
  SHA512:
6
- metadata.gz: b098cf87274c56a0089e795e686d6299ea91339d8bff948486ca25ea5a75e993fb1eb50d533416e2eddd18e035d1dc1330eb055e8a23ddb74e49d54c87f6b406
7
- data.tar.gz: 11c76b5365728cfb495a764e15241d1aea897b8d1cf0642a0dceb870479ce2fc4f3bec87efd1c80ce59b12b8fc28d817cfda79013ec384cba7ed76bf7000635b
6
+ metadata.gz: 347587af896ae12f1647c897c2c8749aecc0546f8d50eb8a143a2d4dc7bd1193f24ca85ee204bf31c2064fd5b290f9b84ba8e7d9ca813a3745e45e9b2f95ffd1
7
+ data.tar.gz: fab3b1e8e9501e5cdb5db0c460a8bc414d4d0189af99c38d585759a49d561bac66124a3b08bc3d876942db5c3956dcf80e9f25316cef8c5a8fd60b546818119f
@@ -0,0 +1,42 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'benchmark/ips'
3
+ require 'imatcher'
4
+
5
+ a = Imatcher::Image.from_file(File.expand_path('../../spec/fixtures/a.png', __FILE__))
6
+ b = Imatcher::Image.from_file(File.expand_path('../../spec/fixtures/a.png', __FILE__))
7
+
8
+ rgb = Imatcher::Matcher.new
9
+ grayscale = Imatcher::Matcher.new mode: :grayscale
10
+ delta = Imatcher::Matcher.new mode: :delta
11
+
12
+ Benchmark.ips do |x|
13
+ x.report 'RGB' do
14
+ rgb.compare(a, b)
15
+ end
16
+
17
+ x.report 'Grayscale' do
18
+ grayscale.compare(a, b)
19
+ end
20
+
21
+ x.report 'Delta E' do
22
+ delta.compare(a, b)
23
+ end
24
+
25
+ x.compare!
26
+ end
27
+
28
+ Benchmark.ips do |x|
29
+ x.report 'RGB' do
30
+ rgb.compare(a, b).difference_image
31
+ end
32
+
33
+ x.report 'Grayscale' do
34
+ grayscale.compare(a, b).difference_image
35
+ end
36
+
37
+ x.report 'Delta E' do
38
+ delta.compare(a, b).difference_image
39
+ end
40
+
41
+ x.compare!
42
+ end
@@ -43,5 +43,9 @@ module Imatcher
43
43
  def render_bounds(left, bot, right, top)
44
44
  rect(left, bot, right, top, rgb(255, 0, 0))
45
45
  end
46
+
47
+ def inspect
48
+ "Image:#{object_id}<#{width}x#{height}>"
49
+ end
46
50
  end
47
51
  end
@@ -18,9 +18,9 @@ module Imatcher
18
18
  @mode = Modes.const_get(MODES[mode_type]).new(options)
19
19
  end
20
20
 
21
- def compare(path_1, path_2)
22
- a = Image.from_file(path_1)
23
- b = Image.from_file(path_2)
21
+ def compare(a, b)
22
+ a = Image.from_file(a) unless a.is_a?(Image)
23
+ b = Image.from_file(b) unless b.is_a?(Image)
24
24
  raise SizesMismatchError,
25
25
  "Size mismatch: first image size: " \
26
26
  "#{a.width}x#{a.height}, " \
@@ -3,7 +3,7 @@ module Imatcher
3
3
  class Base # :nodoc:
4
4
  include ColorMethods
5
5
 
6
- attr_reader :result, :threshold
6
+ attr_reader :result, :threshold, :bounds
7
7
 
8
8
  def initialize(threshold: 0.0)
9
9
  @threshold = threshold
@@ -12,6 +12,7 @@ module Imatcher
12
12
 
13
13
  def compare(a, b)
14
14
  result.image = a
15
+ @bounds = [0, 0, result.image.width - 1, result.image.height - 1]
15
16
 
16
17
  b.compare_each_pixel(a) do |b_pixel, a_pixel, x, y|
17
18
  next if pixels_equal?(b_pixel, a_pixel)
@@ -24,28 +25,25 @@ module Imatcher
24
25
 
25
26
  def diff(bg, diff)
26
27
  diff_image = background(bg)
27
- diff_image.render_bounds(*calculate_bounds(diff))
28
28
  diff.each do |pixels_pair|
29
29
  pixels_diff(diff_image, *pixels_pair)
30
30
  end
31
- create_diff_image(bg, diff_image)
31
+ create_diff_image(bg, diff_image).render_bounds(*bounds)
32
32
  end
33
33
 
34
34
  def score
35
35
  @result.diff.length.to_f / @result.image.pixels.length
36
36
  end
37
37
 
38
- # rubocop:disable Metrics/AbcSize
39
- def calculate_bounds(diff)
40
- xmin, xmax, ymin, ymax = result.image.width, 0, result.image.height, 0
41
- diff.each do |pixels_pair|
42
- xmin = pixels_pair[2] if pixels_pair[2] < xmin
43
- xmax = pixels_pair[2] if pixels_pair[2] > xmax
44
- ymin = pixels_pair[3] if pixels_pair[3] < ymin
45
- ymax = pixels_pair[3] if pixels_pair[3] > ymax
46
- end
38
+ def update_result(*_args, x, y)
39
+ update_bounds(x, y)
40
+ end
47
41
 
48
- [xmin - 1, ymin - 1, xmax + 1, ymax + 1]
42
+ def update_bounds(x, y)
43
+ bounds[0] = [x, bounds[0]].max
44
+ bounds[1] = [y, bounds[1]].max
45
+ bounds[2] = [x, bounds[2]].min
46
+ bounds[3] = [y, bounds[3]].min
49
47
  end
50
48
  end
51
49
  end
@@ -4,10 +4,12 @@ module Imatcher
4
4
 
5
5
  # Compare pixels using Delta E distance.
6
6
  class Delta < Base
7
- def initialize(threshold: 0.0)
8
- @threshold = threshold
9
- @result = Result.new(self, threshold)
7
+ attr_reader :tolerance
8
+
9
+ def initialize(options)
10
+ @tolerance = options.delete(:tolerance) || 0.01
10
11
  @delta_score = 0.0
12
+ super(options)
11
13
  end
12
14
 
13
15
  private
@@ -18,8 +20,10 @@ module Imatcher
18
20
 
19
21
  def update_result(a, b, x, y)
20
22
  d = euclid(a, b) / (MAX * Math.sqrt(3))
23
+ return if d <= tolerance
21
24
  @result.diff << [a, b, x, y, d]
22
25
  @delta_score += d
26
+ super
23
27
  end
24
28
 
25
29
  def background(bg)
@@ -24,6 +24,7 @@ module Imatcher
24
24
  end
25
25
 
26
26
  def update_result(a, b, x, y)
27
+ super
27
28
  @result.diff << [a, b, x, y]
28
29
  end
29
30
 
@@ -10,6 +10,7 @@ module Imatcher
10
10
  end
11
11
 
12
12
  def update_result(a, b, x, y)
13
+ super
13
14
  @result.diff << [a, b, x, y]
14
15
  end
15
16
 
@@ -18,7 +19,7 @@ module Imatcher
18
19
  end
19
20
 
20
21
  def create_diff_image(bg, diff_image)
21
- bg.to_grayscale.compose!(diff_image, 0, 0)
22
+ diff_image
22
23
  end
23
24
 
24
25
  def pixels_diff(d, a, b, x, y)
@@ -1,3 +1,3 @@
1
1
  module Imatcher # :nodoc:
2
- VERSION = "0.1.1".freeze
2
+ VERSION = "0.1.2".freeze
3
3
  end
data/spec/fixtures/a.png CHANGED
Binary file
data/spec/fixtures/b.png CHANGED
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -7,9 +7,9 @@ describe Imatcher::Modes::Delta do
7
7
 
8
8
  let(:options) { { mode: :delta } }
9
9
 
10
- context "with similar images" do
11
- it "score around 0.094" do
12
- expect(subject.score).to be_within(0.0005).of(0.094)
10
+ context "with darker image" do
11
+ it "score around 0.075" do
12
+ expect(subject.score).to be_within(0.005).of(0.075)
13
13
  end
14
14
 
15
15
  context "with custom threshold" do
@@ -32,12 +32,20 @@ describe Imatcher::Modes::Delta do
32
32
  context "with different images" do
33
33
  let(:path_2) { image_path "b" }
34
34
 
35
- it "score around 0.0195" do
36
- expect(subject.score).to be_within(0.0005).of(0.0195)
35
+ it "score around 0.0046" do
36
+ expect(subject.score).to be_within(0.0001).of(0.0046)
37
37
  end
38
38
 
39
39
  it "creates correct difference image" do
40
40
  expect(subject.difference_image).to eq(Imatcher::Image.from_file(image_path("delta_diff")))
41
41
  end
42
+
43
+ context "with high tolerance" do
44
+ let(:options) { { mode: :delta, tolerance: 0.1 } }
45
+
46
+ it "score around 0.0038" do
47
+ expect(subject.score).to be_within(0.0001).of(0.0038)
48
+ end
49
+ end
42
50
  end
43
51
  end
@@ -8,16 +8,16 @@ describe Imatcher::Modes::Grayscale do
8
8
  let(:options) { { mode: :grayscale } }
9
9
 
10
10
  context "darker image" do
11
- it "score around 0.7" do
12
- expect(subject.score).to be_within(0.05).of(0.75)
11
+ it "score around 0.95" do
12
+ expect(subject.score).to be_within(0.05).of(0.95)
13
13
  end
14
14
  end
15
15
 
16
16
  context "different images" do
17
17
  let(:path_2) { image_path "b" }
18
18
 
19
- it "score around 0.02" do
20
- expect(subject.score).to be_within(0.0005).of(0.009)
19
+ it "score around 0.005" do
20
+ expect(subject.score).to be_within(0.001).of(0.005)
21
21
  end
22
22
 
23
23
  it "creates correct difference image" do
@@ -37,8 +37,8 @@ describe Imatcher::Modes::Grayscale do
37
37
  context "different image" do
38
38
  let(:path_2) { image_path "b" }
39
39
 
40
- it "score around 0.97" do
41
- expect(subject.score).to be_within(0.005).of(0.97)
40
+ it "score around 0.016" do
41
+ expect(subject.score).to be_within(0.001).of(0.016)
42
42
  end
43
43
  end
44
44
 
@@ -55,16 +55,16 @@ describe Imatcher::Modes::Grayscale do
55
55
  let(:options) { { mode: :grayscale, tolerance: 8 } }
56
56
 
57
57
  context "darker image" do
58
- it "score around 0.9" do
59
- expect(subject.score).to be_within(0.005).of(0.9)
58
+ it "score around 0.96" do
59
+ expect(subject.score).to be_within(0.005).of(0.96)
60
60
  end
61
61
  end
62
62
 
63
63
  context "different image" do
64
64
  let(:path_2) { image_path "b" }
65
65
 
66
- it "score around 0.027" do
67
- expect(subject.score).to be_within(0.0005).of(0.027)
66
+ it "score around 0.006" do
67
+ expect(subject.score).to be_within(0.0005).of(0.006)
68
68
  end
69
69
  end
70
70
  end
@@ -6,7 +6,7 @@ describe Imatcher::Modes::RGB do
6
6
  subject { Imatcher.compare(path_1, path_2, options) }
7
7
  let(:options) { {} }
8
8
 
9
- context "with similar images" do
9
+ context "with darker" do
10
10
  it "score equals to 1" do
11
11
  expect(subject.score).to eq 1
12
12
  end
@@ -15,8 +15,8 @@ describe Imatcher::Modes::RGB do
15
15
  context "with different images" do
16
16
  let(:path_2) { image_path "b" }
17
17
 
18
- it "score around 0.97" do
19
- expect(subject.score).to be_within(0.005).of(0.97)
18
+ it "score around 0.016" do
19
+ expect(subject.score).to be_within(0.001).of(0.016)
20
20
  end
21
21
 
22
22
  it "creates correct difference image" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imatcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
@@ -97,6 +97,7 @@ files:
97
97
  - Rakefile
98
98
  - bin/console
99
99
  - bin/setup
100
+ - examples/performance.rb
100
101
  - imatcher.gemspec
101
102
  - lib/imatcher.rb
102
103
  - lib/imatcher/color_methods.rb