ArduCAM / Arduino

This is ArduCAM library for Arduino boards
MIT License
477 stars 350 forks source link

How to check RGB value of pixel. #123

Open paekitt opened 7 years ago

paekitt commented 7 years ago

Hi!! How to check RGB value each pixel of picture ?

ArduCAM commented 7 years ago

@paekitt, in the camera playback example the image data is saved as RGB565 format. Each pixel is composed by two consicutive bytes, so you can convert the RGB565 to RGB888 and check the value the way you want.

dprophet commented 7 years ago

RGB565 is stored in a 16bit number with an extra green bit. Bits are laid out as RRRRRGGGGGGBBBBB

https://s2.www.theimagingsource.com/application-0.0.5623/documentation/ic_imaging_control_class/en_US/images/rgb565.gif

You can check the color bits directly.

I believe that Arduino ATMega is little endian so reverse the image and bits to BBBBBGGGGGGRRRRR

I have some RGB resampling code I wrote some 20 years ago I can dig for if your use case is really that necessary.

paekitt commented 7 years ago

@ArduCAM @dprophet Now I use code https://github.com/ArduCAM/Arduino/tree/master/ArduCAM/examples/mini/ArduCAM_Mini_Video_Streaming

And Host App V.2 https://github.com/ArduCAM/Arduino/tree/master/ArduCAM/examples/host_app/ArduCAM_Host_V2.0_Windows

I want to show R G B value on Host App V.2 ( Serial.print(); ) in mode streaming or capture image.

supprot commented 7 years ago

@paekitt The ArduCAM_Mini_Video_Streamimg can't support showing RGB value on Host App V.2. We will update the sample to support this function as soon as possible.

Regards, ArduCAM support team.

supprot commented 7 years ago

@paekitt Hi, You can try this example and ArduCAM_Host_V2 If you want to show RGB value, just to choose 'SetToBMP' at the ArduCAM_Host_V2.

// ArduCAM Mini demo (C)2016 Lee // web: http://www.ArduCAM.com // This program is a demo of how to use most of the functions // of the library with ArduCAM Mini camera, and can run on any Arduino platform. // This demo was made for ArduCAM_Mini_5MP_Plus. // It needs to be used in combination with PC software. // It can take photo continuously as video streaming. // // The demo sketch will do the following tasks: // 1. Set the camera to JEPG output mode. // 2. Read data from Serial port and deal with it // 3. If receive 0x00-0x08,the resolution will be changed. // 4. If receive 0x10,camera will capture a JPEG photo and buffer the image to FIFO.Then write datas to Serial port. // 5. If receive 0x20,camera will capture JPEG photo and write datas continuously.Stop when receive 0x21. // 6. If receive 0x30,camera will capture a BMP photo and buffer the image to FIFO.Then write datas to Serial port. // 7. If receive 0x11 ,set camera to JPEG output mode. // 8. If receive 0x31 ,set camera to BMP output mode. // This program requires the ArduCAM V4.0.0 (or later) library and ArduCAM_Mini_5MP_Plus // and use Arduino IDE 1.5.2 compiler or above

include

include

include

include "memorysaver.h"

//This demo can only work on OV2640_MINI_2MP or OV5642_MINI_5MP or OV5642_MINI_5MP_BIT_ROTATION_FIXED platform.

if !(defined OV5642_MINI_5MP || defined OV5642_MINI_5MP_BIT_ROTATION_FIXED || defined OV2640_MINI_2MP)

error Please select the hardware platform and camera module in the ../libraries/ArduCAM/memorysaver.h file

endif

define BMPIMAGEOFFSET 66

const char bmp_header[BMPIMAGEOFFSET] PROGMEM = { 0x42, 0x4D, 0x36, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00 }; // set pin 7 as the slave select for the digital pot: const int CS = 7; bool is_header = false; int mode = 0; uint8_t start_capture = 0;

if defined (OV2640_MINI_2MP)

ArduCAM myCAM( OV2640, CS );

else

ArduCAM myCAM( OV5642, CS );

endif

uint8_t read_fifo_burst(ArduCAM myCAM);

