Aesthetic design can be hard. After all, people get paid to do it professionally. But as with many things, it’s much easier to recognize good design than create it whole-cloth yourself, especially when it comes to good color selection. So, what if you could use existing images and just a little bit of coding to generate color palettes? Well, now you can, thanks to the computer vision magic of Clarifai!
We have a variety of products available for gleaning information from your images with the power of machine learning. One that you might not know about is the “Color” model, which identifies the dominant colors in any image. You can use this information to programmatically style your app, format documents, or anything else you can imagine. In this tutorial we’ll be showing you how to extract a W3C compatible color scheme from an arbitrary image in a short and sweet web app. Let’s jump in!
(If you just want the full source code, you can download this GitHub Repo.)
Get Your Clarifai Key
Before we begin, your first step should be to sign up for a free Clarifai account.
After you’ve made an account you will need to register an app with Clarifai through the developer interface:
Select your application and click “API Keys.” This hexadecimal string is what will give your app access to Clarifai, so copy it down for later.
HTML — The Skeleton
Next, we will set up the structure of our webpage with HTML. This will be simple: make a new HTML file index.html with a <head> section and a <body> section. In the <head> section, copy in the following code:
https://gist.github.com/RedRussianBear/787ab46d2af1c9c9c1d3b5c8fc8585f4
<!-- Include JS !-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.4.1/tinycolor.min.js"></script>
<script src="https://sdk.clarifai.com/js/clarifai-latest.js"></script>
<script src="colors.js"></script>
<!-- Include Styles !-->
<link rel="stylesheet" href="style.css">
The first two script tags include the jQuery and tinycolor libraries, which we will be using to keep our code clean and succinct. If you’ve never used it before, jQuery is a widely used JavaScript library that makes getting elements by ID, class, and modifying their attributes much easier and cleaner. The third script tag includes the Clarifai JavaScript web SDK, which is what will actually let us access our model and send in images for analysis. The final script tag links in our colors.js file, where we will put our code. The link on the final line connects to our CSS file, styles.css, which will make everything pretty.
Now, in the <body> section, type the following code:
https://gist.github.com/RedRussianBear/360629518e9fc521fd531d44f7feafbf
<div id="work_box">
<h1>Create a Color Scheme with Clarifai!</h1>
<input type="file" id="upload"/>
<div id="colors"></div>
</div>
All we have in here is a <div> to contain all of our work, with an <h1> header to tell the user what’s going on, a file <input> to take in the image for processing, and a nested <div> to hold the list of colors that Clarifai returns after it identifies them in the image. You'll notice some tags have id names, which enables us to access them directly when we use jQuery.
CSS — The Skin
Next, we arrange and style our HTML elements. Make a new file named styles.css, containing the CSS code here:
https://gist.github.com/RedRussianBear/e0ad07f21069897d78dfa08ed40745e0
This CSS file is a set of parameters that alter the display of our HTML. After setting the font and making sure that any background we give the body expands to cover it, we set the size, border, and semi-transparent background color for our ‘work_box’, and make it centered by setting margin: auto. Next, we increase the size and ensure centering of our file upload input. Finally, we space and style each div under #colors, adding a border and forcing any spans within to space out evenly with display: flex.
JS — The Meat
And now, time to make it all work. Make a new file called colors.js to contain our JavaScript. We will be doing all of our work in the web document’s ready() function to ensure that our code doesn’t run before other necessary components have loaded.
https://gist.github.com/RedRussianBear/40a52270ffd623bfb28df94a6c5e35bb
$(document).ready(function () {
// Ensure body resizes appropriately
$('body').css('height', $(window).height());
$(window).resize(function () {$('body').css('height', $(window).height());});
// Connect to Clarifai
const app = new Clarifai.App({
apiKey: 'YOUR_API_KEY'
});
...
}
This is the beginning of our script where we set up two important things: we make sure that the body object resizes appropriately with the window so our image fills the screen, and we connect to Clarifai, making a new App. Remember to swap out 'YOUR_API_KEY' with the hexadecimal key from your own Clarifai account!
Important Note: This JavaScript file is client-side and will get served to all users. If you are using it in production, remember to restrict the scope of your key with the Clarifai API Key Manager. This will make sure that someone can’t just find your key in the code and then go use it to train a custom model on your dime.
Now, still inside of $(document).ready(), we will define getColors(), a function which will take an image file, send it to Clarifai, and print the identified colors to the screen.
https://gist.github.com/RedRussianBear/b7c0868885612209b0697de03d858782
The function consists of a call to app.models.predict(), with the Colors model selected. The Clarifai JavaScript SDK can accept images in one of two forms: as a URL or as base64 byte string. Since we intend for our users to be able to send their own images directly, we will send them to Clarifai in base64. This way our project runs completely client-side, with no backend code, database, or server required from us, and we can host it anywhere as a simple static site.
The predict function runs asynchronously, so we need to define two anonymous functions: one in case of an error and one to handle the response when it comes. The error function will simply log the error to the console.
Meanwhile, in the response function we pull the colors Clarifai identified, and looping over each one, create a new <div> that holds the color’s hex code, W3C name, and prevalence in the image, while setting the <div>’s background to that color as well. We use tinycolor to check if any given color is too light for white text, and if so, set the text color to black.
Now all we need to do is hook up getColors() to our file input. To do this, we hook into the input’s change() method, which triggers whenever the user selects a different file with the input.
https://gist.github.com/RedRussianBear/9be3a48fe91260be987dbd783e85192e
After getting the new file, we instantiate a FileReader to parse file contents into a base64 string. We set the background image to be this file so the user can compare Clarifai’s results to the source for themselves while we're sending for the color scheme. And of course we send it off to be processed by Clarifai (after chopping off the first dozen or so characters, which contain unused header information).
Go Color Scheming Without a Design Degree
Our app is complete! You can run this app by opening index.html in any browser. You should now be able to make W3C compliant color schemes from arbitrary images. This is nice if you’re designing documents around certain photos, but especially powerful if you’re writing a web app that you would like to change appearance based on the background or user input!
Thanks to Mikhail Khrenov, the @RedRussianBear, for this MLH featured hack!