Surface construction using two line segment - graphics

have two line segment in the space, how to construct a surface with two line segment as the boundary?

You may do this parametrically.
Supose your two segments described by:
{s1(t)} = t {a1} + {b1} (0 <= t <= 1)
{s2(t)} = t {a2} + {b2} (0 <= t <= 1)
where the {} indicates vector quantities, {a},{b} constants.
Then, for any t you have two points in space, one in each segment.
The straight line between them can be described by:
{r(v)} = ({s2(t)} - {s1(t)}) v + {s1(t)} (0 <= v <= 1 )
We are almost there. Now we write the function describing the surface, replacing s1 and s2 by their values:
{K(v,t)} = t v ( {a2} - {a1} )+ v ({b2} - {b1}) + t {a1} + {b1} (0<= t,v <=1)
HTH!
Edit
An Example:
a1 = {1, 1, 1};
b1 = {0, 0, 0};
a2 = {1, 1, 0};
b2 = {0, 0, 0};
Show[ParametricPlot3D[
t v a1 (a2 - a1) + v (b2 - b1) + t a1 + b1, {t, 0, 1}, {v, 0, 1},
AxesLabel -> {"x", "y", "z"}],
Graphics3D[{Thick, Red, Line[{b1, a1 + b1}]}],
Graphics3D[{Thick, Red, Line[{b2, a2 + b2}]}]]
Another example, showing a non-flat surface:
a1 = {1, 1, 1};
b1 = {0, 0, 1};
a2 = {1, 0, 0};
b2 = {0, 1, 0};

The two line segments will have to be co-planar (ie: both lie on the surface you want to reconstruct). A cross-product of the two line segments will give you the normal to the surface (a vector perpendicular to the surface).
What I'm not sure about at this point is what you mean by the line segments determining the boundary. If the ends of the line segments are the 4 points of a quad boundary and you want to turn that into a subdivided patch, then you can bilinearly interpolate between the corner points to produce the coordinates for your patch mesh.

Related

Smallest window (substring) that has both uppercase and corresponding lowercase characters

