image_match 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_script:
5
+ - bundle install --path=.bundle
6
+ script:
7
+ - bundle exec rspec spec
8
+
9
+ notifications:
10
+ emails:
11
+ - zuqqhi2@gmail.com
12
+ on_success: always
13
+ on_failure: always
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in image_match.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,30 @@
1
+ The BSD License
2
+
3
+ Copyright (c) 2014 Hidetomo Suzuki
4
+ All rights reserved.
5
+
6
+ Redistribution and use of this software in source and binary forms, with or without modification, are
7
+ permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above
10
+ copyright notice, this list of conditions and the
11
+ following disclaimer.
12
+
13
+ * Redistributions in binary form must reproduce the above
14
+ copyright notice, this list of conditions and the
15
+ following disclaimer in the documentation and/or other
16
+ materials provided with the distribution.
17
+
18
+ * Neither the name of Hidetomo Suzuki. nor the names of its
19
+ contributors may be used to endorse or promote products
20
+ derived from this software without specific prior
21
+ written permission of Hidetomo Suzuki.
22
+
23
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # ImageMatch
2
+
3
+ An simple image match library for view test.
4
+
5
+ * Ruby 1.9.3 and OpenCV 2.4.10 are supported.
6
+
7
+ ## Requirement
8
+
9
+ * OpenCV <http://opencv.org/>
10
+ * [Download](http://sourceforge.net/projects/opencvlibrary/)
11
+ * [Install guide](http://docs.opencv.org/doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.html#table-of-content-introduction)
12
+
13
+ ## Installation of this library
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'image_match'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install image_match
28
+
29
+ ## Usage
30
+
31
+ ### Flow
32
+
33
+ Basic flow is following.
34
+
35
+ 1. Get comparison source and destination image file.
36
+ 2. Compare them with this library.
37
+
38
+ ### Interfaces
39
+
40
+ Following 3 functions are prepared.
41
+
42
+ 1. perfect_match
43
+ Calc match score between image1 and image2.
44
+ This function requires same size image as image1 and image2
45
+ This returns true if match score is higher than limit_similarity.
46
+ When you set true to is_output, you can check matching result with image.
47
+ The image will be created at your current directory.
48
+
49
+ ```ruby
50
+ perfect_match(image1_filename, image2_filename, limit_similarity=0.9, is_output=false)
51
+ ```
52
+
53
+ 2. perfect_match_template
54
+ Try to find template image in scene image.
55
+ This function requires that template image's size is smaller than image2.
56
+ This returns true if match score is higher than limit_similarity.
57
+ When you set true to is_output, you can check matching result with image.
58
+ The output image will be created at your current directory.
59
+
60
+ ```ruby
61
+ perfect_match_template(scene_filename, template_filename, limit_similarity=0.9, is_output=false)
62
+ ```
63
+
64
+ 3. fuzzy_match_template
65
+ Try to find template image in scene image.
66
+ This function requires that template image's size is smaller(or equal) than image2.
67
+ This function ignore image size, color and image detail.
68
+ When you set true to is_output, you can check matching result with image.
69
+ The output image will be created at your current directory.
70
+ Note that ome times this is useful, but accuracy is not so high.
71
+
72
+ ```ruby
73
+ fuzzy_match_template(scene_filename, template_filename, is_output=false)
74
+ ```
75
+
76
+ ### Sample Code
77
+
78
+ A sample to take screen shot on http://google.com/ and compare screen shot and prepared logo image.
79
+ You can check all files related this sample on samples directory(currently sample is only one).
80
+
81
+ #### Gemfile
82
+
83
+ ```ruby
84
+ source 'https://rubygems.org'
85
+
86
+ gem 'capybara'
87
+ gem 'poltergeist'
88
+ gem 'image_match'
89
+ ```
90
+
91
+ #### Main
92
+
93
+ ```ruby
94
+ require 'capybara'
95
+ require 'capybara/poltergeist'
96
+ require 'image_match'
97
+ include ImageMatch
98
+
99
+ # Get current google web page image
100
+ url = 'http://google.com/'
101
+ Capybara.javascript_driver = :poltergeist
102
+ Capybara.register_driver :poltergeist do |app|
103
+ Capybara::Poltergeist::Driver.new app, js_errors: false
104
+ end
105
+ Capybara.default_selector = :xpath
106
+
107
+ session = Capybara::Session.new(:poltergeist)
108
+ session.driver.headers = {'User-Agent' => "Mozilla/5.0 (Macintosh; Intel Mac OS X)"}
109
+ session.visit(url)
110
+
111
+ session.save_screenshot('screenshot.png', full: true)
112
+
113
+ # Compare logo (output match result image)
114
+ if perfect_match_template('./screenshot.png', './google-logo.jpg', 0.9, true)
115
+ puts "Same!"
116
+ else
117
+ puts "Different..."
118
+ end
119
+
120
+ ```
121
+
122
+ ## Contributing
123
+
124
+ 1. Fork it ( https://github.com/[my-github-username]/image_match/fork )
125
+ 2. Create your feature branch (`git checkout -b feature/my-new-feature`)
126
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
127
+ 4. Push to the branch (`git push origin feature/my-new-feature`)
128
+ 5. Create a new Pull Request to develop branch
129
+ Note that develop branch is newest version(not release version).
130
+
131
+ ## LICENSE:
132
+
133
+ The BSD Liscense
134
+
135
+ see LICENSE.txt
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'image_match/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "image_match"
8
+ spec.version = ImageMatch::VERSION
9
+ spec.authors = ["Hidetomo Suzuki"]
10
+ spec.email = ["zuqqhi2@gmail.com"]
11
+ spec.summary = %q{Check web page or widget design with image file automatically}
12
+ spec.description = %q{1.Make page or widget image file. 2.Get current page or widget image on the web. 3.Compare them with this gem.}
13
+ spec.homepage = "https://github.com/zuqqhi2/image_diff"
14
+ spec.license = "The BSD Liscense"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+
25
+ spec.add_dependency "ruby-opencv", "~> 0.0.13"
26
+ end
@@ -0,0 +1,252 @@
1
+ require "opencv"
2
+ include OpenCV
3
+
4
+ require "image_match/version"
5
+
6
+ module ImageMatch
7
+ #====================================================================
8
+ # Private functions
9
+ #====================================================================
10
+
11
+ def compare_surf_descriptors(d1, d2, best, length)
12
+ raise ArgumentError unless (length % 4) == 0
13
+ total_cost = 0
14
+ 0.step(length - 1, 4) { |i|
15
+ t0 = d1[i] - d2[i]
16
+ t1 = d1[i + 1] - d2[i + 1]
17
+ t2 = d1[i + 2] - d2[i + 2]
18
+ t3 = d1[i + 3] - d2[i + 3]
19
+ total_cost += t0 * t0 + t1 * t1 + t2 * t2 + t3 * t3
20
+ break if total_cost > best
21
+ }
22
+ total_cost
23
+ end
24
+
25
+ def naive_nearest_neighbor(vec, laplacian, model_keypoints, model_descriptors)
26
+ length = model_descriptors[0].size
27
+ neighbor = nil
28
+ dist1 = 1e6
29
+ dist2 = 1e6
30
+
31
+ model_descriptors.size.times { |i|
32
+ kp = model_keypoints[i]
33
+ mvec = model_descriptors[i]
34
+ next if laplacian != kp.laplacian
35
+
36
+ d = compare_surf_descriptors(vec, mvec, dist2, length)
37
+ if d < dist1
38
+ dist2 = dist1
39
+ dist1 = d
40
+ neighbor = i
41
+ elsif d < dist2
42
+ dist2 = d
43
+ end
44
+ }
45
+
46
+ return (dist1 < 0.6 * dist2) ? neighbor : nil
47
+ end
48
+
49
+ def find_pairs(template_keypoints, template_descriptors, scene_keypoints, scene_descriptors)
50
+ ptpairs = []
51
+ template_descriptors.size.times { |i|
52
+ kp = template_keypoints[i]
53
+ descriptor = template_descriptors[i]
54
+ nearest_neighbor = naive_nearest_neighbor(descriptor, kp.laplacian, scene_keypoints, scene_descriptors)
55
+ unless nearest_neighbor.nil?
56
+ ptpairs << i
57
+ ptpairs << nearest_neighbor
58
+ end
59
+ }
60
+ ptpairs
61
+ end
62
+
63
+ def locate_planar_template(template_keypoints, template_descriptors, scene_keypoints, scene_descriptors, src_corners)
64
+ ptpairs = find_pairs(template_keypoints, template_descriptors, scene_keypoints, scene_descriptors)
65
+ n = ptpairs.size / 2
66
+
67
+ return nil if n < 4
68
+
69
+ pt1 = []
70
+ pt2 = []
71
+ n.times { |i|
72
+ pt1 << template_keypoints[ptpairs[i * 2]].pt
73
+ pt2 << scene_keypoints[ptpairs[i * 2 + 1]].pt
74
+ }
75
+
76
+ _pt1 = CvMat.new(1, n, CV_32F, 2)
77
+ _pt2 = CvMat.new(1, n, CV_32F, 2)
78
+ _pt1.set_data(pt1)
79
+ _pt2.set_data(pt2)
80
+ h = CvMat.find_homography(_pt1, _pt2, :ransac, 5)
81
+
82
+ dst_corners = []
83
+ 4.times { |i|
84
+ x = src_corners[i].x
85
+ y = src_corners[i].y
86
+ z = 1.0 / (h[6][0] * x + h[7][0] * y + h[8][0])
87
+ x = (h[0][0] * x + h[1][0] * y + h[2][0]) * z
88
+ y = (h[3][0] * x + h[4][0] * y + h[5][0]) * z
89
+ dst_corners << CvPoint.new(x.to_i, y.to_i)
90
+ }
91
+
92
+ dst_corners
93
+ end
94
+
95
+ #====================================================================
96
+ # Public Interface
97
+ #====================================================================
98
+
99
+ ##
100
+ #
101
+ # Calculate matching score of 1st input image and 2nd input image
102
+ # required the sizes are same.
103
+ #
104
+ # @param [String] image1_filename Compare target image1 file path
105
+ # @param [String] image2_filename Compare target image2 file path
106
+ # @param [Int] limit_similarity Accepting similarity (default is 90% matching)
107
+ # @return [Boolean] true if matching score is higher than limit_similarity
108
+ # false otherwise
109
+ #
110
+ def perfect_match(image1_filename, image2_filename, limit_similarity=0.9)
111
+ raise ArgumentError, 'File does not exists.' unless File.exist?(image1_filename) and File.exist?(image2_filename)
112
+ raise ArgumentError, 'limit_similarity must be 0.1 - 1.0.' unless limit_similarity >= 0.1 and limit_similarity <= 1.0
113
+
114
+ image1, image2 = nil, nil
115
+ begin
116
+ image1 = IplImage.load(image1_filename)
117
+ image2 = IplImage.load(image2_filename)
118
+ rescue
119
+ raise RuntimeError, 'Couldn\'t read image files correctly'
120
+ return false
121
+ end
122
+
123
+ return false unless image1.width == image2.width and image1.height == image2.height
124
+
125
+ return perfect_match_template(image1_filename, image2_filename, limit_similarity)
126
+ end
127
+
128
+ ##
129
+ #
130
+ # Calculate matching score of 1st input image and 2nd input image.
131
+ # The 2nd input image size must be smaller than 1st input image.
132
+ # This function is robust for brightness.
133
+ #
134
+ # @param [String] scene_filename Scene image file path
135
+ # @param [String] template_filename template image file path which you want find in scene image
136
+ # @param [Int] limit_similarity Accepting similarity (default is 90% matching)
137
+ # @param [Boolean] is_output if you set true, you can get match result with image (default is false)
138
+ # @return [Boolean] true if matching score is higher than limit_similarity
139
+ # false otherwise
140
+ #
141
+ def perfect_match_template(scene_filename, template_filename, limit_similarity=0.9, is_output=false)
142
+ raise ArgumentError, 'File does not exists.' unless File.exist?(scene_filename) and File.exist?(template_filename)
143
+ raise ArgumentError, 'limit_similarity must be 0.1 - 1.0.' unless limit_similarity >= 0.1 and limit_similarity <= 1.0
144
+ raise ArgumentError, 'is_output must be true or false.' unless is_output == false or is_output == true
145
+
146
+ scene, template = nil, nil
147
+ begin
148
+ scene = IplImage.load(scene_filename)
149
+ template = IplImage.load(template_filename)
150
+ rescue
151
+ raise RuntimeError, 'Couldn\'t read image files correctly'
152
+ return false
153
+ end
154
+
155
+ return false unless scene.width >= template.width and scene.height >= template.height
156
+
157
+ result = scene.match_template(template, :ccoeff_normed)
158
+ min_score, max_score, min_point, max_point = result.min_max_loc
159
+
160
+ if is_output
161
+ from = max_point
162
+ to = CvPoint.new(from.x + template.width, from.y + template.height)
163
+ scene.rectangle!(from, to, :color => CvColor::Red, :thickness => 3)
164
+ scene.save_image(Time.now.to_i.to_s + "_match_result.png")
165
+ end
166
+
167
+ return (max_score >= limit_similarity ? true : false)
168
+ end
169
+
170
+ ##
171
+ #
172
+ # Try to find 2nd input image in 1st input image.
173
+ # This function ignores color, size and shape details.
174
+ # (I mean this func checks whether almost same or clearly different)
175
+ #
176
+ # Note that this function is useful I think,
177
+ # but sometimes it doesn't output correct result which you want.
178
+ # It depends on input images.
179
+ # TODO : improve accuracy
180
+ #
181
+ # @param [String] scene_filename Scene image file path
182
+ # @param [String] template_filename template image file path which you want find in scene image
183
+ # @param [Boolean] is_output if you set true, you can get match result with image (default is false)
184
+ # @return [Boolean] true if 1st input image seems to have 2nd input image
185
+ # false otherwise
186
+ #
187
+ def fuzzy_match_template(scene_filename, template_filename, is_output=false)
188
+ raise ArgumentError, 'File does not exists.' unless File.exist?(scene_filename) and File.exist?(template_filename)
189
+ raise ArgumentError, 'is_output must be true or false.' unless is_output == false or is_output == true
190
+
191
+ scene, template = nil, nil
192
+ begin
193
+ scene = IplImage.load(scene_filename, CV_LOAD_IMAGE_GRAYSCALE)
194
+ template = IplImage.load(template_filename, CV_LOAD_IMAGE_GRAYSCALE)
195
+ rescue
196
+ raise RuntimeError, 'Couldn\'t read image files correctly'
197
+ return false
198
+ end
199
+
200
+ return false unless scene.width >= template.width and scene.height >= template.height
201
+
202
+ param = CvSURFParams.new(1500)
203
+ template_keypoints, template_descriptors = template.extract_surf(param)
204
+ scene_keypoints, scene_descriptors = scene.extract_surf(param)
205
+
206
+ src_corners = [CvPoint.new(0, 0),
207
+ CvPoint.new(template.width, 0),
208
+ CvPoint.new(template.width, template.height),
209
+ CvPoint.new(0, template.height)]
210
+ dst_corners = locate_planar_template(template_keypoints,
211
+ template_descriptors,
212
+ scene_keypoints,
213
+ scene_descriptors,
214
+ src_corners)
215
+
216
+
217
+ if is_output
218
+ correspond = IplImage.new(scene.width, template.height + scene.height, CV_8U, 1);
219
+ correspond.set_roi(CvRect.new(0, 0, template.width, template.height))
220
+ template.copy(correspond)
221
+ correspond.set_roi(CvRect.new(0, template.height, scene.width, scene.height))
222
+ scene.copy(correspond)
223
+ correspond.reset_roi
224
+ correspond = correspond.GRAY2BGR
225
+
226
+ if dst_corners
227
+ 4.times { |i|
228
+ r1 = dst_corners[i % 4]
229
+ r2 = dst_corners[(i + 1) % 4]
230
+ correspond.line!(CvPoint.new(r1.x, r1.y + template.height),
231
+ CvPoint.new(r2.x, r2.y + template.height),
232
+ :color => CvColor::Red,
233
+ :thickness => 2, :line_type => :aa)
234
+ }
235
+ end
236
+
237
+ ptpairs = find_pairs(template_keypoints, template_descriptors, scene_keypoints, scene_descriptors)
238
+
239
+ 0.step(ptpairs.size - 1, 2) { |i|
240
+ r1 = template_keypoints[ptpairs[i]]
241
+ r2 = scene_keypoints[ptpairs[i + 1]]
242
+ correspond.line!(r1.pt, CvPoint.new(r2.pt.x, r2.pt.y + template.height),
243
+ :color => CvColor::Red, :line_type => :aa)
244
+ }
245
+
246
+ correspond.save_image(Time.now.to_i.to_s + "_match_result.png")
247
+ end
248
+
249
+ return (dst_corners ? true : false)
250
+ end
251
+
252
+ end
@@ -0,0 +1,3 @@
1
+ module ImageMatch
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ require 'capybara'
2
+ require 'capybara/poltergeist'
3
+ require 'image_match'
4
+ include ImageMatch
5
+
6
+ # Get current google web page image
7
+ url = 'http://google.com/'
8
+ Capybara.javascript_driver = :poltergeist
9
+ Capybara.register_driver :poltergeist do |app|
10
+ Capybara::Poltergeist::Driver.new app, js_errors: false
11
+ end
12
+ Capybara.default_selector = :xpath
13
+
14
+ session = Capybara::Session.new(:poltergeist)
15
+ session.driver.headers = {'User-Agent' => "Mozilla/5.0 (Macintosh; Intel Mac OS X)"}
16
+ session.visit(url)
17
+
18
+ session.save_screenshot('screenshot.png', full: true)
19
+
20
+ # Compare logo (output match result image)
21
+ if perfect_match_template('./screenshot.png', './google-logo.jpg', 0.9, true)
22
+ puts "Same!"
23
+ else
24
+ puts "Different..."
25
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe ImageMatch do
4
+
5
+ before :all do
6
+ @image_dir = File.expand_path(File.dirname(__FILE__)) + '/images'
7
+ end
8
+
9
+
10
+ describe 'perfect_match' do
11
+ it 'finds that input images are same' do
12
+ result = perfect_match(@image_dir + '/lena.jpg', @image_dir + '/lena.jpg')
13
+ expect(result).to eq true
14
+
15
+ result = perfect_match(@image_dir + '/lena.jpg', @image_dir + '/lena.jpg', 0.95)
16
+ expect(result).to eq true
17
+ end
18
+
19
+ it 'finds that input images are not same' do
20
+ # Require similarity is too high with noise image
21
+ result = perfect_match(@image_dir + '/lena.jpg', @image_dir + '/lena-noise.jpg', 0.98)
22
+ expect(result).to eq false
23
+
24
+ # Size not match
25
+ result = perfect_match(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes.jpg')
26
+ expect(result).to eq false
27
+
28
+ # File does not exists
29
+ expect{ perfect_match(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes-2nd.jpg') }.to raise_error
30
+ end
31
+ end
32
+
33
+ describe 'perfect_match_template' do
34
+ it 'finds that 2nd input image is a part of 1st input image' do
35
+ # Same image
36
+ result = perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena.jpg')
37
+ expect(result).to eq true
38
+
39
+ # Template
40
+ result = perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes.jpg')
41
+ expect(result).to eq true
42
+
43
+ # Set similarity
44
+ result = perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes.jpg', 0.95)
45
+ expect(result).to eq true
46
+
47
+ # Set is_output
48
+ perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes.jpg', 0.95, true)
49
+ path = File.expand_path(File.dirname(__FILE__))
50
+ result = `ls #{path}/../*_match_result.png | wc -l`
51
+ expect(result.chomp).to eq "1"
52
+ end
53
+
54
+ it 'finds that 1st input image doesn\'t contains 2nd input image' do
55
+ # No correlation images
56
+ result = perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/box.jpg')
57
+ expect(result).to eq false
58
+
59
+ # Require similarity is too high with noise image
60
+ result = perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena-noise.jpg', 0.98)
61
+ expect(result).to eq false
62
+
63
+ # Size not match
64
+ result = perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/box_in_scene.jpg')
65
+ expect(result).to eq false
66
+
67
+ # File does not exists
68
+ expect{ perfect_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes-2nd.jpg') }.to raise_error
69
+ end
70
+ end
71
+
72
+ describe 'fuzzy_match_template' do
73
+ it 'finds that 2nd input image is a part of 1st input image' do
74
+ # Same
75
+ result = fuzzy_match_template(@image_dir + '/box_in_scene.jpg', @image_dir + '/box_in_scene.jpg')
76
+ expect(result).to eq true
77
+
78
+ # Template
79
+ result = fuzzy_match_template(@image_dir + '/box_in_scene.jpg', @image_dir + '/box.jpg')
80
+ expect(result).to eq true
81
+
82
+ # Set is_output
83
+ result = fuzzy_match_template(@image_dir + '/box_in_scene.jpg', @image_dir + '/box.jpg')
84
+ path = File.expand_path(File.dirname(__FILE__))
85
+ result = `ls #{path}/../*_match_result.png | wc -l`
86
+ expect(result.chomp).to eq '1'
87
+ end
88
+
89
+ it 'finds that 1st input image doesn\'t contains 2nd input image' do
90
+ # No correlation images
91
+ result = fuzzy_match_template(@image_dir + '/box.jpg', @image_dir + '/lena-eyes.jpg', true)
92
+ expect(result).to eq false
93
+
94
+ # Size not match
95
+ result = fuzzy_match_template(@image_dir + '/lena.jpg', @image_dir + '/box_in_scene.jpg')
96
+ expect(result).to eq false
97
+
98
+ # File does not exists
99
+ expect{ fuzzy_match_template(@image_dir + '/lena.jpg', @image_dir + '/lena-eyes-2nd.jpg') }.to raise_error
100
+ end
101
+ end
102
+
103
+ after :all do
104
+ # Delete created files
105
+ path = File.expand_path(File.dirname(__FILE__))
106
+ result = `ls #{path}/../*_match_result.png | wc -l`
107
+ if result != '0'
108
+ `rm #{path}/../*_match_result.png`
109
+ end
110
+ end
111
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'image_match'
3
+ include ImageMatch
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: image_match
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Hidetomo Suzuki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-11-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.7'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.7'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '10.0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '10.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: ruby-opencv
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.0.13
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.0.13
78
+ description: 1.Make page or widget image file. 2.Get current page or widget image
79
+ on the web. 3.Compare them with this gem.
80
+ email:
81
+ - zuqqhi2@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - .rspec
88
+ - .travis.yml
89
+ - Gemfile
90
+ - LICENSE.txt
91
+ - README.md
92
+ - Rakefile
93
+ - image_match.gemspec
94
+ - lib/image_match.rb
95
+ - lib/image_match/version.rb
96
+ - samples/taking_screenshot_and_match/1416131348_match_result.png
97
+ - samples/taking_screenshot_and_match/google-logo.jpg
98
+ - samples/taking_screenshot_and_match/sample.rb
99
+ - samples/taking_screenshot_and_match/screenshot.png
100
+ - spec/image_match_spec.rb
101
+ - spec/images/box.jpg
102
+ - spec/images/box_in_scene.jpg
103
+ - spec/images/lena-eyes.jpg
104
+ - spec/images/lena-noise.jpg
105
+ - spec/images/lena.jpg
106
+ - spec/spec_helper.rb
107
+ homepage: https://github.com/zuqqhi2/image_diff
108
+ licenses:
109
+ - The BSD Liscense
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ segments:
121
+ - 0
122
+ hash: -702331356302588290
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ segments:
130
+ - 0
131
+ hash: -702331356302588290
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 1.8.23.2
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: Check web page or widget design with image file automatically
138
+ test_files:
139
+ - spec/image_match_spec.rb
140
+ - spec/images/box.jpg
141
+ - spec/images/box_in_scene.jpg
142
+ - spec/images/lena-eyes.jpg
143
+ - spec/images/lena-noise.jpg
144
+ - spec/images/lena.jpg
145
+ - spec/spec_helper.rb