用 Ruby 構建基於顏色的圖像搜索引擎

已發表: 2022-03-11

都說一張圖抵得上一千個字。 在許多方面,圖片中的文字都是顏色。 顏色是我們生活中不可或缺的一部分,我們不能否認它們的重要性。

在查看圖像時,我們經常嘗試識別圖像一部分的顏色。 我們都嘗試過這樣做,但從未詳細做過。 當被要求從圖像中識別顏色時,我們傾向於使用特定的顏色名稱來標記它們,例如紅色、藍色和綠色。 然而,如果我們被要求提取圖像中最突出的 30 種顏色,我們的眼睛就無法輕易地檢測或識別它們。 Camalian就是這樣。 它可以幫助您從圖像中提取顏色,然後使用它們。

Camalian:Ruby 的 Ultiamte 顏色選擇器

在本文中,我們將了解色彩空間的全部內容,Ruby gem Camalian 提供的內容,以及如何使用它來製作一個簡單的圖像搜索引擎,使用顏色來識別和區分它們。

色彩空間

在開始之前,讓我們先了解一些關於顏色的基本概念。 我們屏幕上呈現的圖像使用二維像素陣列表示。 雖然圖像文件的編碼方式可能不同,但對數據進行解壓縮和解碼後的粗略表示是相同的。 在這個基於二維數組的表示中,彩色圖像中的每個像素都具有三個分量:紅色、綠色和藍色。 儘管打印在紙上的圖片也是一個二維點的表面,但點本身通常是四種成分墨水的混合物:青色、品紅色、黃色和黑色。 這些用於表示顏色的其他一些不同技術稱為顏色空間。 一些最常用的色彩空間是 RGB、CMYK、HSL 和 HSV。 CMYK 主要用於印刷行業,而其他所有用於數字媒體。

RGB色彩空間

任何傳輸光的物理電子媒體(如 CRT 屏幕、LCD 或電話)都使用三種成分產生顏色:紅、綠、藍。 人眼可以通過刺激眼睛中的三種顏色受體來檢測數百萬種顏色。 您可以將這些受體與 R、G 和 B 聯繫起來。

理想情況下,每個顏色分量都存儲在一個字節中,其值可以在 0 到 255 之間。

HSL 和 HSV 顏色空間

在立方體上安排 RGB 顏色空間是相當具有挑戰性的。 嘗試在立方體和/或色輪上表示它的結果很差。 在處理百萬或顏色時,每種顏色都無法在 RGB 顏色空間上正確對齊。

紅寶石圖片搜索引擎

為了克服這個問題,研究人員在 1970 年代引入了 HSV(色相、飽和度、值)和 HSL(色相、飽和度、亮度)色彩空間。 這兩種顏色空間都可以在色輪上正確對齊,從而更容易識別其上的各種色調。

顏色的紅寶石

Camalian是關於顏色的。 使用 Camalian 可以做的最簡單的事情之一就是識別圖像中使用的每種顏色。

假設我們有一張有 15 種不同顏色的圖像。

從樣本中識別顏色肯定比從圖像本身識別顏色更容易。 此外,這是一張簡單的圖像,而拍攝的真實照片在其調色板方面往往更加多樣化。 從圖像中提取顏色值需要一些非常棘手的代碼,這就是 Camalian 的用武之地。它為您完成了這些棘手的事情,以便您可以輕鬆地從圖像中提取與顏色相關的信息。

入門

如果使用 Camalian 提取顏色很容易,那麼使用它進行安裝就更容易了。 您可以通過執行以下命令安裝 Ruby gem:

 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在 shell 中運行它。 它應該產生類似於以下內容的輸出:

 ["#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”]

嘗試可視化上面生成的顏色值數組會給我們這樣的結果:

調色板很好,但提取的顏色沒有特定的圖案。 讓我們按相似度對顏色值進行排序,看看是否有幫助。 我們需要做的就是在將數組實際打印到控制台之前再調用一個函數:

 colors = image.prominent_colors(15).sort_similar_colors 

但是如果我們想提取相對較淺的顏色呢? 可能我們想要只有 40% 暗的顏色,或者換句話說,亮度(在 HSL 顏色空間中)值在 0 到 40 之間。我們需要做的就是:

 colors = image.prominent_colors(15).light_colors(0, 40) 

製作圖片搜索引擎

現在我們知道使用 Camalian 處理顏色是多麼容易,讓我們構建一個簡單的 Web 應用程序,它允許您上傳圖像並讓它們按顏色索引。 為簡潔起見,我們將跳過構建 Ruby 應用程序所涉及的各種細節。 相反,我們將專注於處理顏色和 Camalian 用法的細節。

至於這個 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

這有助於提取調色板並保存到數據庫。 請注意我們如何僅提取特定數量的突出顏色(用戶可以在上傳圖像時定義)。

當用戶通過 Web UI 上的表單提交圖像時,圖像會通過 post 處理程序接收,並為其創建一個新的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

它本質上創建了一個具有小正方形 span 的div ,每個跨度的背景顏色都設置為提取的突出顏色之一。

最後,要實現搜索,我們必須使用一些數學和邏輯:

 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 上進一步探索該庫並查看其源代碼。 隨意通過創建問題來報告錯誤或通過發送拉取請求來貢獻。