void setup() { // put your setup code here, to run once: uint8_t vid, pid; uint8_t temp;

if defined(SAM3X8E)

Wire1.begin(); Serial.begin(115200);

else

Wire.begin(); Serial.begin(921600);

endif

Serial.println("ACK CMD ArduCAM Start!");

// set the CS as an output: pinMode(CS, OUTPUT);

// initialize SPI: SPI.begin(); //Check if the ArduCAM SPI bus is OK myCAM.write_reg(ARDUCHIP_TEST1, 0x55); temp = myCAM.read_reg(ARDUCHIP_TEST1); //Serial.println(temp); if (temp != 0x55) { Serial.println("ACK CMD SPI interface Error!"); while(1); }

if defined (OV2640_MINI_2MP)

//Check if the camera module type is OV2640 myCAM.wrSensorReg8_8(0xff, 0x01); myCAM.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid); myCAM.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid); if ((vid != 0x26 ) && (( pid != 0x41 ) || ( pid != 0x42 ))) Serial.println("Can't find OV2640 module!"); else Serial.println("OV2640 detected.");

else

//Check if the camera module type is OV5642 myCAM.wrSensorReg16_8(0xff, 0x01); myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid); myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid); if((vid != 0x56) || (pid != 0x42)) Serial.println("ACK CMD Can't find OV5642 module!"); else Serial.println("ACK CMD OV5642 detected.");

endif

//Change to JPEG capture mode and initialize the OV5642 module myCAM.set_format(JPEG); myCAM.InitCAM();

if defined (OV2640_MINI_2MP)

myCAM.OV2640_set_JPEG_size(OV2640_320x240);

else

myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK); //VSYNC is active HIGH myCAM.OV5642_set_JPEG_size(OV5642_320x240);

endif

delay(1000);

myCAM.clear_fifo_flag();

if !(defined (OV2640_MINI_2MP))

myCAM.write_reg(ARDUCHIP_FRAMES,0x00);

endif

}

