Go Down

Topic: translating shifts from Java (Processing) to C++ (arduino) (Read 2335 times) previous topic - next topic

robvoi

Jan 07, 2013, 02:50 pm Last Edit: Jan 07, 2013, 03:07 pm by robvoi Reason: 1
Hi,

I'm trying to translate/reuse some processing code which uses shifts. (for translating 2 byte RGB to 1byte grayscale)  - I am stuck.
I didn't yet understand the difference between the shift operations.

Maybe someone could enlight me and help with the translation.

Processing code:
Code: [Select]
//loc is defined and (I think) doesn't matter too much for the translation
int msb = packedbuf[2*loc] & 0xff;
int lsb = packedbuf[2*loc+1] & 0xff;
int r = (lsb >>> 3);
int g = ((lsb & 0x7) << 3);
g |= (msb >>> 5);
int b = (msb & 0x1f);

r = (r << 3)|(r >>> 2);
g = (g << 2)|(g >>> 4);
b = (b << 3)|(b >>> 2);


My arduino code, which is wrong as I just removed everything what didn't seemed to be c++ bit shift related:
Code: [Select]
//l is defined and is used instead of loc from the processing code, variables are defined earlier in the code
msb = 2*l;
lsb = 2*l+1;
           
r = (lsb >> 3);
g = (lsb << 3);
g |= (msb >> 5);
b = (msb);

r = (r << 3)|(r >> 2);
g = (g << 2)|(g >> 4);
b = (b << 3)|(b >> 2);


I am going back to wikipedia and google trying to understand the java shift operations ...

Thanks
Robert


robvoi

#1
Jan 07, 2013, 04:49 pm Last Edit: Jan 07, 2013, 04:59 pm by robvoi Reason: 1
Maybe there some explanation on what has to be achived by the code helps:

I have two bytes as RGB value: RRRRRGGG GGGBBBBB. At least that's what I expect to get from the camera. (If I would fully understand what the processing code does, I would be sure :-) )

I want to seperate them into three integers.
int 1= RRRRR
int 2= GGGGG
int 3= BBBBB

I thought it would maybe possible like this:

Code: [Select]
//buf contains the the byte stream
for (unsigned int l= 0; l < TWI_BUFFER_LENGTH/2; ++l){
r = (buf[l*2] >> 16) & 0xff ;     //bitwise shifting
g = (buf[l*2] >> 8) & 0xff ;
b = buf[l*2] & 0xff ;
//here calculate grayscale and write to grayscale img buffer
}


But it only gives me a black picture.

Robert

PeterH


Maybe there some explanation on what has to be achived by the code helps:

I have two bytes as RGB value: RRRRRGGG GGGBBBBB. At least that's what I expect to get from the camera. (If I would fully understand what the processing code does, I would be sure :-) )


I want to seperate them into three integers.
int 1= RRRRR
int 2= GGGGG
int 3= BBBBB


Yes, that is what the Processing code seems to do. The >>> operator is the Java unsigned bit shift operator - when you do an unsigned bit shift, the bits shifted into the most significant position are zero. The code seems to extract three 5-bit values from the 16 bits. The code to extract the g (green) channel is a bit more complicated that the other channels because it has to take three bits from one byte and two bits from the other.
I only provide help via the forum - please do not contact me for private consultancy.

robtillaart


the  A >>> B  pattern translates to a  (A >> B) & C  pattern  where C is a mask with the lower (8-B) bits set to 1

leaves:
Code: [Select]

int msb = packedbuf[2*loc] & 0xff;
int lsb = packedbuf[2*loc+1] & 0xff;

int r = (lsb >> 3) & 0x1F;
int g = ((lsb & 0x07) << 3) | ((msb >> 5) & 0x07) ;
int b = (msb & 0x1f);
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robvoi

This worked. And thanks a lot for the explanation.
As you now finaly also wrote the convertion function for me I now get a grayscale picture from the cam.

I have to tune it as it is too dark, even with the most correct translation function you provided (have to figure out the bit shift part, but also without the calculaiton for the whole picture only takes 0.2 seconds).

I learned a lot from the information you provided. In retrospect all you explained (beside the bit shifting part) is clear and I should have been able to do it myself. But that how it is when you learn something.

Thanks
Robert

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

Quote
have to tune it as it is too dark, even with the most correct translation function you provided

the reason is that the values of R, G, and B are not 0..255 which is assumed in the gray formulas.

Code: [Select]

int r = (lsb >> 3) & 0x1F;
int g = ((lsb & 0x07) << 3) | ((msb >> 5) & 0x07) ;
int b = (msb & 0x1f);

