Budowanie wyszukiwarki grafiki opartej na kolorach w Ruby

Opublikowany: 2022-03-11

Mówi się, że obraz wart jest tysiąca słów. Pod wieloma względami słowa na obrazkach są kolorami. Kolory są integralną częścią naszego życia i nie możemy odmówić im znaczenia.

Patrząc na obraz, często próbowaliśmy zidentyfikować kolor na jego części. Wszyscy próbowaliśmy to robić, ale nigdy nie robiliśmy tego w szczegółach. Poproszeni o zidentyfikowanie kolorów na obrazie zwykle oznaczamy je za pomocą określonych nazw kolorów, takich jak czerwony, niebieski i zielony. Jeśli jednak zostaniemy poproszeni o wyodrębnienie 30 najbardziej wyrazistych kolorów z obrazu, nasze oko nie jest w stanie wykryć ani zidentyfikować ich tak łatwo. Camalian to wszystko. Pomaga wyodrębnić kolory z obrazów, a następnie bawić się nimi.

Camalian: Próbnik kolorów Ultiamte dla Ruby

W tym artykule przyjrzymy się, na czym polegają przestrzenie kolorów, co ma do zaoferowania rubinowy klejnot Camalian i jak można go wykorzystać do stworzenia prostej wyszukiwarki obrazów, która używa kolorów do ich identyfikacji i rozróżniania.

Przestrzeń kolorów

Zanim zaczniemy, najpierw zrozumiemy kilka podstawowych pojęć dotyczących kolorów. Obrazy prezentowane na naszych ekranach są reprezentowane za pomocą dwuwymiarowej tablicy pikseli. Chociaż pliki obrazów mogą być kodowane na różne sposoby, surowa reprezentacja po dekompresji i dekodowaniu danych jest taka sama. W tej reprezentacji opartej na tablicy 2d każdy piksel w obrazie kolorowym ma trzy składniki: czerwony, zielony i niebieski. Chociaż obrazy drukowane na papierze są również dwuwymiarową powierzchnią kropek, same kropki są zwykle mieszanką czterech składowych atramentów: cyjan, magenta, żółtego i czarnego. Te spośród kilku innych technik używanych do przedstawiania kolorów są nazywane przestrzeniami kolorów. Niektóre z najpopularniejszych przestrzeni kolorów to RGB, CMYK, HSL i HSV. CMYK jest najczęściej używany w branży poligraficznej, podczas gdy wszystkie inne są wykorzystywane w mediach cyfrowych.

Przestrzeń kolorów RGB

Wszelkie fizyczne nośniki elektroniczne, takie jak ekrany CRT, wyświetlacze LCD lub telefony, które przepuszczają światło, wytwarzają kolor za pomocą trzech składników: czerwonego, zielonego i niebieskiego. Ludzkie oko może wykryć miliony kolorów poprzez stymulację trzech typów receptorów kolorów w oku. Możesz powiązać te receptory z R, G i B.

Idealnie, każdy składnik koloru jest przechowywany w bajcie, którego wartości mogą mieścić się w zakresie od 0 do 255.

Przestrzeń barw HSL i HSV

Aranżacja przestrzeni kolorów RGB na sześcianie jest dość trudna. Wyniki próby przedstawienia go na sześcianie i/lub na kole kolorów są słabe. Podczas pracy z milionami lub kolorami, każda tinta koloru nie może być prawidłowo wyrównana w przestrzeni kolorów RGB.

Wyszukiwarka grafiki ruby

Aby rozwiązać ten problem, w latach 70. naukowcy wprowadzili przestrzenie kolorów HSV (odcień, nasycenie, wartość) i HSL (odcień, nasycenie, jasność). Obie te przestrzenie kolorów można odpowiednio wyrównać na kole kolorów i ułatwić identyfikację różnych odcieni kolorów na nim.

Rubinowy klejnot dla kolorów

Camalian to przede wszystkim kolory. Jedną z najprostszych rzeczy, które możesz zrobić z Camalianem, jest zidentyfikowanie każdego odcienia koloru użytego na obrazie.