void loop() { // put your main code here, to run repeatedly: uint8_t temp = 0xff,temp_last = 0; bool is_header = false; if (Serial.available()) { temp = Serial.read(); switch (temp) { case 0:

if defined (OV2640_MINI_2MP)

  myCAM.OV2640_set_JPEG_size(OV2640_160x120);delay(1000);
  Serial.println("ACK CMD switch to OV2640_160x120");
  #else
    myCAM.OV5642_set_JPEG_size(OV5642_320x240);delay(1000);
    Serial.println("ACK CMD switch to OV5642_320x240");
   #endif
    temp = 0xff;
    break;
  case 1:

   #if defined (OV2640_MINI_2MP)
   myCAM.OV2640_set_JPEG_size(OV2640_176x144);delay(1000);
     Serial.println("ACK CMD switch to OV2640_176x144");
  #else
   myCAM.OV5642_set_JPEG_size(OV5642_640x480);delay(1000);
   Serial.println("ACK CMD switch to OV5642_640x480");
  #endif
   temp = 0xff;
    break;
  case 2:

  #if defined (OV2640_MINI_2MP)
    myCAM.OV2640_set_JPEG_size(OV2640_320x240);delay(1000);
    Serial.println("ACK CMD switch to OV2640_320x240");
   #else
    myCAM.OV5642_set_JPEG_size(OV5642_1024x768);delay(1000);
    Serial.println("ACK CMD switch to OV5642_1024x768");
   #endif
    temp = 0xff;
    break;
  case 3:
  temp = 0xff;
  #if defined (OV2640_MINI_2MP)
   myCAM.OV2640_set_JPEG_size(OV2640_352x288);delay(1000);
   Serial.println("ACK CMD switch to OV2640_352x288");
   #else
    myCAM.OV5642_set_JPEG_size(OV5642_1280x960);delay(1000);
    Serial.println("ACK CMD switch to OV5642_1280x960");
   #endif
    break;
  case 4:
  temp = 0xff;
  #if defined (OV2640_MINI_2MP)
   myCAM.OV2640_set_JPEG_size(OV2640_640x480);delay(1000);
    Serial.println("ACK CMD switch to OV2640_640x480");
  #else
    myCAM.OV5642_set_JPEG_size(OV5642_1600x1200);delay(1000);
    Serial.println("ACK CMD switch to OV5642_1600x1200");
  #endif
   break;
  case 5:
  temp = 0xff;
 #if defined (OV2640_MINI_2MP)
   myCAM.OV2640_set_JPEG_size(OV2640_800x600);delay(1000);
    Serial.println("ACK CMD switch to OV2640_800x600");
  #else
    myCAM.OV5642_set_JPEG_size(OV5642_2048x1536);delay(1000);
    Serial.println("ACK CMD switch to OV5642_2048x1536");
    #endif
    break;
    case 6:
    temp = 0xff;
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_1024x768);delay(1000);
     Serial.println("ACK CMD switch to OV2640_1024x768");
   #else
   myCAM.OV5642_set_JPEG_size(OV5642_2592x1944);delay(1000);
   Serial.println("ACK CMD switch to OV5642_2592x1944");
  #endif
    break;
  #if defined (OV2640_MINI_2MP)
    case 7:
    temp = 0xff;
   myCAM.OV2640_set_JPEG_size(OV2640_1280x1024);delay(1000);
     Serial.println("ACK CMD switch to OV2640_1280x1024");
    break;
  case 8:
  temp = 0xff;
   myCAM.OV2640_set_JPEG_size(OV2640_1600x1200);delay(1000);
     Serial.println("ACK CMD switch to OV2640_1600x1200");
    break;
 #endif
  case 0x10:
    mode = 1;
     temp = 0xff;
    start_capture = 1;
    Serial.println("ACK CMD CAM start single shoot.");
    break;
  case 0x11:
  temp = 0xff;
   myCAM.set_format(JPEG);
   myCAM.InitCAM();
   #if !(defined (OV2640_MINI_2MP))
   myCAM.set_bit(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
   #endif
    break;
  case 0x20:
    mode = 2;
     temp = 0xff;
    start_capture = 2;
    Serial.println("ACK CMD CAM start video streaming.");
    break;
    case 0x30:
    mode = 3;
     temp = 0xff;
    start_capture = 3;
    Serial.println("CAM start single shoot.");
    break;
  case 0x31:
    temp = 0xff;
    myCAM.set_format(BMP);
    myCAM.InitCAM();
   #if !(defined (OV2640_MINI_2MP))        
    myCAM.clear_bit(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
    #endif
    myCAM.wrSensorReg16_8(0x3818, 0x81);
    myCAM.wrSensorReg16_8(0x3621, 0xA7);
    break;
  default:
    break;
}

} if (mode == 1) { if (start_capture == 1) { myCAM.flush_fifo(); myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); start_capture = 0; } if (myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)) { Serial.println("ACK CMD CAM Capture Done!"); read_fifo_burst(myCAM); //Clear the capture done flag myCAM.clear_fifo_flag(); } } else if (mode == 2) { while (1) { temp = Serial.read(); if (temp == 0x21) { start_capture = 0; mode = 0; Serial.println("ACK CMD CAM stop video streaming!"); break; } if (start_capture == 2) { myCAM.flush_fifo(); myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); start_capture = 0; } if (myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)) { uint32_t length = 0; length = myCAM.read_fifo_length(); if ((length >= MAX_FIFO_SIZE) | (length == 0)) { myCAM.clear_fifo_flag(); start_capture = 2; continue; } myCAM.CS_LOW(); myCAM.set_fifo_burst();//Set fifo burst mode temp = SPI.transfer(0x00); length --; while ( length-- ) { temp_last = temp; temp = SPI.transfer(0x00); if (is_header == true) { Serial.write(temp); } else if ((temp == 0xD8) & (temp_last == 0xFF)) { is_header = true; Serial.println("ACK IMG"); Serial.write(temp_last); Serial.write(temp); } if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while, break; delayMicroseconds(15); } myCAM.CS_HIGH(); myCAM.clear_fifo_flag(); start_capture = 2; is_header = false; } } }

else if (mode == 3) { if (start_capture == 3) { //Flush the FIFO myCAM.flush_fifo(); myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); start_capture = 0; } if (myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)) { Serial.println("ACK CMD CAM Capture Done!");

  uint8_t temp, temp_last;
  uint32_t length = 0;
  length = myCAM.read_fifo_length();
  if (length >= MAX_FIFO_SIZE ) 
  {
    Serial.println("ACK CMD Over size.");
    myCAM.clear_fifo_flag();
    return;
  }

  if (length == 0 ) //0 kb
  {
    Serial.println("ACK CMD Size is 0.");
    myCAM.clear_fifo_flag();
    return;
  }
  myCAM.CS_LOW();
  myCAM.set_fifo_burst();//Set fifo burst mode

  Serial.write(0xFF);
  Serial.write(0xAA);
  for (temp = 0; temp < BMPIMAGEOFFSET; temp++)
  {
    Serial.write(pgm_read_byte(&bmp_header[temp]));
  }
  SPI.transfer(0x00);
  char VH, VL;
  int i = 0, j = 0;
  for (i = 0; i < 240; i++)
  {
    for (j = 0; j < 320; j++)
    {
      VH = SPI.transfer(0x00);;
      VL = SPI.transfer(0x00);;
      Serial.write(VL);
      delayMicroseconds(12);
      Serial.write(VH);
      delayMicroseconds(12);
    }
  }
  Serial.write(0xBB);
  Serial.write(0xCC);
  myCAM.CS_HIGH();
  //Clear the capture done flag
  myCAM.clear_fifo_flag();
}

}

}

