Unable to retrieve high-resolution images in RGB565 format in Spresense

Asked 2 years ago, Updated 2 years ago, 87 views

As stated in the title, I would like you to tell me about obtaining high-resolution images in RGB 565 format in Spresense.

I am trying to obtain images in VGA and FULL HD image quality in RGB565 format using the Camera sample, but I am unable to obtain them due to an error.
RGB565 is able to obtain QVGA and high resolution images in JPG format without any problems.
The RGB 565 QVGA acquisition size is 150KB, so I think I can get it at 600KB if it's about VGA, but I can't do that either.

It seems that the reason is that the memory area of the resense is small, but could you please let me know if you know the countermeasures?

Tried

  • Change the memory size of the spresense to 1536KB ← No effect
  • Stop Streaming function←No effect

Error Contents

  • RGB565VGA Size
    >>Error: Invalid parameter
  • RGB565FULL HD Size
    >>Error: No memory

Changing code part

theCamera.setStillPictureImageFormat(
     CAM_IMGSIZE_VGA_H,
     CAM_IMGSIZE_VGA_V,
     CAM_IMAGE_PIX_FMT_RGB565);

Thank you for your cooperation.

spresense arduino camera

2022-09-30 20:14

2 Answers

I was curious about this before, so I looked into it.

spresense-nuttx/arch/arm/src/cxd56xx/cxd56_cisif.c

Line 59

of
#define YUV_VSIZE_MAX (360)
#define YUV_HSIZE_MAX (480)

and line 749

static int cisif_chk_yuvfrmsize(int w, int h)
{
  if((w<YUV_HSIZE_MIN)||(w>YUV_HSIZE_MAX))
    {
      return-EINVAL;
    }

  if((h<YUV_VSIZE_MIN)||(h>YUV_VSIZE_MAX))
    {
      return-EINVAL;
    }

  return OK;
}

determined 360x480 or less.

From this point of view, the specification is 360x480 or less.


2022-09-30 20:14

It's a tricky technique, but you can take it in JPEG, deploy it to RGB, and print it to a file.For Arduino, libjpeg must be included in the Spresense Arduino Board Package.

I have introduced how to do it here in here, but I think it would be troublesome to make a board package, so I published my own package in the Github repository.Please use it if you need it.You can set the URL to Arduino IDE according to README and install it from Board Manager.

https://github.com/YoshinoTaro/spresense-arduino-libjpeg

Now, the most important thing is that there is a sample in the repository above, but I will include a simplified code.You can save the RGB data from which JPEG has been deployed to a file.(I tried expanding the memory, but it was too big for me because I didn't have enough memory.)

This enhancement also allows you to partially decode only the specified ROI and deploy it to RGB.In this case, if the ROI is small, it can also be deployed to memory.There is a sample in the repository above, so please refer to it if you like.

/* [Caution!]
 * To try this code, use the spresense arduino with libjpeg enabled.
*  Board Package is required.You can retrieve it at the following URL:(V2.4.0 base)
 * (Spresense libjpeg Boards: Spresense libjpeg)
 * * https://github.com/YoshinoTaro/spresense-arduino-libjpeg
 */
# include <Camera.h>
#define HAVE_BOOLEAN

# include <nuttx/config.h>
# include<sys/stat.h>
# include <unistd.h>
# include<libjpeg/jpeglib.h>
# include <string.h>
US>extern "C" {
# include <setjmp.h>
}

const width = CAM_IMGSIZE_VGA_H;
const height = CAM_IMGSIZE_VGA_V;
const char filename [10] = "out.rgb";

external "C" pool decode_jpeg_to_file(uint8_t*imgbuf,uint32_timgsize
  , const char*filename);

void setup() {  
  Serial.begin (115200);
  the Camera.begin();
  TheCamera.setStillPictureImageFormat(
    width, height, CAM_IMAGE_PIX_FMT_JPG);
  CamImage img=theCamera.takePicture();
  if(!img.isAvailable()){
    Serial.println("Cannot take a picture");
    return;
  }

  if(!decode_jpeg_to_file(img.getImgBuff(),img.getImgSize()
                 , filename)) {
    Serial.println("decode error");
    return;
  }

  Serial.println("the decoded image saved as out.rgb");
  Serial.println("Please change the filename to out.data to visualize by GIMP";

  // end the camera to reset the format and free the image buffer
  theCamera.end(); 
}

void loop(){}

Booleandecode_jpeg_to_file(uint8_t*imgbuf,uint32_timgsize)
     , const char*filename) {
      
  structure stat buf;
  for(;;){
    sleep(1);
    intret=stat("/mnt/sd0", & buf);
    if(ret)printf("Please insert formatted SD Card.\n");
    else break;
  }
  
  char path[20] = "/mnt/sd0/";
  strcat(path, filename);
  printf("Filie path:%s\n", path);
  FILE*out=fopen(path, "wb");
  if(out==NULL){
    fprintf(stderr, "can't open%s\n", filename);
    return false;
  }
  printf("create%s\n", filename);
  
  static structure jpeg_decompress_struct cinfo;
  structure jpeg_error_mgr jerr;  

  cinfo.err=jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);

  jpeg_mem_src(&cinfo, imgbuf, imgsize);

  jpeg_read_header(&cinfo,TRUE);

  cinfo.out_color_space=JCS_RGB;

  jpeg_start_decompress(&cinfo);
  printf("cinfo.output_width:%d\n",cinfo.output_width);  
  printf("cinfo.output_height:%d\n",cinfo.output_height);  

  JSAMPARRAY buffer; /* Output row buffer */
  introw_stride; /* physical row width in output buffer */
  row_stride=cinfo.output_width*3;//incase of RGB
  buffer=(*cinfo.mem->alloc_sarray)
                ((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);

  printf("Step6:read scanlines\n");
  intn = 0; /* for debug */
  while(cinfo.output_scanline<height){
    jpeg_read_scanlines(&cinfo, buffer, 1);
    if(row_stride!=fwrite(buffer[0], 1, row_stride, out)){
      printf("fwrite error:%d\n", errno);
    }
    ++n;
  }
  printf("read lines:%d\n",n); /* for debug*/
  fclose(out);

  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
  return true;
}


2022-09-30 20:14

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.