Fastest approximative methods to convert YUV to RGBA? - c

I am looking for a fastest method to convert one YUV array into RGBA array. For example, given a YCbYCr array, which is a sequence of bytes:
YCbYCr = Luma0, Cb0, Luma1, Cr0, Luma2, ...
where 8-bit blue- and 8-bit red- difference chroma components are sampled with period 2, but 8-bit luma is sampled with period 1. For example:
image pixel (0,0) has luma0, Cr0 red-difference chroma, Cb0 blue-difference chroma
image pixel (0,1) has luma1, Cr0 red-difference chroma, Cb0 blue-difference chroma
image pixel (0,2) has luma2, Cr1 red-difference chroma, Cb1 blue-difference chroma
image pixel (0,3) has luma3, Cr1 red-difference chroma, Cb1 blue-difference chroma
etc.
RGBA array should be produced which is:
RGBA = R0, G0, B0, A0, R1, G1, ...
where all elements are unsigned chars and all bits of each A# are zero.
Luma component in YCbYCr is 0..255 unsigned char, Cb and Cr are -127..+126 signed chars. There is a standard approach --- matrix multiplication, but it's very slow for real time apps and it operates with floating point numbers. I am looking for a fast approximate numerical method.

The biggest single computational saving you're likely to get is simply by doing the computation in fixed-point rather than floating-point. It's likely to be an order of magnitude faster (at a guess).
You can also take advantage of the redundancy in the subsampled chroma contributions. Given that the full matrix multiply is of the form:
R a b c Y
G = d e f . Cb
B g h i Cr
You can compute the chroma partial sum half as often:
R' b c
G' = e f . Cb
B' h i Cr
and then simply add it to the luma contribution at the full output rate:
R R' a
G = G' + d . Y
B B' g

Related

Calculating Displacement based on the compass direction

I need some help with programming the calculation of displacement. Given the distance the object has moved in the XY plane, and the yaw (heading) of the object, I'd like to calculate the displacement of the object. For example, the object moved 5m North and 2m East.
The data I have is the distance it travels in the XY plane (X distance and Y distance) and the heading of the device which is determined by the direction of X. I know how to calculate it on paper but I am having trouble to program it.
I've attached two examples that shows how I obtained the calculations. The black dot is the displacement of the object. In the 1st example, the X-distance travelled is 3 meters while the Y-distance is 4 meters and the heading of the X-axis is 70°. After calculating, I managed to get that it has travelled 2.733m South and 4.187m East. In example 2, it travel, the X-distance is -5m and the Y-distance is -12m, the heading is 160°. I calculated that the object travels 8.80m North and 9.566m East.
Example 1
Example 2
Assume you have your XY pane rotated by some angle Zp and have a 2D movement vector within that pane, let's say its direction rotated by Zv – what is total rotation of the vector, relative to the global orientation? Zp + Zv...
So all you need to do is applying the rotation Zp to the movement vector within XY-pane, i. e. apply a rotation matrix to the vector. This matrix for a rotation by z looks like:
cos(z) -sin(z)
sin(z) cos(z)
With our data above:
north = cos(Zp) * x - sin(Zp) * y
east = sin(Zp) * x + cos(Zp) * y
which gives, with your first sample data applied:
north = cos(70°) * 3 - sin(70°) * 4 ~ -2.7327
east = sin(70°) * 3 + cos(70°) * 4 ~ 4.1872
north = cos(160°) * -5 - sin(160°) * -12 ~ 8.8027
east = sin(160°) * -5 + cos(160°) * -12 ~ 9.5662
Corresponding pretty much to the values you calculated (note: negative movement to north is positive movement towards south...).
What you are doing is a conversion from polar to Cartesian coordinates. https://en.wikipedia.org/wiki/Polar_coordinate_system#Converting_between_polar_and_Cartesian_coordinates
If your Cartesian coordinates are not aligned to the polar axis, just compensate by adding the rotation angle to the polar argument.

How to use centre difference method to make the equation semi descrete in terms of time

enter image description here
where u : Ω → R
n is the displacement vector field, C is the stiffness tensor of
the elastic medium, (u) is the linearized strain tensor of displacement, ρ is the
mass density, and f is an external body force.

dependancy between 3 variables in real time embedded c code

