Read blocks of pixeis with arduino mega

Added by Hugo cap about 4 years ago

hi, Sorry to be a bother, but i need some help :s . I'm trying to test a small mathematical algorithm that work with pixel values ​​without compression in 8x8 pixel blocks. For this I bought a arduino mega, CMUcam4 red card and a memory. I've been reading the getting starts but i not understant very well. what I want to do is this:
1 - Take a picture in black and white.
2 - Save the picture on the Memory Card
3 - With arduino obtain blocks of 8x8 pixel image that is in the cards.

Sample image 16x 16 pixel, with values ​​from 0 to 255:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
17,18,19,20,21,22,23,24,25,26 ,27,28,29,30,31,32
,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
17,18,19,20,21,22,23,24,25,26 ,27,28,29,30,31,32
,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64

I want to receive arduino for the blocks like this: (8x8 block of pixels)

1,2,3,4,5,6,7,8,
17,18,19,20,21,22,23,24
, 33,34,35,36,37,38,39,40
, 49,50,51,52,53,54,55,56,
1,2,3,4,5,6,7,8,
17,18,19,20,21,22,23,24
, 33,34,35,36,37,38,39,40
, 49,50,51,52,53,54,55,56,

for to create this array in arduino, like this:
array=[1,2,3,4,5,6,7,8,17,18,19,20,21,22,23,24,33,34,35,36,37,38,39,40,49,50,51,52,53,54,55,56,1,2,3,4,5,6,7,8,17,18,19,20,21,22,23,24,33,34,35,36,37,38,39,40,49,50,51,52,53,54,55,56]

Sera that could help me do this little program?could tell me how to start?

Thanks for the help and sorry for bad english


Replies (16)

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman about 4 years ago

The CMUcam4 doesn't really have any features to do what you want. However, by combining different stuff it can be done. However, it won't be fast (in run time) or easy. The system is really not designed to take pictures. That is an extra feature for the purposes of debugging.

But, if you want to go ahead...

You can use the:

BW 1 <- Go to black and white
DF 3 3 <- Save 80x60 image to the SD card.

After which you can use the PR command to get the image data from the SD card. However, this will require you to understand how a BMP file looks inside and buffer parts of the image.

Instead you can use the "SF 3 3" command to have the CMUcam4 send the Arduino the 80x60 binary image. After which you can select an 8x8 part of the image at a time to run your code on.

I'm not kidding about how slow this will be however... To work through the entire 80x60 image in 8x8 chunks will take about 6 minutes. This also means your subject will have to stay perfectly still for 6 minutes.

A lot of people have asked me if they can do image processing on the Arduino. Due to the lack of memory on the Arduino/Arduino Mega this is not really possible. The CMUcam4 makes all efforts to reduce the amount of data it send to the Arduino. You only have 8K of memory on the Mega which is not enough to store even an 80x60 image.

Thanks,

RE: Read blocks of pixeis with arduino mega - Added by Hugo cap about 4 years ago

Thank you for the reply Kwabena Agyeman, I used my funds in CMUcam4 so go ahead with the CMU ahahahah :). If it's hard to take a picture, which you can save to Memory Card? I know that arduino has little memory, so I thought since the CMUcam4 has slot for Memory Card.

In another post I saw this program.

void loop () {
for (;;) {
uint16_t buffer [H_SIZE V_SIZE *] / / 10 by 10 pixel buffer int xCounter, yCounter;
for (xCounter = 0; xCounter <80/H_SIZE; xCounter + +) {
for (yCounter = 0; yCounter <60/V_SIZE; yCounter + +) {
mySerial.print ("File: \ n");
mySerial.print (cam.sendFrame (3, 3, buffer, H_SIZE, xCounter * H_SIZE, V_SIZE, yCounter V_SIZE *));
mySerial.print ("\ n");
delay (300);
/ / From image processing here ...
}
}
}
/ / Do something else here.
}

i can use this to send blocks to arduino, or save in memory card without take a picture? Real time, with the camera motionless?

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman about 4 years ago

Hi,

I can write the code to get the image from the camera for you.

If you use an SD card to take a picture then the subject will only need to be still (and the lighting needs to be still also) for about 4 seconds. However, saving the image to the SD card will take much longer and more work to read back from the camera.

If you just send images from the camera to the Arduino... then the subject will need to be very still for the 6 minutes mentioned above, but, this will be faster than reading from the SD card.

The reason for this is that the CMUcam4 only has one command to read a file from the SD card that transfer the file at 4KB/s. It will trasnfer the whole file each time you want just one part of the file. So, the code is really tricky. Its easier just to use the send frame command. Your subject just has to be still and in unchanging lighting.

I'll give you the code for send frame at least...

...

Other option:

You can take a picture with the CMUcam4. Save it to the SD card with the DF command. (Subject needs to be still for the one picture taken).

Then use the PR command to transfer the file from the CMUcam4's SD card to the Arduino own SD card. The Arduino will write the image it its own SD card.