r = r << 3;  // as r is only 5 bit we must shift it to the left 3 positions
g = g << 2; // g has 6 bits
b = b << 3;  // ....

and now gray = (r + g + b )/3; or the more sophisticated formulas.

// and for some fun you could add some noise which will have a smoothing effect.

r = r << 3 + random(8); // fills up the 3 zero bits with some noise
g = g << 2 + random(4);
b = b << 3 + random(8);



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

@Robert
1) if this work is done you should post a link to the HarcoCam group so others may use it to.
2) the work is only really done if you make a separate command for downloading grayscale pictures that exists besides the rgb pictures.
    we now patched the dl command maybe create a dg (download gray) command?


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robvoi

#8
Jan 08, 2013, 09:00 am Last Edit: Jan 08, 2013, 01:47 pm by robvoi Reason: 1
Hi robtillaart,

1) I am already in contact with them. They got the link to the discussions right when I created them. So far there is little response. But their website states that they are on vacation until the 13th.
2) Updating the library and the Hub sketch was the plan anyway. I will try another thing (see 3) and than start cleaning up the code and do the library/sketch updating. Maybe the hacrocam guys want to kick in once they are back. :-) Otehrwise I'll provide them the updated code. Gettingthe serial transmition times of the cam down will extend the pissiblities for robotics use (where I want to use it for). This together with the low price tag ... I hope more people will buy the cam and a comunity starts to build up.
3) Once the grayscale bought down the transmition time for the picture to half of the rgb time, I will now try to go to 4 bit grayscale. Should reduce it again by 50%. First step is to dig into the bit shifting and masking thing to combine the two times four bit to one byte.
4) With the alpha correction code you provided....
Code: [Select]
r = r << 3;  // as r is only 5 bit we must shift it to the left 3 positions
g = g << 2; // g has 6 bits
b = b << 3;  // ....

.... I get an image with many black arreas (I think in the most bright areas of the picture). Using the bit shift here and take only green as gray, I get a nearly complete black picture.

Shifting one bit less ...
Code: [Select]
r = r << 2;
g = g << 1;
b = b << 2;

... gives a brighter image without the black areas.


BTW. I am surprised how well only taking the green chanel works. Almost no visible difference to the calculated values.

Thanks
Robert

robtillaart

1) OK
2) OK
3) OK, had the same idea see other thread => you will get colour banding
4)
Quote
I get an image with many black areas

As I have no HW to check things some advices are just based upon the code ;)

Quote
I am surprised how well only taking the green chanel works. Almost no visible difference to the calculated values.

In the formulas green is ~60% of the info. that's why. 

Q: Is it possible to post images ? RGB / gray (printscreen)



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robvoi

Hi,

here is an overview of the pics, including the one with the theoretically correct bit shift- which gives the black areas..
http://picturepush.com/public/11918058

The 4 bit version is simulated only. It still works with 8 bit which I shifted right and left to reduce color depth.
I will now have to combine the two bytes to one and do the decoding on the other side.

Attached you also find the data sheet for the cam. Got it from a nice guy from hacroca (who is actually on vacation).
It shows that the RRRRRGGG GGGBBBBB coding is correct.

Regards,
Robert



Nick Gammon

Quote
Code: [Select]
for (unsigned int l= 0; l < TWI_BUFFER_LENGTH/2; ++l){


Please don't use the variable name l.

That looks amazingly like 1 on my PC, so the code l = 0 looks like "assign zero to one".

And you can imagine what this looks like:

Code: [Select]
b = buf[l*2] & 0xff ;


Also the variable name l and I look very similar (l = lower-case L and I = upper-case i).
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

robvoi

Good point. I'll keep it in mind for new code. For editors we have dev friendly fonts. The browser hasn't. Otherwise using one for the code outline in the forum would have been nice.

Robert


Nick Gammon

Font or not, I wouldn't encourage it.

Imagine code where you had variables l (lower-case L), I (upper-case i) and O (upper-case o). And you had lines like this:

Code: [Select]

a = 1;
b = l;
c = I;
d = 0;
e = O;


You would have to have eagle eyes and good concentration not to get confused by that sort of stuff.

And you don't necessarily control the sort of font that other people who view your code might use.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

From your code above this line:

Code: [Select]
lsb = 2*l+1;

... manages to combine L and one in the same line.

Yes, I know it's nitpicking. But improve on that and other problems will go away as the code is more readable. More spaces would help too.

eg.

Code: [Select]

lsb = (2 * loc) + 1;
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up