uint8_t read_fifo_burst(ArduCAM myCAM) { uint8_t temp = 0, temp_last = 0; uint32_t length = 0; length = myCAM.read_fifo_length(); Serial.println(length, DEC);

if (length >= MAX_FIFO_SIZE) //512 kb { Serial.println("Over size."); return 0; } if (length == 0 ) //0 kb { Serial.println("Size is 0."); return 0; } myCAM.CS_LOW(); myCAM.set_fifo_burst();//Set fifo burst mode temp = SPI.transfer(0x00); length --; while ( length-- ) { temp_last = temp; temp = SPI.transfer(0x00); if (is_header == true) { Serial.write(temp); } else if ((temp == 0xD8) & (temp_last == 0xFF)) { is_header = true; Serial.println("ACK IMG"); Serial.write(temp_last); Serial.write(temp); } if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while, break; delayMicroseconds(15); } myCAM.CS_HIGH(); is_header = false; return 1; }

Regards, ArduCAM support team

paekitt commented 7 years ago

@supprot @ArduCAM @dprophet Hi , I try your example (@supprot) and choose 'SetToBMP' but don't show RGB value.

And I try convert the RGB565 to RGB888.

But Host App V.2 show Number command all the same.

I would like to show and collect RGB data from a snapshot. But I do not get on how to access this data, without storing the image or whatever.

I want RGB value to plot graph in my work.

lbtt0423 commented 7 years ago

@paekitt Hi, We have tested that example we send to you and it can work fine, Please take some picture to us and let us know your detail problems.

Regards, Arducam support team.

dprophet commented 7 years ago

@paekitt

I would like to show and collect RGB data from a snapshot. But I do not get on how to access this data, without storing the image or whatever.

Use a Bitmap (.BMP) or a compressed Bitmap (.PNG). You can use libpng to decompress the pixels and access the RGB.

I dont know your use case but, IMO, but what problem are you trying to solve? I think you are going about the problem wrong.

I dont think you need to build anything yourself. I use the ArduCAM outputs to feed others systems. In the case of image analysis you can use IBM Watson cloud. https://visual-recognition-demo.mybluemix.net/

If you want to analyze it yourself use R. They have a nice image statistical package.

ttps://dahtah.github.io/imager/imager.html

OpenCV has a very nice python interface that allows you to do some great analysis of Images. http://opencv.org/

If you just want to view the RGB values at the host, use something like: http://instant-eyedropper.com/

Just accessing RGB values isnt really solving any problem that I can see. What you are trying to accomplish has likely already been done and you can use those tools.

supprot commented 7 years ago

@paekitt Hi, https://github.com/ArduCAM/Arduino/blob/master/ArduCAM/examples/Shield_V2/ArduCAM_Camera_Playback/ArduCAM_Camera_Playback.ino

Using this example can read RGB data, Please refer to the relevant code in the example:

//Read 320x240x2 byte from FIFO //Save as RGB565 bmp format for (i = 0; i < 240; i++) for (j = 0; j < 320; j++) { VH = myCAM.read_fifo(); VL = myCAM.read_fifo(); buf[k++] = VL; buf[k++] = VH;

regards, ArduCAM support team.

paekitt commented 7 years ago

@supprot @ArduCAM rgb

RGB value from capture , I try print (Serial.print();) but RGB value indirect image ?

convert serial

AliSyech commented 6 years ago

What is the tool for getting RGB value ? Can camera OV7670 is used ?

93450101 commented 6 years ago

I want get data of an arducam image and rebuild image with data I received. I cant speak English very well. where can I find useful example