Then the Arduino can access its own SD MUCH, MUCH, MUCH faster than the one on the CMUcam4. This should make your algorithm run really fast!

You'll have to hack the CMUcam4 interface library a bit to make this possible. But, its the best option for speed.

Thanks,

RE: Read blocks of pixeis with arduino mega - Added by Hugo cap about 4 years ago

hi Kwabena Agyeman

Very many thanks for your help and for your time, I'm so sorry to be using your time, i believe you to be a busy person, so thank you for your time.

If I can make a code I would appreciate greatly. Can I test the simplest option at the beginning. But later when CMUcam4 better understand, I can try your second idea, which sounded more complicated. But what do you think the best solution for now?

I wonder if I can talk to you on skype the other why more quickly in case of any doubt. If you have some time and availability of course.

Thanks a lot Kwabena Agyeman

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman about 4 years ago

I can give you the code for the simple solution with the SD card right now... but it will be very slow.

As for learning how to use the camera... watch this video please: http://www.cmucam.org/projects/cmucam4/wiki/How_to_use_the_CMUcam4_properly.

Thanks,

RE: Read blocks of pixeis with arduino mega - Added by Hugo cap about 4 years ago

If you could give me the code I would appreciate very much.

thanks a lot.

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman about 4 years ago

Here's the code... I haven't tested it, but, I hope you get the idea.

#include <CMUcam4.h>
#include <CMUcom4.h>

#define LED_SETUP 5 // 5 Hz
#define WAIT_TIME 5000 // 5 Seconds

#define H_SIZE 8 // Must be a divisor of the X resolution.
#define V_SIZE 6 // Must be a divisor of the Y resolution.

#define H_SELECT CMUCAM4_HR_80 // Use HR_160, HR_320, and HR_640 here for higher resolutions. 
#define V_SELECT CMUCAM4_VR_60 // Use VR_120, VR_240, and VR_480 here for higher resolutions. 

#define X_RES (640 >> H_SELECT) 
#define Y_RES (480 >> V_SELECT) 

CMUcam4 cam(CMUCOM4_SERIAL);

void setup()
{
  cam.begin();

  // Wait for auto gain and auto white balance to run.

  cam.LEDOn(LED_SETUP);
  delay(WAIT_TIME);

  // Turn auto gain and auto white balance off.

  cam.autoGainControl(false);
  cam.autoWhiteBalance(false);

  cam.LEDOn(CMUCAM4_LED_ON);

  // Go to black and white mode.

  cam.blackAndWhiteMode(true);
}

void loop()
{
  uint16_t buffer[V_SIZE][H_SIZE];

  for(int y = 0; y < Y_RES; y += V_SIZE)
  {
    for(int x = 0; x < X_RES; x += H_SIZE)
    {
      cam.sendFrame(H_SELECT, V_SELECT, (uint16_t *) buffer, H_SIZE, V_SIZE, x, y);

      for(int v = 0; v < V_SIZE; v++)
      {
        for(int h = 0; h < H_SIZE; h++)
        {
          int red = getRed(buffer[v][h]);
          int green = getGreen(buffer[v][h]);
          int blue = getBlue(buffer[v][h]);

          // Do your processing here...
        }
      }
    } 
  }

  for(;;) { } // Spin forever...  
}

int getRed(uint16_t pixel) // Returns the red part of a pixel 0-255.
{
  return ((((pixel >> 11) & 0x1F) * 255) / 31);
}

int getGreen(uint16_t pixel) // Returns the green part of a pixel 0-255.
{
  return ((((pixel >> 5) & 0x3F) * 255) / 63);
}

int getBlue(uint16_t pixel) // Returns the blue part of a pixel 0-255.
{
  return ((((pixel >> 0) & 0x1F) * 255) / 31);
}

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman about 4 years ago

By the way... again. Remember, it takes about 4 seconds to send an image per call to the send frame function. So... this means the loop will take about 400 seconds in the code above...

If you need to speed the code up. Then use a larger window size that is bigger than 8x6 pixels. But, remember that you have limited RAM in the Arduino Mega. You should be able to comfortably use a window size of 40x30 pixels. Then you could break that window yourself into 8x6 pixel blocks. This way it will only take about 16 seconds.

#include <CMUcam4.h>
#include <CMUcom4.h>

#define LED_SETUP 5 // 5 Hz
#define WAIT_TIME 5000 // 5 Seconds

#define H_SIZE 40 // Must be a divisor of the X resolution.
#define V_SIZE 30 // Must be a divisor of the Y resolution.

#define SUB_X_SIZE 8 // Smaller window inside of H_SIZE... must be a divisor of H_SIZE.
#define SUB_Y_SIZE 6 // Smaller window inside of V_SIZE... must be a divisor of V_SIZE.

#define H_SELECT CMUCAM4_HR_80 // Use HR_160, HR_320, and HR_640 here for higher resolutions. 
#define V_SELECT CMUCAM4_VR_60 // Use VR_120, VR_240, and VR_480 here for higher resolutions. 

