Color Correct

ยท 5 min read
Color Correct
The current UI

A "hello world" to machine learning, and solving a real-world inefficiency? Sign me up! This article will share some of the highlights and "Ah-ha!" moments during the build of my latest React app - Color Correct.

Some Context...

Print has always had fairly thin profit margins, and as a result, innovation and lean manufacturing is the name of the game. This can typically be observed at all levels of a print business. I have spent a fair amount of time on the front lines of production in a few print/packaging environments and have found my share of ways to improve efficiency.

The goal of this project is to reduce paper waste, ink waste, and labor hours on a modern printing press. A quick outline of some important print industry terms before moving forward:

  • Make-ready - This can refer to the process of setting a press up to run a job, or more specifically, in this case, the sacrificial sheets before "good" sheets start coming out of the machine.
  • Print Unit/Print Tower - One "section" of the press responsible for transferring a single color to the sheet.
  • Ink Fountain - Each Print Unit's ink resevoir, ink is transferred from here directly to the roller-train
  • Ink Key - There are a series of "flaps" that meter the amount of ink let through to the roller train. These allow the fine-tuning of ink density per region
8 color press - K, C, M, Y (perfector flips the sheet), then K, C, M, Y again
Print unit 4 contains ink keys 102-136

The goal

In lithographic printing, there is a "prepress" department that is responsible for job layouts, creating print plates. Along with the print plates, prepress will generate a file to send to the press that tells the press how much ink to lay down in each area based on how heavy the coverage is in the image. This file is seen as a starting point for the press, and the pressman will adjust from here, and do fine-tuning on the fly. In a lot of cases, these files are not spot-on, due to mechanical changes on the press, ink/water balance, using different chemistry, impression, any one of a seemingly endless list of variables. My goal is to adjust the files from prepress to make for shorter make-readies and more accurate color densities early in each print run. This should reduce paper waste, ink used, and time spent on make-readies.

The Approach

The files prepress generates start as something with a proprietary encoding, however, the final file sent to the press is human-readable. And a nearly identical format is exported from the press when saving a color profile... We can use these exports to compare against the originals and treat this is a polynomial regression problem. I have not done a whole lot with neural nets or machine learning in general, and this seems like a great problem to solve with a neural net. I'll extract the ink key data, convert to tensors, and use TensorFlow to establish the relationship between the two - find the "curve" so to speak.

Each row of the prepress files corresponds to one print unit on the press. Each value/column in the row, corresponds to one of the 34 ink keys across each unit. This will make rank-2 tensors that are easy to work with. I know a few things going into this, that stand to create hurdles in the process:

  1. I will have small datasets (ideally I can train this model on less than 10 samples)
  2. I need to localize the influence the ink keys have on each other; I do not want an ink key from one side of a unit to influence the output of a key at the opposite end.

Neural Net Architecture

I want each ink key to take some amount of influence from it's immediate neighbors, but not further away than that. Given the small datasets and the goal of performing regression on smaller subsets of a larger data array, I will need to be creative here. There may be a few ways to separate each key into it's own zone, but the easiest solution seems to be by using a custom (non-trainable) weight matrix to define my zones, and perform the actual regression in the following layer. There are 8 print units, each with 34 keys across, this is 272 individual keys. As such, I will flatten my data and the input will be a vector of 272 ink key values. The architecture I've settled into is illustrated below.

The human-readable color file. Highlighted is the ink key data.
NN design

Following the input, the first layer is actually 272 parallel single-node layers, they have a fixed weight of 1 for the corresponding node in the input layer, and a fixed .35 for the immediate neighbors. Moving forward these continue as parallel layers, though are allowed to train and develop bias. Both of these layers use linear activation functions, as it is never a question of should a neuron fire or not - they all need to fire. The next layer concatenates these back to (1,272), and not imaged here - reshapes to (8,34), to resemble the original (print units) X (ink keys).

The frontend (for now)

Embedded below is a very quick demo showing the current functionality. The frontend uses react, and react-redux for state management. (there is no audio, don't bother turning your sound up)

Optimizing user interaction

This takes the form of a web app to avoid needing permissions to install or run on a work network. For now the workflow is a bit archaic, but functional.

In the meantime, we will continue sporting drag n' drop elements, and a bare-bones database to save models. The TensorflowJS library generates a multipart/form-data MIME type request with the model architecture as JSON and weights as a binary. This should allow for importing model and weights to Tensorflow's other language libraries... I sense an API coming soon.

Bare-bones DB

Work in Progress

Unlike my graveyard of half projects, this one is not currently on the back burner. Right now I am in somewhat of a testing phase, sorting out when during a print run is best to export ink settings to train with. Every printing press has its own "personality", and while I am getting results that make a lot of sense from the model, honing in on the right training data will really make this shine.

Update 12-14-24

This did, in fact, find it's way to the back burner, and finally the graveyard.
I have since moved away from the print industry and no longer had a need to improve this. However, should anyone come across this that can make use of this, please reach out (danieljhalleck@gmail.com) - I can host or would be happy to collaborate or help integrate this tech to see it used in the real world.