I was asked the following question in an onsite interview:
A string is considered "balanced" when every letter in the string appears both in uppercase and lowercase. For e.g., CATattac is balanced (a, c, t occur in both cases), while Madam is not (a, d only appear in lowercase). Write a function that, given a string, returns the shortest balanced substring of that string. For e.g.,:
“azABaabza” should return “ABaab”
“TacoCat” should return -1 (not balanced)
“AcZCbaBz” should returns the entire string
Doing it with the brute force approach is trivial - calculating all the pairs of substrings and then checking if they are balanced, while keeping track of the size and starting index of the smallest one.
How do I optimize? I have a strong feeling it can be done with a sliding-window/two-pointer approach, but I am not sure how. When to update the pointers of the sliding window?
Edit: Removing the sliding-window tag since this is not a sliding-window problem (as discussed in the comments).
Due to the special property of string. There is only 26 uppercase letters and 26 lowercase letters.
We can loop every 26 letter j and denote the minimum length for any substrings starting from position i to find matches for uppercase and lowercase letter j be len[i][j]
Demo C++ code:
string s = "CATattac";
// if len[i] >= s.size() + 1, it denotes there is no matching
vector<vector<int>> len(s.size(), vector<int>(26, 0));
for (int i = 0; i < 26; ++i) {
int upperPos = s.size() * 2;
int lowerPos = s.size() * 2;
for (int j = s.size() - 1; j >= 0; --j) {
if (s[j] == 'A' + i) {
upperPos = j;
} else if (s[j] == 'a' + i) {
lowerPos = j;
}
len[j][i] = max(lowerPos - j + 1, upperPos - j + 1);
}
}
We also keep track of the count of characters.
// cnt[i][j] denotes the number of characters j in substring s[0..i-1]
// cnt[0][j] is always 0
vector<vector<int>> cnt(s.size() + 1, vector<int>(26, 0));
for (int i = 0; i < s.size(); ++i) {
for (int j = 0; j < 26; ++j) {
cnt[i + 1][j] = cnt[i][j];
if (s[i] == 'A' + j || s[i] == 'a' + j) {
++cnt[i + 1][j];
}
}
}
Then we can loop over s.
int m = s.size() + 1;
for (int i = 0; i < s.size(); ++i) {
bool done = false;
int minLen = 1;
while (!done && i + minLen <= s.size()) {
// execute at most 26 times, a new character must be added to change minLen
int prevMinLen = minLen;
done = true;
for (int j = 0; j < 26 && i + minLen <= s.size(); ++j) {
if (cnt[i + minLen][j] - cnt[i][j] > 0) {
// character j exists in the substring, have to find pair of it
minLen = max(minLen, len[i][j]);
}
}
if (prevMinLen != minLen) done = false;
}
// find overall minLen
if (i + minLen <= s.size())
m = min(m, minLen);
cout << minLen << '\n';
}
Output: (if i + minLen <= s.size(), it is valid. Otherwise substring doesn't exist if starting at that position)
The invalid output difference is due to how the array len is generated.
8
4
15
14
13
12
11
10
I'm not sure whether there is a simpler solution but it is the best I could think of right now.
Time complexity: O(N) with a constant of 26 * 26
Edit: I previously had O(nlog(n)) due to a unnecessary binary search.
I thought of a solution, which is technically O(n), where n is the length of the string, but the constant is pretty large.
For simplicity's sake, let's consider an analogous situation with only two letters, A and B (and their lowercase counterparts), and let l be the size of the alphabet for future reference. I worked on an example string ABabBaaA.
We start by computing the prefix counts of the number of occurrences of each letter. In this case, we get
i: 0, 1, 2, 3, 4, 5, 6, 7, 8
----------------------------
A: 0, 1, 1, 1, 1, 1, 1, 1, 2
a: 0, 0, 0, 1, 1, 1, 2, 3, 3
B: 0, 0, 1, 1, 1, 2, 2, 2, 2
b: 0, 0, 0, 0, 1, 1, 1, 1, 1
This way, assuming we are indexing the string starting from 1 (for implementation's sake you can add an extra character to the beginning, like a dollar sign $), we can get the number of occurrences of each letter on any substring in constant time (or rather -- in O(l), but in my case l is set to 2 and in your case l = 26 so technically this is constant time).
OK now we prepare arrays / vectors / queues of character indices, so if the character A appears on indices 1 and 8, the structure will consist of 1 and 8. We get
A: 1, 8
a: 3, 6, 7
B: 2, 5
b: 4
What is important, is that in arrays and vectors, we can look up certain "lowest element greater than" in amortized constant time by discarding indices which are smaller than every index one by one.
Now, the algorithm. Starting at each (left) index greater than 0, we will find the earliest right index for which the substring bound by [left_index, right_index] is balanced. We do that as follows:
Start with left_index = right_index = i for i = 1, ..., n.
Read the array of prefix counts for right_index and subtract the prefix counts for left_index - 1 receiving the counts for the substring [left_index, right_index]. Find any letter, which fails the "balance" check. If there is none, you found the shortest balanced substring starting at left_index.
Find the first occurrence of the "missing" letter, greater than left_index. Set right_index to the index of that occurrence. Go to step 1 keeping the modified right_index.
For example: starting with left_index = right_index = 1 we see that the number of occurrences of each letter in the substring is 1, 0, 0, 0, so a fails the check. The earliest occurrence of a is 3, so we set right_index = 3. We go back to step 1 receiving a new array of occurrences: 1, 1, 1, 0. Now b fails the check, and its earliest occurrence greater than 1 is 4, so we set right_index to 4. We go to step 1 receiving an array of occurrences 1, 1, 1, 1, which passes the balance check.
Another example: starting with left_index = right_index = 2 we get in step 1 an array of occurrences 0, 0, 1, 0. Now b fails the check. The earliest occurrence of b greater than left_index is 4, so we set right_index to 4. Now we get an array of occurrences 0, 1, 1, 1, so A fails the check. The earliest occurrence of A greater than left_index is 8, so we set right_index to that. Now, the array of occurrences is 2-1, 3-0, 2-0, 1-0, which is 1, 3, 2, 1 and it passes the balance check.
Ultimately we will find the shortest balanced substring to be bB with left_index = 4.
The complexity of this algorithm is O(nl^2) because: we start at n different indices and we perform a maximum of l lookups (for l different letters which can fail the check) in O(1). For each lookup, we have to calculate l differences of prefix sums. But as l is constant (albeit it may be large, like 26), this simplifies to O(n).
I'm using a recursive approach to this; I'm not sure what it's time complexity is though.
The idea is we check what characters in the string are present in both their lower and upper form formats. For any characters that aren't given in both forms, we replace them with a space ' '. We then split the remaining string on ' ' into a list.
In the first case, if we have only one string left after it- we return it's length.
In the second case, if we have no characters left, we return -1.
In the third case, if we have more than one string left, we re-evaluate each of the strings sub-lengths and return the length of the longest string we then evaluate.
from collections import Counter
def findMutual(s):
lower = dict(Counter( [x for x in s if x.lower() == x] ))
upper = dict(Counter( [x for x in s if x.upper() == x] ))
mutual = {}
for charr in lower:
if charr.upper() in upper:
mutual[charr] = upper[charr.upper()] + lower[charr]
matching_charrs = ''.join([x if x.lower() in mutual else ' ' for x in s ]).split()
print(s)
print(matching_charrs)
return matching_charrs
def smallestSubstring(s):
matching_charrs = findMutual(s)
if len(matching_charrs) == 1:
return(len(matching_charrs[0]))
elif len(matching_charrs) == 0:
return(-1)
else:
list_lens = []
for i in matching_charrs:
list_lens.append(smallestSubstring(i))
return max(list_lens)
print(smallestSubstring('azABaabza'))
print(smallestSubstring('dAcZCbaBz'))
print(smallestSubstring('TacoCat'))
print(smallestSubstring('Tt'))
print(smallestSubstring('T'))
print(smallestSubstring('TaCc'))

RGB to HSL conversion

I'm creating a Color Picker tool and for the HSL slider, I need to be able to convert RGB to HSL. When I searched SO for a way to do the conversion, I found this question HSL to RGB color conversion.
While it provides a function to do conversion from RGB to HSL, I see no explanation to what's really going on in the calculation. To understand it better, I've read the HSL and HSV on Wikipedia.
Later, I've rewritten the function from the "HSL to RGB color conversion" using the calculations from the "HSL and HSV" page.
I'm stuck at the calculation of hue if the R is the max value. See the calculation from the "HSL and HSV" page:
This is from another wiki page that's in Dutch:
and this is from the answers to "HSL to RGB color conversion":
case r: h = (g - b) / d + (g < b ? 6 : 0); break; // d = max-min = c
I've tested all three with a few RGB values and they seem to produce similar (if not exact) results. What I'm wondering is are they performing the same thing? Will get I different results for some specific RGB values? Which one should I be using?
hue = (g - b) / c; // dutch wiki
hue = ((g - b) / c) % 6; // eng wiki
hue = (g - b) / c + (g < b ? 6 : 0); // SO answer
function rgb2hsl(r, g, b) {
// see https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
// convert r,g,b [0,255] range to [0,1]
r = r / 255,
g = g / 255,
b = b / 255;
// get the min and max of r,g,b
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
// lightness is the average of the largest and smallest color components
var lum = (max + min) / 2;
var hue;
var sat;
if (max == min) { // no saturation
hue = 0;
sat = 0;
} else {
var c = max - min; // chroma
// saturation is simply the chroma scaled to fill
// the interval [0, 1] for every combination of hue and lightness
sat = c / (1 - Math.abs(2 * lum - 1));
switch(max) {
case r:
// hue = (g - b) / c;
// hue = ((g - b) / c) % 6;
// hue = (g - b) / c + (g < b ? 6 : 0);
break;
case g:
hue = (b - r) / c + 2;
break;
case b:
hue = (r - g) / c + 4;
break;
}
}
hue = Math.round(hue * 60); // °
sat = Math.round(sat * 100); // %
lum = Math.round(lum * 100); // %
return [hue, sat, lum];
}
I've been reading several wiki pages and checking different calculations, and creating visualizations of RGB cube projection onto a hexagon. And I'd like to post my understanding of this conversion. Since I find this conversion (representations of color models using geometric shapes) interesting, I'll try to be as thorough as I can be. First, let's start with RGB.
RGB
Well, this doesn't really need much explanation. In its simplest form, you have 3 values, R, G, and B in the range of [0,255]. For example, 51,153,204. We can represent it using a bar graph:
RGB Cube
We can also represent a color in a 3D space. We have three values R, G, B that corresponds to X, Y, and Z. All three values are in the [0,255] range, which results in a cube. But before creating the RGB cube, let's work on 2D space first. Two combinations of R,G,B gives us: RG, RB, GB. If we were to graph these on a plane, we'd get the following:
These are the first three sides of the RGB cube. If we place them on a 3D space, it results in a half cube:
If you check the above graph, by mixing two colors, we get a new color at (255,255), and these are Yellow, Magenta, and Cyan. Again, two combinations of these gives us: YM, YC, and MC. These are the missing sides of the cube. Once we add them, we get a complete cube:
And the position of 51,153,204 in this cube:
Projection of RGB Cube onto a hexagon
Now that we have the RGB Cube, let's project it onto a hexagon. First, we tilt the cube by 45° on the x, and then 35.264° on the y. After the second tilt, black corner is at the bottom and the white corner is at the top, and they both pass through the z axis.
As you can see, we get the hexagon look we want with the correct hue order when we look at the cube from the top. But we need to project this onto a real hexagon. What we do is draw a hexagon that is in the same size with the cube top view. All the corners of the hexagon corresponds to the corners of the cube and the colors, and the top corner of the cube that is white, is projected onto the center of the hexagon. Black is omitted. And if we map every color onto the hexagon, we get the look at right.
And the position of 51,153,204 on the hexagon would be:
Calculating the Hue
Before we make the calculation, let's define what hue is.
Hue is roughly the angle of the vector to a point in the projection, with red at 0°.
... hue is how far around that hexagon’s edge the point lies.
This is the calculation from the HSL and HSV wiki page. We'll be using it in this explanation.
Examine the hexagon and the position of 51,153,204 on it.
First, we scale the R, G, B values to fill the [0,1] interval.
R = R / 255 R = 51 / 255 = 0.2
G = G / 255 G = 153 / 255 = 0.6
B = B / 255 B = 204 / 255 = 0.8
Next, find the max and min values of R, G, B
M = max(R, G, B) M = max(0.2, 0.6, 0.8) = 0.8
m = min(R, G, B) m = min(0.2, 0.6, 0.8) = 0.2
Then, calculate C (chroma). Chroma is defined as:
... chroma is roughly the distance of the point from the origin.
Chroma is the relative size of the hexagon passing through a point ...
C = OP / OP'
C = M - m
C = 0.8- 0.2 = 0.6
Now, we have the R, G, B, and C values. If we check the conditions, if M = B returns true for 51,153,204. So, we'll be using H'= (R - G) / C + 4.
Let's check the hexagon again. (R - G) / C gives us the length of BP segment.
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
We'll place this segment on the inner hexagon. Starting point of the hexagon is R (red) at 0°. If the segment length is positive, it should be on RY, if negative, it should be on RM. In this case, it is negative -0.6666666666666666, and is on the RM edge.
Next, we need to shift the position of the segment, or rather P₁ towars the B (because M = B). Blue is at 240°. Hexagon has 6 sides. Each side corresponds to 60°. 240 / 60 = 4. We need to shift (increment) the P₁ by 4 (which is 240°). After the shift, P₁ will be at P and we'll get the length of RYGCP.
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
RYGCP = segment + 4 = 3.3333333333333335
Circumference of the hexagon is 6 which corresponds to 360°. 53,151,204's distance to 0° is 3.3333333333333335. If we multiply 3.3333333333333335 by 60, we'll get its position in degrees.
H' = 3.3333333333333335
H = H' * 60 = 200°
In the case of if M = R, since we place one end of the segment at R (0°), we don't need to shift the segment to R if the segment length is positive. The position of P₁ will be positive. But if the segment length is negative, we need to shift it by 6, because negative value means that the angular position is greater than 180° and we need to do a full rotation.
So, neither the Dutch wiki solution hue = (g - b) / c; nor the Eng wiki solution hue = ((g - b) / c) % 6; will work for negative segment length. Only the SO answer hue = (g - b) / c + (g < b ? 6 : 0); works for both negative and positive values.
JSFiddle: Test all three methods for rgb(255,71,99)
JSFiddle: Find a color's position in RGB Cube and hue hexagon visually
Working hue calculation:
console.log(rgb2hue(51,153,204));
console.log(rgb2hue(255,71,99));
console.log(rgb2hue(255,0,0));
console.log(rgb2hue(255,128,0));
console.log(rgb2hue(124,252,0));
function rgb2hue(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var c = max - min;
var hue;
if (c == 0) {
hue = 0;
} else {
switch(max) {
case r:
var segment = (g - b) / c;
var shift = 0 / 60; // R° / (360° / hex sides)
if (segment < 0) { // hue > 180, full rotation
shift = 360 / 60; // R° / (360° / hex sides)
}
hue = segment + shift;
break;
case g:
var segment = (b - r) / c;
var shift = 120 / 60; // G° / (360° / hex sides)
hue = segment + shift;
break;
case b:
var segment = (r - g) / c;
var shift = 240 / 60; // B° / (360° / hex sides)
hue = segment + shift;
break;
}
}
return hue * 60; // hue is in [0,6], scale it up
}
This page provides a function for conversion between color spaces, including RGB to HSL.
function RGBToHSL(r,g,b) {
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r,g,b),
cmax = Math.max(r,g,b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
// Calculate hue
// No difference
if (delta == 0)
h = 0;
// Red is max
else if (cmax == r)
h = ((g - b) / delta) % 6;
// Green is max
else if (cmax == g)
h = (b - r) / delta + 2;
// Blue is max
else
h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0)
h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
return "hsl(" + h + "," + s + "%," + l + "%)";
}
Hue in HSL is like an angle in a circle. Relevant values for such angle reside in the 0..360 interval. However, negative values might come out of the calculation. And that's why those three formulas are different. They do the same in the end, they just handle differently the values outside the 0..360 interval. Or, to be precise, the 0..6 interval which is then eventually multiplied by 60 to 0..360
hue = (g - b) / c; // dutch wiki
does nothing with negative values and presumes the subsequent code can handle negative H values.
hue = ((g - b) / c) % 6; // eng wiki uses the % operator to fit the values inside the 0..6 interval
hue = (g - b) / c + (g < b ? 6 : 0); // SO answer takes care of negative values by adding +6 to make them positive
You see that these are just cosmetic differences. Either the second or the third formula will work fine for you.
Continuing from my comment, the English version looks correct, but I'm not sure what's happening in the Dutch version as I don't understand the WIKI page.
Here is an ES6 version that I made from the English WIKI page, along with some sample data that appear to match the WIKI examples (give or take Javascript's numeric accuracy). Hopefully it may be of use while creating your own function.
// see: https://en.wikipedia.org/wiki/RGB_color_model
// see: https://en.wikipedia.org/wiki/HSL_and_HSV
// expects R, G, B, Cmax and chroma to be in number interval [0, 1]
// returns undefined if chroma is 0, or a number interval [0, 360] degrees
function hue(R, G, B, Cmax, chroma) {
let H;
if (chroma === 0) {
return H;
}
if (Cmax === R) {
H = ((G - B) / chroma) % 6;
} else if (Cmax === G) {
H = ((B - R) / chroma) + 2;
} else if (Cmax === B) {
H = ((R - G) / chroma) + 4;
}
H *= 60;
return H < 0 ? H + 360 : H;
}
// returns the average of the supplied number arguments
function average(...theArgs) {
return theArgs.length ? theArgs.reduce((p, c) => p + c, 0) / theArgs.length : 0;
}
// expects R, G, B, Cmin, Cmax and chroma to be in number interval [0, 1]
// type is by default 'bi-hexcone' equation
// set 'luma601' or 'luma709' for alternatives
// see: https://en.wikipedia.org/wiki/Luma_(video)
// returns a number interval [0, 1]
function lightness(R, G, B, Cmin, Cmax, type = 'bi-hexcone') {
if (type === 'luma601') {
return (0.299 * R) + (0.587 * G) + (0.114 * B);
}
if (type === 'luma709') {
return (0.2126 * R) + (0.7152 * G) + (0.0772 * B);
}
return average(Cmin, Cmax);
}
// expects L and chroma to be in number interval [0, 1]
// returns a number interval [0, 1]
function saturation(L, chroma) {
return chroma === 0 ? 0 : chroma / (1 - Math.abs(2 * L - 1));
}
// returns the value to a fixed number of digits
function toFixed(value, digits) {
return Number.isFinite(value) && Number.isFinite(digits) ? value.toFixed(digits) : value;
}
// expects R, G, and B to be in number interval [0, 1]
// returns a Map of H, S and L in the appropriate interval and digits
function RGB2HSL(R, G, B, fixed = true) {
const Cmin = Math.min(R, G, B);
const Cmax = Math.max(R, G, B);
const chroma = Cmax - Cmin;
// default 'bi-hexcone' equation
const L = lightness(R, G, B, Cmin, Cmax);
// H in degrees interval [0, 360]
// L and S in interval [0, 1]
return new Map([
['H', toFixed(hue(R, G, B, Cmax, chroma), fixed && 1)],
['S', toFixed(saturation(L, chroma), fixed && 3)],
['L', toFixed(L, fixed && 3)]
]);
}
// expects value to be number in interval [0, 255]
// returns normalised value as a number interval [0, 1]
function colourRange(value) {
return value / 255;
};
// expects R, G, and B to be in number interval [0, 255]
function RGBdec2HSL(R, G, B) {
return RGB2HSL(colourRange(R), colourRange(G), colourRange(B));
}
// converts a hexidecimal string into a decimal number
function hex2dec(value) {
return parseInt(value, 16);
}
// slices a string into an array of paired characters
function pairSlicer(value) {
return value.match(/../g);
}
// prepend '0's to the start of a string and make specific length
function prePad(value, count) {
return ('0'.repeat(count) + value).slice(-count);
}
// format hex pair string from value
function hexPair(value) {
return hex2dec(prePad(value, 2));
}
// expects R, G, and B to be hex string in interval ['00', 'FF']
// without a leading '#' character
function RGBhex2HSL(R, G, B) {
return RGBdec2HSL(hexPair(R), hexPair(G), hexPair(B));
}
// expects RGB to be a hex string in interval ['000000', 'FFFFFF']
// with or without a leading '#' character
function RGBstr2HSL(RGB) {
const hex = prePad(RGB.charAt(0) === '#' ? RGB.slice(1) : RGB, 6);
return RGBhex2HSL(...pairSlicer(hex).slice(0, 3));
}
// expects value to be a Map object
function logIt(value) {
console.log(value);
document.getElementById('out').textContent += JSON.stringify([...value]) + '\n';
};
logIt(RGBstr2HSL('000000'));
logIt(RGBstr2HSL('#808080'));
logIt(RGB2HSL(0, 0, 0));
logIt(RGB2HSL(1, 1, 1));
logIt(RGBdec2HSL(0, 0, 0));
logIt(RGBdec2HSL(255, 255, 254));
logIt(RGBhex2HSL('BF', 'BF', '00'));
logIt(RGBstr2HSL('008000'));
logIt(RGBstr2HSL('80FFFF'));
logIt(RGBstr2HSL('8080FF'));
logIt(RGBstr2HSL('BF40BF'));
logIt(RGBstr2HSL('A0A424'));
logIt(RGBstr2HSL('411BEA'));
logIt(RGBstr2HSL('1EAC41'));
logIt(RGBstr2HSL('F0C80E'));
logIt(RGBstr2HSL('B430E5'));
logIt(RGBstr2HSL('ED7651'));
logIt(RGBstr2HSL('FEF888'));
logIt(RGBstr2HSL('19CB97'));
logIt(RGBstr2HSL('362698'));
logIt(RGBstr2HSL('7E7EB8'));
<pre id="out"></pre>

cvIntegral for determining sum of 4X4 blocks

I'd like to sum my 4X4 block. Suppose I have an image and will divide it into 4X4 blocks. Then afterward I'd like to determine the sum of each block using cvIntegral. How can I cope this?
Here is my basic program in order to calculate integral image value of whole image:
float s = 0.0f;
//Read in the image
IplImage* hImage = cvLoadImage("bayer-image.jpg",0);
UINT width = hImage->width; UINT height = hImage->height;
CvMat* sum = cvCreateMat(height + 1, width + 1, CV_32SC1);
CvMat* sqsum = cvCreateMat(height + 1, width + 1, CV_64FC1);
cvIntegral(hImage, sum, sqsum);
cvReleaseImage(&hImage);
cvReleaseMat(&sum);
cvReleaseMat(&sqsum);
What should I do next?
Really thanks in advance.
Check this out
http://en.wikipedia.org/wiki/Summed_area_table
As an example, the block defined by the corners (1, 1) and (4, 4) has the area
a1 = integral(0,0)+integral(4,4)-integral(4,0)-integral(0,4);

Image manipulation with Mathematica

I've created this theme after my previous post. I can't run the following code (written by #belisarius):
a = Image["path/file.png"]
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}, {0}}, {1, 1, 1}];
f[image_, angleMult_] := ImageForwardTransformation[image, (
fi = ArcTan[Abs[#[[2]]/(#[[1]] - .5)]];
fi1 = angleMult fi (#[[1]]^2 + #[[2]]^2)/2;
{(1/2 - Sin[fi1] #[[2]] - Cos[fi1]/2 +
Cos[fi1] #[[1]]), -Sin[fi1]/2 + Sin[fi1] #[[1]] +
Cos[fi1] #[[2]]}) &]
t = Table[f[b, x], {x, 0, .2, .02}];
t1 = Reverse#t;
Export["anim.gif", Join[t, t1], "DisplayDurations" -> .15];
Import["anim.gif", "Animation"]
Here is a list of errors:
ArrayPad::depth: Padding amount {{40,0},{40},{0}} should specify padding in no more than the number of dimensions in array {{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.996078,0.984314,<<142>>},<<49>>,<<145>>}. >>
Image::imgarray: The specified argument ArrayPad[{{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.996078,0.984314,<<142>>},<<49>>,<<145>>},{{40,0},{40},{0}},{1,1,1}] should be an array of rank 2 or 3 with machine-sized numbers. >>
ImageForwardTransformation::imginv: Expecting an image or graphics instead of Image[ArrayPad[{{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.996078,0.984314,<<142>>},<<49>>,<<145>>},{<<1>>},{1,1,1}]]. >>
General::stop: Further output of ImageForwardTransformation::imginv will be suppressed during this calculation. >>
Rasterize::bigraster: Not enough memory available to rasterize ImageForwardTransformation expression. >>
General::stop: Further output of Rasterize::bigraster will be suppressed during this calculation. >>
I'm using Mathematica 8 under Linux.
I think I got it.
The code above is for color images (3 channels) and it seems you are trying to run it over a B&W image (1 channel).
Either use a color image or replace the second line by:
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}}, 1];
Here is the result for your image using the above replacement as:
a = Binarize[Image["path/file.png"]]
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}}, 1];

Color scaling function

I am trying to visualize some values on a form. They range from 0 to 200 and I would like the ones around 0 be green and turn bright red as they go to 200.
Basically the function should return color based on the value inputted. Any ideas ?
Basically, the general method for smooth transition between two values is the following function:
function transition(value, maximum, start_point, end_point):
return start_point + (end_point - start_point)*value/maximum
That given, you define a function that does the transition for triplets (RGB, HSV etc).
function transition3(value, maximum, (s1, s2, s3), (e1, e2, e3)):
r1= transition(value, maximum, s1, e1)
r2= transition(value, maximum, s2, e2)
r3= transition(value, maximum, s3, e3)
return (r1, r2, r3)
Assuming you have RGB colours for the s and e triplets, you can use the transition3 function as-is. However, going through the HSV colour space produces more "natural" transitions. So, given the conversion functions (stolen shamelessly from the Python colorsys module and converted to pseudocode :):
function rgb_to_hsv(r, g, b):
maxc= max(r, g, b)
minc= min(r, g, b)
v= maxc
if minc == maxc then return (0, 0, v)
diff= maxc - minc
s= diff / maxc
rc= (maxc - r) / diff
gc= (maxc - g) / diff
bc= (maxc - b) / diff
if r == maxc then
h= bc - gc
else if g == maxc then
h= 2.0 + rc - bc
else
h = 4.0 + gc - rc
h = (h / 6.0) % 1.0 //comment: this calculates only the fractional part of h/6
return (h, s, v)
function hsv_to_rgb(h, s, v):
if s == 0.0 then return (v, v, v)
i= int(floor(h*6.0)) //comment: floor() should drop the fractional part
f= (h*6.0) - i
p= v*(1.0 - s)
q= v*(1.0 - s*f)
t= v*(1.0 - s*(1.0 - f))
if i mod 6 == 0 then return v, t, p
if i == 1 then return q, v, p
if i == 2 then return p, v, t
if i == 3 then return p, q, v
if i == 4 then return t, p, v
if i == 5 then return v, p, q
//comment: 0 <= i <= 6, so we never come here
, you can have code as following:
start_triplet= rgb_to_hsv(0, 255, 0) //comment: green converted to HSV
end_triplet= rgb_to_hsv(255, 0, 0) //comment: accordingly for red
maximum= 200
… //comment: value is defined somewhere here
rgb_triplet_to_display= hsv_to_rgb(transition3(value, maximum, start_triplet, end_triplet))
You don't say in what environment you're doing this. If you can work with HSV colors, this would be pretty easy to do by setting S = 100 and V = 100, and determining H by:
H = 0.4 * value + 120
Converting from HSV to RGB is also reasonably easy.
[EDIT] Note: in contrast to some other proposed solutions, this will change color green -> yellow -> orange -> red.
red = (float)val / 200 * 255;
green = (float)(200 - val) / 200 * 255;
blue = 0;
return red << 16 + green << 8 + blue;
Pick a green that you like (RGB1 = #00FF00, e.g.) and a Red that you like (RGB2 = #FF0000, e.g.) and then calculate the color like this
R = R1 * (200-i)/200 + R2 * i/200
G = G1 * (200-i)/200 + G2 * i/200
B = B1 * (200-i)/200 + B2 * i/200
For best controllable and accurate effect, you should use the HSV color space. With HSV, you can easily scale Hue, Saturation and/or Brightness seperate from each other. Then, you do the transformation to RGB.
extending upon #tzot's code... you can also set up a mid-point in between the start and end points, which can be useful if you want a "transition color"!
//comment: s = start_triplet, m = mid_triplet, e = end_triplet
function transition3midpoint = (value, maximum, s, m, e):
mid = maximum / 2
if value < mid
return transition3(value, mid, s, m)
else
return transition3(value - mid, mid, m, e)
Looking through this wikipedia article I personally would pick a path through a color space, and map the values onto that path.
But that's a straight function. I think you might be better suited to a javascript color chooser you can find with a quick color that will give you the Hex, and you can store the Hex.
If you use linear ramps for Red and Green values as Peter Parker suggested, the color for value 100 will basically be puke green (127, 127, 0). You ideally want it to be a bright orange or yellow at that midpoint. For that, you can use:
Red = max(value / 100, 1) * 255
Green = (1 - max(value / 100, 1)) * 255
Blue = 0

Resources