hello everyone i performed rgb to grayscale image transformation with fixed point arithmetic on zynq7000 microcontroller and the opperations was faster,now i want to have a threshold of time and perform fixed point arithmetic(reduced precision) or floating point arithmetic(high precision) based on time that i have left.
for example:
if i perform rgb to grayscale with high precision it takes for the cpu 10 seconds.
if i perform rgb to grayscale with low precision it takes for the cpu 5 seconds.
but if the time that i can spend on the task is 7.5 seconds how i will say that i want half of the image to be performed with high precision and the other half with low precition?
i am seeking for a formula that will see my time threshold and will calculate how many values of the image i need to transform to grayscale with high precisionand how many values of the image with low precsion based on that threshold of time!thnx
The formula follows from the equation
h 10 + (1 - h) 5 = 7.5
where h is the fraction at high speed (here 50%).
Being
nH -> number of high precision images
nL -> number of low precision images
uH -> time to process a high precision image
uL -> time to process a low precision image
T -> available time
N -> images to process
To process all the images in less than T:
nH * uH + nL * uL < T
Where high precision plus low precision is equal to all the images to process:
nH + nL = N
Substituting:
nH < (T- (uL * N))/(uH - uL);
nL = N - nH;

Lossless RGB to Y'CbCr transformation

I am trying to losslessly compress an image, and in order to take advantage of regularities, I want to convert the image from RGB to Y'CbCr. (The exact details of what I mean by RGB and Y'CbCr are not important here; the RGB data consists of three bytes, and I have three bytes to store the result in.)
The conversion process itself is pretty straightforward, but there is one problem: although the transformation is mathematically invertible, in practice there will be rounding errors. Of course these errors are small and virtually unnoticeable, but it does mean that the process is not lossless any more.
My question is: does a transformation exist, that converts three eight-bit integers (representing red, green and blue components) into three other eight-bit integers (representing a colour space similar to Y'CbCr, where two components change only slightly with respect to position, or at least less than in an RGB colour space), and that can be inverted without loss of information?
YCoCg24
Here is one color transformation I call "YCoCg24" that that converts three eight-bit integers (representing red, green and blue components) into three other eight-bit (signed) integers (representing a colour space similar to Y'CbCr), and is bijective (and therefore can be inversed without loss of information):
G R B Y Cg Co
| | | | | |
| |->-(-1)->(+) (+)<-(-/2)<-| |
| | | | | |
| (+)<-(/2)-<-| |->-(+1)->(+) |
| | | | | |
|->-(-1)->(+) | | (+)<-(-/2)<-|
| | | | | |
(+)<-(/2)-<-| | | |->-(+1)->(+)
| | | | | |
Y Cg Co G R B
forward transformation reverse transformation
or in pseudocode:
function forward_lift( x, y ):
signed int8 diff = ( y - x ) mod 0x100
average = ( x + ( diff >> 1 ) ) mod 0x100
return ( average, diff )
function reverse_lift( average, signed int8 diff ):
x = ( average - ( diff >> 1 ) ) mod 0x100
y = ( x + diff ) mod 0x100
return ( x, y )
function RGB_to_YCoCg24( red, green, blue ):
(temp, Co) = forward_lift( red, blue )
(Y, Cg) = forward_lift( green, temp )
return( Y, Cg, Co)
function YCoCg24_to_RGB( Y, Cg, Co ):
(green, temp) = reverse_lift( Y, Cg )
(red, blue) = reverse_lift( temp, Co)
return( red, green, blue )
Some example colors:
color R G B Y CoCg24
white 0xFFFFFF 0xFF0000
light grey 0xEFEFEF 0xEF0000
dark grey 0x111111 0x110000
black 0x000000 0x000000
red 0xFF0000 0xFF01FF
lime 0x00FF00 0xFF0001
blue 0x0000FF 0xFFFFFF
G, R-G, B-G color space
Another color transformation that converts three eight-bit integers into three other eight-bit integers.
function RGB_to_GCbCr( red, green, blue ):
Cb = (blue - green) mod 0x100
Cr = (red - green) mod 0x100
return( green, Cb, Cr)
function GCbCr_to_RGB( Y, Cg, Co ):
blue = (Cb + green) mod 0x100
red = (Cr + green) mod 0x100
return( red, green, blue )
Some example colors:
color R G B G CbCr
white 0xFFFFFF 0xFF0000
light grey 0xEFEFEF 0xEF0000
dark grey 0x111111 0x110000
black 0x000000 0x000000
comments
There seem to be quite a few lossless color space transforms.
Several lossless color space transforms are mentioned in Henrique S. Malvar, et al. "Lifting-based reversible color transformations for image compression";
there's the lossless colorspace transformation in JPEG XR;
the original reversible color transform (ORCT) used in several "lossless JPEG" proposals;
G, R-G, B-G color space;
etc.
Malvar et al seem pretty excited about the 26-bit YCoCg-R representation of a 24-bit RGB pixel.
However, nearly all of them require more than 24 bits to store the transformed pixel color.
The "lifting" technique I use in YCoCg24 is similar to the one in Malvar et al and to the lossless colorspace transformation in JPEG XR.
Because addition is reversible (and addition modulo 0x100 is bijective), any transform from (a,b) to (x,y) that can be produced by the following Feistel network is reversible and bijective:
a b
| |
|->-F->-(+)
| |
(+)-<-G-<-|
| |
x y
where (+) indicates 8-bit addition (modulo 0x100), a b x y are all 8-bit values, and F and G indicate any arbitrary function.
details
Why do you only have 3 bytes to store the result in?
That sounds like a counter-productive premature optimization.
If your goal is to losslessly compress an image into as small a compressed file as possible in a reasonable amount of time, then the size of the intermediate stages is irrelevant.
It may even be counter-productive --
a "larger" intermediate representation (such as Reversible Colour Transform or the 26-bit YCoCg-R) may result in smaller final compressed file size than a "smaller" intermediate representation (such as RGB or YCoCg24).
EDIT:
Oopsies.
Either one of "(x) mod 0x100" or "(x) & 0xff" give exactly the same results --
the results I wanted.
But somehow I jumbled them together to produce something that wouldn't work.
I did find one such solution, used by JPEG 2000. It is called a Reversible Colour Transform (RCT), and it is described at Wikipedia as well as the JPEG site (though the rounding methods are not consistent). The results are not as good as with the irreversible colour transform, however.
I also found a better method described in the paper Improved Reversible Integer-to-integer Color Transforms by Soo-Chang Pei and Jian-Jiun Ding. However, the methods described in that paper, and the method used by JPEG 2000, require extra bits to store the result. This means that the transformed values do not fit in 24 bits any more.

inverse a number

As we go up the musical scale the note frequency increases;
#define A4 440 // These are the frequencies of the notes in herts
#define AS4 466
#define B4 494
#define C5 523
#define CS5 554
#define D5 587
I am generating the tones mechanically, I tell a step motor to step, delay, step, delay etc etc very quickly.
The longer the delay between steps, the lower the note. Is there some smart maths I could use to inverse the frequencies so as I climb up the scale the numbers come out lower and lower?
This way I could use the frequencies to help calculate the correct delay to generate a note.
So what you're saying is you want the numbers to represent the time between steps rather than a frequency?
440 Hz means 440 cycles/second. What you want is the number of seconds/cycle (i.e. time between steps). That's just 1 / <frequency>. That means all you have to do is define your values as 1/440, 1/466, etc. (or, if you want the values to be milliseconds, 1000/440, 1000/466 etc.)
If that is too fast (or doesn't match the actual notes), you can multiply each value by a scale factor and the relationships between the audible tones should remain the same.
For example, lets say that you empirically discover that for your machine to make an "A4" tone, the delay between steps is 10 milliseconds. To figure out the scale factor, solve for x:
x / 440 = 10
x = 4400
So define scale = 4400, and define each of your notes as scale / 440, scale / 466 etc.
Yes, that sounds possible! Let's have a look... (some of this you will know but I'll post it anyway)
In what's called an equal tempered scale, you can calculate Hertz values by multiplying by the twelfth root of two for every semitone you go up. There are 12 semitones in a whole octave, and multiplying by this value twelve times doubles the frequency, which raises the tone by an octave.
So, if you wanted to calculate descending semitone frequencies from e.g. A 440, you can calculate double x = pow(2.0, 1.0/12.0) (assuming C), and then repeatedly divide by that value (remember to do the divisions as doubles not ints :) ) and then you'll get your descending scale.
Aside: If you want to do a major scale rather than a chromatic (semitone) scale, this is the pattern of tones and semitones to use: (e.g. in C Major - using T for Tone, S for semitone)
C [T] D [T] E [S] F [T] G [T] A [T] B [S] C

Resources