#define X_RES (640 >> H_SELECT) 
#define Y_RES (480 >> V_SELECT) 

CMUcam4 cam(CMUCOM4_SERIAL);

void setup()
{
  cam.begin();

  // Wait for auto gain and auto white balance to run.

  cam.LEDOn(LED_SETUP);
  delay(WAIT_TIME);

  // Turn auto gain and auto white balance off.

  cam.autoGainControl(false);
  cam.autoWhiteBalance(false);

  cam.LEDOn(CMUCAM4_LED_ON);

  // Go to black and white mode.

  cam.blackAndWhiteMode(true);
}

void loop()
{
  uint16_t buffer[V_SIZE][H_SIZE];

  for(int y = 0; y < Y_RES; y += V_SIZE)
  {
    for(int x = 0; x < X_RES; x += H_SIZE)
    {
      cam.sendFrame(H_SELECT, V_SELECT, (uint16_t *) buffer, H_SIZE, V_SIZE, x, y);

      for(int v = 0; v < V_SIZE; v += SUB_Y_SIZE)
      {
        for(int h = 0; h < H_SIZE; h += SUB_X_SIZE)
        {
          for(int sy = 0; sy < SUB_Y_SIZE; sy++)
          {
            for(int sx = 0; sx < SUB_X_SIZE; sx++)
            {
              int red = getRed(buffer[v + sy][h + sx]);
              int green = getGreen(buffer[v + sy][h + sx]);
              int blue = getBlue(buffer[v + sy][h + sx]);

              // Do your processing here... 
            }
          }
        }
      }
    } 
  }

  for(;;) { } // Spin forever...  
}

int getRed(uint16_t pixel) // Returns the red part of a pixel 0-255.
{
  return ((((pixel >> 11) & 0x1F) * 255) / 31);
}

int getGreen(uint16_t pixel) // Returns the green part of a pixel 0-255.
{
  return ((((pixel >> 5) & 0x3F) * 255) / 63);
}

int getBlue(uint16_t pixel) // Returns the blue part of a pixel 0-255.
{
  return ((((pixel >> 0) & 0x1F) * 255) / 31);
}

Thanks,

RE: Read blocks of pixeis with arduino mega - Added by Hugo cap about 4 years ago

Thank you Kwabena Agyeman , I'll try, but it is a great help in getting started.

thanks :)

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman about 4 years ago

Remember that the subject cannot move while the code is running.

Good luck,

RE: Read blocks of pixeis with arduino mega - Added by Hugo cap almost 4 years ago

hi Kwabena Agyeman

I try your options and I chose this your option , i took a picture, put it in SD card, I used cam.filePrint ("00001BM.BMP", (uint8_t *) buffer, 1920, INCREM), then do 8x8 array blocks for what I do and processing.

I used 1920, because of the memory of the arduino.

Run faster, but still takes a bit because I have to do FilePrint 40 times. Any idea to be faster? thank you

I have another problem, I have the 16-bit pixel (rgb 565 rigth?), But I want to go gray tones for 8-bit pixels, I thought I only get the red, but well lose 3 bits of resolution, do you have any idea? i pretend values 0-255, 8 bits

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman almost 4 years ago

For 8-bit grey scale... just go to YUV mode and then use the Y channel (green). This will give you 6-bits.

The camera is only a 16-bit camera so that is why its RGB565.

You know... if you want, you could just program the CMUcam4 natively... take a look at this project... and especially the SPIN code in the project: http://www.cmucam.org/projects/cmucam4/wiki/Low_Power_Motion_Detection

I wrote a simple driver for the CMUcam4 that lets you grab 8-bit greyscale pictures and store them in memory at 30 FPS with a resolution of 128x96. You'll have to write you code in SPIN, but other than that you would have the functionality you need. There's some easy to follow example code in there.

Thanks,

RE: Read blocks of pixeis with arduino mega - Added by Ali Arslan almost 2 years ago

Kwabena Agyeman
Sir,
I am working on a project in which i need to read .bmp file from card and generate a 10*10 array(in 0 1 format) according to that .bmp file...how can i use your above code for that purpose?

.bmp file is given below

Capture .bmp (5.7 kB)

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman almost 2 years ago

Sorry, you can't - you shouldn't be doing what you want to do with a BMP file. Just save the maze as a text file which is much easier to read with a computer.

RE: Read blocks of pixeis with arduino mega - Added by Ali Arslan almost 2 years ago

Actually Sir i am restricted to use .bmp file and i have no idea what logic should i use to read that .bmp file so that my robot can move on that path specified in .bmp file(white block are opening of arena and black block are hurdles).
and m using Arduino mega 2560 for controlling purposes.

need some guide line?

Capture.bmp (53.7 kB)

RE: Read blocks of pixeis with arduino mega - Added by Kwabena Agyeman almost 2 years ago

Reading a BMP file has nothing to do with the CMUcam4. Anyway, what kind of software is reading the BMP file? Is this a computer application or are you doing everything from scratch?

(1-16/16)