Rubyでのカラーベースの画像検索エンジンの構築
公開: 2022-03-11絵は千の言葉に値すると言われています。 そして多くの点で、写真の言葉は色です。 色は私たちの生活に欠かせないものであり、その重要性を否定することはできません。
画像を見ながら、その一部の色を識別しようとすることがよくあります。 私たちは皆それをやってみましたが、詳細には決してしませんでした。 画像から色を識別するように求められた場合、赤、青、緑などの特定の色の名前を使用してラベルを付ける傾向があります。 ただし、画像内で最も目立つ30色を抽出するように求められた場合、目ではそれらを簡単に検出または識別できません。 カマリアンはこれがすべてです。 それはあなたが画像から色を抽出しそしてそれらで遊ぶのを助けます。
この記事では、色空間とは何か、Ruby gem Camalianが提供するもの、そして色を使用してそれらを識別および区別する単純な画像検索エンジンを作成するためにどのように使用できるかを見ていきます。
カラースペース
始める前に、まず色に関するいくつかの基本的な概念を理解しましょう。 画面に表示される画像は、ピクセルの2次元配列を使用して表されます。 画像ファイルはさまざまな方法でエンコードできますが、データの解凍とデコード後の大まかな表現は同じです。 この2D配列ベースの表現では、カラー画像の各ピクセルには、赤、緑、青の3つのコンポーネントがあります。 紙に印刷された画像もドットの2次元表面ですが、ドット自体は通常、シアン、マゼンタ、イエロー、ブラックの4つのコンポーネントインクの混合物です。 これらは、色を表すために使用される他のいくつかの異なる手法の中で、色空間と呼ばれます。 最も一般的に使用される色空間には、RGB、CMYK、HSL、HSVがあります。 CMYKは主に印刷業界で使用され、他のすべてはデジタルメディアで使用されます。
RGB色空間
光を透過するCRT画面、LCD、電話などの物理的な電子メディアは、赤、緑、青の3つのコンポーネントを使用して色を生成します。 人間の目は、目の中の3種類の色受容体を刺激することにより、何百万もの色を検出できます。 これらの受容体をR、G、Bに関連付けることができます。
理想的には、各色成分は、値が0〜255の範囲であるバイトに格納されます。
HSL&HSVカラースペース
立方体にRGB色空間を配置することはかなり困難です。 立方体やカラーホイールでそれを表現しようとした結果は良くありません。 百万色または複数の色で作業している間、色の各色合いをRGB色空間に適切に配置することはできません。
この問題を克服するために、1970年代に、研究者はHSV(色相、彩度、値)およびHSL(色相、彩度、明るさ)色空間を導入しました。 これらの色空間は両方ともカラーホイール上で適切に位置合わせでき、色のさまざまな色合いを簡単に識別できます。
色のためのRubyGem
カマリアンは色がすべてです。 Camalianでできる最も簡単なことの1つは、画像で使用されている色の各色合いを識別することです。
15の異なる色の画像があるとしましょう。
見本から色を識別することは、画像自体から色を識別するよりも確かに簡単です。 さらに、これは単純な画像であり、実際にキャプチャされた写真は、カラーパレットに関してははるかに多様であることがよくあります。 画像から色の値を抽出するには、かなりトリッキーなコードが必要です。そこでCamalianが登場します。これらのトリッキーな処理を行うことで、画像から色に関連する情報を簡単に抽出できます。
入門
Camalianで色を抽出するのが簡単な場合、それを使用してインストールするのはさらに簡単です。 以下を実行してRubygemをインストールできます。
gem install camalian
このgemを使用するには、Rubyスクリプトに直接要求できます。
require 'camalian'
色の抽出
画像から色を抽出するには、まず画像をメモリにロードし、画像オブジェクトでメソッドを使用する必要があります。
image = Camalian::load( File.join( File.dirname(__FILE__), 'colormap.png') ) colors = image.prominent_colors(15) puts colors.map(&:to_hex)
このコードスニペットは、スクリプトが存在するディレクトリから「colormap.png」という名前の画像を読み込み、そこから最も目立つ15色を抽出します。
実行するには、ファイルを「color_test1.rb」として保存し、 ruby color_test1.rb
によってシェルで実行します。 次のような出力が生成されます。
["#318578", "#41b53f", "#2560a3", "#359169", "#2154b1", "#4dda15", "#1d48bf", "#1530dc", "#296d94", "#193dcd", "#3da94d", "#45c131", "#3da84e", "#2d7986", "#193cce"]
そして、それはとても簡単です! 上の画像で使用されている15色を抽出しました。 ルーピーなコードを使って、あるいはもっと悪いことに、あなたの目でそれをやろうとしていると想像できますか? ノッチでダイヤルアップしましょう。 今回は、より詳細な画像でCamalianを使用してみます。
この画像で同じスクリプトを実行すると、次のようになります。
[“#210b03”, “#723209”, “#974d09”, “#ae5d08”, “#c77414”, “#d77f15”, “#ffea54”, “#94651f”, “#b66a15”, “#c25f06”, “#fdd94d”, “#d39a39”, “#efa540”, “#fffffe”, “#fff655”]
上で生成された色の値の配列を視覚化しようとすると、次のようになります。
パレットは良いですが、抽出された色に特定のパターンはありません。 色の値を類似度で並べ替えて、それが役立つかどうかを確認しましょう。 配列をコンソールに実際に出力する前に、もう1つの関数を呼び出すだけです。
colors = image.prominent_colors(15).sort_similar_colors
しかし、比較的明るい色を抽出したい場合はどうでしょうか。 たぶん、40%だけ暗い色、つまり0から40の間の明度(HSL色空間)の値が必要な場合があります。必要なのは次のとおりです。

colors = image.prominent_colors(15).light_colors(0, 40)
画像検索エンジンの作成
Camalianを使用して色を処理するのがいかに簡単であるかがわかったので、画像をアップロードして色でインデックスを付けることができる簡単なWebアプリケーションを作成しましょう。 簡潔にするために、Rubyアプリケーションの構築に関連するさまざまな詳細はスキップします。 代わりに、色とカマリアンの使用法を扱う詳細に焦点を当てます。
このRubyアプリケーションの範囲は、画像のアップロードの処理、保存する前に画像から色を抽出し、選択した色としきい値に基づいてアップロードされた画像を検索することに限定します。
以下は、アプリケーションの構造を説明するためのモデル図です。
アップロードされたすべての画像は、PortfolioItemオブジェクトを使用して表されます。 各Colorオブジェクトは、アップロードされた画像から検出された固有の色を表し、最後に、PortfolioColorは各画像とその中にある色との関係を表します。
アプリケーションのほとんどの部分は、特に画像のアップロードの処理、モデルエンティティの作成、データベースへの永続化などに関してはかなり標準的です。Ruby開発者の場合、これらは簡単です。 以下は、アップロードされた画像から色を抽出するために使用される方法です。
after_save :extract_colors private def extract_colors image = Camalian::load(self.image.path) colors = image.prominent_colors(self.color_count.to_i).sort_similar_colors colors.each do |color| unless c = Color.where(r: color.r, g: color.g, b: color.b).first c = Color.create(r: color.r, g: color.g, b: color.b, h: color.h, s: color.s, l: color.l) end self.colors << c end end
これは、カラーパレットを抽出し、データベースに保存するのに役立ちます。 特定の数の目立つ色(画像をアップロードするときにユーザーが定義できる色)のみを抽出する方法に注目してください。
ユーザーがWebUIのフォームを介して画像を送信すると、画像はポストハンドラーを介して受信され、新しいPortfolioItemが作成されます。 このメソッドextract_colorsは、ポートフォリオアイテムがデータベースに永続化されるたびに呼び出されます。
ページにカラーパレットをレンダリングできるようにするために、単純なヘルパーを使用します。
module PortfolioItemsHelper def print_color_palette(colors) color_string = '' colors.each do |c| color_string += content_tag :span, ' ', style: "display: block; float: left; width: 35px; height: 35px; background: #{c.to_hex}" end content_tag :div, color_string.html_safe, style: "display: inline-block;" end end
基本的に、小さな正方形のスパンを持つdivを作成し、それぞれの背景色を抽出された目立つ色の1つに設定します。
最後に、検索を実装するには、いくつかの数学とロジックを使用する必要があります。
class PortfolioSearchForm include ActiveModel::Model attr_accessor :color, :similarity validates_presence_of :color, :similarity def color_object @color_object ||= Camalian::Color.new(self.color) end def color_range(color, level) (color_object.send(color) - level)..(color_object.send(color) + level) end def colors_by_rgb level = self.similarity.to_i * 255 / 100.0 Color.where(r: color_range(:r, level), g: color_range(:g, level), b: color_range(:b, level)) end def colors_by_hsl level = self.similarity.to_i Color.where(h: color_range(:h, (self.similarity.to_i * 30 / 100.0) ), s: color_range(:s, level), l: color_range(:l, level)) end end
colors_by_hslメソッドを使用すると、クエリに一致するすべてのColorエンティティをフェッチできます。 そして、これらを使用して、アップロードされたすべての画像を識別し、検索結果ページをレンダリングできます。 クエリ自体はかなり単純です。 特定の色と類似性の値が与えられると、色成分ごとに値の範囲が計算されます。
そして、それはほとんどすべての難しい部分です。
試してみる
完全なコードはGitHubにあります。 このアプリのインスタンスをHerokuにデプロイするか、ローカルで試すことができます。
git clone https://github.com/nazarhussain/camalian-sample-app.git cd camalian-sample-app bundle install rake db:migrate rails s
最終的なアプリケーションは次のようになります。
アプリケーションが実行されたら、Webブラウザでhttp:// localhost:3000を指定します。 画面上のフォームを使用して、さまざまなカラーパレットの画像をいくつかアップロードします。 次に、画像を色で検索するには、右上隅の検索フィールドを使用します。 しきい値ドロップダウンを使用すると、画像の色を一致させるための非類似度の許容範囲を指定できます。
次は何ですか?
この記事で作成したデモアプリケーションはかなり単純ですが、可能性は無限大です。 このライブラリのその他の実用的な用途には、次のものがあります。
- 暗いプロフィール写真のアップロードをユーザーに制限する
- ユーザーがアップロードした画像にサイトのカラーテーマを適合させる
- デザインコンペの場合、提出物をカラーパレットの要件に対して自動的に検証します
GitHubでライブラリをさらに探索し、そのソースコードを確認できます。 問題を作成してバグを報告するか、プルリクエストを送信して貢献してください。