Suppose there are two colors defined in CMYK:
color1 = 30, 40, 50, 60
color2 = 50, 60, 70, 80
If they were to be printed what values would the resulting color have?
color_new = min(cyan1 + cyan2, 100), min(magenta1 + magenta2, 100), min(yellow1 + yellow2, 100), min(black1 + black2, 100)?
Suppose there is a color defined in CMYK:
color = 40, 30, 30, 100
It is possible to print a color at partial intensity, i.e. as a tint. What values would have a 50% tint of that color?
color_new = cyan / 2, magenta / 2, yellow / 2, black / 2?
I'm asking this to better understand the "tintTransform" function in PDF Reference 1.7, 4.5.5 Special Color Spaces, DeviceN Color Spaces
Update:
To better clarify: I'm not entirely concerned with human perception or how the CMYK dyies react to the paper. If someone specifies 90% tint which, when printed, looks like full intensity colorant, that's ok.
In other words, if I asking how to compute 50% of cmyk(40, 30, 30, 100) I'm asking how to compute the new values, regardless of whether the result looks half-dark or not.
Update 2:
I'm confused now. I checked this in InDesign and Acrobat. For example Pantone 3005 has CMYK 100, 34, 0, 2, and its 25% tint has CMYK 25, 8.5, 0, 0.5.
Does it mean I can "monkey around in a linear way"?
No, in general you can't monkey around in a linear way with arbitrary color spaces and hope to see a result that corresponds to human perception. The general strategy is to convert from your color space into CIE Lab or Luv color space, do the transformation, then go back to your color space (which is lossy).
Excellent FAQ: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html
Supposing C,M,Y,K are the % of ink to print. Adding two colors would be:
C = min(100,C1+C2)
M = min(100,M1+M2)
Y = min(100,Y1+Y2)
K = min(100,K1+K2)
And then they must be normalized, because usually no more than three inks are printed, and an equal amount of C,M,Y is replaced by the same amount of black.
G = min(C,M,Y) // Black amount produced by C,M,Y
C -= G
M -= G
Y -= G
K = min(100,K+G)
At this point, you may want to limit C+M+Y+K to some value like 240. You can also try G=min(C,M,Y,100-K).
If you're just doing tints of colours then a straight multiplication will be fine - this ensures that the inks will all be in the same ratios.
You can see this by bringing up the Colors panel in InDesign, and holding down shift and dragging one of the colour sliders. The other sliders will move proportionally.
Adding two colours has the same effect as overprinting (where one colour is printed directly over another colour). So if 100% magenta and 100% cyan were printed, and then 100% black were printed on top, the result would be exactly the same as 100% magenta, 100% cyan and 100% black.
To answer your first question:
color_new = min(cyan1 + cyan2, 100),
min(magenta1 + magenta2, 100),
min(yellow1 + yellow2, 100),
min(black1 + black2, 100)
If this had been RGB values it would result in saturated colours (i.e. colours at or near white). The converse will be true for the CMY part of the CMYK colour - they will tend to black (well practically dark brown). The addition of black means that you get pure black (thanks Skilldrick). After all if you have 100% black and any combination of CMY the result will be black.
Re your second update I would expect that the results you obtained from Acrobat would apply universally.
Using Photoshop's multiply blend as a guide in CMYK mode I came to the following conclusion:
mix = colour1 + colour2 - color1 * color2
So 50% magenta blended with 50% magenta would equate to
50% + 50% - 50% * 50%
100% - 25%
75% magenta
100% black and 100% black would come to (100% + 100% - 100% * 100%) = 100%
It's seems to at least tally with the tests I did in Photoshop and multiply blends. Whether that is right for print, I can't say.
Related
I need to develop an algorithm that assigns a probability to each pixel of a picture according to its RGB color code. If the pixel is completely red the probability is one. The probability lowers the less red the pixel gets. The blue pixels should be assigned with the lowest probability. I work with python. Thanks a lot for your help!
Color pattern of interest
RGB has 3 components: red, green, blue.
You could do it so it's: p = Math.max(0, red - (green + blue)/2)
If you want to discard green, p = Math.max(0, red - blue).
If values are within [0..255] (0x0..0xFF) you can normalize that to the interval [0..1]
I am trying to come up with an algorithm to determine the dominant color in an image (either taken from a devices camera or by selecting an existing photo in the photo library). I have written an iOS 8 application in Swift that can grab the RGB value of each pixel in the image, but I don't really know what to do from there.
For pixels that have a distinct dominant color, say RGB(230, 15, 30), it's pretty easy to determine the dominant color. However, I don't really know what to do for pixels that have RGB values where 2 of the 3 values are similar, say RGB(200, 215, 30).
My original thought was to keep 3 counters (one for each color) and add each pixels corresponding RGB values to that counter. At the end I would divide each counter by the total number of pixels and the max of the 3 values would be the dominant color. However, like I mentioned before, when the results are close to each other I can't say that one color necessarily dominates the other.
Just looking for some thoughts and suggestions
I came up with this problem a few weeks ago, and having read many posts talking about it, I found the best method is Hierarchical Quantization presented by this post: http://aishack.in/tutorials/dominant-color/. Also, I have implemented it in python: https://github.com/wenmin-wu/dominant-colors-py . You can install it with pip:pip install dominantcolors and use it as following:
from dominantcolors import get_image_dominant_colors
dominant_colors = get_image_dominant_colors(image_path='/path/to/image_path',num_colors=3)
An idea:
First step is to reduce the number of colors, for example "Color Quantization using K-Means". In the example from the link, the number of colors was reduced to 64 from 96K.
Second step is to calculate the ratio for every color and pick the biggest value.
You can check my hobby project to find the dominant color in a UIImage: https://github.com/ruuki/ColorFinder
What it does basically is creating clusters of colors of the image and returns the most dominant one in a completion block. You can tweak threshold parameters within the source code. Hope it helps.
i had a similar task to do, here is my python code:
import picamera
import picamera.array
import numpy as np
from math import sqrt, atan2, degrees
def get_colour_name(rgb):
rgb = rgb / 255
alpha = (2 * rgb[0] - rgb[1] - rgb [2])/2
beta = sqrt(3)/2*(rgb[1] - rgb[2])
hue = int(degrees(atan2(beta, alpha)))
std = np.std(rgb)
mean = np.mean(rgb)
if hue < 0:
hue = hue + 360
if std < 0.055:
if mean > 0.85:
colour = "white"
elif mean < 0.15:
colour = "black"
else:
colour = "grey"
elif (hue > 50) and (hue <= 160):
colour = "green"
elif (hue > 160) and (hue <= 250):
colour = "blue"
else:
colour = "red"
if DEBUG:
print rgb, hue, std, mean, colour
return str(int(hue)) + ": " + colour
def scan_colour:
with picamera.PiCamera() as camera:
with picamera.array.PiRGBArray(camera) as stream:
camera.start_preview()
camera.resolution = (100, 100)
for foo in camera.capture_continuous(stream, 'rgb', use_video_port=False, resize=None, splitter_port=0, burst=True):
stream.truncate()
stream.seek(0)
RGBavg = stream.array.mean(axis=0).mean(axis=0)
colour = get_colour_name(RGBavg)
print colour
scan_colour()
What i thought is to build the mean Color of all Pixels and to determine the Color out of the hue angle. For getting grayscale answers i wanted to check if the Color is near the middle line of the Color corpus.
I have a picture of a handwritten letter (say the letter, "y"). Keeping only the first of the three color values (since it is a grayscale image), I get a 111x81 matrix which I call aLetter. I can see this image (please ignore the title) using:
colormap gray; image(aLetter,'CDataMapping','scaled')
What I want is to remove the white space around this letter and somehow average the remaining pixels so that I have an 8x8 matrix (let's call it simpleALetter). Now if I use:
colormap gray; image(simpleALetter,'CDataMapping','scaled')
I should see a pixellated version of the letter:
Any advice on how to do this would be greatly appreciated!
You need several steps to achieve what you want (updated in the light of #rwong's observation that I had white and black flipped…):
Find the approximate 'bounding box' of the letter:
make sure that "text" is the highest value in the image
set things that are "not text" to zero - anything below a threshold
sum along row and column, find non-zero pixels
upsample the image in the bounding box to a multiple of 8
downsample to 8x8
Here is how you might do that with your situation
aLetter = max(aLetter(:)) - aLetter; % invert image: now white = close to zero
aLetter = aLetter - min(aLetter(:)); % make the smallest value zero
maxA = max(aLetter(:));
aLetter(aLetter < 0.1 * maxA) = 0; % thresholding; play with this to set "white" to zero
% find the bounding box:
rowsum = sum(aLetter, 1);
colsum = sum(aLetter, 2);
nonzeroH = find(rowsum);
nonzeroV = find(colsum);
smallerLetter = aLetter(nonzeroV(1):nonzeroV(end), nonzeroH(1):nonzeroH(end));
% now we have the box, but it's not 8x8 yet. Resampling:
sz = size(smallerLetter);
% first upsample in both X and Y by a factor 8:
bigLetter = repmat(reshape(smallerLetter, [1 sz(1) 1 sz(2)]), [8 1 8 1]);
% then reshape and sum so you end up with 8x8 in the final matrix:
letter8 = squeeze(sum(sum(reshape(bigLetter, [sz(1) 8 sz(2) 8]), 3), 1));
% finally, flip it back "the right way" black is black and white is white:
letter8 = 255 - (letter8 * 255 / max(letter8(:)));
You can do this with explicit for loops but it would be much slower.
You can also use some of the blockproc functions in Matlab but I am using Freemat tonight and it doesn't have those… Neither does it have any image processing toolbox functions, so this is "hard core".
As for picking a good threshold: if you know that > 90% of your image is "white", you could determine the correct threshold by sorting the pixels and finding the threshold dynamically - as I mentioned in my comment in the code "play with it" until you find something that works in your situation.
Though I have found a lot of topics on color tint and temperature, but till now I have not seen any definite solution, which is the reason I am creating this post..My apologies for that.
I am interested in adjusting color temp and tint in images from RGB values, somewhat similar to the iPhoto application found in iOS where it can be adjusted with a slider bar from left to right.
Whatever I have found, temp and tint are orthogonal properties, where temp adjustment is along the blue (left; cool colors)--yellow(right; warm colors) and tint along the green (left) -- magenta (right) axis.
How do I adjust them using formulas from RGB values i.e., uderlying implementation of the color temp and tint slider bars.
I can convert them to HSV space and then I can rotate the hue wheel channel towards those (blue, yello, green, magenta) angles, but how to do them in a systematic fashion similar to the slider bar implementation by changing gradually from low level (middle of the slider bar) to high level (right/left ends of the slider bar).
Thanks!
You should try using HSL instead of HSV. HSL saturation separates itself from the hue and luminosity has very definitive range when it comes to mathematical calculation.
In HSL, to add tint you move the L factor between 50-100 and to add shade the L factor varies between 0-50. Also saturation for HSL controls the tone directly unlike HSV.
For temperature, you have to devise your own stratagy changing the color between red and blue but one golden hint that I can give you is "every pure RGB color has one of 3 color values as zero, second fixed to 255 and 3rd varies with the factor of 255/60.
Hope this helps-
Whereas color temparature is a physical value, its expression
in terms of RGB values
not
trivial. If all you need is a pair of orthogonal axes in the RGB colorspace for the visual adjustment of white balance, they can be defined with relative ease in such a way as to resemble the true color temperature and its derivative the tint.
Let us name our RGB temperature BY—for the balance between blue and yellow, and our RGB tint GR—for the balance balance between green and red. Now, these functions must satisfy the following obvious requirements:
They shall not depend on brightness, or be invariant to multiplication of all the RGB components by the same factor:
BY(r,g,b) = BY(kr, kg, kb),
GR(r,g,b) = GR(kr, kg, kb).
They shall be zero for neutral gray:
BY(0,0,0) = 0,
GR(0,0,0) = 0.
They shall belong the to same range, symmetrical around zero point. I will use [-1..+1]
Any combination of BY and GR shall define a valid color.
Now, one of the ways to define them could be:
BY = (r + g - 2b)/(r + g + 2b),
GR = (r - g )/(r + g) .
so that each pair of BY and GR determines a specific proportion
r:g:b = (1 + BY)(1 + GR)
(1 + BY)(1 - GR)
1 - BY
The following image shows the colors of maximum brightness on our BY-GR plane. BY is directed right, GR down, and the neutral point (0,0) is at the center:
Proper
adjustment of white balance consists of multiplication of the linear RGB values by individual factors:
r_new = wb_r * r_old
g_new = wb_g * g_old
b_new = wb_b * b_old
It happens to work on gamma-compressed RGB too, but not so well on sRGB, because of a
piece-wise
definition of its transfer function, but the distortion will be small and often unnoticeable. If you want a perfect adjustment, however, make sure to work in linear RGB.
Once a BY-GR pair is chosen and the corresponding RGB proportion calculated, only one degree of freedom remains—the overall multiplier (see req. 1). Choose it so that no pixels become clipped.
I have an image whose pixel colors I want to change to match a particular color (though not completely).
As an example, I want to tint the image of a red car so that it appears blue. I can do this with the GIMP and with ImageMagick, but I would like to know which algorithm they are using to do this so I can implement it in my own program.
I have tried to do this with simple addition of the difference between the colors but it doesn't work very well.
As just a shot in the dark, untested suggestion from someone who's getting into image processing fairly recently... maybe you could just scale the channels?
For example:
RGB_Pixel.r = RGB_Pixel.r * 0.75;
RGB_Pixel.g = RGB_Pixel.g * 0.75;
RGB_Pixel.b = RGB_Pixel.b * 1.25;
If you loop through your image pixel-by-pixel with those three changes, I'd expect you to see the image shift towards blue, and the numbers of course can be trial-and-error'd.
EDIT:
Now if you want to ONLY change the color of pixels that are a certain color to begin with, say, you want to turn a blue car red without doing anything to the rest of the picture, you'll need to run a check on each pixel to see what color it looks like. One way to do this is to use a Euclidean distance:
int* R = RGB_Pixel.r;
int* G = RGB_Pixel.g;
int* B = RGB_Pixel.b;
// You are looking for Blue, which is [0 0 255];
// this variable D is the distance of your current pixel from the desired color.
float D = sqrt( (R-0)*(R-0) + (G-0)*(G-0) + (B-255)*(B-255) );
if(D < threshold)
{
R = R * 0.75;
G = G * 0.75;
B = B * 1.25;
}
The threshold variable is a number between 1 and 255 that represents the maximum distance a color can be from the color you're looking for and still be considered "close enough". This is because you don't want to only look for [0 0 255], very rarely will you find perfect blue (or perfect anything) in an image.
You want to use the lowest threshold you can get away with so that you don't end up coloring other things that aren't part of the object you're looking for, but you want to make sure your threshold is high enough that it covers your entire image. One way to do this is to set up multiple D variables, each with a different target color, so you can capture a few separate types of "blue" without using a really high threshold. For instance, to the human eye, [102 102 200] looks like blue, but might require a pretty high threshold to catch if [0 0 255] is your target color.
I suggest playing with this calculator to get a feel for which colors you want to search for specifically.