Załóżmy, że mamy obraz z 15 różnymi kolorami.

Identyfikacja kolorów z próbki jest z pewnością łatwiejsza niż identyfikacja ich na podstawie samego obrazu. Co więcej, jest to prosty obraz, a uchwycone prawdziwe zdjęcia są często znacznie bardziej zróżnicowane pod względem palety kolorów. Wyodrębnienie wartości kolorów z obrazu wymaga dość skomplikowanych fragmentów kodu, i tu właśnie wkracza Camalian. Robi te trudne rzeczy za Ciebie, abyś mógł z łatwością wyodrębnić informacje związane z kolorem z obrazu.

Pierwsze kroki

Jeśli wydobywanie kolorów za pomocą Camalian jest łatwe, instalacja za jego pomocą jest jeszcze łatwiejsza. Możesz zainstalować klejnot Ruby, wykonując:

 gem install camalian

Aby użyć tego klejnotu, możesz go zażądać bezpośrednio w skrypcie Ruby:

 require 'camalian'

Wyodrębnianie kolorów

Aby wyodrębnić kolory z obrazu, najpierw musimy załadować go do pamięci i użyć metod na obiekcie obrazu:

 image = Camalian::load( File.join( File.dirname(__FILE__), 'colormap.png') ) colors = image.prominent_colors(15) puts colors.map(&:to_hex)

Ten fragment kodu ładuje obraz o nazwie „colormap.png” z katalogu, w którym znajduje się skrypt i wyodrębnia z niego 15 najbardziej widocznych kolorów.

Aby go uruchomić, zapisz plik jako „color_test1.rb” i uruchom go w powłoce przez ruby color_test1.rb . Powinno to generować dane wyjściowe podobne do następujących:

 ["#318578", "#41b53f", "#2560a3", "#359169", "#2154b1", "#4dda15", "#1d48bf", "#1530dc", "#296d94", "#193dcd", "#3da94d", "#45c131", "#3da84e", "#2d7986", "#193cce"]

I to takie proste! Właśnie wyodrębniliśmy 15 kolorów użytych na powyższym obrazku. Czy możesz sobie wyobrazić, że próbujesz to zrobić za pomocą zapętlonego kodu lub, co gorsza, za pomocą oczu? Podkręćmy trochę sprawy. Tym razem spróbujemy użyć Camalian na obrazie z większą ilością szczegółów:

Uruchamiając ten sam skrypt na tym obrazie, otrzymujemy:

 [“#210b03”, “#723209”, “#974d09”, “#ae5d08”, “#c77414”, “#d77f15”, “#ffea54”, “#94651f”, “#b66a15”, “#c25f06”, “#fdd94d”, “#d39a39”, “#efa540”, “#fffffe”, “#fff655”]

Próba wizualizacji tablicy wartości kolorów wygenerowanych powyżej daje nam coś takiego:

Paleta jest dobra, ale nie ma konkretnego wzoru w wyodrębnionych kolorach. Posortujmy wartości kolorów według podobieństwa i zobaczmy, czy to pomoże. Wszystko, co musimy zrobić, to wywołać jeszcze jedną funkcję przed faktycznym wydrukowaniem tablicy do konsoli:

 colors = image.prominent_colors(15).sort_similar_colors 

Ale co, gdybyśmy chcieli wydobyć kolory, które są stosunkowo jaśniejsze? Być może chcemy, aby kolory były tylko 40% ciemne, lub innymi słowy, miały wartość jasności (w przestrzeni kolorów HSL) od 0 do 40. Wszystko, co musimy zrobić, to:

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

Tworzenie wyszukiwarki obrazów

Teraz, gdy wiemy, jak łatwo jest radzić sobie z kolorami za pomocą Camalian, zbudujmy prostą aplikację internetową, która pozwoli Ci przesyłać obrazy i indeksować je według kolorów. Dla zwięzłości pominiemy różne szczegóły związane z budowaniem aplikacji Ruby. Zamiast tego skupimy się na konkretach, które dotyczą kolorów i kamalii.

Jeśli chodzi o zakres tej aplikacji Ruby, ograniczymy się do obsługi przesyłania obrazu, wyodrębniania kolorów z obrazu przed ich zapisaniem oraz wyszukiwania wgranego obrazu na podstawie wybranego koloru i progu.

Poniżej znajduje się schemat modelowy wyjaśniający strukturę naszej aplikacji:

Każdy przesłany obraz jest reprezentowany za pomocą obiektu PortfolioItem. Każdy obiekt Color reprezentuje unikalne kolory odkryte przez przesłane obrazy, a wreszcie PortfolioColor reprezentuje relację między każdym obrazem a znalezionymi w nim kolorami.

Większość części aplikacji jest dość standardowa, zwłaszcza jeśli chodzi o obsługę przesyłania obrazów, tworzenie encji modelu i utrwalanie ich w bazie danych itp. Jeśli jesteś programistą Ruby, nie powinno to być problemem. Poniżej znajduje się metoda używana do wyodrębnienia koloru z przesłanego obrazu:

 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

Pomaga to wyodrębniając paletę kolorów i zapisując do bazy danych. Zwróć uwagę, jak wyodrębniamy tylko określoną liczbę wyróżniających się kolorów (coś, co użytkownik może zdefiniować podczas przesyłania obrazu).

Gdy użytkownik przesyła obraz za pomocą formularza w internetowym interfejsie użytkownika, obraz jest odbierany przez program obsługi postów i tworzony jest dla niego nowy element PortfolioItem . Ta metoda, extract_colors , jest wywoływana za każdym razem, gdy element portfela jest utrwalany w bazie danych.

Aby móc renderować paletę kolorów na stronach, korzystamy z prostego pomocnika:

 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

Zasadniczo tworzy div z małymi kwadratowymi rozpiętościami , każdy z kolorem tła ustawionym na jeden z wyodrębnionych wyraźnych kolorów.

Wreszcie, aby zaimplementować wyszukiwanie, musimy użyć trochę matematyki i logiki:

 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

Za pomocą metody colors_by_hsl możemy pobrać wszystkie encje Color , które pasują do naszego zapytania. Dzięki nim możemy zidentyfikować wszystkie przesłane obrazy i wyrenderować naszą stronę wyników wyszukiwania. Samo zapytanie jest dość proste. Mając określony kolor i wartość podobieństwa, dla każdego składnika koloru obliczany jest zakres wartości.

I to prawie wszystkie trudne części.

Wypróbowanie

Pełny kod można znaleźć na GitHub. Możesz wdrożyć instancję tej aplikacji w Heroku lub wypróbować ją lokalnie:

 git clone https://github.com/nazarhussain/camalian-sample-app.git cd camalian-sample-app bundle install rake db:migrate rails s

Ostateczna aplikacja wygląda mniej więcej tak:

Po uruchomieniu aplikacji skieruj przeglądarkę internetową na http://localhost:3000. Korzystając z formularza na ekranie, prześlij kilka obrazów o różnych paletach kolorów. Następnie, aby wyszukać obrazy według koloru, użyj pola wyszukiwania w prawym górnym rogu. Lista rozwijana Próg pozwala określić tolerancję odmienności dla dopasowania kolorów obrazów.

Co dalej?

Aplikacja demonstracyjna, którą zbudowaliśmy w tym artykule jest dość prosta, ale możliwości są nieograniczone! Niektóre inne praktyczne zastosowania tej biblioteki mogą obejmować:

  • Ograniczanie użytkownikom możliwości przesyłania ciemnych zdjęć profilowych
  • Dostosuj motyw kolorystyczny witryny do jakiegoś zdjęcia przesłanego przez użytkownika
  • W przypadku konkursów projektowych automatycznie weryfikuj zgłoszenia pod kątem wymagań dotyczących palety kolorów

Możesz dalej eksplorować bibliotekę na GitHub i sprawdzić jej kod źródłowy. Zachęcamy do zgłaszania błędów, tworząc problemy lub wnosząc swój wkład, wysyłając pull requesty.