kolors 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 +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +22 -0
- data/README.md +48 -0
- data/README.textile +31 -0
- data/Rakefile +7 -0
- data/kolors.gemspec +27 -0
- data/lib/kolors.rb +36 -0
- data/lib/kolors/dominant_colors.rb +93 -0
- data/lib/kolors/rgb.rb +98 -0
- data/lib/kolors/version.rb +3 -0
- metadata +143 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
kolors (0.0.1)
|
5
|
+
ai4r
|
6
|
+
cocaine
|
7
|
+
oily_png
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (3.2.11)
|
13
|
+
i18n (~> 0.6)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
ai4r (1.12)
|
16
|
+
chunky_png (1.2.7)
|
17
|
+
climate_control (0.0.3)
|
18
|
+
activesupport (>= 3.0)
|
19
|
+
cocaine (0.5.1)
|
20
|
+
climate_control (>= 0.0.3, < 1.0)
|
21
|
+
diff-lcs (1.1.3)
|
22
|
+
i18n (0.6.1)
|
23
|
+
multi_json (1.5.0)
|
24
|
+
oily_png (1.0.3)
|
25
|
+
chunky_png (~> 1.2.1)
|
26
|
+
rake (10.0.3)
|
27
|
+
rspec (2.12.0)
|
28
|
+
rspec-core (~> 2.12.0)
|
29
|
+
rspec-expectations (~> 2.12.0)
|
30
|
+
rspec-mocks (~> 2.12.0)
|
31
|
+
rspec-core (2.12.2)
|
32
|
+
rspec-expectations (2.12.1)
|
33
|
+
diff-lcs (~> 1.1.3)
|
34
|
+
rspec-mocks (2.12.2)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
kolors!
|
41
|
+
rake
|
42
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Eric Larson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Kolors
|
2
|
+
|
3
|
+
Uses KMeans clustering and the L*A*B* colorspace to extract "approximate human vision" dominant colors from an image. Optionally, map those dominant colors into preferred "color bins" for a search index facet-by-color solution.
|
4
|
+
|
5
|
+
LARGELY based off the neat work of the [Miro gem](https://github.com/jonbuda/miro). If you want faster, RGB-based dominant color extraction, use Miro.
|
6
|
+
|
7
|
+
## Dependencies
|
8
|
+
|
9
|
+
Requires Imagemagick. On OSX use homebrew to install: brew install imagemagick
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
$ gem install kolors
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'kolors'
|
19
|
+
|
20
|
+
# Use path to a local image or URL for remote image
|
21
|
+
kolors = Kolors::DominantColors.new('../colors/images/QFZMF57HPHVGJ8Z_thumb.png')
|
22
|
+
|
23
|
+
# Return the dominant colors in LAB
|
24
|
+
kolors.to_lab
|
25
|
+
=> [[52.406, -18.186, 27.618], [88.523, -10.393, 16.203], [64.944, -16.181, 24.419], [28.486, -16.665, 22.73]]
|
26
|
+
|
27
|
+
# Return the mapped color bins and color percentage for facet-by-color
|
28
|
+
kolors.to_facets
|
29
|
+
=> [{"Moss"=>50.05952380952381}, {"Mercury"=>9.880952380952381}, {"Aluminum"=>19.186507936507937}, {"Iron"=>20.873015873015873}]
|
30
|
+
```
|
31
|
+
|
32
|
+
## TODOS
|
33
|
+
|
34
|
+
1. LAB to RGB conversion
|
35
|
+
2. Simplify configuration of "color bins" for facet-by-color mapping
|
36
|
+
3. Tests
|
37
|
+
|
38
|
+
## Thanks
|
39
|
+
|
40
|
+
Special thanks to my buddy [Nate Vack](https://github.com/njvack) for help getting this off of the ground.
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
1. Fork it
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
48
|
+
5. Create new Pull Request
|
data/README.textile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
h1. Colors
|
2
|
+
|
3
|
+
A neat facet-by-color script (proof-of-concept).
|
4
|
+
|
5
|
+
* Uses "Miro":https://github.com/jonbuda/miro to pull the dominant colors from an image.
|
6
|
+
* Uses "Euclidian distance":http://en.wikipedia.org/wiki/Euclidean_distance to map dominant colors into pre-defined facet color bins
|
7
|
+
|
8
|
+
h3. To use
|
9
|
+
|
10
|
+
Install ImageMagick, via Homebrew (OS X)
|
11
|
+
Install Solr 4.0.0
|
12
|
+
|
13
|
+
Install these fine gems:
|
14
|
+
require 'mechanize' # Crawl a UW Digital Collection for data, images
|
15
|
+
require 'chunky_png' # Pure Ruby image manipulation
|
16
|
+
require 'miro' # Detect dominant image colors
|
17
|
+
require 'rsolr' # Solr
|
18
|
+
require 'fileutils' # Save files, delete files, etc.
|
19
|
+
require 'awesome_print'
|
20
|
+
require 'active_support/core_ext/string'
|
21
|
+
|
22
|
+
Start Solr:
|
23
|
+
$> cd /apache-solr-4.0.0/example/
|
24
|
+
$> java -jar start.jar
|
25
|
+
|
26
|
+
Run the script:
|
27
|
+
$> ./colors.rb
|
28
|
+
|
29
|
+
h3. Todo
|
30
|
+
|
31
|
+
This is just play for now, should make a *real* tool of this someday...
|
data/Rakefile
ADDED
data/kolors.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kolors/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "kolors"
|
8
|
+
gem.version = Kolors::VERSION
|
9
|
+
gem.authors = ["Eric Larson"]
|
10
|
+
gem.email = ["ewlarson@gmail.com"]
|
11
|
+
gem.description = %q{Uses KMeans clustering and the L*A*B* colorspace to extract "approximate human vision" dominant colors from an image. Optionally, use Euclidean Distance to map those dominant colors into preferred "color bins" for a search index facet-by-color solution.}
|
12
|
+
gem.summary = %q{Uses KMeans clustering and the L*A*B* colorspace to extract "approximate human vision" dominant colors from an image.}
|
13
|
+
gem.homepage = "https://github.com/ewlarson/kolors"
|
14
|
+
|
15
|
+
gem.requirements = 'ImageMagick'
|
16
|
+
gem.add_dependency 'ai4r'
|
17
|
+
gem.add_dependency 'cocaine'
|
18
|
+
gem.add_dependency 'oily_png'
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'rspec'
|
22
|
+
|
23
|
+
gem.files = `git ls-files`.split($/)
|
24
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
25
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
26
|
+
gem.require_paths = ["lib"]
|
27
|
+
end
|
data/lib/kolors.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'kolors/version'
|
2
|
+
require 'oily_png' # Fast ChunkyPNG
|
3
|
+
require 'ai4r' # KMeans Clustering
|
4
|
+
require 'cocaine'
|
5
|
+
require 'open-uri'
|
6
|
+
require "tempfile"
|
7
|
+
|
8
|
+
require 'kolors/rgb'
|
9
|
+
require 'kolors/dominant_colors'
|
10
|
+
|
11
|
+
# Define a list of key LAB colors
|
12
|
+
def key_colors
|
13
|
+
# OSX Crayons in LAB
|
14
|
+
{ [82.046, 0.004, -0.009] => 'Silver', [21.247, 0.002, -0.003] => 'Tungsten', [72.944, 0.004, -0.008] => 'Magnesium', [32.319, 0.002, -0.004] => 'Iron', [63.223, 0.004, -0.007] => 'Aluminum', [43.192, 0.003, -0.005] => 'Steel', [53.585, 0.003, -0.006] => 'Nickel', [53.193, 0.003, -0.006] => 'Tin', [25.531, 48.055, 38.060] => 'Cayenne', [51.868, -12.931, 56.677] => 'Asparagus', [46.229, -51.700, 49.898] => 'Clover', [48.256, -28.842, -8.481] => 'Teal', [12.975, 47.508, -64.704] => 'Midnight', [29.782, 58.940, -36.498] => 'Plum', [34.510, 23.976, 44.820] => 'Mocha', [47.660, -39.672, 51.639] => 'Fern', [46.722, -45.498, 26.354] => 'Moss', [27.367, 9.122, -41.018] => 'Ocean', [18.577, 50.163, -55.230] => 'Eggplant', [26.619, 50.976, 0.503] => 'Maroon', [53.233, 80.109, 67.220] => 'Maraschino', [97.138, -21.556, 94.482] => 'Lemon', [87.737, -86.185, 83.181] => 'Spring', [91.117, -48.080, -14.138] => 'Turquoise', [32.303, 79.197, -107.864] => 'Blueberry', [60.320, 98.254, -60.843] => 'Magenta', [67.050, 42.832, 74.026] => 'Tangerine', [89.910, -67.789, 85.826] => 'Lime', [88.485, -76.749, 46.572] => 'Sea Foam', [54.719, 18.790, -70.925] => 'Aqua', [40.911, 83.182, -93.300] => 'Grape', [54.885, 84.552, 4.066] => 'Strawberry', [63.112, 58.245, 30.548] => 'Salmon', [97.527, -18.441, 70.899] => 'Banana', [89.535, -69.168, 59.807] => 'Flora', [92.382, -39.947, -12.114] => 'Ice', [51.322, 43.621, -76.298] => 'Orchid', [68.008, 76.237, -48.630] => 'Bubblegum', [8.757, 0.001, -0.002] => 'Lead', [91.293, 0.005, -0.010] => 'Mercury', [84.692, 7.020, 56.682] => 'Cantaloupe', [94.019, -38.132, 66.065] => 'Honeydew', [91.100, -52.338, 12.396] => 'Spindrift', [78.011, -15.169, -33.928] => 'Sky', [61.273, 64.277, -59.740] => 'Lavender', [67.377, 65.168, -23.019] => "Carnation", [0.000, 0.000, 0.000] => "Licorice", [100.000, 0.005, -0.010] => 'Snow' }
|
15
|
+
|
16
|
+
# Crayola Crayons - 16ct
|
17
|
+
# { [0.0, 0.0, 0.0] => 'Black', [47.909, 35.209, -82.012] => 'Blue', [56.951, -21.113, -26.486] => 'Blue Green', [42.436, 30.554, -49.715] => 'Blue Violet', [47.76, 32.728, 31.38] => 'Brown', [77.727, 37.465, -4.165] => 'Pink', [59.159, -50.156, 20.795] => 'Green', [62.726, 54.468, 64.68] => 'Orange', [50.193, 76.218, 36.382] => 'Red', [57.137, 70.48, 50.904] => 'Red Orange', [45.117, 60.767, -14.844] => 'Red Violet', [45.101, 31.746, -33.512] => 'Violet (Purple)', [100.0, 0.005, -0.01] => 'White', [91.412, -8.107, 59.726] => 'Yellow', [85.567, -25.05, 47.104] => 'Yellow Green', [77.236, 20.651, 64.455] => 'Yellow Orange' }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Euclidean distance
|
21
|
+
# - Take a dominant color from an image, return nearest key color
|
22
|
+
def dist(p1, p2)
|
23
|
+
(0...p1.length).map {|i| (p1[i]-p2[i])**2}.inject(0) {|sum, i| sum+i}**0.5
|
24
|
+
end
|
25
|
+
|
26
|
+
module Kolors
|
27
|
+
class << self
|
28
|
+
def options
|
29
|
+
@options ||= {
|
30
|
+
:image_magick_path => '/usr/local/bin/convert',
|
31
|
+
:resolution => '100x100',
|
32
|
+
:color_count => 4
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Kolors
|
2
|
+
class DominantColors
|
3
|
+
attr_accessor :src_image_path
|
4
|
+
|
5
|
+
def initialize(src_image_path)
|
6
|
+
@src_image_path = src_image_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_facets
|
10
|
+
# Map each centroid to key_colors
|
11
|
+
facets = to_lab.each_with_index.collect do |color,index|
|
12
|
+
{ key_colors[key_colors.keys.sort_by {|c| dist(color, c) }.first] => kmeans_result.clusters[index].data_items.size}
|
13
|
+
end
|
14
|
+
percentize(group_hashes_sum_values(facets))
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_lab
|
18
|
+
kmeans_result.centroids.collect{|r,g,b| Kolors::Rgb.new(r,g,b).to_lab}
|
19
|
+
end
|
20
|
+
|
21
|
+
def kmeans_result
|
22
|
+
@kmeans_result ||= extract_colors_from_image
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def percentize(hash)
|
28
|
+
hash.collect{|color, count| {color => ((count.to_f / @colors.size.to_f)*100)}}
|
29
|
+
end
|
30
|
+
|
31
|
+
def group_hashes_sum_values(array)
|
32
|
+
array.inject{|color, count| color.merge( count ){|k, old_v, new_v| old_v + new_v}}
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_colors_from_image
|
36
|
+
create_thumb_crop_and_convert_to_png!
|
37
|
+
colors = detect_dominant_colors
|
38
|
+
cleanup_temporary_files!
|
39
|
+
return colors
|
40
|
+
end
|
41
|
+
|
42
|
+
def remote_source_image?
|
43
|
+
@src_image_path =~ /^https?:\/\//
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_thumb_crop_and_convert_to_png!
|
47
|
+
@source_image = open_source_image
|
48
|
+
@downsampled_image = open_downsampled_image
|
49
|
+
|
50
|
+
Cocaine::CommandLine.new(Kolors.options[:image_magick_path], "':in[0]' -resize :resolution -gravity Center -crop 90x80%+0+0 :out").
|
51
|
+
run(:in => File.expand_path(@source_image.path),
|
52
|
+
:resolution => Kolors.options[:resolution],
|
53
|
+
:out => File.expand_path(@downsampled_image.path))
|
54
|
+
end
|
55
|
+
|
56
|
+
def open_source_image
|
57
|
+
if remote_source_image?
|
58
|
+
original_extension = URI.parse(@src_image_path).path.split('.').last
|
59
|
+
|
60
|
+
tempfile = Tempfile.open(["source", ".#{original_extension}"])
|
61
|
+
remote_file_data = open(@src_image_path).read
|
62
|
+
|
63
|
+
tempfile.write(RUBY_VERSION =~ /1.9/ ? remote_file_data.force_encoding("UTF-8") : remote_file_data)
|
64
|
+
tempfile.close
|
65
|
+
return tempfile
|
66
|
+
else
|
67
|
+
return File.open(@src_image_path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def open_downsampled_image
|
72
|
+
tempfile = Tempfile.open(["downsampled", '.png'])
|
73
|
+
tempfile.binmode
|
74
|
+
tempfile
|
75
|
+
end
|
76
|
+
|
77
|
+
def detect_dominant_colors
|
78
|
+
# Detect dominant colors
|
79
|
+
# - Fetches colors from ChunkyPNG directly
|
80
|
+
@colors = ChunkyPNG::Image.from_file(File.expand_path(@downsampled_image.path)).pixels.collect {|c| ChunkyPNG::Color.to_truecolor_bytes c }
|
81
|
+
|
82
|
+
# Kmeans cluster
|
83
|
+
data = Ai4r::Data::DataSet.new(:data_items => @colors)
|
84
|
+
kmeans = Ai4r::Clusterers::KMeans.new
|
85
|
+
result = kmeans.build(data, Kolors.options[:color_count])
|
86
|
+
end
|
87
|
+
|
88
|
+
def cleanup_temporary_files!
|
89
|
+
@source_image.close(true) if remote_source_image?
|
90
|
+
@downsampled_image.close(true)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/kolors/rgb.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
module Kolors
|
2
|
+
class Rgb
|
3
|
+
attr_reader :r, :g, :b
|
4
|
+
attr_reader :l, :a, :b
|
5
|
+
|
6
|
+
def initialize(r,g,b)
|
7
|
+
@r = r
|
8
|
+
@g = g
|
9
|
+
@b = b
|
10
|
+
end
|
11
|
+
|
12
|
+
# EasyRGB - RGB to LAB
|
13
|
+
# - LAB gives us a perceptually accurate colorspace
|
14
|
+
def to_lab
|
15
|
+
x,y,z = rgb_to_xyz(@r,@g,@b)
|
16
|
+
l,a,b = xyz_to_lab(x,y,z)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
# EasyRGB - RGB to XYZ
|
22
|
+
def rgb_to_xyz(r,g,b)
|
23
|
+
r = r * 1.0
|
24
|
+
g = g * 1.0
|
25
|
+
b = b * 1.0
|
26
|
+
|
27
|
+
var_R = ( r / 255.0 ) #R from 0 to 255
|
28
|
+
var_G = ( g / 255.0 ) #G from 0 to 255
|
29
|
+
var_B = ( b / 255.0 ) #B from 0 to 255
|
30
|
+
|
31
|
+
if ( var_R > 0.04045 )
|
32
|
+
var_R = ( ( var_R + 0.055 ) / 1.055 ) ** 2.4
|
33
|
+
else
|
34
|
+
var_R = var_R / 12.92
|
35
|
+
end
|
36
|
+
|
37
|
+
if ( var_G > 0.04045 )
|
38
|
+
var_G = ( ( var_G + 0.055 ) / 1.055 ) ** 2.4
|
39
|
+
else
|
40
|
+
var_G = var_G / 12.92
|
41
|
+
end
|
42
|
+
|
43
|
+
if ( var_B > 0.04045 )
|
44
|
+
var_B = ( ( var_B + 0.055 ) / 1.055 ) ** 2.4
|
45
|
+
else
|
46
|
+
var_B = var_B / 12.92
|
47
|
+
end
|
48
|
+
|
49
|
+
var_R = var_R * 100
|
50
|
+
var_G = var_G * 100
|
51
|
+
var_B = var_B * 100
|
52
|
+
|
53
|
+
# Observer. = 2°, Illuminant = D65
|
54
|
+
x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
|
55
|
+
y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
|
56
|
+
z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
|
57
|
+
|
58
|
+
return [x,y,z]
|
59
|
+
end
|
60
|
+
|
61
|
+
# EasyRGB - XYZ to CIELAB
|
62
|
+
def xyz_to_lab(x,y,z)
|
63
|
+
var_X = x / 95.047 #ref_X = 95.047 Observer= 2°, Illuminant= D65
|
64
|
+
var_Y = y / 100.000 #ref_Y = 100.000
|
65
|
+
var_Z = z / 108.883 #ref_Z = 108.883
|
66
|
+
|
67
|
+
if ( var_X > 0.008856 )
|
68
|
+
var_X = var_X ** ( 1.0/3.0 )
|
69
|
+
else
|
70
|
+
var_X = ( 7.787 * var_X ) + ( 16.0 / 116.0 )
|
71
|
+
end
|
72
|
+
|
73
|
+
if ( var_Y > 0.008856 )
|
74
|
+
var_Y = var_Y ** ( 1.0/3.0 )
|
75
|
+
else
|
76
|
+
var_Y = ( 7.787 * var_Y ) + ( 16.0 / 116.0 )
|
77
|
+
end
|
78
|
+
|
79
|
+
if ( var_Z > 0.008856 )
|
80
|
+
var_Z = var_Z ** ( 1.0/3.0 )
|
81
|
+
else
|
82
|
+
var_Z = ( 7.787 * var_Z ) + ( 16.0 / 116.0 )
|
83
|
+
end
|
84
|
+
|
85
|
+
l = ( 116.0 * var_Y ) - 16.0
|
86
|
+
a = 500.0 * ( var_X - var_Y )
|
87
|
+
b = 200.0 * ( var_Y - var_Z )
|
88
|
+
|
89
|
+
return [l.round(3),a.round(3),b.round(3)]
|
90
|
+
end
|
91
|
+
|
92
|
+
# EasyRGB - RGB to LAB
|
93
|
+
def rgb_to_lab(r,g,b)
|
94
|
+
x,y,z = rgb_to_xyz(r,g,b)
|
95
|
+
l,a,b = xyz_to_lab(x,y,z)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kolors
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eric Larson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ai4r
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: cocaine
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: oily_png
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
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: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Uses KMeans clustering and the L*A*B* colorspace to extract "approximate
|
95
|
+
human vision" dominant colors from an image. Optionally, use Euclidean Distance
|
96
|
+
to map those dominant colors into preferred "color bins" for a search index facet-by-color
|
97
|
+
solution.
|
98
|
+
email:
|
99
|
+
- ewlarson@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- Gemfile
|
106
|
+
- Gemfile.lock
|
107
|
+
- LICENSE
|
108
|
+
- README.md
|
109
|
+
- README.textile
|
110
|
+
- Rakefile
|
111
|
+
- kolors.gemspec
|
112
|
+
- lib/kolors.rb
|
113
|
+
- lib/kolors/dominant_colors.rb
|
114
|
+
- lib/kolors/rgb.rb
|
115
|
+
- lib/kolors/version.rb
|
116
|
+
homepage: https://github.com/ewlarson/kolors
|
117
|
+
licenses: []
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements:
|
135
|
+
- ImageMagick
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 1.8.24
|
138
|
+
signing_key:
|
139
|
+
specification_version: 3
|
140
|
+
summary: Uses KMeans clustering and the L*A*B* colorspace to extract "approximate
|
141
|
+
human vision" dominant colors from an image.
|
142
|
+
test_files: []
|
143
|
+
has_rdoc:
|