Go Down

Topic: HacroCam - recalculate to greyscale before sending (processing example) (Read 4 times) previous topic - next topic

robvoi

@Hacrocam users

Attached you find an updated arduino library, the arduhub sketch and an updated processing example for the Hacrocam.
The update allows to convert the image to 8bit grayscale before submitting it via serial link. This halves the time required for the transfer. Great for low baud rate serial links.
In addition you can take more than one picture without restarting the sketch. Press w to take a picture.

The processing example has an added user definable variable g_grayscaleImage to enable/disable grayscale convertion.

Many thanks @robtillaart who solved the hard part. I just put together the puzzle pieces and extended the library and sketches.

Trying to extend it with a 4bit grayscale option now.

Robert

robtillaart

HI,

I did have the same idea yesterday to get a 4bit gray-scale image.

Another idea is to send an image progressively. Suppose you have an image of 8x8 pixels. Then you send the pixels in this order:
// layer 0 lowest resolution (stepsize n/2)
[0,0]
[4,0]
[0,4]
[4,4]

// layer 1  (stepsize n/4 but not those already send)
[2,0], [6,0]
[0,2], [2,2], [4,2], [6,2]
[2,4], [6,4],
[0,6], [2,6], [4,6], [6,6]

// layer 2 (stepsize n/8 but not those already send => which are all remaining pixels for an 8x8 bitmap.
[1,0], [3,0], 5,0], [7,0]
etc

There advantage of progressive images is that you get an idea of the overall picture and it refines gradually.
It also allows to stop transmitting when the resolution is high enough.

Besides the proposed schema, there are many more schemas. The best known is the alternating lines.
First send all the even lines and than all odd lines.

Another speed up of transmission could be run length encoding. This is especially useful if you go to the 4 bit modes.

A byte could become a {run length; colour } tuple, with a run length of 1..15 and a 4 bit colour.
If you have 6 bytes of a certain colour (e.g. colour 9) you send { 6, 9 } or as byte B0110 1001

Rob Tillaart

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

robvoi

Hi,

send an image progressively is a good idea. Unfortunately in my case it will not work for two reasons:

1)
The image gets streamed from the camera to the Arduino via TWI/I2C though a 32byte buffer (so 16 pixels).
Only the buffer can be reworked. That's because auf the limited RAM available. The image in total would not fit into the RAM.
I could download the image pixel by pixel from the cam. But this would slow things down again an negate the compression work done.

2)
At the moment in Processing the picture doesn't get rendered during the download. I tried to change that (to see the pixels arriving) but didn't succeed. As I am one of the many victims of the "new topic button now showing in the Processing forum" bug, I can't even post to get help there. ?


The run length encoding is interesting too. But I would lose half of the space for pixels. Maybe it would be possible to mix 4bit grayscale and run length encoding with some signaling byte. But as I can only process 16 pixels at a time, I am not sure if this in reality would improve speed. Taking into account the lost information space and the calculation time.
I looked at other compression methods. But they are all too heavy for an Arduino.

I also looked at other color schemes. 3-3-2 RGB looked nice too. But as far as I read the shading depth is more important for the human brain than the color. (especially for me, as I am partially color blind  XD )

If you have more ideas - please through them in. Maybe we get it to stream a video over the 115k baud.  ]:D

Thanks
Robert

robvoi

I tried the 4bit grayscale. The saved trasmission time gets eaten up by the calculation time. It may still be worth the effor, as it will help on speeds slower than 115k baud.

I think I got close but don't get a correct picture. I think the error is on the decoding side. But I don't get it. Maybe if I look at it later again.

(Still l and one char variables in, as it's the old code. The newly added variable names are better. :-))

encoding:
Code: [Select]

//*pbuf is the pointer to the 32 byte RGB pixel buffer

           void rgbTo4Bit (byte *pbuf, int bufflength){
for (unsigned int l= 0; l < bufflength/4; ++l){
int msbLeft = pbuf[4*l] & 0xff;
int lsbLeft = pbuf[4*l+1] & 0xff;
int rLeft = (lsbLeft >> 3) & 0x1F;
int gLeft = ((lsbLeft & 0x07) << 3) | ((msbLeft >> 5) & 0x07) ;
int bLeft = (msbLeft & 0x1f);
rLeft = rLeft << 2;
gLeft = gLeft << 1;
bLeft = bLeft << 2;
int grayLeft=(77 * rLeft + 150* gLeft + 29 * bLeft) >> 8;
grayLeft = grayLeft >> 4;
grayLeft = grayLeft << 4;


int msbRight = pbuf[4*l+2] & 0xff;
int lsbRight = pbuf[4*l+3] & 0xff;
int rRight = (lsbRight >> 3) & 0x1F;
int gRight = ((lsbRight & 0x07) << 3) | ((msbRight >> 5) & 0x07) ;
int bRight = (msbRight & 0x1f);
rRight = rRight << 2;
gRight = gRight << 1;
bRight = bRight << 2;
int grayRight=(77 * rRight + 150* gRight + 29 * bRight) >> 8;
grayRight= grayRight >> 4;

pbuf[l]=(grayLeft | grayRight);
}
}


decoding (in Processing):
Code: [Select]
for (int row = imageh-1; row >= 0; --row)
{
  for (int col = 0; col < imagew; col=col+2)
  {
    int loc = imagew*row+col;
          int LeftPixel= packedbuf[loc] >>> 4;
          LeftPixel= LeftPixel << 4;
          int RightPixel= packedbuf[loc] << 4;
          img.pixels[loc] = color(LeftPixel,LeftPixel, LeftPixel);
          img.pixels[loc+1] = color(RightPixel, RightPixel, RightPixel);
    }
  }


It loos like this: http://picturepush.com/public/11920881
Must be something wrong with the col and row count I think,

Robert

robtillaart


decoding:
Code: [Select]

for (int row = imageh-1; row >= 0; --row)
{
  for (int col = 0; col < imagew; col += 2)
  {
    int loc = imagew*row + col;
    int LeftPixel = packedbuf[loc] & 0XF0;  // mask the higher 4 bits is enough
    int RightPixel = packedbuf[loc] << 4;

    img.pixels[loc] = color(LeftPixel,LeftPixel, LeftPixel);
    img.pixels[loc+1] = color(RightPixel, RightPixel, RightPixel);
  }
}
Rob Tillaart

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

Go Up