kolors 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|